@unofficialbox/box-open-elements 0.31.2 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -13
- package/dist/native-types.d.ts +1 -0
- package/dist/patterns/process-modeler/design.d.ts +1 -1
- package/dist/patterns/process-modeler/design.js +13 -6
- package/dist/patterns/process-modeler/model.d.ts +42 -1
- package/dist/patterns/process-modeler/process-modeler.d.ts +23 -1
- package/dist/patterns/process-modeler/process-modeler.js +457 -103
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
Browse the full catalog on the **[live docs site](https://unofficialbox.github.io/box-open-elements)** — live previews, an events/properties inspector, per-framework code snippets (React / Angular / Vue / Svelte / HTML), and the foundations pages.
|
|
14
14
|
|
|
15
|
-
The library is organized around three layers (see [taxonomy](https://github.com/unofficialbox/box-open-elements/blob/v0.
|
|
15
|
+
The library is organized around three layers (see [taxonomy](https://github.com/unofficialbox/box-open-elements/blob/v0.32.0/docs/taxonomy.md) for the canonical model):
|
|
16
16
|
|
|
17
17
|
- **Foundations** — design decisions as data: tokens, color, typography, iconography, accessibility, theming
|
|
18
18
|
- **Components** — accessible Web Components for single controls, organized by category
|
|
@@ -77,7 +77,7 @@ selection.toggleSelection("1");
|
|
|
77
77
|
- optimized component entrypoints: `@unofficialbox/box-open-elements/<name>`
|
|
78
78
|
- patterns: `@unofficialbox/box-open-elements/patterns/<area>` and `@unofficialbox/box-open-elements/patterns/<area>/<module>`
|
|
79
79
|
|
|
80
|
-
See the versioned [API guidelines](https://github.com/unofficialbox/box-open-elements/blob/v0.
|
|
80
|
+
See the versioned [API guidelines](https://github.com/unofficialbox/box-open-elements/blob/v0.32.0/docs/api-guidelines.md).
|
|
81
81
|
|
|
82
82
|
## Developing
|
|
83
83
|
|
|
@@ -91,17 +91,17 @@ bun run docs # build + serve the docs site at http://localhost:4600
|
|
|
91
91
|
|
|
92
92
|
## Documentation
|
|
93
93
|
|
|
94
|
-
The versioned docs index is at [docs/README.md](https://github.com/unofficialbox/box-open-elements/blob/v0.
|
|
95
|
-
|
|
96
|
-
- [Taxonomy](https://github.com/unofficialbox/box-open-elements/blob/v0.
|
|
97
|
-
- [Architecture](https://github.com/unofficialbox/box-open-elements/blob/v0.
|
|
98
|
-
- [API Guidelines](https://github.com/unofficialbox/box-open-elements/blob/v0.
|
|
99
|
-
- [Components catalog](https://github.com/unofficialbox/box-open-elements/blob/v0.
|
|
100
|
-
- [Using with React, Angular, Vue, and Svelte](https://github.com/unofficialbox/box-open-elements/blob/v0.
|
|
101
|
-
- [Design Tokens](https://github.com/unofficialbox/box-open-elements/blob/v0.
|
|
102
|
-
- [Content Explorer](https://github.com/unofficialbox/box-open-elements/blob/v0.
|
|
103
|
-
- [Box Server Integration](https://github.com/unofficialbox/box-open-elements/blob/v0.
|
|
104
|
-
- [Agent UI guidelines](https://github.com/unofficialbox/box-open-elements/blob/v0.
|
|
94
|
+
The versioned docs index is at [docs/README.md](https://github.com/unofficialbox/box-open-elements/blob/v0.32.0/docs/README.md). The most important entries:
|
|
95
|
+
|
|
96
|
+
- [Taxonomy](https://github.com/unofficialbox/box-open-elements/blob/v0.32.0/docs/taxonomy.md)
|
|
97
|
+
- [Architecture](https://github.com/unofficialbox/box-open-elements/blob/v0.32.0/docs/architecture.md)
|
|
98
|
+
- [API Guidelines](https://github.com/unofficialbox/box-open-elements/blob/v0.32.0/docs/api-guidelines.md)
|
|
99
|
+
- [Components catalog](https://github.com/unofficialbox/box-open-elements/blob/v0.32.0/docs/components/catalog.md) and [patterns catalog](https://github.com/unofficialbox/box-open-elements/blob/v0.32.0/docs/patterns/catalog.md)
|
|
100
|
+
- [Using with React, Angular, Vue, and Svelte](https://github.com/unofficialbox/box-open-elements/blob/v0.32.0/docs/integration/frameworks.md)
|
|
101
|
+
- [Design Tokens](https://github.com/unofficialbox/box-open-elements/blob/v0.32.0/docs/foundations/tokens.md)
|
|
102
|
+
- [Content Explorer](https://github.com/unofficialbox/box-open-elements/blob/v0.32.0/docs/patterns/content-explorer.md)
|
|
103
|
+
- [Box Server Integration](https://github.com/unofficialbox/box-open-elements/blob/v0.32.0/docs/integration/box-server.md)
|
|
104
|
+
- [Agent UI guidelines](https://github.com/unofficialbox/box-open-elements/blob/v0.32.0/docs/patterns/agent-ui-guidelines.md), [building blocks](https://github.com/unofficialbox/box-open-elements/blob/v0.32.0/docs/patterns/agent-ui.md), and [motion](https://github.com/unofficialbox/box-open-elements/blob/v0.32.0/docs/foundations/motion.md)
|
|
105
105
|
|
|
106
106
|
## Contributing
|
|
107
107
|
|
package/dist/native-types.d.ts
CHANGED
|
@@ -931,6 +931,7 @@ export interface BoxElementEventMap {
|
|
|
931
931
|
positions: readonly import("./patterns/process-modeler/model.js").ProcessPositionSnapshot[];
|
|
932
932
|
version: string | number;
|
|
933
933
|
}>;
|
|
934
|
+
"process-copy-request": CustomEvent<import("./patterns/process-modeler/model.js").ProcessCopyRequest>;
|
|
934
935
|
"process-edit-request": CustomEvent<import("./patterns/process-modeler/model.js").ProcessEditRequest>;
|
|
935
936
|
"process-field-change-request": CustomEvent<{
|
|
936
937
|
boxId: string;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Riptide Diagram anatomy expressed through public Box Open Elements tokens. */
|
|
2
|
-
export declare const processModelerDesign = "\n :host([hidden]), [hidden] { display: none !important; }\n *, *::before, *::after { box-sizing: border-box; }\n button, input, textarea, select { font: inherit; color: inherit; }\n button { min-height: 36px; padding: 8px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 8px; background: var(--boe-token-surface-surface, #fff); cursor: pointer; }\n button:disabled { opacity: .5; cursor: default; }\n :is(button,input,textarea,select,[part=canvas],[part=minimap],[part=box],[part=frame]):focus-visible { outline: 2px solid var(--boe-token-surface-surface-brand, #0061d5); outline-offset: 2px; }\n :host {\n display: block;\n position: relative;\n isolation: isolate;\n min-width: 0;\n --boe-process-box-edge: color-mix(in srgb, var(--boe-token-text-text, #141413) 55%, var(--boe-token-surface-surface, #fff));\n color: var(--boe-token-text-text, #141413);\n background: var(--boe-token-surface-surface, #fff);\n font: 14px/1.5 var(--boe-token-font-family-base, Inter, sans-serif);\n }\n [part=sr-only], [part=status], [part=urgent-status] { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }\n [part=toolbar] {\n min-height: 56px;\n margin: 0;\n padding: 8px 16px;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 8px;\n flex-wrap: wrap;\n border-bottom: 1px solid var(--boe-token-stroke-stroke, #e8e8e8);\n background: var(--boe-token-surface-surface, #fff);\n }\n [part=toolbar] button, [part=controls] button, [part=selection-toolbar] button {\n min-height: 30px;\n padding: 4px 10px;\n border: 1px solid transparent;\n border-radius: 8px;\n background: transparent;\n font-size: 13px;\n font-weight: 600;\n }\n [part=toolbar] svg, [part=controls] svg { width: 16px; height: 16px; display: block; }\n [part=toolbar] [data-command=undo], [part=toolbar] [data-command=redo], [part=controls] button:not([data-command=reset]) { width: 30px; height: 30px; padding: 6px; display: grid; place-items: center; }\n [part=controls] [data-command=snap][aria-pressed=true], [part=controls] [data-command=lock][aria-pressed=true] { background: color-mix(in srgb, var(--boe-token-surface-surface-brand, #0061d5) 10%, var(--boe-token-surface-surface, #fff)); color: var(--boe-token-surface-surface-brand, #0061d5); }\n [part=toolbar] button:hover, [part=controls] button:hover, [part=selection-toolbar] button:hover {\n background: var(--boe-token-surface-surface-hover, #f4f4f4);\n }\n [part=toolbar] [data-command=tidy] { border-color: var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 18px; }\n [part=view-switch] { display: flex; gap: 2px; padding: 3px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 20px; }\n [part=view-switch] button { border-radius: 16px; }\n [part=view-switch] button[aria-pressed=true] { border-color: var(--boe-token-stroke-stroke, #e8e8e8); background: var(--boe-token-surface-surface, #fff); }\n [part=run-toggle] { display: flex; align-items: center; gap: 8px; white-space: nowrap; font-size: 13px; font-weight: 600; cursor: pointer; }\n [part=run-toggle] input { appearance: none; position: relative; width: 32px; height: 18px; margin: 0; border: 0; border-radius: 9px; background: var(--boe-token-surface-surface-hover, #f4f4f4); cursor: pointer; transition: background var(--boe-profile-motion-interactive, 200ms) ease-out; }\n [part=run-toggle] input::after { content: ''; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: var(--boe-token-surface-surface, #fff); box-shadow: 0 1px 2px rgb(0 0 0 / .25); transition: transform var(--boe-profile-motion-interactive, 200ms) ease-out; }\n [part=run-toggle] input:checked { background: var(--boe-token-surface-surface-brand, #0061d5); }\n [part=run-toggle] input:checked::after { transform: translateX(14px); }\n [part=run-toggle] input:focus-visible { outline: 2px solid var(--boe-token-surface-surface-brand, #0061d5); outline-offset: 2px; }\n [part=toolbar] [data-command=checks-status] { white-space: nowrap; color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=toolbar] [data-command=checks-status][data-state=bad] { color: var(--boe-token-text-status-text-error, #b92340); }\n [part=view-menu] { display: none; position: relative; }\n [part=view-menu] summary { list-style: none; padding: 4px 14px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 18px; font-size: 13px; font-weight: 600; cursor: pointer; }\n [part=view-menu][open] { z-index: 20; }\n [part=view-menu-options] { position: absolute; z-index: 20; top: calc(100% + 4px); left: 0; width: 192px; padding: 6px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 10px; background: var(--boe-token-surface-surface, #fff); box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .16)); }\n [part=view-menu] button { display: block; width: 100%; text-align: start; background: transparent; }\n [part=layout] {\n display: grid;\n grid-template-columns: 248px minmax(0, 1fr) 320px;\n gap: 0;\n min-height: 0;\n height: var(--boe-process-height, 660px);\n overflow: hidden;\n }\n [part=pane-drawer] { display: contents; color: inherit; }\n [part=canvas-stack] { display: grid; grid-template-rows: auto minmax(0, 1fr); min-width: 0; min-height: 0; }\n /* The hidden hold leaves row 1 empty. Keep the canvas in the flexible row\n explicitly; auto-placement otherwise puts its absolute world in a 0px row. */\n [part=canvas-stack] > [part=hold] { grid-row: 1; }\n [part=canvas-stack] > [part=canvas] { grid-row: 2; }\n [part=insert-chooser]::backdrop { background: rgb(0 0 0 / .45); }\n [part=pane-scrim] { position: absolute; inset: 0; z-index: 30; background: rgb(0 0 0 / .45); }\n [part=pane-title], [part=pane-close], [data-command=palette], [data-command=details] { display: none; }\n [part=palette], [part=inspector] {\n min-width: 0;\n overflow: auto;\n padding: 12px;\n border: 0;\n border-radius: 0;\n background: var(--boe-token-surface-surface, #fff);\n }\n [part=palette] { display: flex; flex-direction: column; gap: 12px; border-right: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); }\n [part=palette-heading] { margin: 0 4px; font-size: 14px; font-weight: 650; line-height: 20px; }\n [part=skip-link] { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }\n [part=skip-link]:focus-visible { position: static; width: auto; height: auto; clip-path: none; }\n [part=inspector] { border-left: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); padding: 16px 0; }\n [part=palette] label { font-size: 0; position: relative; }\n [part=search-icon] { position: absolute; left: 12px; top: 9px; width: 18px; height: 18px; color: var(--boe-token-text-text-secondary, #6f6f6f); pointer-events: none; }\n [part=palette] input {\n width: 100%; min-width: 0;\n height: 36px;\n padding: 0 12px 0 36px;\n border: 1px solid transparent;\n border-radius: 24px;\n background: var(--boe-token-surface-surface-hover, #f4f4f4);\n font-size: 13px;\n }\n [part=palette] input:focus-visible { border-color: var(--boe-token-surface-surface-brand, #0061d5); background: var(--boe-token-surface-surface, #fff); }\n [part=choices] { display: grid; align-content: start; gap: 4px; max-height: none; overflow: visible; }\n [part=group] { margin: 4px 4px 6px; font-size: 12px; font-weight: 650; color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=choice] {\n display: grid; grid-template-columns: 20px minmax(0,1fr); gap: 0 10px;\n min-height: 44px; padding: 8px 10px; border: 1px solid transparent; border-radius: 10px;\n text-align: start; background: transparent; cursor: grab;\n }\n [part=choice]:hover { border-color: var(--boe-token-stroke-stroke, #e8e8e8); background: var(--boe-token-surface-surface-hover, #f4f4f4); }\n [part=choice-icon] { grid-row: span 2; width: 20px; height: 20px; color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=choice][data-tone=accent] [part=choice-icon] { color: var(--boe-token-surface-surface-brand, #0061d5); }\n [part=choice-icon] svg { width: 20px; height: 20px; }\n [part=choice-name] { font-size: 13px; font-weight: 600; line-height: 1.3; }\n [part=choice-description] { grid-column: 2; color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 12px; line-height: 1.35; }\n [part=palette-hint] { margin: 4px; color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 12px; line-height: 1.45; }\n [part=canvas] {\n position: relative; min-width: 0; height: 100%; overflow: hidden;\n border: 0; border-radius: 0;\n background-color: var(--boe-token-surface-surface-secondary, #fbfbfb);\n background-image: radial-gradient(circle, color-mix(in srgb, var(--boe-token-text-text-secondary, #6f6f6f) 26%, transparent) 1px, transparent 1.2px);\n background-size: 12px 12px;\n touch-action: none; user-select: none; cursor: grab;\n }\n [part=canvas][data-panning] { cursor: grabbing; }\n [part=hold] { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding: 10px 16px; border-bottom: 1px solid color-mix(in srgb, var(--boe-token-text-status-text-warning, #9a6b00) 45%, var(--boe-token-stroke-stroke, #e8e8e8)); background: color-mix(in srgb, var(--boe-token-surface-status-surface-inprogress, #ffc447) 14%, var(--boe-token-surface-surface, #fff)); color: var(--boe-token-text-status-text-warning, #6b4a00); font-size: 13px; }\n [part=hold-text] { flex: 1 1 280px; min-width: 0; }\n [part=hold] button { min-height: 28px; padding: 3px 8px; border: 1px solid currentColor; border-radius: 6px; background: transparent; font-size: 12px; font-weight: 650; white-space: nowrap; }\n [part=world] { position: absolute; inset: 0; transform-origin: 0 0; }\n [part=lines] { position: absolute; inset: 0; width: 1px; height: 1px; overflow: visible; pointer-events: none; z-index: 3; }\n [part=line] { stroke: var(--boe-token-text-text-secondary, #6f6f6f); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; fill: none; }\n [part=line][data-selected=true] { stroke: var(--boe-token-surface-surface-brand, #0061d5); stroke-width: 2; }\n [part=line][data-drop=true] { stroke: var(--boe-token-surface-surface-brand, #0061d5); stroke-width: 2.5; stroke-dasharray: 6 4; }\n [part=line-hit] { fill: none; stroke: transparent; stroke-width: 24; pointer-events: stroke; }\n [part=connection-preview] { fill: none; stroke: var(--boe-token-surface-surface-brand, #0061d5); stroke-width: 2.5; stroke-dasharray: 6 4; }\n [part=pinned-end] { fill: var(--boe-token-surface-surface-brand, #0061d5); pointer-events: none; }\n [part=box], [part=frame] {\n position: absolute; touch-action: none; text-align: start; z-index: 4; display: grid; grid-template-columns: 20px minmax(0,1fr); align-content: center;\n gap: 2px 10px; min-width: 0; min-height: 64px; padding: 11px 12px;\n border: 1px solid var(--boe-process-box-edge, var(--boe-control-edge, #858585));\n border-radius: 8px; background: var(--boe-token-surface-surface, #fff);\n font-size: 13px; line-height: 1.3;\n transition: border-color var(--boe-profile-motion-interactive, 200ms) ease-out,\n background var(--boe-profile-motion-interactive, 200ms) ease-out;\n }\n [part=box][data-shape=task] { align-content: normal; font-size: 14px; line-height: 1.45; }\n [part=box][data-shape=task] > [part=icon] { grid-row: span 4; margin-top: 1px; }\n [part=box]:hover, [part=frame]:hover { border-color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [data-connect-target=true] { border-color: var(--boe-token-surface-surface-brand, #0061d5) !important; }\n [part=box] strong, [part=frame] strong { overflow-wrap: anywhere; }\n [part=box] strong, [part=frame] strong { font-size: 13.5px; font-weight: 650; line-height: 1.3; }\n [part=box] small, [part=frame] small { grid-column: 2; color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 12.5px; line-height: 1.35; }\n [part=technical-description] { font: 12px/1.4 ui-monospace, 'SF Mono', Menlo, Consolas, monospace !important; overflow-wrap: anywhere; }\n [part=metrics] { grid-column: 2; display: flex; gap: 6px; flex-wrap: wrap; margin-top: 3px; font-size: 12px; line-height: 1.45; font-variant-numeric: tabular-nums; }\n [part=metrics][data-state=unmeasured] { color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=metric-separator] { color: var(--boe-token-text-text-tertiary, #767676); }\n [part=technical-summary] { overflow-wrap: anywhere; }\n [part=technical-inline-code] { font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; }\n [part=metric-warning] { color: var(--boe-token-text-status-text-warning, #8a5800); }\n [part=icon] { grid-row: span 3; width: 20px; height: 20px; color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=icon] svg { display: block; width: 20px; height: 20px; }\n [data-tone=accent] > [part=icon] { color: var(--boe-token-surface-surface-brand, #0061d5); }\n [part=box][aria-current=true], [part=frame][aria-current=true] {\n border: 1px solid var(--boe-token-surface-surface-brand, #0061d5);\n background: color-mix(in srgb, var(--boe-token-surface-surface-brand, #0061d5) 7%, var(--boe-token-surface-surface, #fff));\n }\n [data-invalid=true] { border-color: var(--boe-token-text-status-text-error, #b92340) !important; }\n [part=problem] { grid-column: 1 / -1; color: var(--boe-token-text-status-text-error, #b92340); font-size: 12px; }\n [part=frame] { z-index: 1; align-content: start; border-radius: 12px; background: color-mix(in srgb, var(--boe-token-surface-surface, #fff) 78%, transparent); }\n [part=frame] small { grid-column: 2; }\n [part=loop-mark] { position: absolute; right: 12px; bottom: 8px; font-size: 20px; line-height: 1; color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=frame-resize] { position: absolute; right: -12px; bottom: -12px; z-index: 8; width: 28px; height: 28px; min-height: 28px; padding: 0; border: 0; border-radius: 8px; background: var(--boe-token-surface-surface, #fff); box-shadow: 0 0 0 1px var(--boe-process-box-edge, #858585); cursor: nwse-resize; }\n [part=frame-resize]::before { content: ''; position: absolute; right: 7px; bottom: 7px; width: 11px; height: 11px; border-right: 2px solid var(--boe-token-text-text-secondary, #6f6f6f); border-bottom: 2px solid var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=frame]:not([aria-current=true]) [part=frame-resize] { visibility: hidden; }\n [data-shape=gateway], [data-shape=event] { width: 56px !important; height: 56px !important; min-height: 0; padding: 0; border: 0 !important; background: transparent !important; display: block; overflow: visible; }\n [data-shape=gateway]::before { content: ''; position: absolute; left: 8px; top: 8px; width: 40px; height: 40px; rotate: 45deg; border: 1.5px solid var(--boe-process-box-edge, var(--boe-control-edge, #858585)); border-radius: 8px; background: var(--boe-token-surface-surface, #fff); }\n [data-shape=event]::before { content: ''; position: absolute; left: 8px; top: 8px; width: 40px; height: 40px; border: 1.5px solid var(--boe-process-box-edge, var(--boe-control-edge, #858585)); border-radius: 50%; background: var(--boe-token-surface-surface, #fff); }\n [data-shape=event][data-kind=finish]::before { border-width: 4px; }\n [data-shape=event][data-kind=scheduled-start]::after { content: ''; position: absolute; left: 13px; top: 13px; width: 30px; height: 30px; border: 1px solid currentColor; border-radius: 50%; }\n [data-shape=gateway] > [part=icon], [data-shape=event] > [part=icon] { position: absolute; left: 18px; top: 18px; z-index: 1; }\n [data-shape=gateway] > strong, [data-shape=event] > strong { position: absolute; top: 58px; left: 50%; width: 150px; translate: -50% 0; text-align: center; font-size: 12px; }\n [data-shape=gateway] > small { display: none; }\n [part=caption] { position: absolute; left: 50%; translate: -50% 0; width: max-content; max-width: 168px; padding: 1px 4px; border-radius: 4px; text-align: center; background: color-mix(in srgb, var(--boe-token-surface-surface-hover, #f4f4f4) 88%, transparent); }\n [part=caption][data-side=below] { top: 60px; }\n [part=caption][data-side=above] { bottom: 60px; }\n [part=caption] strong { font-size: 12.5px; font-weight: 600; line-height: 1.3; }\n [part=caption] small { display: block; font-weight: 400; }\n [part=caption] [part=technical-description] { font: 10.5px ui-monospace, 'SF Mono', Menlo, Consolas, monospace !important; white-space: nowrap; }\n [data-shape=event] > small { position: absolute; top: 75px; left: 50%; width: 172px; translate: -50% 0; text-align: center; font-size: 11px; line-height: 1.25; }\n [part=event-details] { position: absolute; top: 75px; left: 50%; width: 172px; translate: -50% 0; text-align: center; }\n [part=event-details] small { display: block; font-size: 11px; line-height: 1.25; }\n [data-shape=gateway][aria-current=true]::before, [data-shape=event][aria-current=true]::before { border-color: var(--boe-token-surface-surface-brand, #0061d5); background: color-mix(in srgb, var(--boe-token-surface-surface-brand, #0061d5) 7%, var(--boe-token-surface-surface, #fff)); }\n [part=port] { position: absolute; z-index: 5; width: 24px; height: 24px; min-height: 24px; padding: 0; border: 0; border-radius: 50%; background: transparent; opacity: 0; }\n [part=port][data-side=north] { left: calc(50% - 12px); top: -12px; }\n [part=port][data-side=south] { left: calc(50% - 12px); bottom: -12px; }\n [part=port][data-side=east] { right: -12px; top: calc(50% - 12px); }\n [part=port][data-side=west] { left: -12px; top: calc(50% - 12px); }\n [part=port]::before { content: ''; display: block; width: 10px; height: 10px; margin: 7px; border: 1.5px solid var(--boe-token-surface-surface-brand, #0061d5); border-radius: 50%; background: var(--boe-token-surface-surface, #fff); }\n [part=port]:hover::before, [part=port]:focus-visible::before { width: 22px; height: 22px; margin: 1px; background: var(--boe-token-surface-surface-brand, #0061d5); }\n [part=port]::after { position: absolute; inset: 1px; display: none; place-items: center; color: #fff; font-size: 15px; font-weight: 700; line-height: 1; }\n [part=port][data-side=north]::after { content: '\u2191'; }\n [part=port][data-side=east]::after { content: '\u2192'; }\n [part=port][data-side=south]::after { content: '\u2193'; }\n [part=port][data-side=west]::after { content: '\u2190'; }\n [part=port]:hover::after, [part=port]:focus-visible::after, [part=port][data-hot=true]::after { display: grid; }\n [part=port][data-hot=true] { opacity: 1; }\n [part=port][data-hot=true]::before { width: 22px; height: 22px; margin: 1px; background: var(--boe-token-surface-surface-brand, #0061d5); }\n [part=end-grip] { position: absolute; z-index: 8; width: 24px; height: 24px; min-height: 24px; padding: 0; border: 0; border-radius: 50%; background: transparent; }\n [part=end-grip]::before { content: ''; display: block; width: 10px; height: 10px; margin: 7px; border: 1.5px solid var(--boe-token-surface-surface-brand, #0061d5); border-radius: 50%; background: var(--boe-token-surface-surface, #fff); }\n [part=box]:hover [part=port], [part=box]:focus-within [part=port], [part=box][aria-current=true] [part=port], [part=frame]:hover [part=port] { opacity: 1; }\n [part=connection] { position: absolute; z-index: 5; display: flex; align-items: center; gap: 4px; transform: translate(-50%,-50%); min-width: 0; min-height: 0; padding: 2px 6px; border-radius: 6px; background: var(--boe-token-surface-surface-secondary, #fbfbfb); font-size: 12px; font-weight: 600; white-space: nowrap; }\n /* Unlabelled lines still need a reachable midpoint for pointer insert/selection. */\n [part=connection]:has(> span:empty):not(:has(> small)) { padding: 0; background: transparent; min-width: calc(24px * var(--boe-process-inverse-zoom, 1)); min-height: calc(24px * var(--boe-process-inverse-zoom, 1)); }\n [part=connection] > small { margin-left: 4px; color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 11px; font-weight: 400; font-variant-numeric: tabular-nums; }\n [part=connection-actions] { position: absolute; top: 100%; left: 50%; transform: translateX(-50%); display: flex; gap: 4px; width: max-content; padding: 4px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 8px; background: var(--boe-token-surface-surface, #fff); box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .16)); opacity: 0; pointer-events: none; }\n [part=connection]:hover [part=connection-actions], [part=connection]:focus-within [part=connection-actions] { opacity: 1; pointer-events: auto; }\n [part=connection-actions] button { min-height: 32px; padding: 4px; font-size: 12px; }\n [part=note] { width: 208px; border: 1px dashed var(--boe-process-box-edge, var(--boe-control-edge, #858585)); border-radius: 8px; }\n [part=section] { z-index: 0; border: 1px solid var(--boe-process-box-edge, var(--boe-control-edge, #858585)); border-radius: 16px; background: color-mix(in srgb, var(--boe-token-surface-surface, #fff) 45%, transparent); }\n [part=section] strong { display: block; font-size: 12.5px; font-weight: 650; line-height: 1.3; }\n [part=section] small { display: block; color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 11.5px; line-height: 1.35; }\n [part=note], [part=section] { position: absolute; padding: 8px; pointer-events: none; }\n [part=marquee] { position: absolute; border: 2px solid var(--boe-token-surface-surface-brand, #0061d5); background: color-mix(in srgb, var(--boe-token-surface-surface-brand, #0061d5) 12%, transparent); pointer-events: none; }\n [part=connect-tooltip] { position: absolute; z-index: 20; max-width: 240px; padding: 5px 8px; border-radius: 7px; background: var(--boe-token-text-text, #141413); color: var(--boe-token-surface-surface, #fff); font-size: 12px; pointer-events: none; box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .16)); }\n [part=connect-tooltip][data-invalid=true] { background: var(--boe-token-text-status-text-error, #b92340); color: #fff; }\n [part=ghost-box], [part=palette-ghost] { position: absolute; z-index: 5; display: flex; align-items: center; padding: 11px 12px; border: 1.5px dashed var(--boe-token-surface-surface-brand, #0061d5); border-radius: 8px; background: color-mix(in srgb, var(--boe-token-surface-surface-brand, #0061d5) 10%, var(--boe-token-surface-surface, #fff)); font-size: 13px; font-weight: 650; pointer-events: none; }\n [part=guide] { position: absolute; background: var(--boe-token-surface-surface-brand, #0061d5); pointer-events: none; }\n [part=measure] { position: absolute; padding: 4px; background: var(--boe-token-surface-surface, #fff); font-size: 12px; pointer-events: none; }\n [part=insert-chooser] { max-width: calc(100vw - 32px); max-height: 65vh; overflow: auto; padding: 12px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 12px; background: var(--boe-token-surface-surface, #fff); }\n [part=keyboard-chooser] { position: fixed; inset: auto; width: min(320px, calc(100vw - 24px)); max-height: min(420px, calc(100dvh - 24px)); margin: 0; overflow: auto; padding: 12px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 12px; background: var(--boe-token-surface-surface, #fff); color: var(--boe-token-text-text, #141413); box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .16)); }\n [part=chooser-title] { margin: 0 0 10px; font-size: 12px; font-weight: 650; line-height: 1.4; color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=controls] { position: absolute; left: 16px; bottom: 16px; z-index: 10; display: flex; align-items: center; gap: 2px; padding: 4px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 12px; background: var(--boe-token-surface-surface, #fff); box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .16)); }\n [part=controls] [data-command=reset] { min-width: 56px; font-variant-numeric: tabular-nums; }\n [part=minimap] { position: absolute; right: 16px; bottom: 16px; width: 208px; height: 136px; touch-action: none; background: var(--boe-token-surface-surface, #fff); border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 12px; box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .16)); }\n [part=minimap] rect:not([data-viewport]) { fill: color-mix(in srgb, var(--boe-token-text-text-secondary, #6f6f6f) 35%, transparent); }\n [part=minimap] rect[data-selected=true] { fill: var(--boe-token-surface-surface-brand, #0061d5); }\n [part=minimap] rect[data-section] { fill: color-mix(in srgb, var(--boe-token-text-text-secondary, #6f6f6f) 8%, transparent); }\n [part=minimap] [data-viewport] { fill: color-mix(in srgb, var(--boe-token-surface-surface-brand, #0061d5) 8%, transparent); stroke: var(--boe-token-surface-surface-brand, #0061d5); stroke-width: 1.5; vector-effect: non-scaling-stroke; }\n [part=selection-toolbar] { position: absolute; bottom: auto; z-index: 11; display: flex; flex-wrap: nowrap; gap: 2px; padding: 4px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 12px; background: var(--boe-token-surface-surface, #fff); box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .16)); white-space: nowrap; }\n [part=selection-toolbar] button { display: inline-flex; align-items: center; gap: 4px; }\n [part=selection-plus] { font-size: 18px; line-height: 12px; font-weight: 500; }\n [part=checks] { display: grid; gap: 6px; margin: 0; padding: 0; }\n [part=checks] button { width: 100%; display: grid; grid-template-columns: 16px 1fr; align-items: start; gap: 8px; padding: 8px 10px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 10px; text-align: start; background: var(--boe-token-surface-surface, #fff); color: var(--boe-token-text-text, #222); line-height: 1.45; }\n [part=check-icon] { flex: 0 0 16px; width: 16px; height: 16px; margin-top: 1px; color: var(--boe-token-text-status-text-error, #b92340); }\n [part=checks] strong { display: block; font-size: 13px; font-weight: 600; line-height: 1.45; }\n [part=checks] small { color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 12.5px; }\n [part=check-icon][data-tone=success] { color: var(--boe-token-text-status-text-success, #138a58); }\n [part=problem] { display: flex; align-items: center; gap: 4px; }\n [part=problem] [part=check-icon] { flex-basis: 12px; width: 12px; height: 12px; margin: 0; }\n [part=checks-ready] { display: flex; align-items: center; gap: 8px; margin: 0; color: var(--boe-token-text-text, #222); font-size: 13px; line-height: 1.45; }\n [part=process-heading] { display: grid; gap: 2px; padding: 0 16px 12px; }\n [part=process-title] { font-size: 15px; line-height: 1.4; }\n [part=process-summary] { color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 12.5px; }\n [part=pane-tabs] { display: flex; flex-wrap: nowrap; gap: 4px; margin: 0; padding: 0 16px; border-bottom: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); overflow-x: auto; }\n [part=pane-tabs] button { flex: none; min-height: 40px; border: 0; border-bottom: 2px solid transparent; border-radius: 0; background: transparent; color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 13px; font-weight: 600; }\n [part=pane-tabs] button[aria-selected=true] { color: var(--boe-token-text-text, #141413); border-bottom-color: currentColor; }\n [part=editor], [part=pane-content] { padding: 8px 16px; }\n [part=editor] { display: grid; align-content: start; gap: 12px; }\n [part=inspector-kind] { display: none; }\n [part=inspector-purpose] { margin: 0; color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 12.5px; }\n [part=field] { display: grid; gap: 4px; }\n [part=field] label { display: grid; gap: 5px; font-size: 12.5px; font-weight: 650; }\n [part=field] :is(input:not([type=checkbox]),textarea,select) { width: 100%; min-height: 36px; padding: 7px 10px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 8px; background: var(--boe-token-surface-surface, #fff); color: var(--boe-token-text-text, #141413); font-family: inherit; font-size: 13px; line-height: 1.4; }\n [part=field] textarea { min-height: 76px; resize: vertical; }\n [part=field]:has([part=action-options]) { position: relative; }\n [part=field]:has([part=action-options]) input { padding-right: 34px; }\n [part=action-caret] { position: absolute; z-index: 1; top: 25px; right: 2px; width: 32px; min-height: 32px; padding: 0; border: 0; background: transparent; font-size: 18px; }\n [part=action-options] { position: absolute; z-index: 30; top: calc(100% - 1px); left: 0; right: 0; max-height: 280px; overflow: auto; padding: 6px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 10px; background: var(--boe-token-surface-surface, #fff); box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .16)); }\n [part=action-options][hidden] { display: none; }\n [part=action-options] button { display: block; width: 100%; min-height: 36px; padding: 7px 9px; border: 0; border-radius: 7px; text-align: start; background: transparent; font-size: 12.5px; }\n [part=action-options] button:hover, [part=action-options] [aria-selected=true] { background: var(--boe-token-surface-surface-hover, #f4f4f4); }\n [part=action-options] button strong { display: block; font-size: 13px; font-weight: 650; }\n [part=action-options] button small { display: block; color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=action-options] [part=action-back] { color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=field] input[type=checkbox] { justify-self: start; width: 18px; height: 18px; accent-color: var(--boe-token-surface-surface-brand, #0061d5); }\n [part=field] small { color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 12px; line-height: 1.4; }\n [part=field] [part=field-problem] { color: var(--boe-token-text-status-text-error, #b92340); }\n [part=variable-chips] { display: flex; flex-wrap: wrap; gap: 4px; }\n [part=variable-chips] button { min-height: 24px; padding: 2px 8px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 12px; background: var(--boe-token-surface-surface-secondary, #fbfbfb); font-size: 11.5px; }\n [part=leads-to] { display: grid; gap: 6px; padding-top: 10px; border-top: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); }\n [part=leads-to] h3 { margin: 0; font-size: 12.5px; }\n [part=lead-row] { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 12.5px; }\n [part=lead-row] button, [part=leads-to] > button, [part=inspector-actions] button { min-height: 28px; padding: 4px 8px; font-size: 12px; }\n [part=inspector-metrics] { margin: 0; font-size: 12.5px; line-height: 1.5; font-variant-numeric: tabular-nums; }\n [part=inspector-metrics] h3 { margin: 0 0 6px; font-size: 12.5px; }\n [part=inspector-metrics] p { margin: 0; color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=inspector-metrics] table { width: 100%; border-collapse: collapse; font-size: 13px; line-height: 1.45; }\n [part=inspector-metrics] :is(th,td) { padding: 5px 0; border-bottom: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); font-weight: 400; }\n [part=inspector-metrics] th { text-align: start; font-variant-numeric: normal; }\n [part=inspector-metrics] td { text-align: right; font-variant-numeric: tabular-nums; }\n [part=inspector-actions] { display: flex; gap: 8px; padding-top: 10px; border-top: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); }\n [part=arrange-actions] { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 6px; }\n [part=arrange-actions] button { min-height: 32px; padding: 5px 7px; font-size: 12px; text-align: start; }\n [part=outline-intro] { margin: 4px 0 14px; color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 12.5px; line-height: 1.5; }\n [part=copy-outline] { justify-self: start; min-height: 32px; margin-top: 4px; padding: 0 14px; border-radius: 20px; font-size: 13px; font-weight: 600; letter-spacing: .01em; }\n [part=outline-list] { margin: 0; padding-left: 22px; font-size: 13.5px; line-height: 1.5; }\n [part=outline-list] [part=outline-list] { margin-top: 2px; }\n [part=outline-list] li { margin: 3px 0; padding-left: 2px; }\n [part=outline-list] li::marker { color: var(--boe-token-text-text-secondary, #6f6f6f); font-variant-numeric: tabular-nums; font-size: 12.5px; }\n [part=outline-list] button, [part=outline-list] strong { border: 0; border-radius: 4px; background: transparent; padding: 0; min-height: 24px; display: inline-block; font-size: 13.5px; font-weight: 600; line-height: 24px; text-align: start; }\n [part=outline-list] button:hover { color: var(--boe-token-surface-surface-brand, #0061d5); text-decoration: underline; text-underline-offset: 2px; }\n [part=outline-list] button[aria-current=true] { color: var(--boe-token-surface-surface-brand, #0061d5); }\n [part=outline-list] p { margin: 0; color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 12.5px; line-height: 1.5; }\n [part=inspector-heading] { margin: 0 0 2px; font-size: 15px; font-weight: 650; }\n [part=inspector-heading][data-single=true]:not(:focus-visible) { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }\n [part=variable-row], [part=connection-row] { display: grid; gap: 4px; padding: 10px 0; border-bottom: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); font-size: 12.5px; }\n :host([data-variables-editable]) [part=variable-row] { grid-template-columns: minmax(0,1fr) minmax(0,1fr) 32px; gap: 6px; align-items: center; }\n :host([data-variables-editable]) [part=variable-row] label:has([data-variable-key=name]) { grid-column: 1; grid-row: 1; }\n :host([data-variables-editable]) [part=variable-row] label:has([data-variable-key=value]) { grid-column: 2; grid-row: 1; }\n :host([data-variables-editable]) [part=variable-row] label:has([data-variable-key=scope]) { grid-column: 2; grid-row: 2; }\n :host([data-variables-editable]) [part=variable-remove] { grid-column: 3; grid-row: 1; }\n :host([data-variables-editable]) [part=variable-row] :is(input,select) { width: 100%; min-width: 0; min-height: 32px; border-radius: 10px; font-size: 12.5px; }\n :host([data-variables-editable]) [part=variable-row] p { grid-column: 1 / -1; }\n :host([data-variables-editable]) [part=variable-row] [part=field-problem] { color: var(--boe-token-text-status-text-error, #b92340); }\n [part=variable-remove], [part=variable-add] { min-height: 32px; align-self: end; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 8px; background: var(--boe-token-surface-surface, #fff); color: inherit; cursor: pointer; }\n [part=variable-row] p { margin: 0; color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=variable-scope] { color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 11.5px; }\n [part=variable-row] label { display: grid; gap: 4px; font-weight: 650; }\n [part=variable-row] :is(input,select) { min-height: 36px; padding: 7px 10px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 8px; background: var(--boe-token-surface-surface, #fff); }\n [part=help] { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }\n :host([data-narrow]) [part=layout] { grid-template-columns: minmax(0,1fr); }\n :host([data-narrow]) [part=layout] { overflow: visible; }\n :host([data-narrow]) [part=pane-drawer] { display: none; position: absolute; z-index: 40; margin: 0; max-width: none; max-height: none; padding: 0; overflow: auto; border: 0; border-radius: 0; background: var(--boe-token-surface-surface, #fff); box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .24)); }\n :host([data-narrow]) [part=pane-drawer][open] { display: block; }\n :host([data-narrow]) [part=pane-title] { display: block; position: absolute; top: 18px; left: 16px; margin: 0; font-size: 14px; font-weight: 650; line-height: 20px; }\n :host([data-narrow]) [part=pane-close], :host([data-narrow]) [data-command=palette], :host([data-narrow]) [data-command=details] { display: inline-block; }\n :host([data-narrow]) [part=pane-close] { position: absolute; top: 12px; right: 12px; z-index: 1; width: 28px; height: 28px; padding: 0; border-radius: 50%; font-size: 16px; font-weight: 600; line-height: 1; }\n :host([data-narrow]) [part=pane-drawer][data-pane=palette] { left: 0; top: 0; bottom: auto; width: min(320px, 86%); height: 100%; max-height: 100%; }\n :host([data-narrow]) [part=pane-drawer][data-pane=inspector] { left: 0; right: 0; top: auto; bottom: 0; width: 100%; height: min(62%, 560px); border-radius: 24px 24px 0 0; }\n :host([data-narrow]) [part=pane-drawer][data-pane=inspector]::before { content: ''; display: block; width: 36px; height: 4px; margin: 6px auto; border-radius: 2px; background: var(--boe-token-text-text-secondary, #767676); opacity: .55; }\n :host([data-narrow]) [part=palette], :host([data-narrow]) [part=inspector] { height: 100%; }\n :host([data-narrow]) [part=inspector] { border-left: 0; }\n :host([data-narrow]) [part=palette] { padding-top: 54px; }\n :host([data-narrow]) [part=palette-heading] { display: none; }\n :host([data-narrow]) [part=minimap] { display: none; }\n :host([data-narrow]) [part=toolbar] { justify-content: flex-start; }\n :host([data-narrow]) [data-command=palette] { order: -2; }\n :host([data-narrow]) [part=view-menu] { order: -1; }\n :host([data-narrow]) [part=view-switch], :host([data-narrow]) [part=run-toggle] { display: none; }\n :host([data-narrow]) [data-command=checks-status] { display: none; }\n :host([data-narrow]) [part=view-menu] { display: block; }\n :host([data-narrow]) [part=controls] { left: 12px; bottom: 12px; }\n :host([data-narrow]) [part=selection-toolbar] [part=selection-plus] + span { display: none; }\n :host([data-phone]) [data-command=tidy] { display: none; }\n :host([data-phone]) [data-command=undo], :host([data-phone]) [data-command=redo] { display: none; }\n @media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition-duration: 0s !important; animation-duration: 0s !important; scroll-behavior: auto !important; } }\n";
|
|
2
|
+
export declare const processModelerDesign = "\n :host([hidden]), [hidden] { display: none !important; }\n *, *::before, *::after { box-sizing: border-box; }\n button, input, textarea, select { font: inherit; color: inherit; }\n button { min-height: 36px; padding: 8px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 8px; background: var(--boe-token-surface-surface, #fff); cursor: pointer; }\n button:disabled { opacity: .5; cursor: default; }\n :is(button,input,textarea,select,[part=canvas],[part=minimap],[part=box],[part=frame]):focus-visible { outline: 2px solid var(--boe-token-surface-surface-brand, #0061d5); outline-offset: 2px; }\n :host {\n display: block;\n position: relative;\n isolation: isolate;\n min-width: 0;\n --boe-process-box-edge: color-mix(in srgb, var(--boe-token-text-text, #141413) 55%, var(--boe-token-surface-surface, #fff));\n color: var(--boe-token-text-text, #141413);\n background: var(--boe-token-surface-surface, #fff);\n font: 14px/1.5 var(--boe-token-font-family-base, Inter, sans-serif);\n }\n [part=sr-only], [part=status], [part=urgent-status] { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }\n [part=toolbar] {\n min-height: 56px;\n margin: 0;\n padding: 8px 16px;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 8px;\n flex-wrap: wrap;\n border-bottom: 1px solid var(--boe-token-stroke-stroke, #e8e8e8);\n background: var(--boe-token-surface-surface, #fff);\n }\n [part=toolbar] button, [part=controls] button, [part=selection-toolbar] button {\n min-height: 30px;\n padding: 4px 10px;\n border: 1px solid transparent;\n border-radius: 8px;\n background: transparent;\n font-size: 13px;\n font-weight: 600;\n }\n [part=toolbar] svg, [part=controls] svg { width: 16px; height: 16px; display: block; }\n [part=toolbar] [data-command=undo], [part=toolbar] [data-command=redo], [part=controls] button:not([data-command=reset]) { width: 30px; height: 30px; padding: 6px; display: grid; place-items: center; }\n [part=controls] [data-command=snap][aria-pressed=true], [part=controls] [data-command=lock][aria-pressed=true] { background: color-mix(in srgb, var(--boe-token-surface-surface-brand, #0061d5) 10%, var(--boe-token-surface-surface, #fff)); color: var(--boe-token-surface-surface-brand, #0061d5); }\n [part=toolbar] button:hover, [part=controls] button:hover, [part=selection-toolbar] button:hover {\n background: var(--boe-token-surface-surface-hover, #f4f4f4);\n }\n [part=toolbar] [data-command=tidy] { border-color: var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 18px; }\n [part=view-switch] { display: flex; gap: 2px; padding: 3px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 20px; }\n [part=view-switch] button { border-radius: 16px; }\n [part=view-switch] button[aria-pressed=true] { border-color: var(--boe-token-stroke-stroke, #e8e8e8); background: var(--boe-token-surface-surface, #fff); }\n [part=run-toggle] { display: flex; align-items: center; gap: 8px; white-space: nowrap; font-size: 13px; font-weight: 600; cursor: pointer; }\n [part=run-toggle] input { appearance: none; position: relative; width: 32px; height: 18px; margin: 0; border: 0; border-radius: 9px; background: var(--boe-token-surface-surface-hover, #f4f4f4); cursor: pointer; transition: background var(--boe-profile-motion-interactive, 200ms) ease-out; }\n [part=run-toggle] input::after { content: ''; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: var(--boe-token-surface-surface, #fff); box-shadow: 0 1px 2px rgb(0 0 0 / .25); transition: transform var(--boe-profile-motion-interactive, 200ms) ease-out; }\n [part=run-toggle] input:checked { background: var(--boe-token-surface-surface-brand, #0061d5); }\n [part=run-toggle] input:checked::after { transform: translateX(14px); }\n [part=run-toggle] input:focus-visible { outline: 2px solid var(--boe-token-surface-surface-brand, #0061d5); outline-offset: 2px; }\n [part=toolbar] [data-command=checks-status] { white-space: nowrap; color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=toolbar] [data-command=checks-status][data-state=bad] { color: var(--boe-token-text-status-text-error, #b92340); }\n [part=view-menu] { display: none; position: relative; }\n [part=view-menu] summary { list-style: none; padding: 4px 14px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 18px; font-size: 13px; font-weight: 600; cursor: pointer; }\n [part=view-menu][open] { z-index: 20; }\n [part=view-menu-options] { position: absolute; z-index: 20; top: calc(100% + 4px); left: 0; width: 192px; padding: 6px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 10px; background: var(--boe-token-surface-surface, #fff); box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .16)); }\n [part=view-menu] button { display: block; width: 100%; text-align: start; background: transparent; }\n [part=layout] {\n display: grid;\n grid-template-columns: 248px minmax(0, 1fr) 320px;\n gap: 0;\n min-height: 0;\n height: var(--boe-process-height, 660px);\n overflow: hidden;\n }\n [part=pane-drawer] { display: contents; color: inherit; }\n [part=canvas-stack] { display: grid; grid-template-rows: auto minmax(0, 1fr); min-width: 0; min-height: 0; }\n /* The hidden hold leaves row 1 empty. Keep the canvas in the flexible row\n explicitly; auto-placement otherwise puts its absolute world in a 0px row. */\n [part=canvas-stack] > [part=hold] { grid-row: 1; }\n [part=canvas-stack] > [part=canvas] { grid-row: 2; }\n [part=insert-chooser]::backdrop { background: rgb(0 0 0 / .45); }\n [part=pane-scrim] { position: absolute; inset: 0; z-index: 30; background: rgb(0 0 0 / .45); }\n [part=pane-title], [part=pane-close], [data-command=palette], [data-command=details] { display: none; }\n [part=palette], [part=inspector] {\n min-width: 0;\n overflow: auto;\n padding: 12px;\n border: 0;\n border-radius: 0;\n background: var(--boe-token-surface-surface, #fff);\n }\n [part=palette] { display: flex; flex-direction: column; gap: 12px; border-right: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); }\n [part=palette-heading] { margin: 0 4px; font-size: 14px; font-weight: 650; line-height: 20px; }\n [part=skip-link] { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }\n [part=skip-link]:focus-visible { position: static; width: auto; height: auto; clip-path: none; }\n [part=inspector] { border-left: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); padding: 16px 0; }\n [part=palette] label { font-size: 0; position: relative; }\n [part=search-icon] { position: absolute; left: 12px; top: 9px; width: 18px; height: 18px; color: var(--boe-token-text-text-secondary, #6f6f6f); pointer-events: none; }\n [part=palette] input {\n width: 100%; min-width: 0;\n height: 36px;\n padding: 0 12px 0 36px;\n border: 1px solid transparent;\n border-radius: 24px;\n background: var(--boe-token-surface-surface-hover, #f4f4f4);\n font-size: 13px;\n }\n [part=palette] input:focus-visible { border-color: var(--boe-token-surface-surface-brand, #0061d5); background: var(--boe-token-surface-surface, #fff); }\n [part=choices] { display: grid; align-content: start; gap: 4px; max-height: none; overflow: visible; }\n [part=group] { margin: 4px 4px 6px; font-size: 12px; line-height: 1.45; font-weight: 650; color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=choice] {\n display: grid; grid-template-columns: 20px minmax(0,1fr); gap: 0 10px;\n min-height: 44px; padding: 8px 10px; border: 1px solid transparent; border-radius: 10px;\n text-align: start; background: transparent; cursor: grab; touch-action: none;\n }\n [part=choice]:hover { border-color: var(--boe-token-stroke-stroke, #e8e8e8); background: var(--boe-token-surface-surface-hover, #f4f4f4); }\n [part=choice-icon] { grid-row: span 2; width: 20px; height: 20px; color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=choice][data-tone=accent] [part=choice-icon] { color: var(--boe-token-surface-surface-brand, #0061d5); }\n [part=choice-icon] svg { width: 20px; height: 20px; }\n [part=choice-name] { font-size: 13px; font-weight: 600; line-height: 1.45; }\n [part=choice-description] { grid-column: 2; color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 12px; line-height: 1.35; }\n [part=palette-hint] { margin: 4px; color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 12px; line-height: 1.45; }\n [part=canvas] {\n position: relative; min-width: 0; height: 100%; overflow: hidden;\n border: 0; border-radius: 0;\n background-color: var(--boe-token-surface-surface-secondary, #fbfbfb);\n background-image: radial-gradient(circle, color-mix(in srgb, var(--boe-token-text-text-secondary, #6f6f6f) 26%, transparent) 1px, transparent 1.2px);\n background-size: 12px 12px;\n touch-action: none; user-select: none; cursor: grab;\n }\n [part=canvas][data-panning] { cursor: grabbing; }\n [part=hold] { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding: 10px 16px; border-bottom: 1px solid color-mix(in srgb, var(--boe-token-text-status-text-warning, #9a6b00) 45%, var(--boe-token-stroke-stroke, #e8e8e8)); background: color-mix(in srgb, var(--boe-token-surface-status-surface-inprogress, #ffc447) 14%, var(--boe-token-surface-surface, #fff)); color: var(--boe-token-text-status-text-warning, #6b4a00); font-size: 13px; }\n [part=hold-text] { flex: 1 1 280px; min-width: 0; }\n [part=hold] button { min-height: 28px; padding: 3px 8px; border: 1px solid currentColor; border-radius: 6px; background: transparent; font-size: 12px; font-weight: 650; white-space: nowrap; }\n [part=world] { position: absolute; inset: 0; transform-origin: 0 0; }\n [part=lines] { position: absolute; inset: 0; width: 1px; height: 1px; overflow: visible; pointer-events: none; z-index: 3; }\n [part=line] { stroke: var(--boe-token-text-text-secondary, #6f6f6f); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; fill: none; }\n [part=line][data-selected=true] { stroke: var(--boe-token-surface-surface-brand, #0061d5); stroke-width: 2; }\n [part=line][data-drop=true] { stroke: var(--boe-token-surface-surface-brand, #0061d5); stroke-width: 2.5; stroke-dasharray: 6 4; }\n [part=line-hit] { fill: none; stroke: transparent; stroke-width: 24; pointer-events: stroke; }\n [part=connection-preview] { fill: none; stroke: var(--boe-token-surface-surface-brand, #0061d5); stroke-width: 2.5; stroke-dasharray: 6 4; }\n [part=pinned-end] { fill: var(--boe-token-surface-surface-brand, #0061d5); pointer-events: none; }\n [part=box], [part=frame] {\n position: absolute; touch-action: none; text-align: start; z-index: 4; display: grid; grid-template-columns: 20px minmax(0,1fr); align-content: center;\n gap: 2px 10px; min-width: 0; min-height: 64px; padding: 11px 12px;\n border: 1px solid var(--boe-process-box-edge, var(--boe-control-edge, #858585));\n border-radius: 8px; background: var(--boe-token-surface-surface, #fff);\n font-size: 13px; line-height: 1.3;\n transition: border-color var(--boe-profile-motion-interactive, 200ms) ease-out,\n background var(--boe-profile-motion-interactive, 200ms) ease-out;\n }\n [part=box][data-shape=task] { align-content: normal; font-size: 14px; line-height: 1.45; }\n [part=box][data-shape=task] > [part=icon] { grid-row: span 4; margin-top: 1px; }\n [part=box]:hover, [part=frame]:hover { border-color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [data-connect-target=true][data-connect-invalid=true] { border-color: var(--boe-token-text-status-text-error, #b92340) !important; }\n [part=connection-preview][data-invalid=true] { stroke: var(--boe-token-text-status-text-error, #b92340); }\n [data-connect-target=true] { border-color: var(--boe-token-surface-surface-brand, #0061d5) !important; }\n [part=box] strong, [part=frame] strong { overflow-wrap: anywhere; }\n [part=box] strong, [part=frame] strong { font-size: 13.5px; font-weight: 650; line-height: 1.3; }\n [part=box] small, [part=frame] small { grid-column: 2; color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 12.5px; line-height: 1.35; }\n [part=technical-description] { font: 12px/1.4 ui-monospace, 'SF Mono', Menlo, Consolas, monospace !important; overflow-wrap: anywhere; }\n [part=metrics] { grid-column: 2; display: flex; gap: 6px; flex-wrap: wrap; margin-top: 3px; font-size: 12px; line-height: 1.45; font-variant-numeric: tabular-nums; }\n [part=metrics][data-state=unmeasured] { color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=metric-separator] { color: var(--boe-token-text-text-tertiary, #767676); }\n [part=technical-summary] { overflow-wrap: anywhere; }\n [part=technical-inline-code] { font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; }\n [part=metric-warning] { color: var(--boe-token-text-status-text-warning, #8a5800); }\n [part=icon] { grid-row: span 3; width: 20px; height: 20px; color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=icon] svg { display: block; width: 20px; height: 20px; }\n [data-tone=accent] > [part=icon] { color: var(--boe-token-surface-surface-brand, #0061d5); }\n [part=box][aria-current=true], [part=frame][aria-current=true] {\n border: 1px solid var(--boe-token-surface-surface-brand, #0061d5);\n background: color-mix(in srgb, var(--boe-token-surface-surface-brand, #0061d5) 7%, var(--boe-token-surface-surface, #fff));\n }\n [data-invalid=true] { border-color: var(--boe-token-text-status-text-error, #b92340) !important; }\n [part=problem] { grid-column: 1 / -1; color: var(--boe-token-text-status-text-error, #b92340); font-size: 12px; }\n [part=frame] { z-index: 1; align-content: start; border-radius: 12px; background: color-mix(in srgb, var(--boe-token-surface-surface, #fff) 78%, transparent); }\n [part=frame] small { grid-column: 2; }\n [part=loop-mark] { position: absolute; right: 12px; bottom: 8px; font-size: 20px; line-height: 1; color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=frame][data-palette-drop=true] { border-color: var(--boe-token-surface-surface-brand, #0061d5); box-shadow: 0 0 0 2px color-mix(in srgb, var(--boe-token-surface-surface-brand, #0061d5) 18%, transparent); }\n [part=frame-resize] { position: absolute; right: -12px; bottom: -12px; z-index: 8; width: 28px; height: 28px; min-height: 28px; padding: 0; border: 0; border-radius: 8px; background: var(--boe-token-surface-surface, #fff); box-shadow: 0 0 0 1px var(--boe-process-box-edge, #858585); cursor: nwse-resize; }\n [part=frame-resize]::before { content: ''; position: absolute; right: 7px; bottom: 7px; width: 11px; height: 11px; border-right: 2px solid var(--boe-token-text-text-secondary, #6f6f6f); border-bottom: 2px solid var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=frame]:not([aria-current=true]) [part=frame-resize] { visibility: hidden; }\n [data-shape=gateway], [data-shape=event] { width: 56px !important; height: 56px !important; min-height: 0; padding: 0; border: 0 !important; background: transparent !important; display: block; overflow: visible; }\n [data-shape=gateway]::before { content: ''; position: absolute; left: 8px; top: 8px; width: 40px; height: 40px; rotate: 45deg; border: 1.5px solid var(--boe-process-box-edge, var(--boe-control-edge, #858585)); border-radius: 8px; background: var(--boe-token-surface-surface, #fff); }\n [data-shape=event]::before { content: ''; position: absolute; left: 8px; top: 8px; width: 40px; height: 40px; border: 1.5px solid var(--boe-process-box-edge, var(--boe-control-edge, #858585)); border-radius: 50%; background: var(--boe-token-surface-surface, #fff); }\n [data-shape=event][data-kind=finish]::before { border-width: 4px; }\n [data-shape=event][data-kind=scheduled-start]::after { content: ''; position: absolute; left: 13px; top: 13px; width: 30px; height: 30px; border: 1px solid currentColor; border-radius: 50%; }\n [data-shape=gateway] > [part=icon], [data-shape=event] > [part=icon] { position: absolute; left: 18px; top: 18px; z-index: 1; }\n [data-shape=gateway] > strong, [data-shape=event] > strong { position: absolute; top: 58px; left: 50%; width: 150px; translate: -50% 0; text-align: center; font-size: 12px; }\n [data-shape=gateway] > small { display: none; }\n [part=caption] { position: absolute; left: 50%; translate: -50% 0; width: max-content; max-width: 168px; padding: 1px 4px; border-radius: 4px; text-align: center; background: color-mix(in srgb, var(--boe-token-surface-surface-hover, #f4f4f4) 88%, transparent); }\n [part=caption][data-side=below] { top: 60px; }\n [part=caption][data-side=above] { bottom: 60px; }\n [part=caption] strong { font-size: 12.5px; font-weight: 600; line-height: 1.3; }\n [part=caption] small { display: block; font-weight: 400; }\n [part=caption] [part=technical-description] { font: 10.5px ui-monospace, 'SF Mono', Menlo, Consolas, monospace !important; white-space: nowrap; }\n [data-shape=event] > small { position: absolute; top: 75px; left: 50%; width: 172px; translate: -50% 0; text-align: center; font-size: 11px; line-height: 1.25; }\n [part=event-details] { position: absolute; top: 75px; left: 50%; width: 172px; translate: -50% 0; text-align: center; }\n [part=event-details] small { display: block; font-size: 11px; line-height: 1.25; }\n [data-shape=gateway][aria-current=true]::before, [data-shape=event][aria-current=true]::before { border-color: var(--boe-token-surface-surface-brand, #0061d5); background: color-mix(in srgb, var(--boe-token-surface-surface-brand, #0061d5) 7%, var(--boe-token-surface-surface, #fff)); }\n [part=port] { position: absolute; z-index: 5; width: 24px; height: 24px; min-height: 24px; padding: 0; border: 0; border-radius: 50%; background: transparent; opacity: 0; }\n [part=port][data-side=north] { left: calc(50% - 12px); top: -12px; }\n [part=port][data-side=south] { left: calc(50% - 12px); bottom: -12px; }\n [part=port][data-side=east] { right: -12px; top: calc(50% - 12px); }\n [part=port][data-side=west] { left: -12px; top: calc(50% - 12px); }\n [part=port]::before { content: ''; display: block; width: 10px; height: 10px; margin: 7px; border: 1.5px solid var(--boe-token-surface-surface-brand, #0061d5); border-radius: 50%; background: var(--boe-token-surface-surface, #fff); }\n [part=port]:hover::before, [part=port]:focus-visible::before { width: 22px; height: 22px; margin: 1px; background: var(--boe-token-surface-surface-brand, #0061d5); }\n [part=port]::after { position: absolute; inset: 1px; display: none; place-items: center; color: #fff; font-size: 15px; font-weight: 700; line-height: 1; }\n [part=port][data-side=north]::after { content: '\u2191'; }\n [part=port][data-side=east]::after { content: '\u2192'; }\n [part=port][data-side=south]::after { content: '\u2193'; }\n [part=port][data-side=west]::after { content: '\u2190'; }\n [part=port]:hover::after, [part=port]:focus-visible::after, [part=port][data-hot=true]::after { display: grid; }\n [part=port][data-hot=true] { opacity: 1; }\n [part=port][data-hot=true]::before { width: 22px; height: 22px; margin: 1px; background: var(--boe-token-surface-surface-brand, #0061d5); }\n [part=end-grip] { position: absolute; z-index: 8; width: 24px; height: 24px; min-height: 24px; padding: 0; border: 0; border-radius: 50%; background: transparent; }\n [part=end-grip]::before { content: ''; display: block; width: 10px; height: 10px; margin: 7px; border: 1.5px solid var(--boe-token-surface-surface-brand, #0061d5); border-radius: 50%; background: var(--boe-token-surface-surface, #fff); }\n [part=box]:hover [part=port], [part=box]:focus-within [part=port], [part=box][aria-current=true] [part=port], [part=frame]:hover [part=port] { opacity: 1; }\n [part=connection] { position: absolute; z-index: 5; display: flex; align-items: center; gap: 4px; transform: translate(-50%,-50%); min-width: 0; min-height: 0; padding: 2px 6px; border-radius: 6px; background: var(--boe-token-surface-surface-secondary, #fbfbfb); font-size: 12px; font-weight: 600; white-space: nowrap; }\n /* Unlabelled lines still need a reachable midpoint for pointer insert/selection. */\n [part=connection]:has(> span:empty):not(:has(> small)) { padding: 0; background: transparent; min-width: calc(24px * var(--boe-process-inverse-zoom, 1)); min-height: calc(24px * var(--boe-process-inverse-zoom, 1)); }\n [part=connection] > small { margin-left: 4px; color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 11px; font-weight: 400; font-variant-numeric: tabular-nums; }\n [part=connection-actions] { position: absolute; top: 100%; left: 50%; transform: translateX(-50%); display: flex; gap: 4px; width: max-content; padding: 4px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 8px; background: var(--boe-token-surface-surface, #fff); box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .16)); opacity: 0; pointer-events: none; }\n [part=connection]:hover [part=connection-actions], [part=connection]:focus-within [part=connection-actions] { opacity: 1; pointer-events: auto; }\n [part=connection-actions] button { min-height: 32px; padding: 4px; font-size: 12px; }\n [part=note] { width: 208px; border: 1px dashed var(--boe-process-box-edge, var(--boe-control-edge, #858585)); border-radius: 8px; }\n [part=section] { z-index: 0; border: 1px solid var(--boe-process-box-edge, var(--boe-control-edge, #858585)); border-radius: 16px; background: color-mix(in srgb, var(--boe-token-surface-surface, #fff) 45%, transparent); }\n [part=section] strong { display: block; font-size: 12.5px; font-weight: 650; line-height: 1.3; }\n [part=section] small { display: block; color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 11.5px; line-height: 1.35; }\n [part=note], [part=section] { position: absolute; padding: 8px; pointer-events: none; }\n [part=marquee] { position: absolute; border: 2px solid var(--boe-token-surface-surface-brand, #0061d5); background: color-mix(in srgb, var(--boe-token-surface-surface-brand, #0061d5) 12%, transparent); pointer-events: none; }\n [part=connect-tooltip] { position: absolute; z-index: 20; max-width: 240px; padding: 5px 8px; border-radius: 7px; background: var(--boe-token-text-text, #141413); color: var(--boe-token-surface-surface, #fff); font-size: 12px; pointer-events: none; box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .16)); }\n [part=connect-tooltip][data-invalid=true] { background: var(--boe-token-text-status-text-error, #b92340); color: #fff; }\n [part=ghost-box], [part=palette-ghost] { position: absolute; z-index: 5; display: flex; align-items: center; padding: 11px 12px; border: 1.5px dashed var(--boe-token-surface-surface-brand, #0061d5); border-radius: 8px; background: color-mix(in srgb, var(--boe-token-surface-surface-brand, #0061d5) 10%, var(--boe-token-surface-surface, #fff)); font-size: 13px; font-weight: 650; pointer-events: none; }\n [part=palette-ghost][data-pointer] { position: fixed; z-index: 100; padding: 8px 12px; border: 1px solid var(--boe-token-surface-surface-brand, #0061d5); border-radius: 10px; background: var(--boe-token-surface-surface, #fff); box-shadow: var(--boe-token-elevation-overlay, 0 8px 24px #0002); font-size: 13px; font-weight: 600; line-height: 1.45; gap: 8px; translate: -50% -50%; }\n [part=palette-ghost][data-pointer] svg { width: 20px; height: 20px; }\n [part=guide] { position: absolute; background: var(--boe-token-surface-surface-brand, #0061d5); pointer-events: none; }\n [part=measure] { position: absolute; padding: 4px; background: var(--boe-token-surface-surface, #fff); font-size: 12px; pointer-events: none; }\n [part=insert-chooser] { max-width: calc(100vw - 32px); max-height: 65vh; overflow: auto; padding: 12px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 12px; background: var(--boe-token-surface-surface, #fff); }\n [part=keyboard-chooser] { position: fixed; inset: auto; width: min(320px, calc(100vw - 24px)); max-height: min(420px, calc(100dvh - 24px)); margin: 0; overflow: auto; padding: 12px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 12px; background: var(--boe-token-surface-surface, #fff); color: var(--boe-token-text-text, #141413); box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .16)); }\n [part=chooser-title] { margin: 0 0 10px; font-size: 12px; font-weight: 650; line-height: 1.4; color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=controls] { position: absolute; left: 16px; bottom: 16px; z-index: 10; display: flex; align-items: center; gap: 2px; padding: 4px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 12px; background: var(--boe-token-surface-surface, #fff); box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .16)); }\n [part=controls] button:not([data-command=reset]) { width: 32px; padding: 0; }\n [part=controls-divider] { width: 1px; height: 20px; margin: 0 4px; background: var(--boe-token-stroke-stroke, #e8e8e8); }\n [part=controls] [data-command=reset] { min-width: 56px; padding: 0 6px; font-variant-numeric: tabular-nums; }\n [part=minimap] { position: absolute; right: 16px; bottom: 16px; width: 208px; height: 136px; touch-action: none; background: var(--boe-token-surface-surface, #fff); border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 12px; box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .16)); }\n [part=minimap] rect:not([data-viewport]) { fill: color-mix(in srgb, var(--boe-token-text-text-secondary, #6f6f6f) 35%, transparent); }\n [part=minimap] rect[data-selected=true] { fill: var(--boe-token-surface-surface-brand, #0061d5); }\n [part=minimap] rect[data-section] { fill: color-mix(in srgb, var(--boe-token-text-text-secondary, #6f6f6f) 8%, transparent); }\n [part=minimap] [data-viewport] { fill: color-mix(in srgb, var(--boe-token-surface-surface-brand, #0061d5) 8%, transparent); stroke: var(--boe-token-surface-surface-brand, #0061d5); stroke-width: 1.5; vector-effect: non-scaling-stroke; }\n [part=selection-toolbar] { position: absolute; bottom: auto; z-index: 11; display: flex; flex-wrap: nowrap; gap: 2px; padding: 4px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 12px; background: var(--boe-token-surface-surface, #fff); box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .16)); white-space: nowrap; }\n [part=selection-toolbar] button { display: inline-flex; align-items: center; gap: 4px; }\n [part=selection-plus] { font-size: 18px; line-height: 12px; font-weight: 500; }\n [part=checks] { display: grid; gap: 6px; margin: 0; padding: 0; }\n [part=checks] button { width: 100%; display: grid; grid-template-columns: 16px 1fr; align-items: start; gap: 8px; padding: 8px 10px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 10px; text-align: start; background: var(--boe-token-surface-surface, #fff); color: var(--boe-token-text-text, #222); line-height: 1.45; }\n [part=check-icon] { flex: 0 0 16px; width: 16px; height: 16px; margin-top: 1px; color: var(--boe-token-text-status-text-error, #b92340); }\n [part=checks] strong { display: block; font-size: 13px; font-weight: 600; line-height: 1.45; }\n [part=checks] small { color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 12.5px; }\n [part=check-icon][data-tone=success] { color: var(--boe-token-text-status-text-success, #138a58); }\n [part=problem] { display: flex; align-items: center; gap: 4px; }\n [part=problem] [part=check-icon] { flex-basis: 12px; width: 12px; height: 12px; margin: 0; }\n [part=checks-ready] { display: flex; align-items: center; gap: 8px; margin: 0; color: var(--boe-token-text-text, #222); font-size: 13px; line-height: 1.45; }\n [part=process-heading] { display: grid; gap: 2px; padding: 0 16px 12px; }\n [part=process-title] { font-size: 15px; line-height: 1.4; }\n [part=process-summary] { color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 12.5px; }\n [part=pane-tabs] { display: flex; flex-wrap: nowrap; gap: 4px; margin: 0; padding: 0 16px; border-bottom: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); overflow-x: auto; }\n [part=pane-tabs] button { flex: none; min-height: 40px; border: 0; border-bottom: 2px solid transparent; border-radius: 0; background: transparent; color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 13px; font-weight: 600; }\n [part=pane-tabs] button[aria-selected=true] { color: var(--boe-token-text-text, #141413); border-bottom-color: currentColor; }\n [part=editor], [part=pane-content] { padding: 8px 16px; }\n [part=editor] { display: grid; align-content: start; gap: 12px; }\n [part=inspector-kind] { display: none; }\n [part=inspector-purpose] { margin: 0; color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 12.5px; }\n [part=field] { display: grid; gap: 4px; }\n [part=field] label { display: grid; gap: 5px; font-size: 12.5px; font-weight: 650; }\n [part=field] :is(input:not([type=checkbox]),textarea,select) { width: 100%; min-height: 36px; padding: 7px 10px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 8px; background: var(--boe-token-surface-surface, #fff); color: var(--boe-token-text-text, #141413); font-family: inherit; font-size: 13px; line-height: 1.4; }\n [part=field] textarea { min-height: 76px; resize: vertical; }\n [part=field]:has([part=action-options]) { position: relative; }\n [part=field]:has([part=action-options]) input { padding-right: 34px; }\n [part=action-caret] { position: absolute; z-index: 1; top: 25px; right: 2px; width: 32px; min-height: 32px; padding: 0; border: 0; background: transparent; font-size: 18px; }\n [part=action-options] { position: absolute; z-index: 30; top: calc(100% - 1px); left: 0; right: 0; max-height: 280px; overflow: auto; padding: 6px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 10px; background: var(--boe-token-surface-surface, #fff); box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .16)); }\n [part=action-options][hidden] { display: none; }\n [part=action-options] button { display: block; width: 100%; min-height: 36px; padding: 7px 9px; border: 0; border-radius: 7px; text-align: start; background: transparent; font-size: 12.5px; }\n [part=action-options] button:hover, [part=action-options] [aria-selected=true] { background: var(--boe-token-surface-surface-hover, #f4f4f4); }\n [part=action-options] button strong { display: block; font-size: 13px; font-weight: 650; }\n [part=action-options] button small { display: block; color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=action-options] [part=action-back] { color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=field] input[type=checkbox] { justify-self: start; width: 18px; height: 18px; accent-color: var(--boe-token-surface-surface-brand, #0061d5); }\n [part=field] small { color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 12px; line-height: 1.4; }\n [part=field] [part=field-problem] { color: var(--boe-token-text-status-text-error, #b92340); }\n [part=variable-chips] { display: flex; flex-wrap: wrap; gap: 4px; }\n [part=variable-chips] button { min-height: 24px; padding: 2px 8px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 12px; background: var(--boe-token-surface-surface-secondary, #fbfbfb); font-size: 11.5px; }\n [part=leads-to] { display: grid; gap: 6px; padding-top: 10px; border-top: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); }\n [part=leads-to] h3 { margin: 0; font-size: 12.5px; }\n [part=lead-row] { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 12.5px; }\n [part=lead-row] button, [part=leads-to] > button, [part=inspector-actions] button { min-height: 28px; padding: 4px 8px; font-size: 12px; }\n [part=inspector-metrics] { margin: 0; font-size: 12.5px; line-height: 1.5; font-variant-numeric: tabular-nums; }\n [part=inspector-metrics] h3 { margin: 0 0 6px; font-size: 12.5px; }\n [part=inspector-metrics] p { margin: 0; color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=inspector-metrics] table { width: 100%; border-collapse: collapse; font-size: 13px; line-height: 1.45; }\n [part=inspector-metrics] :is(th,td) { padding: 5px 0; border-bottom: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); font-weight: 400; }\n [part=inspector-metrics] th { text-align: start; font-variant-numeric: normal; }\n [part=inspector-metrics] td { text-align: right; font-variant-numeric: tabular-nums; }\n [part=inspector-actions] { display: flex; gap: 8px; padding-top: 10px; border-top: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); }\n [part=arrange-actions] { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 6px; }\n [part=arrange-actions] button { min-height: 32px; padding: 5px 7px; font-size: 12px; text-align: start; }\n [part=outline-intro] { margin: 4px 0 14px; color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 12.5px; line-height: 1.5; }\n [part=copy-outline] { justify-self: start; min-height: 32px; margin-top: 4px; padding: 0 14px; border-radius: 20px; font-size: 13px; font-weight: 600; letter-spacing: .01em; }\n [part=outline-list] { margin: 0; padding-left: 22px; font-size: 13.5px; line-height: 1.5; }\n [part=outline-list] [part=outline-list] { margin-top: 2px; }\n [part=outline-list] li { margin: 3px 0; padding-left: 2px; }\n [part=outline-list] li::marker { color: var(--boe-token-text-text-secondary, #6f6f6f); font-variant-numeric: tabular-nums; font-size: 12.5px; }\n [part=outline-list] button, [part=outline-list] strong { border: 0; border-radius: 4px; background: transparent; padding: 0; min-height: 24px; display: inline-block; font-size: 13.5px; font-weight: 600; line-height: 24px; text-align: start; }\n [part=outline-list] button:hover { color: var(--boe-token-surface-surface-brand, #0061d5); text-decoration: underline; text-underline-offset: 2px; }\n [part=outline-list] button[aria-current=true] { color: var(--boe-token-surface-surface-brand, #0061d5); }\n [part=outline-list] p { margin: 0; color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 12.5px; line-height: 1.5; }\n [part=inspector-heading] { margin: 0 0 2px; font-size: 15px; font-weight: 650; }\n [part=inspector-heading][data-single=true]:not(:focus-visible) { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }\n [part=variable-row], [part=connection-row] { display: grid; gap: 4px; padding: 10px 0; border-bottom: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); font-size: 12.5px; }\n :host([data-variables-editable]) [part=variable-row] { grid-template-columns: minmax(0,1fr) minmax(0,1fr) 32px; gap: 6px; align-items: center; }\n :host([data-variables-editable]) [part=variable-row] label:has([data-variable-key=name]) { grid-column: 1; grid-row: 1; }\n :host([data-variables-editable]) [part=variable-row] label:has([data-variable-key=value]) { grid-column: 2; grid-row: 1; }\n :host([data-variables-editable]) [part=variable-row] label:has([data-variable-key=scope]) { grid-column: 2; grid-row: 2; }\n :host([data-variables-editable]) [part=variable-remove] { grid-column: 3; grid-row: 1; }\n :host([data-variables-editable]) [part=variable-row] :is(input,select) { width: 100%; min-width: 0; min-height: 32px; border-radius: 10px; font-size: 12.5px; }\n :host([data-variables-editable]) [part=variable-row] p { grid-column: 1 / -1; }\n :host([data-variables-editable]) [part=variable-row] [part=field-problem] { color: var(--boe-token-text-status-text-error, #b92340); }\n [part=variable-remove], [part=variable-add] { min-height: 32px; align-self: end; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 8px; background: var(--boe-token-surface-surface, #fff); color: inherit; cursor: pointer; }\n [part=variable-row] p { margin: 0; color: var(--boe-token-text-text-secondary, #6f6f6f); }\n [part=variable-scope] { color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 11.5px; }\n [part=variable-row] label { display: grid; gap: 4px; font-weight: 650; }\n [part=variable-row] :is(input,select) { min-height: 36px; padding: 7px 10px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 8px; background: var(--boe-token-surface-surface, #fff); }\n [part=help] { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }\n :host([data-narrow]) [part=layout] { grid-template-columns: minmax(0,1fr); }\n :host([data-narrow]) [part=layout] { overflow: visible; }\n :host([data-narrow]) [part=pane-drawer] { display: none; position: absolute; z-index: 40; margin: 0; max-width: none; max-height: none; padding: 0; overflow: auto; border: 0; border-radius: 0; background: var(--boe-token-surface-surface, #fff); box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .24)); }\n :host([data-narrow]) [part=pane-drawer][open] { display: block; }\n :host([data-narrow]) [part=pane-title] { display: block; position: absolute; top: 18px; left: 16px; margin: 0; font-size: 14px; font-weight: 650; line-height: 20px; }\n :host([data-narrow]) [part=pane-close], :host([data-narrow]) [data-command=palette], :host([data-narrow]) [data-command=details] { display: inline-block; }\n :host([data-narrow]) [part=pane-close] { position: absolute; top: 12px; right: 12px; z-index: 1; width: 28px; height: 28px; padding: 0; border-radius: 50%; font-size: 16px; font-weight: 600; line-height: 1; }\n :host([data-narrow]) [part=pane-drawer][data-pane=palette] { left: 0; top: 0; bottom: auto; width: min(320px, 86%); height: 100%; max-height: 100%; }\n :host([data-narrow]) [part=pane-drawer][data-pane=inspector] { left: 0; right: 0; top: auto; bottom: 0; width: 100%; height: min(62%, 560px); border-radius: 24px 24px 0 0; }\n :host([data-narrow]) [part=pane-drawer][data-pane=inspector]::before { content: ''; display: block; width: 36px; height: 4px; margin: 6px auto; border-radius: 2px; background: var(--boe-token-text-text-secondary, #767676); opacity: .55; }\n :host([data-narrow]) [part=palette], :host([data-narrow]) [part=inspector] { height: 100%; }\n :host([data-narrow]) [part=inspector] { border-left: 0; }\n :host([data-narrow]) [part=palette] { padding-top: 54px; }\n :host([data-narrow]) [part=palette-heading] { display: none; }\n :host([data-narrow]) [part=minimap] { display: none; }\n :host([data-narrow]) [part=toolbar] { justify-content: flex-start; }\n :host([data-narrow]) [data-command=palette] { order: -2; }\n :host([data-narrow]) [part=view-menu] { order: -1; }\n :host([data-narrow]) [part=view-switch], :host([data-narrow]) [part=run-toggle] { display: none; }\n :host([data-narrow]) [data-command=checks-status] { display: none; }\n :host([data-narrow]) [part=view-menu] { display: block; }\n :host([data-hide-tidy]) [part=controls] { left: 12px; bottom: 12px; }\n :host([data-narrow]) [part=selection-toolbar] [part=selection-plus] + span { display: none; }\n :host([data-hide-tidy]) [data-command=tidy] { display: none; }\n :host([data-phone]) [data-command=undo], :host([data-phone]) [data-command=redo] { display: none; }\n @media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition-duration: 0s !important; animation-duration: 0s !important; scroll-behavior: auto !important; } }\n";
|
|
@@ -104,17 +104,17 @@ export const processModelerDesign = `
|
|
|
104
104
|
}
|
|
105
105
|
[part=palette] input:focus-visible { border-color: var(--boe-token-surface-surface-brand, #0061d5); background: var(--boe-token-surface-surface, #fff); }
|
|
106
106
|
[part=choices] { display: grid; align-content: start; gap: 4px; max-height: none; overflow: visible; }
|
|
107
|
-
[part=group] { margin: 4px 4px 6px; font-size: 12px; font-weight: 650; color: var(--boe-token-text-text-secondary, #6f6f6f); }
|
|
107
|
+
[part=group] { margin: 4px 4px 6px; font-size: 12px; line-height: 1.45; font-weight: 650; color: var(--boe-token-text-text-secondary, #6f6f6f); }
|
|
108
108
|
[part=choice] {
|
|
109
109
|
display: grid; grid-template-columns: 20px minmax(0,1fr); gap: 0 10px;
|
|
110
110
|
min-height: 44px; padding: 8px 10px; border: 1px solid transparent; border-radius: 10px;
|
|
111
|
-
text-align: start; background: transparent; cursor: grab;
|
|
111
|
+
text-align: start; background: transparent; cursor: grab; touch-action: none;
|
|
112
112
|
}
|
|
113
113
|
[part=choice]:hover { border-color: var(--boe-token-stroke-stroke, #e8e8e8); background: var(--boe-token-surface-surface-hover, #f4f4f4); }
|
|
114
114
|
[part=choice-icon] { grid-row: span 2; width: 20px; height: 20px; color: var(--boe-token-text-text-secondary, #6f6f6f); }
|
|
115
115
|
[part=choice][data-tone=accent] [part=choice-icon] { color: var(--boe-token-surface-surface-brand, #0061d5); }
|
|
116
116
|
[part=choice-icon] svg { width: 20px; height: 20px; }
|
|
117
|
-
[part=choice-name] { font-size: 13px; font-weight: 600; line-height: 1.
|
|
117
|
+
[part=choice-name] { font-size: 13px; font-weight: 600; line-height: 1.45; }
|
|
118
118
|
[part=choice-description] { grid-column: 2; color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 12px; line-height: 1.35; }
|
|
119
119
|
[part=palette-hint] { margin: 4px; color: var(--boe-token-text-text-secondary, #6f6f6f); font-size: 12px; line-height: 1.45; }
|
|
120
120
|
[part=canvas] {
|
|
@@ -149,6 +149,8 @@ export const processModelerDesign = `
|
|
|
149
149
|
[part=box][data-shape=task] { align-content: normal; font-size: 14px; line-height: 1.45; }
|
|
150
150
|
[part=box][data-shape=task] > [part=icon] { grid-row: span 4; margin-top: 1px; }
|
|
151
151
|
[part=box]:hover, [part=frame]:hover { border-color: var(--boe-token-text-text-secondary, #6f6f6f); }
|
|
152
|
+
[data-connect-target=true][data-connect-invalid=true] { border-color: var(--boe-token-text-status-text-error, #b92340) !important; }
|
|
153
|
+
[part=connection-preview][data-invalid=true] { stroke: var(--boe-token-text-status-text-error, #b92340); }
|
|
152
154
|
[data-connect-target=true] { border-color: var(--boe-token-surface-surface-brand, #0061d5) !important; }
|
|
153
155
|
[part=box] strong, [part=frame] strong { overflow-wrap: anywhere; }
|
|
154
156
|
[part=box] strong, [part=frame] strong { font-size: 13.5px; font-weight: 650; line-height: 1.3; }
|
|
@@ -172,6 +174,7 @@ export const processModelerDesign = `
|
|
|
172
174
|
[part=frame] { z-index: 1; align-content: start; border-radius: 12px; background: color-mix(in srgb, var(--boe-token-surface-surface, #fff) 78%, transparent); }
|
|
173
175
|
[part=frame] small { grid-column: 2; }
|
|
174
176
|
[part=loop-mark] { position: absolute; right: 12px; bottom: 8px; font-size: 20px; line-height: 1; color: var(--boe-token-text-text-secondary, #6f6f6f); }
|
|
177
|
+
[part=frame][data-palette-drop=true] { border-color: var(--boe-token-surface-surface-brand, #0061d5); box-shadow: 0 0 0 2px color-mix(in srgb, var(--boe-token-surface-surface-brand, #0061d5) 18%, transparent); }
|
|
175
178
|
[part=frame-resize] { position: absolute; right: -12px; bottom: -12px; z-index: 8; width: 28px; height: 28px; min-height: 28px; padding: 0; border: 0; border-radius: 8px; background: var(--boe-token-surface-surface, #fff); box-shadow: 0 0 0 1px var(--boe-process-box-edge, #858585); cursor: nwse-resize; }
|
|
176
179
|
[part=frame-resize]::before { content: ''; position: absolute; right: 7px; bottom: 7px; width: 11px; height: 11px; border-right: 2px solid var(--boe-token-text-text-secondary, #6f6f6f); border-bottom: 2px solid var(--boe-token-text-text-secondary, #6f6f6f); }
|
|
177
180
|
[part=frame]:not([aria-current=true]) [part=frame-resize] { visibility: hidden; }
|
|
@@ -227,13 +230,17 @@ export const processModelerDesign = `
|
|
|
227
230
|
[part=connect-tooltip] { position: absolute; z-index: 20; max-width: 240px; padding: 5px 8px; border-radius: 7px; background: var(--boe-token-text-text, #141413); color: var(--boe-token-surface-surface, #fff); font-size: 12px; pointer-events: none; box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .16)); }
|
|
228
231
|
[part=connect-tooltip][data-invalid=true] { background: var(--boe-token-text-status-text-error, #b92340); color: #fff; }
|
|
229
232
|
[part=ghost-box], [part=palette-ghost] { position: absolute; z-index: 5; display: flex; align-items: center; padding: 11px 12px; border: 1.5px dashed var(--boe-token-surface-surface-brand, #0061d5); border-radius: 8px; background: color-mix(in srgb, var(--boe-token-surface-surface-brand, #0061d5) 10%, var(--boe-token-surface-surface, #fff)); font-size: 13px; font-weight: 650; pointer-events: none; }
|
|
233
|
+
[part=palette-ghost][data-pointer] { position: fixed; z-index: 100; padding: 8px 12px; border: 1px solid var(--boe-token-surface-surface-brand, #0061d5); border-radius: 10px; background: var(--boe-token-surface-surface, #fff); box-shadow: var(--boe-token-elevation-overlay, 0 8px 24px #0002); font-size: 13px; font-weight: 600; line-height: 1.45; gap: 8px; translate: -50% -50%; }
|
|
234
|
+
[part=palette-ghost][data-pointer] svg { width: 20px; height: 20px; }
|
|
230
235
|
[part=guide] { position: absolute; background: var(--boe-token-surface-surface-brand, #0061d5); pointer-events: none; }
|
|
231
236
|
[part=measure] { position: absolute; padding: 4px; background: var(--boe-token-surface-surface, #fff); font-size: 12px; pointer-events: none; }
|
|
232
237
|
[part=insert-chooser] { max-width: calc(100vw - 32px); max-height: 65vh; overflow: auto; padding: 12px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 12px; background: var(--boe-token-surface-surface, #fff); }
|
|
233
238
|
[part=keyboard-chooser] { position: fixed; inset: auto; width: min(320px, calc(100vw - 24px)); max-height: min(420px, calc(100dvh - 24px)); margin: 0; overflow: auto; padding: 12px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 12px; background: var(--boe-token-surface-surface, #fff); color: var(--boe-token-text-text, #141413); box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .16)); }
|
|
234
239
|
[part=chooser-title] { margin: 0 0 10px; font-size: 12px; font-weight: 650; line-height: 1.4; color: var(--boe-token-text-text-secondary, #6f6f6f); }
|
|
235
240
|
[part=controls] { position: absolute; left: 16px; bottom: 16px; z-index: 10; display: flex; align-items: center; gap: 2px; padding: 4px; border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 12px; background: var(--boe-token-surface-surface, #fff); box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .16)); }
|
|
236
|
-
[part=controls] [data-command=reset] {
|
|
241
|
+
[part=controls] button:not([data-command=reset]) { width: 32px; padding: 0; }
|
|
242
|
+
[part=controls-divider] { width: 1px; height: 20px; margin: 0 4px; background: var(--boe-token-stroke-stroke, #e8e8e8); }
|
|
243
|
+
[part=controls] [data-command=reset] { min-width: 56px; padding: 0 6px; font-variant-numeric: tabular-nums; }
|
|
237
244
|
[part=minimap] { position: absolute; right: 16px; bottom: 16px; width: 208px; height: 136px; touch-action: none; background: var(--boe-token-surface-surface, #fff); border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8); border-radius: 12px; box-shadow: var(--boe-shadow-overlay, 0 4px 12px rgb(0 0 0 / .16)); }
|
|
238
245
|
[part=minimap] rect:not([data-viewport]) { fill: color-mix(in srgb, var(--boe-token-text-text-secondary, #6f6f6f) 35%, transparent); }
|
|
239
246
|
[part=minimap] rect[data-selected=true] { fill: var(--boe-token-surface-surface-brand, #0061d5); }
|
|
@@ -342,9 +349,9 @@ export const processModelerDesign = `
|
|
|
342
349
|
:host([data-narrow]) [part=view-switch], :host([data-narrow]) [part=run-toggle] { display: none; }
|
|
343
350
|
:host([data-narrow]) [data-command=checks-status] { display: none; }
|
|
344
351
|
:host([data-narrow]) [part=view-menu] { display: block; }
|
|
345
|
-
:host([data-
|
|
352
|
+
:host([data-hide-tidy]) [part=controls] { left: 12px; bottom: 12px; }
|
|
346
353
|
:host([data-narrow]) [part=selection-toolbar] [part=selection-plus] + span { display: none; }
|
|
347
|
-
:host([data-
|
|
354
|
+
:host([data-hide-tidy]) [data-command=tidy] { display: none; }
|
|
348
355
|
:host([data-phone]) [data-command=undo], :host([data-phone]) [data-command=redo] { display: none; }
|
|
349
356
|
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition-duration: 0s !important; animation-duration: 0s !important; scroll-behavior: auto !important; } }
|
|
350
357
|
`;
|
|
@@ -141,8 +141,18 @@ export interface ProcessLastRun {
|
|
|
141
141
|
/** Keys are projected box IDs, supplied by the host. */
|
|
142
142
|
steps: Readonly<Record<string, ProcessStepMetrics>>;
|
|
143
143
|
}
|
|
144
|
+
/** A proposed host-owned connection, also used when reattaching a line. */
|
|
145
|
+
export interface ProcessConnectionProposal {
|
|
146
|
+
readonly from: string;
|
|
147
|
+
readonly to: string;
|
|
148
|
+
/** Exclude this existing line from duplicate/outgoing-limit checks. */
|
|
149
|
+
readonly ignoreLineId?: string;
|
|
150
|
+
}
|
|
144
151
|
export interface ProcessModel<D = unknown, N = unknown> {
|
|
145
152
|
project(document: D): ProcessProjection<N>;
|
|
153
|
+
/** Pure synchronous host rule: a nonempty reason rejects preview and commit.
|
|
154
|
+
* Returning null permits an edit request; the host must still accept it. */
|
|
155
|
+
connectionProblem?(document: D, proposal: ProcessConnectionProposal, projection: ProcessProjection<N>): string | null;
|
|
146
156
|
/** Optional host arrangement, used by Tidy up and for missing positions. */
|
|
147
157
|
arrange?(projection: ProcessProjection<N>): ProcessLayout;
|
|
148
158
|
/**
|
|
@@ -188,9 +198,17 @@ export interface ProcessCheck {
|
|
|
188
198
|
path?: NodePath;
|
|
189
199
|
}
|
|
190
200
|
export interface ProcessEdit {
|
|
191
|
-
type: "add" | "delete" | "duplicate" | "connect" | "disconnect" | "reattach" | "insert" | "reparent";
|
|
201
|
+
type: "add" | "delete" | "duplicate" | "connect" | "disconnect" | "reattach" | "insert" | "reparent" | "reset-line";
|
|
192
202
|
boxId?: string;
|
|
193
203
|
sourceId?: string;
|
|
204
|
+
/** Duplicate these roots and descendants/internal edges in one host transaction.
|
|
205
|
+
* Plural requests omit sourceId; unsupported hosts must refuse the whole group. */
|
|
206
|
+
sourceIds?: readonly string[];
|
|
207
|
+
/** One world-coordinate translation for every node in a duplicate group. */
|
|
208
|
+
offset?: Readonly<{
|
|
209
|
+
x: number;
|
|
210
|
+
y: number;
|
|
211
|
+
}>;
|
|
194
212
|
from?: string;
|
|
195
213
|
to?: string;
|
|
196
214
|
lineId?: string;
|
|
@@ -208,11 +226,34 @@ export interface ReversibleProcessEdit {
|
|
|
208
226
|
redo(): void;
|
|
209
227
|
/** The already-applied edit's layout, recorded atomically with the document. */
|
|
210
228
|
layout?: ProcessLayout;
|
|
229
|
+
/** Selection after acceptance; recorded with layout for undo and redo. */
|
|
230
|
+
selectionIds?: readonly string[];
|
|
211
231
|
}
|
|
212
232
|
/** Host applies the edit, then calls accept with its inverse and replay. */
|
|
213
233
|
export interface ProcessEditRequest extends ProcessEdit {
|
|
214
234
|
accept(command: ReversibleProcessEdit): void;
|
|
215
235
|
}
|
|
236
|
+
/** Host-owned immutable capture; BOE never serializes the captured graph. */
|
|
237
|
+
export interface ProcessClipboard {
|
|
238
|
+
readonly itemCount: number;
|
|
239
|
+
paste(request: ProcessPasteRequest): void;
|
|
240
|
+
dispose?(): void;
|
|
241
|
+
}
|
|
242
|
+
/** Copy capture is synchronous and once-only. Unsupported hosts leave it unhandled. */
|
|
243
|
+
export interface ProcessCopyRequest {
|
|
244
|
+
readonly sourceIds: readonly string[];
|
|
245
|
+
capture(clipboard: ProcessClipboard): void;
|
|
246
|
+
refuse(message?: string): void;
|
|
247
|
+
}
|
|
248
|
+
/** Host applies one synchronous graph transaction, then accepts it once. */
|
|
249
|
+
export interface ProcessPasteRequest {
|
|
250
|
+
readonly offset: Readonly<{
|
|
251
|
+
x: number;
|
|
252
|
+
y: number;
|
|
253
|
+
}>;
|
|
254
|
+
accept(command: ReversibleProcessEdit): void;
|
|
255
|
+
refuse(message?: string): void;
|
|
256
|
+
}
|
|
216
257
|
export declare function validateProjection<N>(projection: ProcessProjection<N>): void;
|
|
217
258
|
/** Deterministic fallback, preserving host-authored positions. */
|
|
218
259
|
export declare function completeLayout<N>(projection: ProcessProjection<N>, layout: ProcessLayout): ProcessLayout;
|
|
@@ -37,7 +37,9 @@ export declare class ProcessModeler<D = ProcessProjection, N = unknown> extends
|
|
|
37
37
|
private activeDrawer?;
|
|
38
38
|
private drawerReturn?;
|
|
39
39
|
private selectedIds;
|
|
40
|
-
private
|
|
40
|
+
private clipboard;
|
|
41
|
+
private clipboardSession;
|
|
42
|
+
private restoringBoxFocus;
|
|
41
43
|
private selectionToolbarKey;
|
|
42
44
|
private sectionSequence;
|
|
43
45
|
private versionValue;
|
|
@@ -62,6 +64,9 @@ export declare class ProcessModeler<D = ProcessProjection, N = unknown> extends
|
|
|
62
64
|
private spacePressed;
|
|
63
65
|
private dropLine?;
|
|
64
66
|
private paletteDragKind;
|
|
67
|
+
private palettePointer?;
|
|
68
|
+
private suppressPaletteClick;
|
|
69
|
+
private readonly escapePalettePointer;
|
|
65
70
|
private narrowValue;
|
|
66
71
|
private suppressClick;
|
|
67
72
|
private resizeObserver?;
|
|
@@ -148,7 +153,9 @@ export declare class ProcessModeler<D = ProcessProjection, N = unknown> extends
|
|
|
148
153
|
selectLine(id: string | null): void;
|
|
149
154
|
setValidation(checks: readonly ProcessCheck[]): void;
|
|
150
155
|
setValidationAtPath(message: string, path: NodePath): void;
|
|
156
|
+
private connectionProblem;
|
|
151
157
|
requestEdit(edit: ProcessEdit): void;
|
|
158
|
+
private editAcceptance;
|
|
152
159
|
undo(): void;
|
|
153
160
|
redo(): void;
|
|
154
161
|
private commitLayout;
|
|
@@ -184,7 +191,13 @@ export declare class ProcessModeler<D = ProcessProjection, N = unknown> extends
|
|
|
184
191
|
arrangeSelection(action: 'left' | 'center' | 'right' | 'top' | 'middle' | 'bottom' | 'distribute-horizontal' | 'distribute-vertical'): void;
|
|
185
192
|
makeSection(title?: string): void;
|
|
186
193
|
protected setupListeners(): void;
|
|
194
|
+
private clearClipboard;
|
|
195
|
+
private copySelection;
|
|
196
|
+
private pasteClipboard;
|
|
197
|
+
private duplicateBoxes;
|
|
187
198
|
private onKey;
|
|
199
|
+
private navigateSelection;
|
|
200
|
+
private revealBox;
|
|
188
201
|
private pointerDown;
|
|
189
202
|
private distance;
|
|
190
203
|
private pointerMove;
|
|
@@ -194,6 +207,7 @@ export declare class ProcessModeler<D = ProcessProjection, N = unknown> extends
|
|
|
194
207
|
private sideAt;
|
|
195
208
|
private lineAt;
|
|
196
209
|
private markDropLine;
|
|
210
|
+
private paintDropLine;
|
|
197
211
|
private alignedPoint;
|
|
198
212
|
private openChooser;
|
|
199
213
|
private nextEdit;
|
|
@@ -211,6 +225,14 @@ export declare class ProcessModeler<D = ProcessProjection, N = unknown> extends
|
|
|
211
225
|
private collectChecks;
|
|
212
226
|
private renderWorld;
|
|
213
227
|
private place;
|
|
228
|
+
private activatePaletteKind;
|
|
229
|
+
private paletteLineAt;
|
|
230
|
+
private paletteFrameAt;
|
|
231
|
+
private markPaletteDrop;
|
|
232
|
+
private paletteCanvasPoint;
|
|
233
|
+
private movePalettePointer;
|
|
234
|
+
private cancelPalettePointer;
|
|
235
|
+
private finishPalettePointer;
|
|
214
236
|
private renderPalette;
|
|
215
237
|
private renderChecks;
|
|
216
238
|
private renderField;
|
|
@@ -74,7 +74,9 @@ export class ProcessModeler extends BaseElement {
|
|
|
74
74
|
activeDrawer;
|
|
75
75
|
drawerReturn;
|
|
76
76
|
selectedIds = new Set();
|
|
77
|
-
|
|
77
|
+
clipboard = null;
|
|
78
|
+
clipboardSession = 0;
|
|
79
|
+
restoringBoxFocus = false;
|
|
78
80
|
selectionToolbarKey = "";
|
|
79
81
|
sectionSequence = 0;
|
|
80
82
|
versionValue = 0;
|
|
@@ -99,6 +101,14 @@ export class ProcessModeler extends BaseElement {
|
|
|
99
101
|
spacePressed = false;
|
|
100
102
|
dropLine;
|
|
101
103
|
paletteDragKind = null;
|
|
104
|
+
palettePointer;
|
|
105
|
+
suppressPaletteClick = false;
|
|
106
|
+
escapePalettePointer = (event) => {
|
|
107
|
+
if (event.key !== 'Escape' || !this.palettePointer)
|
|
108
|
+
return;
|
|
109
|
+
this.cancelPalettePointer();
|
|
110
|
+
event.preventDefault();
|
|
111
|
+
};
|
|
102
112
|
narrowValue = false;
|
|
103
113
|
suppressClick = false;
|
|
104
114
|
resizeObserver;
|
|
@@ -157,6 +167,7 @@ export class ProcessModeler extends BaseElement {
|
|
|
157
167
|
};
|
|
158
168
|
}
|
|
159
169
|
load(document, options = {}) {
|
|
170
|
+
this.cancelPalettePointer();
|
|
160
171
|
const projection = this.model.project(document);
|
|
161
172
|
validateProjection(projection);
|
|
162
173
|
this.documentValue = document;
|
|
@@ -170,7 +181,7 @@ export class ProcessModeler extends BaseElement {
|
|
|
170
181
|
this.selectedId = null;
|
|
171
182
|
this.selectedLineId = null;
|
|
172
183
|
this.selectedIds.clear();
|
|
173
|
-
this.
|
|
184
|
+
this.clearClipboard();
|
|
174
185
|
this.refresh();
|
|
175
186
|
if (options.selectedPath)
|
|
176
187
|
this.selectedPath = options.selectedPath;
|
|
@@ -259,6 +270,8 @@ export class ProcessModeler extends BaseElement {
|
|
|
259
270
|
}
|
|
260
271
|
set locked(value) {
|
|
261
272
|
this.toggleAttribute("locked", value);
|
|
273
|
+
if (value)
|
|
274
|
+
this.cancelPalettePointer();
|
|
262
275
|
}
|
|
263
276
|
get snapToGrid() {
|
|
264
277
|
return this.hasAttribute("snap-to-grid");
|
|
@@ -281,6 +294,8 @@ export class ProcessModeler extends BaseElement {
|
|
|
281
294
|
}
|
|
282
295
|
disconnectedCallback() {
|
|
283
296
|
this.resizeObserver?.disconnect();
|
|
297
|
+
this.clearClipboard();
|
|
298
|
+
this.cancelPalettePointer();
|
|
284
299
|
this.closeDrawer();
|
|
285
300
|
const chooser = this.shadowRoot?.querySelector("[part=insert-chooser]");
|
|
286
301
|
if (chooser)
|
|
@@ -341,56 +356,85 @@ export class ProcessModeler extends BaseElement {
|
|
|
341
356
|
setValidationAtPath(message, path) {
|
|
342
357
|
this.setValidation(message ? [{ message, path }] : []);
|
|
343
358
|
}
|
|
359
|
+
connectionProblem(edit) {
|
|
360
|
+
if (!this.model.connectionProblem || this.documentValue === undefined || !['connect', 'reattach'].includes(edit.type))
|
|
361
|
+
return null;
|
|
362
|
+
if (!this.isRendered) {
|
|
363
|
+
this.projection = this.model.project(this.documentValue);
|
|
364
|
+
validateProjection(this.projection);
|
|
365
|
+
}
|
|
366
|
+
const line = edit.type === 'reattach' ? this.projection.lines.find(line => line.id === edit.lineId) : undefined;
|
|
367
|
+
const from = edit.from ?? line?.from;
|
|
368
|
+
const to = edit.to ?? line?.to;
|
|
369
|
+
if (!from || !to)
|
|
370
|
+
return null;
|
|
371
|
+
return this.model.connectionProblem(this.documentValue, { from, to, ...(line ? { ignoreLineId: line.id } : {}) }, this.projection) || null;
|
|
372
|
+
}
|
|
344
373
|
requestEdit(edit) {
|
|
345
374
|
if (this.locked || (this.disableConnections && (edit.type === "connect" || edit.type === "disconnect" || edit.type === 'reattach')))
|
|
346
375
|
return;
|
|
376
|
+
const problem = this.connectionProblem(edit);
|
|
377
|
+
if (problem) {
|
|
378
|
+
this.setStatus(problem, true);
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
const request = { ...edit, accept: this.editAcceptance(edit) };
|
|
382
|
+
emit(this, "process-edit-request", request);
|
|
383
|
+
}
|
|
384
|
+
editAcceptance(edit) {
|
|
347
385
|
const before = this.layout;
|
|
386
|
+
const beforeSelection = [...this.selectedIds];
|
|
348
387
|
const previousIds = new Set(this.projection.boxes.map((box) => box.id));
|
|
349
388
|
let accepted = false;
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
this.emitPositions();
|
|
376
|
-
};
|
|
377
|
-
this.history.record({
|
|
378
|
-
undo: () => {
|
|
379
|
-
command.undo();
|
|
380
|
-
restore(before);
|
|
381
|
-
},
|
|
382
|
-
redo: () => {
|
|
383
|
-
command.redo();
|
|
384
|
-
restore(after);
|
|
385
|
-
},
|
|
386
|
-
});
|
|
389
|
+
return (command) => {
|
|
390
|
+
if (accepted)
|
|
391
|
+
return;
|
|
392
|
+
accepted = true;
|
|
393
|
+
if (command.layout)
|
|
394
|
+
this.layoutValue = structuredClone(command.layout);
|
|
395
|
+
if (edit.type === 'reset-line' && edit.lineId)
|
|
396
|
+
delete this.layoutValue.lines?.[edit.lineId];
|
|
397
|
+
this.refresh();
|
|
398
|
+
const inserted = edit.type === 'insert' && !edit.boxId && !command.layout
|
|
399
|
+
? this.projection.boxes.find(box => !previousIds.has(box.id)) : undefined;
|
|
400
|
+
const reflowed = inserted ? this.reflowStraightInsert(edit, inserted.id, before) : false;
|
|
401
|
+
if (!reflowed &&
|
|
402
|
+
!command.layout &&
|
|
403
|
+
edit.position &&
|
|
404
|
+
Number.isFinite(edit.position.x) &&
|
|
405
|
+
Number.isFinite(edit.position.y)) {
|
|
406
|
+
const added = this.projection.boxes.find(box => box.id === edit.boxId) ?? this.projection.boxes.find((box) => !previousIds.has(box.id));
|
|
407
|
+
if (added)
|
|
408
|
+
this.layoutValue = this.translatedLayout(added.id, edit.position.x, edit.position.y);
|
|
409
|
+
}
|
|
410
|
+
const after = this.layout;
|
|
411
|
+
const acceptedSelection = command.selectionIds ? [...command.selectionIds] : undefined;
|
|
412
|
+
const restore = (layout) => {
|
|
413
|
+
this.layoutValue = structuredClone(layout);
|
|
387
414
|
this.refresh();
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
415
|
+
this.emitPositions();
|
|
416
|
+
};
|
|
417
|
+
this.history.record({
|
|
418
|
+
undo: () => {
|
|
419
|
+
command.undo();
|
|
420
|
+
restore(before);
|
|
421
|
+
if (acceptedSelection)
|
|
422
|
+
this.selectMany(beforeSelection);
|
|
423
|
+
},
|
|
424
|
+
redo: () => {
|
|
425
|
+
command.redo();
|
|
426
|
+
restore(after);
|
|
427
|
+
if (acceptedSelection)
|
|
428
|
+
this.selectMany(acceptedSelection);
|
|
429
|
+
},
|
|
430
|
+
});
|
|
431
|
+
if (acceptedSelection)
|
|
432
|
+
this.selectMany(acceptedSelection);
|
|
433
|
+
this.refresh();
|
|
434
|
+
if (JSON.stringify(before) !== JSON.stringify(after))
|
|
435
|
+
this.emitPositions();
|
|
436
|
+
announce("Process updated", "polite", this.ownerDocument);
|
|
392
437
|
};
|
|
393
|
-
emit(this, "process-edit-request", request);
|
|
394
438
|
}
|
|
395
439
|
undo() {
|
|
396
440
|
if (this.locked)
|
|
@@ -541,6 +585,13 @@ export class ProcessModeler extends BaseElement {
|
|
|
541
585
|
});
|
|
542
586
|
}
|
|
543
587
|
resetLine(id) {
|
|
588
|
+
const line = this.projection.lines.find(line => line.id === id);
|
|
589
|
+
if (this.locked || !line)
|
|
590
|
+
return;
|
|
591
|
+
if (line.fromSide || line.toSide || line.points?.length) {
|
|
592
|
+
this.requestEdit({ type: 'reset-line', lineId: id });
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
544
595
|
if (!this.layoutValue.lines?.[id])
|
|
545
596
|
return;
|
|
546
597
|
const next = this.layout;
|
|
@@ -763,7 +814,7 @@ export class ProcessModeler extends BaseElement {
|
|
|
763
814
|
palette.prepend(skip, paletteHeading);
|
|
764
815
|
const hint = document.createElement("p");
|
|
765
816
|
hint.setAttribute("part", "palette-hint");
|
|
766
|
-
hint.textContent = "Drag onto the canvas, a
|
|
817
|
+
hint.textContent = "Drag onto the canvas, onto a line to insert, or into a frame. Choosing one with a step selected adds it after that step. Or click a dot beside any step to add one that way.";
|
|
767
818
|
palette.append(hint);
|
|
768
819
|
for (const [part, label] of [["palette", "Building blocks"], ["inspector", "Process details"]]) {
|
|
769
820
|
const pane = root.querySelector(`[part=${part}]`);
|
|
@@ -864,6 +915,12 @@ export class ProcessModeler extends BaseElement {
|
|
|
864
915
|
controls.setAttribute("role", "toolbar");
|
|
865
916
|
controls.setAttribute("aria-label", "Canvas view controls");
|
|
866
917
|
for (const command of ["zoom-out", "reset", "zoom-in", "fit", "snap", "lock"]) {
|
|
918
|
+
if (command === 'snap') {
|
|
919
|
+
const divider = document.createElement('span');
|
|
920
|
+
divider.setAttribute('part', 'controls-divider');
|
|
921
|
+
divider.setAttribute('aria-hidden', 'true');
|
|
922
|
+
controls.append(divider);
|
|
923
|
+
}
|
|
867
924
|
const button = root.querySelector(`[data-command=${command}]`);
|
|
868
925
|
if (button)
|
|
869
926
|
controls.append(button);
|
|
@@ -896,6 +953,7 @@ export class ProcessModeler extends BaseElement {
|
|
|
896
953
|
this.narrowValue = narrow;
|
|
897
954
|
this.toggleAttribute("data-narrow", narrow);
|
|
898
955
|
this.toggleAttribute('data-phone', entries[0].contentRect.width < 560);
|
|
956
|
+
this.toggleAttribute('data-hide-tidy', entries[0].contentRect.width <= 560);
|
|
899
957
|
this.renderSelectionToolbar();
|
|
900
958
|
this.positionSelectionToolbar();
|
|
901
959
|
if (!narrow)
|
|
@@ -1326,6 +1384,16 @@ export class ProcessModeler extends BaseElement {
|
|
|
1326
1384
|
this.setSection({ id, title, x, y, width: right - x, height: bottom - y });
|
|
1327
1385
|
}
|
|
1328
1386
|
setupListeners() {
|
|
1387
|
+
this.addEventListener('pointermove', event => this.movePalettePointer(event));
|
|
1388
|
+
this.addEventListener('pointerup', event => this.finishPalettePointer(event));
|
|
1389
|
+
this.addEventListener('pointercancel', event => { if (event.pointerId === this.palettePointer?.id)
|
|
1390
|
+
this.cancelPalettePointer(); });
|
|
1391
|
+
this.addEventListener('lostpointercapture', event => { if (event.pointerId === this.palettePointer?.id)
|
|
1392
|
+
this.cancelPalettePointer(); });
|
|
1393
|
+
this.shadowRoot.addEventListener('keydown', event => { if (event.key === 'Escape' && this.palettePointer) {
|
|
1394
|
+
this.cancelPalettePointer();
|
|
1395
|
+
event.preventDefault();
|
|
1396
|
+
} }, true);
|
|
1329
1397
|
this.shadowRoot.addEventListener("click", (event) => {
|
|
1330
1398
|
const command = event.target.closest("button")?.dataset.command;
|
|
1331
1399
|
if (command === "zoom-in")
|
|
@@ -1455,6 +1523,92 @@ export class ProcessModeler extends BaseElement {
|
|
|
1455
1523
|
this.paintViewport();
|
|
1456
1524
|
});
|
|
1457
1525
|
}
|
|
1526
|
+
clearClipboard() {
|
|
1527
|
+
const previous = this.clipboard;
|
|
1528
|
+
this.clipboard = null;
|
|
1529
|
+
this.clipboardSession++;
|
|
1530
|
+
previous?.dispose?.();
|
|
1531
|
+
}
|
|
1532
|
+
copySelection() {
|
|
1533
|
+
this.clearClipboard();
|
|
1534
|
+
const session = this.clipboardSession;
|
|
1535
|
+
let active = true;
|
|
1536
|
+
let claimed = false;
|
|
1537
|
+
const request = {
|
|
1538
|
+
sourceIds: Object.freeze([...this.selectedIds]),
|
|
1539
|
+
capture: clipboard => {
|
|
1540
|
+
if (!active || claimed || session !== this.clipboardSession || !this.isConnected)
|
|
1541
|
+
return;
|
|
1542
|
+
claimed = true;
|
|
1543
|
+
if (!Number.isInteger(clipboard?.itemCount) || clipboard.itemCount < 1 || typeof clipboard.paste !== 'function' || (clipboard.dispose !== undefined && typeof clipboard.dispose !== 'function')) {
|
|
1544
|
+
this.setStatus('The host did not supply a valid clipboard');
|
|
1545
|
+
return;
|
|
1546
|
+
}
|
|
1547
|
+
this.clipboard = Object.freeze({ itemCount: clipboard.itemCount, paste: clipboard.paste.bind(clipboard), ...(clipboard.dispose ? { dispose: clipboard.dispose.bind(clipboard) } : {}) });
|
|
1548
|
+
this.setStatus(`${clipboard.itemCount} steps copied`);
|
|
1549
|
+
},
|
|
1550
|
+
refuse: message => { if (!active || claimed || session !== this.clipboardSession || !this.isConnected)
|
|
1551
|
+
return; claimed = true; this.setStatus(message ?? 'Copy is not supported by this host'); },
|
|
1552
|
+
};
|
|
1553
|
+
try {
|
|
1554
|
+
emit(this, 'process-copy-request', request);
|
|
1555
|
+
}
|
|
1556
|
+
finally {
|
|
1557
|
+
active = false;
|
|
1558
|
+
}
|
|
1559
|
+
if (!claimed && session === this.clipboardSession && this.isConnected)
|
|
1560
|
+
this.setStatus('Copy is not supported by this host');
|
|
1561
|
+
return claimed;
|
|
1562
|
+
}
|
|
1563
|
+
pasteClipboard() {
|
|
1564
|
+
const clipboard = this.clipboard;
|
|
1565
|
+
if (!clipboard || this.locked)
|
|
1566
|
+
return;
|
|
1567
|
+
const session = this.clipboardSession;
|
|
1568
|
+
const accept = this.editAcceptance({ type: 'duplicate' });
|
|
1569
|
+
let active = true;
|
|
1570
|
+
let settled = false;
|
|
1571
|
+
const request = {
|
|
1572
|
+
offset: Object.freeze({ x: 32, y: 32 }),
|
|
1573
|
+
accept: command => {
|
|
1574
|
+
if (!active || settled || session !== this.clipboardSession || this.locked)
|
|
1575
|
+
return;
|
|
1576
|
+
settled = true;
|
|
1577
|
+
accept(command);
|
|
1578
|
+
},
|
|
1579
|
+
refuse: message => { if (!active || settled || session !== this.clipboardSession || !this.isConnected)
|
|
1580
|
+
return; settled = true; this.setStatus(message ?? 'Paste was refused by this host'); },
|
|
1581
|
+
};
|
|
1582
|
+
try {
|
|
1583
|
+
clipboard.paste(request);
|
|
1584
|
+
}
|
|
1585
|
+
finally {
|
|
1586
|
+
active = false;
|
|
1587
|
+
}
|
|
1588
|
+
if (!settled && session === this.clipboardSession)
|
|
1589
|
+
this.setStatus('Paste was not accepted by this host');
|
|
1590
|
+
}
|
|
1591
|
+
duplicateBoxes(ids, distance) {
|
|
1592
|
+
const selected = new Set(ids);
|
|
1593
|
+
if (!selected.size || [...selected].some(id => !this.projection.boxes.some(box => box.id === id) || !this.layoutValue.boxes[id]))
|
|
1594
|
+
return;
|
|
1595
|
+
const sources = [...selected].filter(id => {
|
|
1596
|
+
let parent = this.projection.boxes.find(box => box.id === id)?.parentId;
|
|
1597
|
+
while (parent) {
|
|
1598
|
+
if (selected.has(parent))
|
|
1599
|
+
return false;
|
|
1600
|
+
parent = this.projection.boxes.find(box => box.id === parent)?.parentId;
|
|
1601
|
+
}
|
|
1602
|
+
return true;
|
|
1603
|
+
});
|
|
1604
|
+
if (sources.length === 1) {
|
|
1605
|
+
const position = this.layoutValue.boxes[sources[0]];
|
|
1606
|
+
this.requestEdit({ type: 'duplicate', sourceId: sources[0], position: { x: position.x + distance, y: position.y + distance } });
|
|
1607
|
+
}
|
|
1608
|
+
else {
|
|
1609
|
+
this.requestEdit({ type: 'duplicate', sourceIds: sources, offset: { x: distance, y: distance } });
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1458
1612
|
onKey(event) {
|
|
1459
1613
|
if (event.defaultPrevented)
|
|
1460
1614
|
return;
|
|
@@ -1483,20 +1637,18 @@ export class ProcessModeler extends BaseElement {
|
|
|
1483
1637
|
return;
|
|
1484
1638
|
}
|
|
1485
1639
|
if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'c' && this.selectedIds.size) {
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
this.setStatus(`${this.clipboardIds.length} steps copied`);
|
|
1640
|
+
if (this.copySelection())
|
|
1641
|
+
event.preventDefault();
|
|
1489
1642
|
return;
|
|
1490
1643
|
}
|
|
1491
|
-
if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'v' && this.
|
|
1644
|
+
if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'v' && this.clipboard && !this.locked) {
|
|
1492
1645
|
event.preventDefault();
|
|
1493
|
-
this.
|
|
1494
|
-
this.requestEdit({ type: 'duplicate', sourceId: id, position: { x: position.x + 32 * (index + 1), y: position.y + 32 * (index + 1) } }); });
|
|
1646
|
+
this.pasteClipboard();
|
|
1495
1647
|
return;
|
|
1496
1648
|
}
|
|
1497
1649
|
if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'd' && this.selectedIds.size && !this.locked) {
|
|
1498
1650
|
event.preventDefault();
|
|
1499
|
-
[...this.selectedIds]
|
|
1651
|
+
this.duplicateBoxes([...this.selectedIds], 48);
|
|
1500
1652
|
return;
|
|
1501
1653
|
}
|
|
1502
1654
|
if (event.key === "Escape") {
|
|
@@ -1506,6 +1658,7 @@ export class ProcessModeler extends BaseElement {
|
|
|
1506
1658
|
if (this.selectedLineId)
|
|
1507
1659
|
this.selectLine(null);
|
|
1508
1660
|
this.portDrag = undefined;
|
|
1661
|
+
this.endDrag = undefined;
|
|
1509
1662
|
this.marquee = undefined;
|
|
1510
1663
|
this.segmentDrag = undefined;
|
|
1511
1664
|
this.drag = undefined;
|
|
@@ -1532,6 +1685,18 @@ export class ProcessModeler extends BaseElement {
|
|
|
1532
1685
|
this.openKeyboardChooser(box);
|
|
1533
1686
|
return;
|
|
1534
1687
|
}
|
|
1688
|
+
const direction = {
|
|
1689
|
+
ArrowLeft: [-1, 0],
|
|
1690
|
+
ArrowRight: [1, 0],
|
|
1691
|
+
ArrowUp: [0, -1],
|
|
1692
|
+
ArrowDown: [0, 1],
|
|
1693
|
+
}[event.key];
|
|
1694
|
+
const canInsertDirection = event.ctrlKey && event.altKey && box && !this.locked && this.catalog.length && !this.disableConnections;
|
|
1695
|
+
if (direction && !canInsertDirection && (event.altKey || !box || this.locked)) {
|
|
1696
|
+
event.preventDefault();
|
|
1697
|
+
this.navigateSelection(direction);
|
|
1698
|
+
return;
|
|
1699
|
+
}
|
|
1535
1700
|
if (!box || this.locked)
|
|
1536
1701
|
return;
|
|
1537
1702
|
if (event.key === "Enter") {
|
|
@@ -1560,12 +1725,6 @@ export class ProcessModeler extends BaseElement {
|
|
|
1560
1725
|
event.preventDefault();
|
|
1561
1726
|
this.selectionCommand("delete-many");
|
|
1562
1727
|
}
|
|
1563
|
-
const direction = {
|
|
1564
|
-
ArrowLeft: [-1, 0],
|
|
1565
|
-
ArrowRight: [1, 0],
|
|
1566
|
-
ArrowUp: [0, -1],
|
|
1567
|
-
ArrowDown: [0, 1],
|
|
1568
|
-
}[event.key];
|
|
1569
1728
|
if (direction) {
|
|
1570
1729
|
event.preventDefault();
|
|
1571
1730
|
if (event.ctrlKey && event.altKey && this.catalog.length && !this.disableConnections) {
|
|
@@ -1578,31 +1737,52 @@ export class ProcessModeler extends BaseElement {
|
|
|
1578
1737
|
this.openAnchoredChooser(this.nextEdit(box, side, { x: pos.x + direction[0] * 320, y: pos.y + direction[1] * 170 }), this.nextChooserTitle(box, side), anchor, returnFocus);
|
|
1579
1738
|
return;
|
|
1580
1739
|
}
|
|
1581
|
-
if (event.altKey) {
|
|
1582
|
-
const origin = this.layoutValue.boxes[box.id];
|
|
1583
|
-
const center = { x: origin.x + (origin.width ?? 224) / 2, y: origin.y + (origin.height ?? 64) / 2 };
|
|
1584
|
-
const candidates = this.projection.boxes.filter(candidate => candidate.id !== box.id).map(candidate => {
|
|
1585
|
-
const position = this.layoutValue.boxes[candidate.id];
|
|
1586
|
-
const dx = position.x + (position.width ?? 224) / 2 - center.x;
|
|
1587
|
-
const dy = position.y + (position.height ?? 64) / 2 - center.y;
|
|
1588
|
-
const forward = dx * direction[0] + dy * direction[1];
|
|
1589
|
-
const sideways = Math.abs(dx * direction[1] - dy * direction[0]);
|
|
1590
|
-
return { candidate, forward, score: forward + sideways * 2 };
|
|
1591
|
-
}).filter(item => item.forward > 0).sort((a, b) => a.score - b.score || a.candidate.id.localeCompare(b.candidate.id));
|
|
1592
|
-
const next = candidates[0]?.candidate;
|
|
1593
|
-
if (next) {
|
|
1594
|
-
this.select(next.id);
|
|
1595
|
-
this.focusBox(next.id);
|
|
1596
|
-
this.setStatus(`${next.title} selected`);
|
|
1597
|
-
}
|
|
1598
|
-
return;
|
|
1599
|
-
}
|
|
1600
1740
|
const pos = this.layoutValue.boxes[box.id];
|
|
1601
1741
|
const distance = event.shiftKey ? 64 : 16;
|
|
1602
1742
|
this.move(box.id, pos.x + direction[0] * distance, pos.y + direction[1] * distance);
|
|
1603
1743
|
this.focusBox(box.id);
|
|
1604
1744
|
}
|
|
1605
1745
|
}
|
|
1746
|
+
navigateSelection(direction) {
|
|
1747
|
+
const canvas = this.shadowRoot.querySelector('[part=canvas]');
|
|
1748
|
+
const box = this.selected;
|
|
1749
|
+
const origin = box ? this.layoutValue.boxes[box.id] : undefined;
|
|
1750
|
+
const originSize = box ? this.selectionDimensions(box) : undefined;
|
|
1751
|
+
const center = origin && originSize
|
|
1752
|
+
? { x: origin.x + originSize.width / 2, y: origin.y + originSize.height / 2 }
|
|
1753
|
+
: { x: (canvas.clientWidth / 2 - this.viewport.x) / this.viewport.zoom, y: (canvas.clientHeight / 2 - this.viewport.y) / this.viewport.zoom };
|
|
1754
|
+
const candidates = this.projection.boxes.filter(candidate => candidate.id !== box?.id && candidate.kind !== 'section').map(candidate => {
|
|
1755
|
+
const position = this.layoutValue.boxes[candidate.id];
|
|
1756
|
+
const size = this.selectionDimensions(candidate);
|
|
1757
|
+
const dx = position.x + size.width / 2 - center.x;
|
|
1758
|
+
const dy = position.y + size.height / 2 - center.y;
|
|
1759
|
+
const forward = dx * direction[0] + dy * direction[1];
|
|
1760
|
+
const sideways = Math.abs(dx * direction[1] - dy * direction[0]);
|
|
1761
|
+
return { candidate, forward, score: forward + sideways * 2.5 };
|
|
1762
|
+
}).filter(item => item.forward > 4).sort((a, b) => a.score - b.score);
|
|
1763
|
+
const next = candidates[0]?.candidate;
|
|
1764
|
+
if (!next) {
|
|
1765
|
+
this.setStatus('Nothing further that way');
|
|
1766
|
+
return;
|
|
1767
|
+
}
|
|
1768
|
+
this.select(next.id);
|
|
1769
|
+
this.revealBox(next);
|
|
1770
|
+
this.focusBox(next.id);
|
|
1771
|
+
this.setStatus(`${next.title} selected`);
|
|
1772
|
+
}
|
|
1773
|
+
revealBox(box) {
|
|
1774
|
+
const canvas = this.shadowRoot.querySelector('[part=canvas]');
|
|
1775
|
+
if (!canvas.clientWidth || !canvas.clientHeight)
|
|
1776
|
+
return;
|
|
1777
|
+
const position = this.layoutValue.boxes[box.id];
|
|
1778
|
+
const size = this.selectionDimensions(box);
|
|
1779
|
+
const left = position.x * this.viewport.zoom + this.viewport.x;
|
|
1780
|
+
const top = position.y * this.viewport.zoom + this.viewport.y;
|
|
1781
|
+
if (left > 48 && top > 48 && left + size.width * this.viewport.zoom < canvas.clientWidth - 48 && top + size.height * this.viewport.zoom < canvas.clientHeight - 48)
|
|
1782
|
+
return;
|
|
1783
|
+
this.setView({ x: canvas.clientWidth / 2 - (position.x + size.width / 2) * this.viewport.zoom,
|
|
1784
|
+
y: canvas.clientHeight / 2 - (position.y + size.height / 2) * this.viewport.zoom, zoom: this.viewport.zoom });
|
|
1785
|
+
}
|
|
1606
1786
|
pointerDown(event) {
|
|
1607
1787
|
if (event.button !== 0)
|
|
1608
1788
|
return;
|
|
@@ -1706,10 +1886,12 @@ export class ProcessModeler extends BaseElement {
|
|
|
1706
1886
|
const start = this.portDrag.start;
|
|
1707
1887
|
ghost.setAttribute("points", `${start.x},${start.y} ${point.x},${start.y} ${point.x},${point.y}`);
|
|
1708
1888
|
const target = this.boxAt(point, this.portDrag.id);
|
|
1709
|
-
const
|
|
1710
|
-
|
|
1889
|
+
const problem = target ? this.connectionProblem({ type: 'connect', from: this.portDrag.id, to: target.id }) : null;
|
|
1890
|
+
const pinned = target && !problem ? this.sideAt(target, point) : undefined;
|
|
1891
|
+
ghost.dataset.invalid = String(Boolean(problem));
|
|
1892
|
+
this.shadowRoot.querySelectorAll('[data-box-id]').forEach(box => { box.dataset.connectTarget = String(box.dataset.boxId === target?.id); box.dataset.connectInvalid = String(box.dataset.boxId === target?.id && Boolean(problem)); });
|
|
1711
1893
|
this.shadowRoot.querySelectorAll('[part=port]').forEach(port => { port.dataset.hot = String(port.dataset.owner === target?.id && port.dataset.side === pinned); });
|
|
1712
|
-
this.showConnectTooltip(point, target ? pinned ? `Pin to the ${pinned} of ${target.title}` : `Connect to ${target.title}` : 'Drop here to add a connected step');
|
|
1894
|
+
this.showConnectTooltip(point, problem ?? (target ? pinned ? `Pin to the ${pinned} of ${target.title}` : `Connect to ${target.title}` : 'Drop here to add a connected step'), Boolean(problem));
|
|
1713
1895
|
return;
|
|
1714
1896
|
}
|
|
1715
1897
|
if (this.endDrag) {
|
|
@@ -1725,11 +1907,13 @@ export class ProcessModeler extends BaseElement {
|
|
|
1725
1907
|
if (fixed)
|
|
1726
1908
|
ghost.setAttribute('points', `${fixed.x},${fixed.y} ${point.x},${fixed.y} ${point.x},${point.y}`);
|
|
1727
1909
|
const target = this.boxAt(point);
|
|
1728
|
-
const
|
|
1729
|
-
|
|
1910
|
+
const problem = target ? this.connectionProblem({ type: 'reattach', lineId: this.endDrag.lineId, [this.endDrag.end]: target.id }) : null;
|
|
1911
|
+
const pinned = target && !problem ? this.sideAt(target, point) : undefined;
|
|
1912
|
+
ghost.dataset.invalid = String(Boolean(problem) || !target);
|
|
1913
|
+
this.shadowRoot.querySelectorAll('[data-box-id]').forEach(box => { box.dataset.connectTarget = String(box.dataset.boxId === target?.id); box.dataset.connectInvalid = String(box.dataset.boxId === target?.id && Boolean(problem)); });
|
|
1730
1914
|
this.shadowRoot.querySelectorAll('[part=port]').forEach(port => { port.dataset.hot = String(port.dataset.owner === target?.id && port.dataset.side === pinned); });
|
|
1731
|
-
this.showConnectTooltip(point, target ? pinned ? `Pin to the ${pinned} of ${target.title}` : `Attach to ${target.title}` : 'Drop on a step to reattach', !target);
|
|
1732
|
-
this.setStatus(target ? `Release to attach the connection to ${target.title}` : 'Move over a step to attach this connection');
|
|
1915
|
+
this.showConnectTooltip(point, problem ?? (target ? pinned ? `Pin to the ${pinned} of ${target.title}` : `Attach to ${target.title}` : 'Drop on a step to reattach'), Boolean(problem) || !target);
|
|
1916
|
+
this.setStatus(problem ?? (target ? `Release to attach the connection to ${target.title}` : 'Move over a step to attach this connection'));
|
|
1733
1917
|
return;
|
|
1734
1918
|
}
|
|
1735
1919
|
if (this.segmentDrag) {
|
|
@@ -1828,7 +2012,7 @@ export class ProcessModeler extends BaseElement {
|
|
|
1828
2012
|
this.portDrag = undefined;
|
|
1829
2013
|
this.shadowRoot.querySelector('[part=connection-preview]')?.remove();
|
|
1830
2014
|
this.shadowRoot.querySelector('[part=connect-tooltip]')?.remove();
|
|
1831
|
-
this.shadowRoot.querySelectorAll('[data-connect-target]').forEach(box => { delete box.dataset.connectTarget; });
|
|
2015
|
+
this.shadowRoot.querySelectorAll('[data-connect-target]').forEach(box => { delete box.dataset.connectTarget; delete box.dataset.connectInvalid; });
|
|
1832
2016
|
this.shadowRoot.querySelectorAll('[part=port]').forEach(port => { delete port.dataset.hot; });
|
|
1833
2017
|
if (commit) {
|
|
1834
2018
|
if (Math.hypot(point.x - port.start.x, point.y - port.start.y) < 8) {
|
|
@@ -1860,7 +2044,7 @@ export class ProcessModeler extends BaseElement {
|
|
|
1860
2044
|
this.endDrag = undefined;
|
|
1861
2045
|
this.shadowRoot.querySelector('[part=connection-preview]')?.remove();
|
|
1862
2046
|
this.shadowRoot.querySelector('[part=connect-tooltip]')?.remove();
|
|
1863
|
-
this.shadowRoot.querySelectorAll('[data-connect-target]').forEach(box => { delete box.dataset.connectTarget; });
|
|
2047
|
+
this.shadowRoot.querySelectorAll('[data-connect-target]').forEach(box => { delete box.dataset.connectTarget; delete box.dataset.connectInvalid; });
|
|
1864
2048
|
this.shadowRoot.querySelectorAll('[part=port]').forEach(port => { delete port.dataset.hot; });
|
|
1865
2049
|
if (commit) {
|
|
1866
2050
|
if (Math.hypot(point.x - drag.start.x, point.y - drag.start.y) < 8) {
|
|
@@ -1976,6 +2160,9 @@ export class ProcessModeler extends BaseElement {
|
|
|
1976
2160
|
}
|
|
1977
2161
|
markDropLine(point, except) {
|
|
1978
2162
|
this.dropLine = point ? this.lineAt(point, except)?.id : undefined;
|
|
2163
|
+
this.paintDropLine();
|
|
2164
|
+
}
|
|
2165
|
+
paintDropLine() {
|
|
1979
2166
|
this.shadowRoot.querySelectorAll('[part=line]').forEach(path => { const active = path.dataset.lineId === this.dropLine; path.dataset.drop = String(active); path.setAttribute('marker-end', `url(#${active || path.dataset.selected === 'true' ? 'boe-process-arrow-brand' : 'boe-process-arrow'})`); });
|
|
1980
2167
|
}
|
|
1981
2168
|
alignedPoint(id, x, y) {
|
|
@@ -2192,8 +2379,15 @@ export class ProcessModeler extends BaseElement {
|
|
|
2192
2379
|
this.updateToolbar();
|
|
2193
2380
|
if (selectionBefore !== JSON.stringify({ ids: [...this.selectedIds], path: this.selectedPath }))
|
|
2194
2381
|
emit(this, "selection-changed", { box: this.selected, boxes: this.selectedBoxes, path: this.selectedPath });
|
|
2195
|
-
if (focused)
|
|
2196
|
-
this.
|
|
2382
|
+
if (focused) {
|
|
2383
|
+
this.restoringBoxFocus = true;
|
|
2384
|
+
try {
|
|
2385
|
+
this.focusBox(focused);
|
|
2386
|
+
}
|
|
2387
|
+
finally {
|
|
2388
|
+
this.restoringBoxFocus = false;
|
|
2389
|
+
}
|
|
2390
|
+
}
|
|
2197
2391
|
}
|
|
2198
2392
|
get allChecks() { return this.computedChecks; }
|
|
2199
2393
|
collectChecks() {
|
|
@@ -2222,6 +2416,13 @@ export class ProcessModeler extends BaseElement {
|
|
|
2222
2416
|
for (const box of [...this.projection.boxes].sort((a, b) => Number(Boolean(b.frame)) - Number(Boolean(a.frame)))) {
|
|
2223
2417
|
const element = document.createElement("div");
|
|
2224
2418
|
element.tabIndex = 0;
|
|
2419
|
+
element.addEventListener('focus', () => {
|
|
2420
|
+
if (!this.restoringBoxFocus && !this.pointers.size && !this.portDrag && !this.endDrag && !this.segmentDrag && !this.marquee && !this.frameResize) {
|
|
2421
|
+
this.select(box.id);
|
|
2422
|
+
if (box.kind !== 'section')
|
|
2423
|
+
this.revealBox(box);
|
|
2424
|
+
}
|
|
2425
|
+
});
|
|
2225
2426
|
element.setAttribute("role", "group");
|
|
2226
2427
|
element.setAttribute("part", box.frame ? "frame" : "box");
|
|
2227
2428
|
element.dataset.boxId = box.id;
|
|
@@ -2394,6 +2595,7 @@ export class ProcessModeler extends BaseElement {
|
|
|
2394
2595
|
for (const side of ["north", "east", "south", "west"]) {
|
|
2395
2596
|
const port = document.createElement("button");
|
|
2396
2597
|
port.type = "button";
|
|
2598
|
+
port.tabIndex = -1;
|
|
2397
2599
|
port.setAttribute("part", "port");
|
|
2398
2600
|
port.dataset.side = side;
|
|
2399
2601
|
port.dataset.owner = box.id;
|
|
@@ -2599,6 +2801,145 @@ export class ProcessModeler extends BaseElement {
|
|
|
2599
2801
|
height: `${position.height ?? 64}px`,
|
|
2600
2802
|
});
|
|
2601
2803
|
}
|
|
2804
|
+
activatePaletteKind(kind) {
|
|
2805
|
+
if (this.locked)
|
|
2806
|
+
return;
|
|
2807
|
+
if (this.narrowValue) {
|
|
2808
|
+
this.closeDrawer();
|
|
2809
|
+
this.shadowRoot.querySelector('[part=canvas]').focus({ preventScroll: true });
|
|
2810
|
+
}
|
|
2811
|
+
if (kind.placement) {
|
|
2812
|
+
this.addLayoutKind(kind);
|
|
2813
|
+
return;
|
|
2814
|
+
}
|
|
2815
|
+
const selected = this.selectedIds.size === 1 ? this.selected : null;
|
|
2816
|
+
const from = selected && !selected.frame && selected.kind !== 'section' && !['end', 'finish'].includes(selected.kind) ? selected.id : undefined;
|
|
2817
|
+
const outgoing = from ? this.projection.lines.filter(line => line.from === from) : [];
|
|
2818
|
+
const line = outgoing.length === 1 ? outgoing[0] : undefined;
|
|
2819
|
+
this.requestEdit(line ? { type: 'insert', kind, lineId: line.id, from: line.from, to: line.to } : { type: 'add', kind, ...(from ? { from } : {}) });
|
|
2820
|
+
}
|
|
2821
|
+
paletteLineAt(point) {
|
|
2822
|
+
let nearest;
|
|
2823
|
+
let best = 20 / this.viewport.zoom;
|
|
2824
|
+
for (const line of this.projection.lines) {
|
|
2825
|
+
const points = this.routedLines.get(line.id) ?? [];
|
|
2826
|
+
for (let i = 1; i < points.length; i++) {
|
|
2827
|
+
const a = points[i - 1], b = points[i], dx = b.x - a.x, dy = b.y - a.y, length = dx * dx + dy * dy;
|
|
2828
|
+
const t = length ? Math.max(0, Math.min(1, ((point.x - a.x) * dx + (point.y - a.y) * dy) / length)) : 0;
|
|
2829
|
+
const distance = Math.hypot(point.x - a.x - t * dx, point.y - a.y - t * dy);
|
|
2830
|
+
if (distance < best) {
|
|
2831
|
+
best = distance;
|
|
2832
|
+
nearest = line;
|
|
2833
|
+
}
|
|
2834
|
+
}
|
|
2835
|
+
}
|
|
2836
|
+
return nearest;
|
|
2837
|
+
}
|
|
2838
|
+
paletteFrameAt(point) {
|
|
2839
|
+
let nearest;
|
|
2840
|
+
let depth = -1;
|
|
2841
|
+
for (const box of this.projection.boxes) {
|
|
2842
|
+
if (!box.frame)
|
|
2843
|
+
continue;
|
|
2844
|
+
const p = this.layoutValue.boxes[box.id];
|
|
2845
|
+
if (!p)
|
|
2846
|
+
continue;
|
|
2847
|
+
const { width, height } = this.selectionDimensions(box);
|
|
2848
|
+
if (point.x < p.x || point.x > p.x + width || point.y < p.y || point.y > p.y + height)
|
|
2849
|
+
continue;
|
|
2850
|
+
let level = 0, parent = box.parentId;
|
|
2851
|
+
while (parent) {
|
|
2852
|
+
level++;
|
|
2853
|
+
parent = this.projection.boxes.find(box => box.id === parent)?.parentId;
|
|
2854
|
+
}
|
|
2855
|
+
if (level > depth) {
|
|
2856
|
+
depth = level;
|
|
2857
|
+
nearest = box;
|
|
2858
|
+
}
|
|
2859
|
+
}
|
|
2860
|
+
return nearest;
|
|
2861
|
+
}
|
|
2862
|
+
markPaletteDrop(point) {
|
|
2863
|
+
this.dropLine = point ? this.paletteLineAt(point)?.id : undefined;
|
|
2864
|
+
const frame = point && !this.dropLine ? this.paletteFrameAt(point) : undefined;
|
|
2865
|
+
this.shadowRoot.querySelectorAll('[part=frame]').forEach(element => { element.dataset.paletteDrop = String(element.dataset.boxId === frame?.id); });
|
|
2866
|
+
this.paintDropLine();
|
|
2867
|
+
}
|
|
2868
|
+
paletteCanvasPoint(event) {
|
|
2869
|
+
const rect = this.shadowRoot.querySelector('[part=canvas]').getBoundingClientRect();
|
|
2870
|
+
if (event.clientX <= rect.left || event.clientX >= rect.right || event.clientY <= rect.top || event.clientY >= rect.bottom)
|
|
2871
|
+
return;
|
|
2872
|
+
return this.canvasPoint(event);
|
|
2873
|
+
}
|
|
2874
|
+
movePalettePointer(event) {
|
|
2875
|
+
const drag = this.palettePointer;
|
|
2876
|
+
if (!drag || drag.id !== event.pointerId)
|
|
2877
|
+
return;
|
|
2878
|
+
if (this.locked) {
|
|
2879
|
+
this.cancelPalettePointer();
|
|
2880
|
+
return;
|
|
2881
|
+
}
|
|
2882
|
+
if (!drag.moved && Math.hypot(event.clientX - drag.x, event.clientY - drag.y) < 5)
|
|
2883
|
+
return;
|
|
2884
|
+
if (!drag.moved) {
|
|
2885
|
+
drag.moved = true;
|
|
2886
|
+
if (this.narrowValue)
|
|
2887
|
+
this.closeDrawer();
|
|
2888
|
+
}
|
|
2889
|
+
let ghost = this.shadowRoot.querySelector('[part=palette-ghost]');
|
|
2890
|
+
if (!ghost) {
|
|
2891
|
+
ghost = document.createElement('div');
|
|
2892
|
+
ghost.setAttribute('part', 'palette-ghost');
|
|
2893
|
+
ghost.dataset.pointer = 'true';
|
|
2894
|
+
ghost.setAttribute('aria-hidden', 'true');
|
|
2895
|
+
if (drag.kind.icon)
|
|
2896
|
+
ghost.append(drag.kind.icon());
|
|
2897
|
+
ghost.append(document.createTextNode(drag.kind.label));
|
|
2898
|
+
this.shadowRoot.append(ghost);
|
|
2899
|
+
}
|
|
2900
|
+
ghost.style.left = `${event.clientX}px`;
|
|
2901
|
+
ghost.style.top = `${event.clientY}px`;
|
|
2902
|
+
this.markPaletteDrop(!drag.kind.placement && drag.kind.kind !== 'end' ? this.paletteCanvasPoint(event) : undefined);
|
|
2903
|
+
event.preventDefault();
|
|
2904
|
+
}
|
|
2905
|
+
cancelPalettePointer() {
|
|
2906
|
+
const drag = this.palettePointer;
|
|
2907
|
+
this.palettePointer = undefined;
|
|
2908
|
+
this.ownerDocument.removeEventListener('keydown', this.escapePalettePointer, true);
|
|
2909
|
+
if (!drag)
|
|
2910
|
+
return;
|
|
2911
|
+
this.suppressPaletteClick = true;
|
|
2912
|
+
this.shadowRoot?.querySelector('[part=palette-ghost]')?.remove();
|
|
2913
|
+
this.markPaletteDrop(undefined);
|
|
2914
|
+
try {
|
|
2915
|
+
this.releasePointerCapture(drag.id);
|
|
2916
|
+
}
|
|
2917
|
+
catch { /* Capture may already have been lost. */ }
|
|
2918
|
+
}
|
|
2919
|
+
finishPalettePointer(event) {
|
|
2920
|
+
const drag = this.palettePointer;
|
|
2921
|
+
if (!drag || drag.id !== event.pointerId)
|
|
2922
|
+
return;
|
|
2923
|
+
const point = this.paletteCanvasPoint(event);
|
|
2924
|
+
this.cancelPalettePointer();
|
|
2925
|
+
if (this.locked)
|
|
2926
|
+
return;
|
|
2927
|
+
if (!drag.moved) {
|
|
2928
|
+
this.activatePaletteKind(drag.kind);
|
|
2929
|
+
if (this.narrowValue)
|
|
2930
|
+
this.closeDrawer();
|
|
2931
|
+
return;
|
|
2932
|
+
}
|
|
2933
|
+
if (!point)
|
|
2934
|
+
return;
|
|
2935
|
+
if (drag.kind.placement) {
|
|
2936
|
+
this.addLayoutKind(drag.kind, point);
|
|
2937
|
+
return;
|
|
2938
|
+
}
|
|
2939
|
+
const line = drag.kind.kind === 'end' ? undefined : this.paletteLineAt(point);
|
|
2940
|
+
const frame = line ? undefined : this.paletteFrameAt(point);
|
|
2941
|
+
this.requestEdit({ type: line ? 'insert' : 'add', kind: drag.kind, lineId: line?.id, from: line?.from, to: line?.to, parentId: frame?.id, position: point });
|
|
2942
|
+
}
|
|
2602
2943
|
renderPalette() {
|
|
2603
2944
|
const choices = this.shadowRoot.querySelector("[part=choices]");
|
|
2604
2945
|
const query = this.shadowRoot.querySelector("[part=search]").value.toLowerCase();
|
|
@@ -2631,19 +2972,30 @@ export class ProcessModeler extends BaseElement {
|
|
|
2631
2972
|
description.textContent = kind.description;
|
|
2632
2973
|
button.append(icon, name, description);
|
|
2633
2974
|
button.disabled = this.locked;
|
|
2634
|
-
button.draggable =
|
|
2635
|
-
button.addEventListener(
|
|
2636
|
-
if (
|
|
2637
|
-
this.addLayoutKind(kind);
|
|
2975
|
+
button.draggable = false;
|
|
2976
|
+
button.addEventListener('pointerdown', event => {
|
|
2977
|
+
if (this.locked || event.button !== 0 || event.isPrimary === false)
|
|
2638
2978
|
return;
|
|
2979
|
+
this.cancelPalettePointer();
|
|
2980
|
+
this.suppressPaletteClick = false;
|
|
2981
|
+
this.palettePointer = { kind, id: event.pointerId, x: event.clientX, y: event.clientY, moved: false };
|
|
2982
|
+
this.ownerDocument.addEventListener('keydown', this.escapePalettePointer, true);
|
|
2983
|
+
try {
|
|
2984
|
+
this.setPointerCapture(event.pointerId);
|
|
2639
2985
|
}
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
this.requestEdit(line ? { type: "insert", kind, lineId: line.id, from: line.from, to: line.to } : { type: "add", kind, ...(from ? { from } : {}) });
|
|
2986
|
+
catch { /* Detached synthetic pointers cannot be captured. */ }
|
|
2987
|
+
event.preventDefault();
|
|
2988
|
+
event.stopPropagation();
|
|
2644
2989
|
});
|
|
2645
|
-
button.addEventListener(
|
|
2646
|
-
|
|
2990
|
+
button.addEventListener('click', event => {
|
|
2991
|
+
if (event.detail > 0 && this.suppressPaletteClick) {
|
|
2992
|
+
this.suppressPaletteClick = false;
|
|
2993
|
+
return;
|
|
2994
|
+
}
|
|
2995
|
+
this.activatePaletteKind(kind);
|
|
2996
|
+
});
|
|
2997
|
+
button.addEventListener('dragstart', event => { this.paletteDragKind = kind; event.dataTransfer?.setData('application/boe-process-kind', kind.kind); });
|
|
2998
|
+
button.addEventListener('dragend', () => { this.paletteDragKind = null; this.shadowRoot?.querySelector('[part=palette-ghost]')?.remove(); this.markDropLine(undefined); });
|
|
2647
2999
|
choices.append(button);
|
|
2648
3000
|
}
|
|
2649
3001
|
const canvas = this.shadowRoot.querySelector("[part=canvas]");
|
|
@@ -3106,7 +3458,7 @@ export class ProcessModeler extends BaseElement {
|
|
|
3106
3458
|
duplicate.type = 'button';
|
|
3107
3459
|
duplicate.textContent = 'Duplicate';
|
|
3108
3460
|
duplicate.disabled = this.locked;
|
|
3109
|
-
duplicate.onclick = () => this.
|
|
3461
|
+
duplicate.onclick = () => this.duplicateBoxes([selected.id], 48);
|
|
3110
3462
|
const remove = document.createElement('button');
|
|
3111
3463
|
remove.type = 'button';
|
|
3112
3464
|
remove.textContent = 'Delete';
|
|
@@ -3119,7 +3471,7 @@ export class ProcessModeler extends BaseElement {
|
|
|
3119
3471
|
}
|
|
3120
3472
|
renderSelectionToolbar() {
|
|
3121
3473
|
const toolbar = this.shadowRoot.querySelector('[part=selection-toolbar]');
|
|
3122
|
-
const key = `${[...this.selectedIds].join(',')}|${this.selected?.kind}|${this.selected?.shape}|${this.selectedLineId}|${Boolean(this.
|
|
3474
|
+
const key = `${[...this.selectedIds].join(',')}|${this.selected?.kind}|${this.selected?.shape}|${this.selectedLineId}|${Boolean(this.selectedLine && (this.layoutValue.lines?.[this.selectedLine.id] || this.selectedLine.fromSide || this.selectedLine.toSide || this.selectedLine.points?.length))}|${this.locked}|${this.narrowValue}|${this.projection.lines.filter(line => line.from === this.selectedId).map(line => `${line.id}:${line.label}:${line.dashed}`).join(',')}`;
|
|
3123
3475
|
if (key === this.selectionToolbarKey)
|
|
3124
3476
|
return;
|
|
3125
3477
|
this.selectionToolbarKey = key;
|
|
@@ -3148,7 +3500,7 @@ export class ProcessModeler extends BaseElement {
|
|
|
3148
3500
|
if (this.selectedLine) {
|
|
3149
3501
|
const line = this.selectedLine;
|
|
3150
3502
|
add('Insert a step', 'insert', () => this.openLineChooser(line, toolbar.querySelector('[data-selection-command=insert]') ?? undefined), true);
|
|
3151
|
-
if (this.layoutValue.lines?.[line.id])
|
|
3503
|
+
if (this.layoutValue.lines?.[line.id] || line.fromSide || line.toSide || line.points?.length)
|
|
3152
3504
|
add('Reset line', 'reset-line', () => this.resetLine(line.id));
|
|
3153
3505
|
if (!this.disableConnections)
|
|
3154
3506
|
add('Delete', 'delete-line', () => this.requestEdit({ type: 'disconnect', lineId: line.id }));
|
|
@@ -3163,7 +3515,7 @@ export class ProcessModeler extends BaseElement {
|
|
|
3163
3515
|
if (failurePath)
|
|
3164
3516
|
add('If it fails', 'add-failure', () => this.openAnchoredChooser({ type: 'add', from: box.id, routeLabel: 'If it fails', dashed: true }, `If a step in ${box.title} fails`, toolbar.querySelector('[data-selection-command=add-failure]') ?? undefined, Array.from(this.shadowRoot.querySelectorAll('[data-box-id]')).find(element => element.dataset.boxId === box.id)), true);
|
|
3165
3517
|
if (!['start', 'timer', 'section'].includes(box.kind))
|
|
3166
|
-
add('Duplicate', 'duplicate', () =>
|
|
3518
|
+
add('Duplicate', 'duplicate', () => this.duplicateBoxes([box.id], 48));
|
|
3167
3519
|
if (!['start', 'timer'].includes(box.kind))
|
|
3168
3520
|
add('Delete', 'delete-many', () => this.selectionCommand('delete-many'));
|
|
3169
3521
|
}
|
|
@@ -3266,9 +3618,11 @@ export class ProcessModeler extends BaseElement {
|
|
|
3266
3618
|
focusBox(id) {
|
|
3267
3619
|
Array.from(this.shadowRoot.querySelectorAll("[data-box-id]"))
|
|
3268
3620
|
.find((box) => box.dataset.boxId === id)
|
|
3269
|
-
?.focus();
|
|
3621
|
+
?.focus({ preventScroll: true });
|
|
3270
3622
|
}
|
|
3271
3623
|
setStatus(message, urgent = false) {
|
|
3624
|
+
if (!this.isRendered)
|
|
3625
|
+
return;
|
|
3272
3626
|
this.shadowRoot.querySelector(urgent ? "[part=status]" : "[part=urgent-status]").textContent = "";
|
|
3273
3627
|
this.shadowRoot.querySelector(urgent ? "[part=urgent-status]" : "[part=status]").textContent = message;
|
|
3274
3628
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unofficialbox/box-open-elements",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.32.0",
|
|
4
4
|
"description": "Box Open Elements: an open, framework-agnostic design system and web component library for Box-style experiences",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://unofficialbox.github.io/box-open-elements",
|