@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.
- package/README.md +15 -12
- package/dist/components/actions/button.js +3 -3
- package/dist/components/actions/menu-item.js +1 -1
- package/dist/components/actions/menu.js +1 -1
- package/dist/components/actions/segmented-control.d.ts +1 -0
- package/dist/components/actions/segmented-control.js +20 -6
- package/dist/components/collections/carousel.js +1 -1
- package/dist/components/collections/draggable-list.js +1 -1
- package/dist/components/collections/grid-view.js +1 -1
- package/dist/components/collections/pagination.js +1 -1
- package/dist/components/collections/result-blocks.d.ts +13 -1
- package/dist/components/collections/result-blocks.js +22 -10
- package/dist/components/collections/tree-grid.js +1 -1
- package/dist/components/feedback/alert.js +2 -2
- package/dist/components/feedback/chip.js +1 -1
- package/dist/components/feedback/empty-state.js +1 -1
- package/dist/components/feedback/nudge.js +1 -1
- package/dist/components/feedback/progress-bar.js +2 -2
- package/dist/components/feedback/status-icon.d.ts +2 -0
- package/dist/components/feedback/status-icon.js +6 -5
- package/dist/components/feedback/toast.js +1 -1
- package/dist/components/files/drop-zone.js +1 -1
- package/dist/components/forms/category-selector.js +1 -1
- package/dist/components/forms/checkbox-group.js +1 -1
- package/dist/components/forms/checkbox.js +5 -3
- package/dist/components/forms/code-editor.d.ts +61 -0
- package/dist/components/forms/code-editor.js +382 -0
- package/dist/components/forms/combobox.js +1 -1
- package/dist/components/forms/date-field.js +1 -1
- package/dist/components/forms/dropdown.js +1 -1
- package/dist/components/forms/multi-select.js +1 -1
- package/dist/components/forms/number-input.js +5 -2
- package/dist/components/forms/radio-group.js +1 -1
- package/dist/components/forms/range-slider.js +1 -1
- package/dist/components/forms/slider.js +1 -1
- package/dist/components/forms/tile-group.js +1 -1
- package/dist/components/layout/sidebar-toggle-button.js +1 -1
- package/dist/components/navigation/accordion.js +1 -1
- package/dist/components/navigation/tabs.js +1 -1
- package/dist/components/output/code-block.js +1 -1
- package/dist/components/overlays/dialog.js +1 -1
- package/dist/components/overlays/drawer.js +1 -1
- package/dist/components/overlays/guide-tooltip.js +1 -1
- package/dist/components/overlays/popover.js +1 -1
- package/dist/components/overlays/tooltip.js +1 -1
- package/dist/core/form-associated.d.ts +1 -0
- package/dist/core/form-associated.js +3 -0
- package/dist/entries/code-editor.d.ts +1 -0
- package/dist/entries/code-editor.js +1 -0
- package/dist/foundations/icons/box-iconography.generated.d.ts +1 -472
- package/dist/foundations/icons/box-iconography.generated.js +2 -472
- package/dist/foundations/icons/glyphs/constants.d.ts +472 -0
- package/dist/foundations/icons/glyphs/constants.js +473 -0
- package/dist/foundations/icons/glyphs/index.d.ts +1 -1
- package/dist/foundations/icons/glyphs/index.js +1 -1
- package/dist/foundations/motion/scroll-pin.d.ts +10 -2
- package/dist/foundations/motion/scroll-pin.js +43 -7
- package/dist/foundations/motion/tokens.d.ts +1 -0
- package/dist/foundations/motion/tokens.js +1 -0
- package/dist/foundations/profiles/built-ins.js +8 -0
- package/dist/foundations/profiles/registry.d.ts +1 -0
- package/dist/foundations/profiles/registry.js +1 -0
- package/dist/foundations/profiles/types.d.ts +1 -0
- package/dist/foundations/status/index.d.ts +4 -2
- package/dist/foundations/status/index.js +10 -6
- package/dist/foundations/theming/controller.js +3 -1
- package/dist/foundations/tokens/box-defaults.d.ts +2 -0
- package/dist/foundations/tokens/box-defaults.js +32 -5
- package/dist/foundations/tokens/index.d.ts +1 -1
- package/dist/foundations/tokens/index.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/patterns/agent-chat/agent-chat.js +9 -10
- package/dist/patterns/agent-chat/controller.js +8 -4
- package/dist/patterns/agent-chat/ndjson.d.ts +1 -0
- package/dist/patterns/agent-chat/ndjson.js +20 -4
- package/dist/patterns/agent-chat/types.d.ts +7 -0
- package/dist/patterns/agent-workspace/agent-workspace.d.ts +13 -1
- package/dist/patterns/agent-workspace/agent-workspace.js +47 -15
- package/dist/patterns/agent-workspace/controller.d.ts +7 -1
- package/dist/patterns/agent-workspace/controller.js +41 -3
- package/dist/patterns/call-console/call-console.d.ts +10 -0
- package/dist/patterns/call-console/call-console.js +23 -8
- package/dist/patterns/call-console/controller.d.ts +2 -1
- package/dist/patterns/call-console/controller.js +5 -3
- package/dist/patterns/call-console/http-transport.js +13 -2
- package/dist/patterns/call-console/types.d.ts +1 -1
- package/dist/patterns/call-console/types.js +2 -2
- package/dist/patterns/comments/comment-thread.js +1 -1
- package/dist/patterns/content-explorer/adapters/action-menu.js +1 -1
- package/dist/patterns/content-explorer/adapters/list.js +1 -1
- package/dist/patterns/content-explorer/adapters/table.js +1 -1
- package/dist/patterns/content-explorer/adapters/toolbar.js +1 -1
- package/dist/patterns/content-uploader/content-uploader.js +1 -1
- package/dist/patterns/file-request/file-request-builder.js +1 -1
- package/dist/patterns/flow-builder/flow-builder.d.ts +2 -0
- package/dist/patterns/flow-builder/flow-builder.js +14 -8
- package/dist/patterns/flow-builder/model.d.ts +2 -0
- package/dist/patterns/flow-builder/model.js +3 -3
- package/dist/patterns/flow-builder/primitives.d.ts +1 -0
- package/dist/patterns/flow-builder/primitives.js +5 -4
- package/dist/patterns/governance/governance-panel.js +1 -1
- package/dist/patterns/insights/chart-panel.js +1 -1
- package/dist/patterns/insights/metric-card.js +3 -3
- package/dist/patterns/item/bulk-action-bar.js +1 -1
- package/dist/patterns/item/item-details-panel.js +1 -1
- package/dist/patterns/item/item-form.js +1 -1
- package/dist/patterns/item/preview-header.js +1 -1
- package/dist/patterns/metadata/metadata-filter-builder.js +1 -1
- package/dist/patterns/metadata/metadata-inspector.js +1 -1
- package/dist/patterns/preview/annotation-inspector.js +1 -1
- package/dist/patterns/preview/annotation-toolbar.js +1 -1
- package/dist/patterns/process-modeler/index.d.ts +2 -0
- package/dist/patterns/process-modeler/index.js +2 -0
- package/dist/patterns/process-modeler/model.d.ts +95 -0
- package/dist/patterns/process-modeler/model.js +113 -0
- package/dist/patterns/process-modeler/process-modeler.d.ts +82 -0
- package/dist/patterns/process-modeler/process-modeler.js +861 -0
- package/dist/patterns/run/progress.d.ts +1 -1
- package/dist/patterns/run/progress.js +1 -1
- package/dist/patterns/run/run-summary.js +18 -4
- package/dist/patterns/run/run-trace.js +19 -5
- package/dist/patterns/search/filter-bar.js +1 -1
- package/dist/patterns/search/saved-view-picker.js +1 -1
- package/dist/patterns/search/search-results-header.js +1 -1
- package/dist/patterns/share/invite-collaborators-modal.js +1 -1
- package/dist/patterns/share/permission-matrix.js +1 -1
- package/dist/patterns/share/share-panel.js +1 -1
- package/dist/patterns/share/unified-share-modal.js +1 -1
- package/dist/patterns/task/review-queue-item.js +1 -1
- package/dist/patterns/task/task-assignment-panel.js +1 -1
- package/dist/patterns/undo/index.js +5 -3
- package/docs/api-guidelines.md +284 -0
- package/docs/foundations/motion.md +83 -0
- package/docs/patterns/agent-ui-guidelines.md +57 -0
- package/docs/patterns/agent-ui.md +197 -0
- 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
|
-
|
|
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}
|
|
92
|
-
</style><div part="error" hidden></div><div part="layout"><box-flow-spine exportparts="${FLOW_SPINE_PARTS.join(", ")}"></box-flow-spine><
|
|
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("
|
|
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(
|
|
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
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseElement } from "../../core/index.js";
|
|
2
|
-
import { boeFocusVisibleStyles } from "../../foundations/tokens/
|
|
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}
|
|
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(
|
|
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/
|
|
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("&", "&")
|
|
@@ -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/
|
|
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("&", "&")
|
|
@@ -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/
|
|
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("&", "&")
|
|
@@ -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:
|
|
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:
|
|
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/
|
|
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/
|
|
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("&", "&")
|
|
@@ -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/
|
|
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("&", "&")
|
|
@@ -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/
|
|
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("&", "&")
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseElement } from "../../core/index.js";
|
|
2
|
-
import { boeNeutralInteractiveStyles } from "../../foundations/tokens/
|
|
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/
|
|
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/
|
|
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("&", "&")
|
|
@@ -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/
|
|
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("&", "&")
|
|
@@ -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
|
+
}
|