@unofficialbox/box-open-elements 0.22.0 → 0.24.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.
Files changed (137) hide show
  1. package/README.md +15 -12
  2. package/dist/components/actions/button.js +3 -3
  3. package/dist/components/actions/menu-item.js +1 -1
  4. package/dist/components/actions/menu.js +1 -1
  5. package/dist/components/actions/segmented-control.d.ts +1 -0
  6. package/dist/components/actions/segmented-control.js +20 -6
  7. package/dist/components/collections/carousel.js +1 -1
  8. package/dist/components/collections/draggable-list.js +1 -1
  9. package/dist/components/collections/grid-view.js +1 -1
  10. package/dist/components/collections/pagination.js +1 -1
  11. package/dist/components/collections/result-blocks.d.ts +13 -1
  12. package/dist/components/collections/result-blocks.js +22 -10
  13. package/dist/components/collections/tree-grid.js +1 -1
  14. package/dist/components/feedback/alert.js +2 -2
  15. package/dist/components/feedback/chip.js +1 -1
  16. package/dist/components/feedback/empty-state.js +1 -1
  17. package/dist/components/feedback/nudge.js +1 -1
  18. package/dist/components/feedback/progress-bar.js +2 -2
  19. package/dist/components/feedback/status-icon.d.ts +2 -0
  20. package/dist/components/feedback/status-icon.js +6 -5
  21. package/dist/components/feedback/toast.js +1 -1
  22. package/dist/components/files/drop-zone.js +1 -1
  23. package/dist/components/forms/category-selector.js +1 -1
  24. package/dist/components/forms/checkbox-group.js +1 -1
  25. package/dist/components/forms/checkbox.js +5 -3
  26. package/dist/components/forms/code-editor.d.ts +61 -0
  27. package/dist/components/forms/code-editor.js +382 -0
  28. package/dist/components/forms/combobox.js +1 -1
  29. package/dist/components/forms/date-field.js +1 -1
  30. package/dist/components/forms/dropdown.js +1 -1
  31. package/dist/components/forms/multi-select.js +1 -1
  32. package/dist/components/forms/number-input.js +5 -2
  33. package/dist/components/forms/radio-group.js +1 -1
  34. package/dist/components/forms/range-slider.js +1 -1
  35. package/dist/components/forms/slider.js +1 -1
  36. package/dist/components/forms/tile-group.js +1 -1
  37. package/dist/components/layout/sidebar-toggle-button.js +1 -1
  38. package/dist/components/navigation/accordion.js +1 -1
  39. package/dist/components/navigation/tabs.js +1 -1
  40. package/dist/components/output/code-block.js +1 -1
  41. package/dist/components/overlays/dialog.js +1 -1
  42. package/dist/components/overlays/drawer.js +1 -1
  43. package/dist/components/overlays/guide-tooltip.js +1 -1
  44. package/dist/components/overlays/popover.js +1 -1
  45. package/dist/components/overlays/tooltip.js +1 -1
  46. package/dist/core/form-associated.d.ts +1 -0
  47. package/dist/core/form-associated.js +3 -0
  48. package/dist/entries/code-editor.d.ts +1 -0
  49. package/dist/entries/code-editor.js +1 -0
  50. package/dist/foundations/icons/box-iconography.generated.d.ts +1 -472
  51. package/dist/foundations/icons/box-iconography.generated.js +2 -472
  52. package/dist/foundations/icons/glyphs/constants.d.ts +472 -0
  53. package/dist/foundations/icons/glyphs/constants.js +473 -0
  54. package/dist/foundations/icons/glyphs/index.d.ts +1 -1
  55. package/dist/foundations/icons/glyphs/index.js +1 -1
  56. package/dist/foundations/motion/scroll-pin.d.ts +10 -2
  57. package/dist/foundations/motion/scroll-pin.js +43 -7
  58. package/dist/foundations/motion/tokens.d.ts +1 -0
  59. package/dist/foundations/motion/tokens.js +1 -0
  60. package/dist/foundations/profiles/built-ins.js +8 -0
  61. package/dist/foundations/profiles/registry.d.ts +1 -0
  62. package/dist/foundations/profiles/registry.js +1 -0
  63. package/dist/foundations/profiles/types.d.ts +1 -0
  64. package/dist/foundations/status/index.d.ts +4 -2
  65. package/dist/foundations/status/index.js +10 -6
  66. package/dist/foundations/theming/controller.js +3 -1
  67. package/dist/foundations/tokens/box-defaults.d.ts +2 -0
  68. package/dist/foundations/tokens/box-defaults.js +32 -5
  69. package/dist/foundations/tokens/index.d.ts +1 -1
  70. package/dist/foundations/tokens/index.js +1 -1
  71. package/dist/index.d.ts +2 -1
  72. package/dist/index.js +2 -1
  73. package/dist/patterns/agent-chat/agent-chat.js +9 -10
  74. package/dist/patterns/agent-chat/controller.js +8 -4
  75. package/dist/patterns/agent-chat/ndjson.d.ts +1 -0
  76. package/dist/patterns/agent-chat/ndjson.js +20 -4
  77. package/dist/patterns/agent-chat/types.d.ts +7 -0
  78. package/dist/patterns/agent-workspace/agent-workspace.d.ts +13 -1
  79. package/dist/patterns/agent-workspace/agent-workspace.js +47 -15
  80. package/dist/patterns/agent-workspace/controller.d.ts +7 -1
  81. package/dist/patterns/agent-workspace/controller.js +41 -3
  82. package/dist/patterns/call-console/call-console.d.ts +10 -0
  83. package/dist/patterns/call-console/call-console.js +23 -8
  84. package/dist/patterns/call-console/controller.d.ts +2 -1
  85. package/dist/patterns/call-console/controller.js +5 -3
  86. package/dist/patterns/call-console/http-transport.js +13 -2
  87. package/dist/patterns/call-console/types.d.ts +1 -1
  88. package/dist/patterns/call-console/types.js +2 -2
  89. package/dist/patterns/comments/comment-thread.js +1 -1
  90. package/dist/patterns/content-explorer/adapters/action-menu.js +1 -1
  91. package/dist/patterns/content-explorer/adapters/list.js +1 -1
  92. package/dist/patterns/content-explorer/adapters/table.js +1 -1
  93. package/dist/patterns/content-explorer/adapters/toolbar.js +1 -1
  94. package/dist/patterns/content-uploader/content-uploader.js +1 -1
  95. package/dist/patterns/file-request/file-request-builder.js +1 -1
  96. package/dist/patterns/flow-builder/flow-builder.d.ts +2 -0
  97. package/dist/patterns/flow-builder/flow-builder.js +14 -8
  98. package/dist/patterns/flow-builder/model.d.ts +2 -0
  99. package/dist/patterns/flow-builder/model.js +3 -3
  100. package/dist/patterns/flow-builder/primitives.d.ts +1 -0
  101. package/dist/patterns/flow-builder/primitives.js +5 -4
  102. package/dist/patterns/governance/governance-panel.js +1 -1
  103. package/dist/patterns/insights/chart-panel.js +1 -1
  104. package/dist/patterns/insights/metric-card.js +3 -3
  105. package/dist/patterns/item/bulk-action-bar.js +1 -1
  106. package/dist/patterns/item/item-details-panel.js +1 -1
  107. package/dist/patterns/item/item-form.js +1 -1
  108. package/dist/patterns/item/preview-header.js +1 -1
  109. package/dist/patterns/metadata/metadata-filter-builder.js +1 -1
  110. package/dist/patterns/metadata/metadata-inspector.js +1 -1
  111. package/dist/patterns/preview/annotation-inspector.js +1 -1
  112. package/dist/patterns/preview/annotation-toolbar.js +1 -1
  113. package/dist/patterns/process-modeler/index.d.ts +2 -0
  114. package/dist/patterns/process-modeler/index.js +2 -0
  115. package/dist/patterns/process-modeler/model.d.ts +95 -0
  116. package/dist/patterns/process-modeler/model.js +113 -0
  117. package/dist/patterns/process-modeler/process-modeler.d.ts +82 -0
  118. package/dist/patterns/process-modeler/process-modeler.js +861 -0
  119. package/dist/patterns/run/progress.d.ts +1 -1
  120. package/dist/patterns/run/progress.js +1 -1
  121. package/dist/patterns/run/run-summary.js +18 -4
  122. package/dist/patterns/run/run-trace.js +19 -5
  123. package/dist/patterns/search/filter-bar.js +1 -1
  124. package/dist/patterns/search/saved-view-picker.js +1 -1
  125. package/dist/patterns/search/search-results-header.js +1 -1
  126. package/dist/patterns/share/invite-collaborators-modal.js +1 -1
  127. package/dist/patterns/share/permission-matrix.js +1 -1
  128. package/dist/patterns/share/share-panel.js +1 -1
  129. package/dist/patterns/share/unified-share-modal.js +1 -1
  130. package/dist/patterns/task/review-queue-item.js +1 -1
  131. package/dist/patterns/task/task-assignment-panel.js +1 -1
  132. package/dist/patterns/undo/index.js +5 -3
  133. package/docs/api-guidelines.md +284 -0
  134. package/docs/foundations/motion.md +83 -0
  135. package/docs/patterns/agent-ui-guidelines.md +57 -0
  136. package/docs/patterns/agent-ui.md +197 -0
  137. package/package.json +23 -2
@@ -39,6 +39,8 @@ export declare class FlowBuilder<N extends FlowNodeBase = FlowNode> extends Base
39
39
  private drawer;
40
40
  private error;
41
41
  static get observedAttributes(): string[];
42
+ get headingLevel(): number;
43
+ set headingLevel(value: number);
42
44
  get nodes(): N[];
43
45
  set nodes(value: N[]);
44
46
  /** How to read the host document; defaults to `body` / `branches` ({@link FlowNode}). */
@@ -1,4 +1,6 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
+ import { Drawer } from "../../components/overlays/drawer.js";
3
+ Drawer.register();
2
4
  import { announce } from "../../foundations/a11y/index.js";
3
5
  import { defaultFlowModel, nodeAtPath, nodeDescription, nodeTitle } from "./model.js";
4
6
  import { FLOW_SPINE_PARTS, InsertPoint, KIND_PICKER_PARTS } from "./primitives.js";
@@ -31,7 +33,9 @@ export class FlowBuilder extends BaseElement {
31
33
  inspector;
32
34
  drawer;
33
35
  error;
34
- static get observedAttributes() { return ["start-label", "end-label"]; }
36
+ static get observedAttributes() { return ["start-label", "end-label", "heading-level"]; }
37
+ get headingLevel() { const level = Number(this.getAttribute("heading-level") ?? 2); return Number.isInteger(level) && level >= 1 && level <= 6 ? level : 2; }
38
+ set headingLevel(value) { this.setAttribute("heading-level", String(value)); }
35
39
  get nodes() { return this.nodesValue; }
36
40
  set nodes(value) { this.nodesValue = value; this.refresh(); }
37
41
  /** How to read the host document; defaults to `body` / `branches` ({@link FlowNode}). */
@@ -83,15 +87,15 @@ export class FlowBuilder extends BaseElement {
83
87
  this.shadowRoot.innerHTML = `<style>
84
88
  :host{display:block;min-width:0;font:inherit;color:var(--boe-token-text-text,#222)}
85
89
  :host([hidden]){display:none!important}
86
- [part=layout]{display:grid;grid-template-columns:minmax(0,1fr) minmax(240px,320px);gap:24px;align-items:start}
90
+ [part=layout]{display:grid;grid-template-columns:minmax(0,1fr) minmax(var(--boe-flow-inspector-min-width,240px),var(--boe-flow-inspector-width,320px));gap:24px;align-items:start}
87
91
  [part=layout][data-narrow=true]{grid-template-columns:minmax(0,1fr)}
88
- aside{min-width:0;padding:16px;border:1px solid var(--boe-token-stroke-stroke,#ddd);border-radius:12px;background:var(--boe-token-surface-surface,#fff)}
92
+ [part=inspector]{min-width:0;position:sticky;top:var(--boe-flow-inspector-top,16px);max-height:calc(100dvh - var(--boe-flow-inspector-top,16px) - 16px);overflow:auto;box-sizing:border-box;padding:16px;border:1px solid var(--boe-token-stroke-stroke,#ddd);border-radius:12px;background:var(--boe-token-surface-surface,#fff)}
89
93
  [part=picker-popup]{position:fixed;z-index:1000;max-width:min(360px,calc(100vw - 24px));max-height:65vh;overflow:auto;padding:16px;background:var(--boe-token-surface-surface,#fff);border:1px solid var(--boe-token-stroke-stroke,#ddd);border-radius:12px;box-shadow:0 8px 32px #0003}
90
94
  [part=error]{color:var(--boe-token-text-status-text-error,#b92340);margin-bottom:16px;overflow-wrap:anywhere}
91
- [hidden]{display:none!important} h2{font:inherit;font-weight:650;margin:0 0 12px}
92
- </style><div part="error" hidden></div><div part="layout"><box-flow-spine exportparts="${FLOW_SPINE_PARTS.join(", ")}"></box-flow-spine><aside part="inspector"><box-kind-picker exportparts="${KIND_PICKER_PARTS.join(", ")}"></box-kind-picker><div part="editor"></div></aside></div><div part="picker-popup" hidden><box-kind-picker exportparts="${KIND_PICKER_PARTS.join(", ")}"></box-kind-picker></div><box-drawer position="bottom" size="large"></box-drawer>`;
95
+ [hidden]{display:none!important} [part=inspector-heading]{font:inherit;font-weight:650;margin:0 0 12px}
96
+ </style><div part="error" hidden></div><div part="layout"><box-flow-spine exportparts="${FLOW_SPINE_PARTS.join(", ")}"></box-flow-spine><div part="inspector" role="region" aria-label="Add a step"><box-kind-picker exportparts="${KIND_PICKER_PARTS.join(", ")}"></box-kind-picker><div part="editor"></div></div></div><div part="picker-popup" hidden><box-kind-picker exportparts="${KIND_PICKER_PARTS.join(", ")}"></box-kind-picker></div><box-drawer position="bottom" size="large"></box-drawer>`;
93
97
  this.spine = this.shadowRoot.querySelector("box-flow-spine");
94
- this.aside = this.shadowRoot.querySelector("aside");
98
+ this.aside = this.shadowRoot.querySelector("[part=inspector]");
95
99
  this.palette = this.aside.querySelector("box-kind-picker");
96
100
  this.inspector = this.aside.querySelector("[part=editor]");
97
101
  this.popup = this.shadowRoot.querySelector("[part=picker-popup]");
@@ -198,6 +202,7 @@ export class FlowBuilder extends BaseElement {
198
202
  this.spine.nodes = this.nodes;
199
203
  this.spine.catalog = this.catalog;
200
204
  this.spine.model = this.model;
205
+ this.spine.headingLevel = Math.min(6, this.headingLevel + 1);
201
206
  this.spine.startLabel = this.startLabel;
202
207
  this.spine.endLabel = this.endLabel;
203
208
  this.spine.selected = this.selected;
@@ -208,12 +213,13 @@ export class FlowBuilder extends BaseElement {
208
213
  this.updateInspector();
209
214
  }
210
215
  updateInspector() {
216
+ this.aside.setAttribute("aria-label", this.selected ? "Step editor" : "Add a step");
211
217
  this.aside.hidden = this.narrow;
212
218
  this.palette.hidden = Boolean(this.selected);
213
219
  const target = this.narrow ? this.drawer : this.aside;
214
220
  if (this.inspector.parentElement !== target)
215
221
  target.append(this.inspector);
216
- if (this.inspected === this.selected && this.renderedRenderer === this.renderer) {
222
+ if (this.inspected === this.selected && this.renderedRenderer === this.renderer && (!this.selected || this.headingEl?.tagName === `H${this.headingLevel}`)) {
217
223
  this.drawer.open = this.narrow && Boolean(this.selected);
218
224
  return;
219
225
  }
@@ -223,7 +229,7 @@ export class FlowBuilder extends BaseElement {
223
229
  this.inspected = this.selected;
224
230
  this.renderedRenderer = this.renderer;
225
231
  if (this.selected) {
226
- const heading = document.createElement("h2");
232
+ const heading = document.createElement(`h${this.headingLevel}`);
227
233
  heading.setAttribute("part", "inspector-heading");
228
234
  heading.textContent = nodeTitle(this.selected, this.catalog, this.model);
229
235
  this.inspector.append(heading);
@@ -33,6 +33,8 @@ export interface FlowChildList {
33
33
  * (selection, undo, validation paths) is preserved.
34
34
  */
35
35
  export interface FlowModel<N extends FlowNodeBase = FlowNodeBase> {
36
+ /** Catalog entry used to draw this node; does not change its document kind. */
37
+ kind?(node: N): string | undefined;
36
38
  /** Nested lists under `node`, in display order. */
37
39
  children(node: N): FlowChildList[];
38
40
  /** A distinct name for the node; falls back to its kind's label. */
@@ -8,10 +8,10 @@ export const defaultFlowModel = {
8
8
  description: node => node.description,
9
9
  status: node => node.status,
10
10
  };
11
- export const nodeTitle = (node, catalog = [], model = defaultFlowModel) => model.title?.(node) || catalog.find(kind => kind.kind === node.kind)?.label || "Step";
12
- export const nodeDescription = (node, catalog = [], model = defaultFlowModel) => model.description?.(node) || catalog.find(kind => kind.kind === node.kind)?.description || "";
11
+ export const nodeTitle = (node, catalog = [], model = defaultFlowModel) => model.title?.(node) || catalog.find(kind => kind.kind === (model.kind?.(node) ?? node.kind))?.label || "Step";
12
+ export const nodeDescription = (node, catalog = [], model = defaultFlowModel) => model.description?.(node) || catalog.find(kind => kind.kind === (model.kind?.(node) ?? node.kind))?.description || "";
13
13
  export function cardLabel(node, catalog = [], invalid = false, model = defaultFlowModel) {
14
- const kind = catalog.find(entry => entry.kind === node.kind);
14
+ const kind = catalog.find(entry => entry.kind === (model.kind?.(node) ?? node.kind));
15
15
  const title = nodeTitle(node, catalog, model);
16
16
  return [title, kind?.label !== title ? kind?.label : "", nodeDescription(node, catalog, model), model.status?.(node), invalid ? "Needs attention" : ""].filter(Boolean).join(". ");
17
17
  }
@@ -46,6 +46,7 @@ export declare class FlowSpine extends BaseElement {
46
46
  invalid: FlowNodeBase | null;
47
47
  startLabel: string;
48
48
  endLabel: string;
49
+ headingLevel: number;
49
50
  private cards;
50
51
  protected renderTemplate(): void;
51
52
  refresh(): void;
@@ -1,5 +1,5 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
- import { boeFocusVisibleStyles } from "../../foundations/tokens/index.js";
2
+ import { boeFocusVisibleStyles } from "../../foundations/tokens/interaction.js";
3
3
  import { cardLabel, defaultFlowModel, insertLabel, nodeDescription, nodeTitle } from "./model.js";
4
4
  const styles = `
5
5
  :host { display:block; min-width:0; color:var(--boe-token-text-text,#222); font:inherit; }
@@ -36,7 +36,7 @@ export class FlowCard extends BaseElement {
36
36
  this.update(); }
37
37
  focus(options) { this.shadowRoot?.querySelector("button")?.focus(options); }
38
38
  update() {
39
- const kind = this.catalog.find(kind => kind.kind === this.node.kind);
39
+ const kind = this.catalog.find(kind => kind.kind === (this.model.kind?.(this.node) ?? this.node.kind));
40
40
  const title = nodeTitle(this.node, this.catalog, this.model);
41
41
  const button = this.shadowRoot.querySelector("button");
42
42
  button.setAttribute("aria-pressed", String(this.selected));
@@ -148,8 +148,9 @@ export class FlowSpine extends BaseElement {
148
148
  invalid = null;
149
149
  startLabel = "Flow starts";
150
150
  endLabel = "Flow ends";
151
+ headingLevel = 3;
151
152
  cards = new Map();
152
- renderTemplate() { this.shadowRoot.innerHTML = `<style>${styles} [part=spine]{display:grid;gap:0;min-width:0} [part=branches]{display:flex;gap:16px;overflow-x:auto;max-width:100%;padding:8px} [part=branch]{flex:1 0 240px;min-width:0} [part=body]{margin:0 0 0 16px;border-inline-start:2px solid var(--boe-token-stroke-stroke,#ddd);padding:8px 12px} [part=endpoint]{text-align:center;font-weight:600;padding:12px} [part=branch-header]{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:1em 0} h3{font:inherit;font-weight:600;margin:0} [part=branch-remove],[part=branch-add]{border:1px solid var(--boe-token-stroke-stroke,#ddd);border-radius:16px;background:var(--boe-token-surface-surface,#fff);padding:4px 10px} [part=branch-add]{justify-self:center;margin:4px 0}</style><div part="spine"></div>`; }
153
+ renderTemplate() { this.shadowRoot.innerHTML = `<style>${styles} [part=spine]{display:grid;gap:0;min-width:0} [part=branches]{display:flex;gap:16px;overflow-x:auto;max-width:100%;padding:8px} [part=branch]{flex:1 0 240px;min-width:0} [part=body]{margin:0 0 0 16px;border-inline-start:2px solid var(--boe-token-stroke-stroke,#ddd);padding:8px 12px} [part=endpoint]{text-align:center;font-weight:600;padding:12px} [part=branch-header]{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:1em 0} [part=branch-label]{font:inherit;font-weight:600;margin:0} [part=branch-remove],[part=branch-add]{border:1px solid var(--boe-token-stroke-stroke,#ddd);border-radius:16px;background:var(--boe-token-surface-surface,#fff);padding:4px 10px} [part=branch-add]{justify-self:center;margin:4px 0}</style><div part="spine"></div>`; }
153
154
  refresh() { if (this.isRendered)
154
155
  this.update(); }
155
156
  /** Re-render one card after its fields change, without rebuilding the spine. */
@@ -208,7 +209,7 @@ export class FlowSpine extends BaseElement {
208
209
  column.setAttribute("aria-label", label);
209
210
  const header = document.createElement("div");
210
211
  header.setAttribute("part", "branch-header");
211
- const heading = document.createElement("h3");
212
+ const heading = document.createElement(`h${this.headingLevel}`);
212
213
  heading.setAttribute("part", "branch-label");
213
214
  heading.textContent = label;
214
215
  header.append(heading);
@@ -1,6 +1,6 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
2
  import { boePanel } from "../../foundations/geometry/index.js";
3
- import { boeBrandInteractiveStyles, boeNeutralInteractiveStyles, } from "../../foundations/tokens/index.js";
3
+ import { boeBrandInteractiveStyles, boeNeutralInteractiveStyles, } from "../../foundations/tokens/interaction.js";
4
4
  const DEFAULT_TAG_NAME = "box-governance-panel";
5
5
  const escapeHtml = (value) => value
6
6
  .replaceAll("&", "&amp;")
@@ -1,6 +1,6 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
2
  import { boePanel } from "../../foundations/geometry/index.js";
3
- import { boeBrandInteractiveStyles, boeNeutralInteractiveStyles, } from "../../foundations/tokens/index.js";
3
+ import { boeBrandInteractiveStyles, boeNeutralInteractiveStyles, } from "../../foundations/tokens/interaction.js";
4
4
  const DEFAULT_TAG_NAME = "box-chart-panel";
5
5
  const escapeHtml = (value) => value
6
6
  .replaceAll("&", "&amp;")
@@ -1,6 +1,6 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
2
  import { boePanel } from "../../foundations/geometry/index.js";
3
- import { boeBrandInteractiveStyles, boeNeutralInteractiveStyles, } from "../../foundations/tokens/index.js";
3
+ import { boeBrandInteractiveStyles, boeNeutralInteractiveStyles, } from "../../foundations/tokens/interaction.js";
4
4
  const DEFAULT_TAG_NAME = "box-metric-card";
5
5
  const escapeHtml = (value) => value
6
6
  .replaceAll("&", "&amp;")
@@ -39,7 +39,7 @@ const elementStyles = `
39
39
  font-size: 0.76rem;
40
40
  font-weight: 700;
41
41
  letter-spacing: 0.08em;
42
- text-transform: uppercase;
42
+ text-transform: none;
43
43
  color: var(--boe-token-text-text-secondary, #6f6f6f);
44
44
  }
45
45
 
@@ -68,7 +68,7 @@ const elementStyles = `
68
68
  font-size: 0.74rem;
69
69
  font-weight: 700;
70
70
  letter-spacing: 0.05em;
71
- text-transform: uppercase;
71
+ text-transform: none;
72
72
  }
73
73
 
74
74
  [part="value"] {
@@ -1,6 +1,6 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
2
  import { applyRovingTabindex, handleRovingKeydown } from "../../foundations/a11y/index.js";
3
- import { boeNeutralInteractiveStyles } from "../../foundations/tokens/index.js";
3
+ import { boeNeutralInteractiveStyles } from "../../foundations/tokens/interaction.js";
4
4
  import { boeMotionDuration, boeMotionEasing } from "../../foundations/motion/index.js";
5
5
  import { boePanel } from "../../foundations/geometry/index.js";
6
6
  const DEFAULT_TAG_NAME = "box-bulk-action-bar";
@@ -1,6 +1,6 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
2
  import { boePanel, boeRadius } from "../../foundations/geometry/index.js";
3
- import { boeBrandInteractiveStyles, boeNeutralInteractiveStyles, } from "../../foundations/tokens/index.js";
3
+ import { boeBrandInteractiveStyles, boeNeutralInteractiveStyles, } from "../../foundations/tokens/interaction.js";
4
4
  const DEFAULT_TAG_NAME = "box-item-details-panel";
5
5
  const escapeHtml = (value) => value
6
6
  .replaceAll("&", "&amp;")
@@ -1,6 +1,6 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
2
  import { boePanel, boeRadius } from "../../foundations/geometry/index.js";
3
- import { boeBrandInteractiveStyles, boeFocusVisibleStyles, boeNeutralInteractiveStyles, } from "../../foundations/tokens/index.js";
3
+ import { boeBrandInteractiveStyles, boeFocusVisibleStyles, boeNeutralInteractiveStyles, } from "../../foundations/tokens/interaction.js";
4
4
  const DEFAULT_TAG_NAME = "box-item-form";
5
5
  const escapeHtml = (value) => value
6
6
  .replaceAll("&", "&amp;")
@@ -1,6 +1,6 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
2
  import { boePanel } from "../../foundations/geometry/index.js";
3
- import { boeBrandInteractiveStyles, boeNeutralInteractiveStyles, } from "../../foundations/tokens/index.js";
3
+ import { boeBrandInteractiveStyles, boeNeutralInteractiveStyles, } from "../../foundations/tokens/interaction.js";
4
4
  const DEFAULT_TAG_NAME = "box-preview-header";
5
5
  const escapeHtml = (value) => value
6
6
  .replaceAll("&", "&amp;")
@@ -1,5 +1,5 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
- import { boeNeutralInteractiveStyles } from "../../foundations/tokens/index.js";
2
+ import { boeNeutralInteractiveStyles } from "../../foundations/tokens/interaction.js";
3
3
  import { boePanel, boeRadius } from "../../foundations/geometry/index.js";
4
4
  const DEFAULT_TAG_NAME = "box-metadata-filter-builder";
5
5
  const escapeHtml = (value) => value
@@ -1,5 +1,5 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
- import { boeNeutralInteractiveStyles } from "../../foundations/tokens/index.js";
2
+ import { boeNeutralInteractiveStyles } from "../../foundations/tokens/interaction.js";
3
3
  import { boePanel } from "../../foundations/geometry/index.js";
4
4
  const DEFAULT_TAG_NAME = "box-metadata-inspector";
5
5
  const escapeHtml = (value) => value
@@ -1,6 +1,6 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
2
  import { boePanel, boeRadius } from "../../foundations/geometry/index.js";
3
- import { boeBrandInteractiveStyles, boeNeutralInteractiveStyles, } from "../../foundations/tokens/index.js";
3
+ import { boeBrandInteractiveStyles, boeNeutralInteractiveStyles, } from "../../foundations/tokens/interaction.js";
4
4
  const DEFAULT_TAG_NAME = "box-annotation-inspector";
5
5
  const escapeHtml = (value) => value
6
6
  .replaceAll("&", "&amp;")
@@ -1,7 +1,7 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
2
  import { applyRovingTabindex, handleRovingKeydown } from "../../foundations/a11y/index.js";
3
3
  import { boePanel, boeRadius } from "../../foundations/geometry/index.js";
4
- import { boeBrandInteractiveStyles, boeNeutralInteractiveStyles, } from "../../foundations/tokens/index.js";
4
+ import { boeBrandInteractiveStyles, boeNeutralInteractiveStyles, } from "../../foundations/tokens/interaction.js";
5
5
  const DEFAULT_TAG_NAME = "box-annotation-toolbar";
6
6
  const escapeHtml = (value) => value
7
7
  .replaceAll("&", "&amp;")
@@ -0,0 +1,2 @@
1
+ export * from "./model.js";
2
+ export * from "./process-modeler.js";
@@ -0,0 +1,2 @@
1
+ export * from "./model.js";
2
+ export * from "./process-modeler.js";
@@ -0,0 +1,95 @@
1
+ import type { FlowKind, NodePath } from "../flow-builder/model.js";
2
+ export interface ProcessBox<N = unknown> {
3
+ id: string;
4
+ node: N;
5
+ kind: string;
6
+ title: string;
7
+ description?: string;
8
+ path?: NodePath;
9
+ /** A frame draws behind its children and connects as one box. */
10
+ frame?: boolean;
11
+ parentId?: string;
12
+ }
13
+ export interface ProcessLine {
14
+ id: string;
15
+ from: string;
16
+ to: string;
17
+ label?: string;
18
+ dashed?: boolean;
19
+ points?: {
20
+ x: number;
21
+ y: number;
22
+ }[];
23
+ }
24
+ export interface ProcessProjection<N = unknown> {
25
+ boxes: readonly ProcessBox<N>[];
26
+ lines: readonly ProcessLine[];
27
+ }
28
+ export interface ProcessModel<D = unknown, N = unknown> {
29
+ project(document: D): ProcessProjection<N>;
30
+ }
31
+ export interface BoxPosition {
32
+ x: number;
33
+ y: number;
34
+ width?: number;
35
+ height?: number;
36
+ }
37
+ export interface ProcessLayout {
38
+ boxes: Record<string, BoxPosition>;
39
+ notes?: {
40
+ id: string;
41
+ text: string;
42
+ x: number;
43
+ y: number;
44
+ }[];
45
+ sections?: {
46
+ id: string;
47
+ title: string;
48
+ x: number;
49
+ y: number;
50
+ width: number;
51
+ height: number;
52
+ }[];
53
+ lines?: Record<string, {
54
+ x: number;
55
+ y: number;
56
+ }[]>;
57
+ }
58
+ export interface ProcessCheck {
59
+ message: string;
60
+ boxId?: string;
61
+ path?: NodePath;
62
+ }
63
+ export interface ProcessEdit {
64
+ type: "add" | "delete" | "connect" | "disconnect" | "insert";
65
+ boxId?: string;
66
+ from?: string;
67
+ to?: string;
68
+ lineId?: string;
69
+ kind?: FlowKind;
70
+ position?: BoxPosition;
71
+ }
72
+ export interface ReversibleProcessEdit {
73
+ undo(): void;
74
+ redo(): void;
75
+ }
76
+ /** Host applies the edit, then calls accept with its inverse and replay. */
77
+ export interface ProcessEditRequest extends ProcessEdit {
78
+ accept(command: ReversibleProcessEdit): void;
79
+ }
80
+ export declare function validateProjection<N>(projection: ProcessProjection<N>): void;
81
+ /** Deterministic fallback, preserving host-authored positions. */
82
+ export declare function completeLayout<N>(projection: ProcessProjection<N>, layout: ProcessLayout): ProcessLayout;
83
+ /** Bounded history shared by layout edits and host-accepted document commands. */
84
+ export declare class ProcessHistory {
85
+ private replayingInternal;
86
+ private past;
87
+ private future;
88
+ get canUndo(): boolean;
89
+ get canRedo(): boolean;
90
+ get replaying(): boolean;
91
+ record(command: ReversibleProcessEdit): void;
92
+ undo(): void;
93
+ redo(): void;
94
+ clear(): void;
95
+ }
@@ -0,0 +1,113 @@
1
+ export function validateProjection(projection) {
2
+ const ids = new Set();
3
+ for (const box of projection.boxes) {
4
+ if (!box.id || ids.has(box.id))
5
+ throw new TypeError("Process boxes need unique non-empty IDs");
6
+ ids.add(box.id);
7
+ }
8
+ for (const box of projection.boxes) {
9
+ const ancestors = new Set([box.id]);
10
+ let parent = box.parentId;
11
+ while (parent) {
12
+ const frame = projection.boxes.find((candidate) => candidate.id === parent);
13
+ if (!frame?.frame || ancestors.has(parent))
14
+ throw new TypeError("Frame parents must exist and cannot form a cycle");
15
+ ancestors.add(parent);
16
+ parent = frame.parentId;
17
+ }
18
+ }
19
+ const lines = new Set();
20
+ for (const line of projection.lines) {
21
+ if (!line.id ||
22
+ lines.has(line.id) ||
23
+ !ids.has(line.from) ||
24
+ !ids.has(line.to))
25
+ throw new TypeError("Process lines need unique IDs and existing endpoints");
26
+ lines.add(line.id);
27
+ }
28
+ }
29
+ /** Deterministic fallback, preserving host-authored positions. */
30
+ export function completeLayout(projection, layout) {
31
+ const boxes = { ...layout.boxes };
32
+ const sizes = new Map();
33
+ const measure = (box) => {
34
+ const children = projection.boxes
35
+ .filter((child) => child.parentId === box.id)
36
+ .map(measure);
37
+ const size = {
38
+ width: Math.max(box.frame ? 320 : 220, ...children.map((child) => child.width + 40)),
39
+ height: box.frame
40
+ ? Math.max(180, 64 + children.reduce((sum, child) => sum + child.height + 24, 0))
41
+ : 96,
42
+ };
43
+ sizes.set(box.id, size);
44
+ return size;
45
+ };
46
+ const roots = projection.boxes.filter((box) => !box.parentId);
47
+ roots.forEach(measure);
48
+ const place = (siblings, x, top) => {
49
+ let y = top;
50
+ for (const box of siblings) {
51
+ const size = sizes.get(box.id);
52
+ boxes[box.id] ??= { x, y, ...size };
53
+ const position = boxes[box.id];
54
+ place(projection.boxes.filter((child) => child.parentId === box.id), position.x + 20, position.y + 64);
55
+ y += (position.height ?? size.height) + 60;
56
+ }
57
+ };
58
+ place(roots, 40, 40);
59
+ return { ...layout, boxes };
60
+ }
61
+ /** Bounded history shared by layout edits and host-accepted document commands. */
62
+ export class ProcessHistory {
63
+ replayingInternal = false;
64
+ past = [];
65
+ future = [];
66
+ get canUndo() {
67
+ return this.past.length > 0;
68
+ }
69
+ get canRedo() {
70
+ return this.future.length > 0;
71
+ }
72
+ get replaying() {
73
+ return this.replayingInternal;
74
+ }
75
+ record(command) {
76
+ this.past.push(command);
77
+ if (this.past.length > 100)
78
+ this.past.shift();
79
+ this.future = [];
80
+ }
81
+ undo() {
82
+ const command = this.past.at(-1);
83
+ if (!command)
84
+ return;
85
+ this.replayingInternal = true;
86
+ try {
87
+ command.undo();
88
+ }
89
+ finally {
90
+ this.replayingInternal = false;
91
+ }
92
+ this.past.pop();
93
+ this.future.push(command);
94
+ }
95
+ redo() {
96
+ const command = this.future.at(-1);
97
+ if (!command)
98
+ return;
99
+ this.replayingInternal = true;
100
+ try {
101
+ command.redo();
102
+ }
103
+ finally {
104
+ this.replayingInternal = false;
105
+ }
106
+ this.future.pop();
107
+ this.past.push(command);
108
+ }
109
+ clear() {
110
+ this.past = [];
111
+ this.future = [];
112
+ }
113
+ }
@@ -0,0 +1,82 @@
1
+ import { BaseElement } from "../../core/index.js";
2
+ import type { FlowKind, NodePath } from "../flow-builder/model.js";
3
+ import { ProcessHistory, type ProcessBox, type ProcessCheck, type ProcessEdit, type ProcessLayout, type ProcessModel, type ProcessProjection } from "./model.js";
4
+ /** Projects host documents without owning workflow schemas or persistence. */
5
+ export declare class ProcessModeler<D = ProcessProjection, N = unknown> extends BaseElement {
6
+ static readonly tagName = "box-process-modeler";
7
+ static get observedAttributes(): string[];
8
+ private documentValue?;
9
+ private modelValue;
10
+ private projection;
11
+ private layoutValue;
12
+ private catalogValue;
13
+ private selectedId;
14
+ private connecting;
15
+ private checks;
16
+ private renderer?;
17
+ private cleanupInspector?;
18
+ private inspected?;
19
+ private inspectedId?;
20
+ private historyValue;
21
+ private viewport;
22
+ private pointers;
23
+ private drag?;
24
+ private pinchDistance;
25
+ private gestureZoom;
26
+ get document(): D | undefined;
27
+ get history(): ProcessHistory;
28
+ set history(value: ProcessHistory);
29
+ set document(value: D | undefined);
30
+ get model(): ProcessModel<D, N>;
31
+ set model(value: ProcessModel<D, N>);
32
+ get layout(): ProcessLayout;
33
+ set layout(value: ProcessLayout);
34
+ get catalog(): readonly FlowKind[];
35
+ set catalog(value: readonly FlowKind[]);
36
+ get locked(): boolean;
37
+ set locked(value: boolean);
38
+ get snapToGrid(): boolean;
39
+ set snapToGrid(value: boolean);
40
+ get selected(): ProcessBox<N> | null;
41
+ get renderInspector(): ((node: N, container: HTMLElement) => void | (() => void)) | undefined;
42
+ set renderInspector(value: ((node: N, container: HTMLElement) => void | (() => void)) | undefined);
43
+ disconnectedCallback(): void;
44
+ refresh(): void;
45
+ select(id: string | null): void;
46
+ setValidation(checks: readonly ProcessCheck[]): void;
47
+ setValidationAtPath(message: string, path: NodePath): void;
48
+ requestEdit(edit: ProcessEdit): void;
49
+ undo(): void;
50
+ redo(): void;
51
+ private commitLayout;
52
+ move(id: string, x: number, y: number): void;
53
+ private translatedLayout;
54
+ tidy(): void;
55
+ resize(id: string, width: number, height: number): void;
56
+ routeLine(id: string, points: readonly {
57
+ x: number;
58
+ y: number;
59
+ }[]): void;
60
+ setNote(note: NonNullable<ProcessLayout["notes"]>[number] | null, id?: string | undefined): void;
61
+ setSection(section: NonNullable<ProcessLayout["sections"]>[number] | null, id?: string | undefined): void;
62
+ zoomBy(factor: number): void;
63
+ fit(): void;
64
+ private bounds;
65
+ protected renderTemplate(): void;
66
+ protected setupListeners(): void;
67
+ private onKey;
68
+ private pointerDown;
69
+ private distance;
70
+ private pointerMove;
71
+ private pointerEnd;
72
+ protected update(): void;
73
+ private renderWorld;
74
+ private place;
75
+ private renderPalette;
76
+ private renderChecks;
77
+ private renderSelection;
78
+ private updateToolbar;
79
+ private paintViewport;
80
+ private focusBox;
81
+ private setStatus;
82
+ }