// Node styles for Vue Flow custom nodes export const nodeStyles = ` .custom-node { position: relative; color: #333; font-size: 12px; transition: all 0.2s; border: 1px solid transparent; } .custom-node.selected { border-color: #ff6b6b; box-shadow: 0 0 0 2px rgba(255, 107, 107, 0.2); } /* Handle positioning and styling */ .handle-top { top: -6px !important; left: 50% !important; transform: translateX(-50%) !important; width: 12px !important; height: 12px !important; border-radius: 50% !important; background: #fff !important; border: 2px solid #666 !important; opacity: 0; transition: all 0.2s ease; cursor: crosshair; z-index: 100 !important; position: absolute !important; } .handle-bottom { bottom: -6px !important; left: 50% !important; transform: translateX(-50%) !important; width: 12px !important; height: 12px !important; border-radius: 50% !important; background: #fff !important; border: 2px solid #666 !important; opacity: 0; transition: all 0.2s ease; cursor: crosshair; z-index: 100 !important; position: absolute !important; } .handle-left { left: -6px !important; top: 50% !important; transform: translateY(-50%) !important; width: 12px !important; height: 12px !important; border-radius: 50% !important; background: #fff !important; border: 2px solid #666 !important; opacity: 0; transition: all 0.2s ease; cursor: crosshair; z-index: 100 !important; position: absolute !important; } .handle-right { right: -6px !important; top: 50% !important; transform: translateY(-50%) !important; width: 12px !important; height: 12px !important; border-radius: 50% !important; background: #fff !important; border: 2px solid #666 !important; opacity: 0; transition: all 0.2s ease; cursor: crosshair; z-index: 100 !important; position: absolute !important; } /* Show handles on hover and during connection */ .custom-node:hover .handle-top, .custom-node:hover .handle-bottom, .custom-node:hover .handle-left, .custom-node:hover .handle-right, .vue-flow__node.connecting .handle-top, .vue-flow__node.connecting .handle-bottom, .vue-flow__node.connecting .handle-left, .vue-flow__node.connecting .handle-right { opacity: 1; } /* Show all handles when any node is being connected */ .vue-flow.connecting .handle-top, .vue-flow.connecting .handle-bottom, .vue-flow.connecting .handle-left, .vue-flow.connecting .handle-right { opacity: 1 !important; } /* Active handle styles for connection mode */ .vue-flow__handle.connecting, .vue-flow__handle.valid { opacity: 1 !important; transform: scale(1.3) !important; border-width: 3px !important; box-shadow: 0 0 10px rgba(37, 99, 235, 0.5); } /* Ensure handles are clickable and properly sized */ .vue-flow__handle { pointer-events: all !important; min-width: 12px !important; min-height: 12px !important; position: absolute !important; } /* Force handle visibility during connection */ .vue-flow.connecting .vue-flow__handle { opacity: 1 !important; pointer-events: all !important; z-index: 1000 !important; } /* Connection line styles */ .vue-flow__connection-line { stroke: #2563eb; stroke-width: 3; stroke-dasharray: 5,5; z-index: 1000; } /* Target handle highlighting during connection */ .vue-flow__handle.target:hover, .vue-flow__handle.valid { background: #2563eb !important; border-color: #1d4ed8 !important; transform: scale(1.3) !important; } /* Handle hover effects */ .handle-top:hover, .handle-bottom:hover, .handle-left:hover, .handle-right:hover { transform: scale(1.1); border-width: 3px; } .handle-top:hover { transform: translateX(-50%) scale(1.1); } .handle-bottom:hover { transform: translateX(-50%) scale(1.1); } .handle-left:hover { transform: translateY(-50%) scale(1.1); } .handle-right:hover { transform: translateY(-50%) scale(1.1); } /* Source handles (output) */ .handle-start-output, .handle-gateway-output, .handle-form-output, .handle-script-output, .handle-api-output, .handle-business-rule-output, .handle-notification-output { border-color: #4CAF50; background: #e8f5e9; } .handle-start-output:hover, .handle-gateway-output:hover, .handle-form-output:hover, .handle-script-output:hover, .handle-api-output:hover, .handle-business-rule-output:hover, .handle-notification-output:hover { background: #4CAF50; border-color: #2E7D32; } /* Target handles (input) */ .handle-end-input, .handle-gateway-input, .handle-form-input, .handle-script-input, .handle-api-input, .handle-business-rule-input, .handle-notification-input { border-color: #2196F3; background: #e3f2fd; } .handle-end-input:hover, .handle-gateway-input:hover, .handle-form-input:hover, .handle-script-input:hover, .handle-api-input:hover, .handle-business-rule-input:hover, .handle-notification-input:hover { background: #2196F3; border-color: #1565C0; } /* Base styles for different node types */ .node-form, .node-script, .node-api, .node-business-rule, .node-notification { width: 180px; background: white; border-radius: 4px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); min-height: 50px; display: flex; flex-direction: column; padding: 0; border: 1px solid #e0e0e0; } /* Override base styles for shaped nodes */ .node-form.shape-hexagon, .node-script.shape-hexagon, .node-api.shape-hexagon, .node-business-rule.shape-hexagon, .node-notification.shape-hexagon, .node-html.shape-hexagon, .node-subprocess.shape-hexagon { background: none !important; border: none !important; border-radius: 0 !important; box-shadow: none !important; } .node-form.shape-trapezoid, .node-script.shape-trapezoid, .node-api.shape-trapezoid, .node-business-rule.shape-trapezoid, .node-notification.shape-trapezoid, .node-html.shape-trapezoid, .node-subprocess.shape-trapezoid { background: none !important; border: none !important; border-radius: 0 !important; box-shadow: none !important; } .node-gateway { width: 120px !important; height: 120px !important; background: white; transform: rotate(45deg); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); border: 2px solid #f97316; position: relative; transition: all 0.2s ease; display: flex; align-items: center; justify-content: center; } .node-start, .node-end { width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); } .node-start { background: #e8f5e9; border: 1px solid #4CAF50; } .node-end { background: #ffebee; border: 1px solid #f44336; } /* Content positioning */ .custom-node-content { padding: 8px; position: relative; z-index: 2; } .node-gateway .custom-node-content { position: absolute; top: 0; left: 0; right: 0; bottom: 0; transform: rotate(-45deg); width: 100%; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 0; text-align: center; z-index: 10; } .node-start .custom-node-content, .node-end .custom-node-content { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%; padding: 0; } .custom-node-icon { margin-right: 6px; display: inline-flex; align-items: center; } .node-start .custom-node-icon, .node-end .custom-node-icon { margin: 0; } .custom-node-icon .material-icons { font-size: 16px; } .node-start .material-icons, .node-end .material-icons { font-size: 14px; } .custom-node-label { font-weight: 500; font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .node-form .custom-node-title, .node-script .custom-node-title, .node-api .custom-node-title, .node-business-rule .custom-node-title, .node-notification .custom-node-title { font-weight: 500; font-size: 11px; display: flex; align-items: center; margin-bottom: 4px; } .node-gateway .custom-node-label { font-size: 9px; font-weight: 700; color: #c2410c; margin: 0 0 4px 0; text-align: center; width: 70px; white-space: normal; overflow: hidden; line-height: 1.0; max-height: 18px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; word-break: break-word; } .node-details { margin-top: 4px; } .node-description { margin-bottom: 2px; color: #666; white-space: normal; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; font-size: 10px; } .node-rule-detail { display: flex; font-size: 10px; color: #666; align-items: center; margin-bottom: 2px; } .node-rule-detail-label { font-weight: 500; margin-right: 4px; } .node-rule-detail-value { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* Position handles correctly for gateway node */ .node-gateway .handle-top { top: -6px !important; left: 50% !important; transform: translateX(-50%) rotate(-45deg) !important; border-color: #f97316 !important; background: #fff !important; } .node-gateway .handle-bottom { bottom: -6px !important; left: 50% !important; transform: translateX(-50%) rotate(-45deg) !important; border-color: #f97316 !important; background: #fff !important; } .node-gateway .handle-left { left: -6px !important; top: 50% !important; transform: translateY(-50%) rotate(-45deg) !important; border-color: #f97316 !important; background: #fff !important; } .node-gateway .handle-right { right: -6px !important; top: 50% !important; transform: translateY(-50%) rotate(-45deg) !important; border-color: #f97316 !important; background: #fff !important; } .node-gateway:hover .handle-top, .node-gateway:hover .handle-bottom, .node-gateway:hover .handle-left, .node-gateway:hover .handle-right { opacity: 1 !important; } .node-gateway .handle-top:hover { transform: translateX(-50%) rotate(-45deg) scale(1.1) !important; background: #f97316 !important; } .node-gateway .handle-bottom:hover { transform: translateX(-50%) rotate(-45deg) scale(1.1) !important; background: #f97316 !important; } .node-gateway .handle-left:hover { transform: translateY(-50%) rotate(-45deg) scale(1.1) !important; background: #f97316 !important; } .node-gateway .handle-right:hover { transform: translateY(-50%) rotate(-45deg) scale(1.1) !important; background: #f97316 !important; } /* Gateway specific styles */ .node-gateway:hover { border-color: #ea580c; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } .node-gateway .node-description { text-align: center; margin-bottom: 2px; font-size: 8px; line-height: 1.1; overflow: hidden; max-width: 80px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; max-width: 90px; } .node-gateway .node-rule-detail { display: flex; font-size: 8px; color: #666; align-items: center; justify-content: center; width: 80%; margin-bottom: 2px; } .node-gateway .node-rule-detail-label { font-weight: 500; margin-right: 4px; } .node-gateway .node-rule-detail-value { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 8px; max-width: 50px; text-align: center; font-weight: 600; color: #c2410c; } .node-gateway .material-icons { font-size: 16px; color: #f97316; margin-bottom: 2px; } /* Update node-specific styles to be more consistent */ .node-form { width: 180px; background: white; border-radius: 4px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); min-height: 50px; display: flex; flex-direction: column; padding: 0; border: 1px solid #ddd; border-left: 4px solid #9333ea; /* Purple border to match icon color */ } .node-form.shape-hexagon, .node-form.shape-trapezoid { background: none !important; border: none !important; border-radius: 0 !important; box-shadow: none !important; } .node-api { width: 180px; background: white; border-radius: 4px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); min-height: 50px; display: flex; flex-direction: column; padding: 0; border: 1px solid #ddd; border-left: 4px solid #6366f1; /* Indigo border to match icon color */ } .node-api.shape-hexagon, .node-api.shape-trapezoid { background: none !important; border: none !important; border-radius: 0 !important; box-shadow: none !important; } /* Script node styling */ .node-script { width: 180px; background: white; border-radius: 4px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); min-height: 50px; display: flex; flex-direction: column; padding: 0; border: 1px solid #ddd; border-left: 4px solid #6b7280; /* Gray border to match icon color */ } /* Business rule node styling */ .node-business-rule { width: 180px; background: white; border-radius: 4px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); min-height: 50px; display: flex; flex-direction: column; padding: 0; border: 1px solid #ddd; border-left: 4px solid #a855f7; /* Purple border to match icon color */ } /* Notification node styling */ .node-notification { width: 180px; background: white; border-radius: 4px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); min-height: 50px; display: flex; flex-direction: column; padding: 0; border: 1px solid #ddd; border-left: 4px solid #0ea5e9; /* Blue border to match icon color */ } /* HTML node styling */ .node-html { width: 180px; background: white; border-radius: 4px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); min-height: 50px; display: flex; flex-direction: column; padding: 0; border: 1px solid #ddd; border-left: 4px solid #0ea5e9; /* Blue border to match icon color */ background-color: #f0f9ff; } /* Subprocess node styling */ .node-subprocess { width: 180px; background: white; border-radius: 4px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); min-height: 50px; display: flex; flex-direction: column; padding: 0; border: 1px solid #ddd; border-left: 4px solid #14b8a6; /* Teal border to match icon color */ } /* Global overrides for all shaped nodes to remove conflicting base styles */ [class*="node-"].shape-hexagon, [class*="node-"].shape-trapezoid { background: none !important; border: none !important; border-radius: 0 !important; box-shadow: none !important; } /* Shape node styles */ .shape-node { position: relative; border: 2px solid #e5e7eb; border-radius: 8px; background: white; cursor: move; transition: all 0.2s ease; } .shape-node.selected { border-color: #3b82f6; box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); } .shape-node:hover { border-color: #94a3b8; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); } .shape-content { position: relative; z-index: 1; text-align: center; overflow: hidden; padding: 8px; } .shape-label { font-weight: 500; margin-bottom: 4px; user-select: none; word-wrap: break-word; } .shape-description { font-size: 12px; opacity: 0.7; user-select: none; word-wrap: break-word; } /* Specific shape styles */ .swimlane-horizontal { border-style: solid; border-width: 2px 0; border-radius: 0; } .swimlane-vertical { border-style: solid; border-width: 0 2px; border-radius: 0; } .text-annotation { border-style: dashed; background: rgba(255, 251, 235, 0.8); font-style: italic; } .process-group { border-width: 3px; border-style: solid; border-radius: 12px; } .rectangle-shape { border-radius: 4px; } /* Shape classes for flowchart nodes */ .custom-node.shape-rectangle { border-radius: 4px; } .custom-node.shape-rounded-rectangle { border-radius: 12px; } .custom-node.shape-circle { border-radius: 50%; min-width: 120px; min-height: 120px; width: 120px; height: 120px; display: flex; align-items: center; justify-content: center; } .custom-node.shape-circle .custom-node-content { text-align: center; display: flex; flex-direction: column; align-items: center; justify-content: center; } .custom-node.shape-diamond { transform: rotate(45deg); border-radius: 8px; min-width: 120px; min-height: 120px; width: 120px; height: 120px; display: flex; align-items: center; justify-content: center; } .custom-node.shape-diamond .custom-node-content { transform: rotate(-45deg); text-align: center; display: flex; flex-direction: column; align-items: center; justify-content: center; } .custom-node.shape-hexagon { position: relative; border-radius: 0 !important; background: none !important; border: none !important; min-width: 140px; min-height: 80px; } .custom-node.shape-hexagon::before { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: var(--node-bg-color, white); border: 2px solid var(--node-border-color, #ddd); clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%); z-index: 0; } .custom-node.shape-hexagon .custom-node-content { position: relative; z-index: 1; } .custom-node.shape-parallelogram { transform: skew(-20deg); border-radius: 4px; min-width: 140px; } .custom-node.shape-parallelogram .custom-node-content { transform: skew(20deg); } .custom-node.shape-trapezoid { position: relative; border-radius: 0 !important; background: none !important; border: none !important; min-width: 140px; min-height: 80px; } .custom-node.shape-trapezoid::before { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: var(--node-bg-color, white); border: 2px solid var(--node-border-color, #ddd); clip-path: polygon(20% 0%, 80% 0%, 100% 100%, 0% 100%); z-index: 0; } .custom-node.shape-trapezoid .custom-node-content { position: relative; z-index: 1; } /* Special backgrounds for business-rule, notification, and api hexagon shapes */ .node-business-rule.shape-hexagon::before { border-left: 4px solid var(--node-border-color, #9333ea); } .node-notification.shape-hexagon::before { border-left: 4px solid var(--node-border-color, #3b82f6); } .node-api.shape-hexagon::before { border-left: 4px solid var(--node-border-color, #10b981); } .node-form.shape-hexagon::before { border-left: 4px solid var(--node-border-color, #9333ea); } .node-script.shape-hexagon::before { border-left: 4px solid var(--node-border-color, #6b7280); } .node-html.shape-hexagon::before { border-left: 4px solid var(--node-border-color, #0ea5e9); } .node-subprocess.shape-hexagon::before { border-left: 4px solid var(--node-border-color, #14b8a6); } .node-gateway.shape-hexagon::before { border: 2px solid var(--node-border-color, #FF9800); } /* Special backgrounds for business-rule, notification, and api trapezoid shapes */ .node-business-rule.shape-trapezoid::before { border-left: 4px solid var(--node-border-color, #9333ea); } .node-notification.shape-trapezoid::before { border-left: 4px solid var(--node-border-color, #3b82f6); } .node-api.shape-trapezoid::before { border-left: 4px solid var(--node-border-color, #10b981); } .node-form.shape-trapezoid::before { border-left: 4px solid var(--node-border-color, #9333ea); } .node-script.shape-trapezoid::before { border-left: 4px solid var(--node-border-color, #6b7280); } .node-html.shape-trapezoid::before { border-left: 4px solid var(--node-border-color, #0ea5e9); } .node-subprocess.shape-trapezoid::before { border-left: 4px solid var(--node-border-color, #14b8a6); } .node-gateway.shape-trapezoid::before { border: 2px solid var(--node-border-color, #FF9800); } /* Handle positioning adjustments for different shapes */ .custom-node.shape-circle .vue-flow__handle { width: 10px; height: 10px; } .custom-node.shape-circle .handle-top { top: -5px; left: 50%; transform: translateX(-50%); } .custom-node.shape-circle .handle-bottom { bottom: -5px; left: 50%; transform: translateX(-50%); } .custom-node.shape-circle .handle-left { left: -5px; top: 50%; transform: translateY(-50%); } .custom-node.shape-circle .handle-right { right: -5px; top: 50%; transform: translateY(-50%); } .custom-node.shape-diamond .vue-flow__handle { width: 10px; height: 10px; } .custom-node.shape-diamond .handle-top { top: -5px; left: 50%; transform: translateX(-50%); } .custom-node.shape-diamond .handle-bottom { bottom: -5px; left: 50%; transform: translateX(-50%); } .custom-node.shape-diamond .handle-left { left: -5px; top: 50%; transform: translateY(-50%); } .custom-node.shape-diamond .handle-right { right: -5px; top: 50%; transform: translateY(-50%); } .custom-node.shape-hexagon .vue-flow__handle { width: 10px; height: 10px; } .custom-node.shape-hexagon .handle-top { top: -5px; left: 50%; transform: translateX(-50%); } .custom-node.shape-hexagon .handle-bottom { bottom: -5px; left: 50%; transform: translateX(-50%); } .custom-node.shape-hexagon .handle-left { left: 5px; top: 50%; transform: translateY(-50%); } .custom-node.shape-hexagon .handle-right { right: 5px; top: 50%; transform: translateY(-50%); } .custom-node.shape-trapezoid .vue-flow__handle { width: 10px; height: 10px; } .custom-node.shape-trapezoid .handle-top { top: -5px; left: 50%; transform: translateX(-50%); } .custom-node.shape-trapezoid .handle-bottom { bottom: -5px; left: 50%; transform: translateX(-50%); } .custom-node.shape-trapezoid .handle-left { left: 10px; top: 50%; transform: translateY(-50%); } .custom-node.shape-trapezoid .handle-right { right: 10px; top: 50%; transform: translateY(-50%); } .custom-node.shape-parallelogram .vue-flow__handle { width: 10px; height: 10px; } /* Ensure shapes don't interfere with node connections */ .shape-node * { pointer-events: none; } .shape-node { pointer-events: all; } /* Resize handles for shapes when selected */ .shape-node.selected::after { content: ''; position: absolute; bottom: -4px; right: -4px; width: 8px; height: 8px; background: #3b82f6; border: 2px solid white; border-radius: 50%; cursor: nw-resize; pointer-events: all; } `;