@unofficialbox/box-open-elements 0.21.0 → 0.23.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 -12
- package/dist/components/actions/menu-item.js +1 -1
- package/dist/components/actions/menu.js +1 -1
- 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 +1 -1
- 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/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 +1 -1
- 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 +1 -1
- 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/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 +1 -1
- package/dist/index.js +1 -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 +45 -14
- package/dist/patterns/flow-builder/flow-builder.js +54 -11
- package/dist/patterns/flow-builder/model.d.ts +57 -9
- package/dist/patterns/flow-builder/model.js +20 -8
- package/dist/patterns/flow-builder/primitives.d.ts +17 -7
- package/dist/patterns/flow-builder/primitives.js +80 -16
- 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 +1 -1
- 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/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 +6 -2
|
@@ -3,17 +3,27 @@ export class ScrollPinController {
|
|
|
3
3
|
viewport;
|
|
4
4
|
onChange;
|
|
5
5
|
pinned = true;
|
|
6
|
+
behind = false;
|
|
6
7
|
cleanup = [];
|
|
7
8
|
observer;
|
|
8
9
|
pointer = false;
|
|
9
10
|
lastTop = 0;
|
|
11
|
+
lastHeight = 0;
|
|
12
|
+
content;
|
|
13
|
+
lastNotified;
|
|
10
14
|
touchY = 0;
|
|
11
15
|
constructor(viewport, onChange = () => { }) {
|
|
12
16
|
this.viewport = viewport;
|
|
13
17
|
this.onChange = onChange;
|
|
18
|
+
this.content = viewport;
|
|
14
19
|
}
|
|
15
20
|
connect(content = this.viewport) {
|
|
16
21
|
this.disconnect();
|
|
22
|
+
this.content = content;
|
|
23
|
+
this.lastHeight = content.scrollHeight;
|
|
24
|
+
this.lastTop = this.viewport.scrollTop;
|
|
25
|
+
this.behind = false;
|
|
26
|
+
this.lastNotified = undefined;
|
|
17
27
|
const on = (kind, fn) => {
|
|
18
28
|
this.viewport.addEventListener(kind, fn);
|
|
19
29
|
this.cleanup.push(() => this.viewport.removeEventListener(kind, fn));
|
|
@@ -25,16 +35,25 @@ export class ScrollPinController {
|
|
|
25
35
|
on("touchstart", e => { this.touchY = e.touches[0]?.clientY ?? 0; });
|
|
26
36
|
on("touchmove", e => { const y = e.touches[0]?.clientY ?? this.touchY; if (y > this.touchY)
|
|
27
37
|
this.unpin(); this.touchY = y; });
|
|
28
|
-
on("pointerdown",
|
|
38
|
+
on("pointerdown", e => {
|
|
39
|
+
const bounds = this.viewport.getBoundingClientRect();
|
|
40
|
+
const gutter = Math.max(0, bounds.width - this.viewport.clientWidth);
|
|
41
|
+
this.pointer = gutter > 0 && (e.clientX < bounds.left + gutter || e.clientX > bounds.right - gutter);
|
|
42
|
+
this.lastTop = this.viewport.scrollTop;
|
|
43
|
+
});
|
|
29
44
|
const release = () => { this.pointer = false; };
|
|
30
45
|
this.viewport.ownerDocument.addEventListener("pointerup", release);
|
|
31
46
|
this.cleanup.push(() => this.viewport.ownerDocument.removeEventListener("pointerup", release));
|
|
47
|
+
this.viewport.ownerDocument.addEventListener("pointercancel", release);
|
|
48
|
+
this.cleanup.push(() => this.viewport.ownerDocument.removeEventListener("pointercancel", release));
|
|
32
49
|
on("scroll", () => {
|
|
33
50
|
if (this.pointer && this.viewport.scrollTop < this.lastTop)
|
|
34
51
|
this.unpin();
|
|
35
52
|
this.lastTop = this.viewport.scrollTop;
|
|
36
|
-
if (this.atBottom())
|
|
53
|
+
if (this.atBottom()) {
|
|
37
54
|
this.pinned = true;
|
|
55
|
+
this.behind = false;
|
|
56
|
+
}
|
|
38
57
|
this.notify();
|
|
39
58
|
});
|
|
40
59
|
if (typeof ResizeObserver !== "undefined") {
|
|
@@ -45,16 +64,33 @@ export class ScrollPinController {
|
|
|
45
64
|
}
|
|
46
65
|
}
|
|
47
66
|
atBottom() { return this.viewport.scrollHeight - this.viewport.clientHeight - this.viewport.scrollTop < 40; }
|
|
48
|
-
notify() {
|
|
67
|
+
notify() {
|
|
68
|
+
const state = { pinned: this.pinned, behind: this.behind };
|
|
69
|
+
if (this.lastNotified?.pinned === state.pinned && this.lastNotified.behind === state.behind)
|
|
70
|
+
return;
|
|
71
|
+
this.lastNotified = state;
|
|
72
|
+
this.onChange(state);
|
|
73
|
+
}
|
|
49
74
|
unpin() { this.pinned = false; this.notify(); }
|
|
50
|
-
contentChanged(newMessage = false) {
|
|
51
|
-
|
|
52
|
-
|
|
75
|
+
contentChanged(newMessage = false) {
|
|
76
|
+
const height = this.content.scrollHeight;
|
|
77
|
+
if (newMessage) {
|
|
78
|
+
this.pinned = true;
|
|
79
|
+
this.behind = false;
|
|
80
|
+
}
|
|
81
|
+
else if (!this.pinned && height > this.lastHeight)
|
|
82
|
+
this.behind = true;
|
|
83
|
+
this.lastHeight = height;
|
|
84
|
+
if (this.pinned)
|
|
85
|
+
this.viewport.scrollTop = this.viewport.scrollHeight;
|
|
86
|
+
this.notify();
|
|
87
|
+
}
|
|
53
88
|
jump() {
|
|
54
89
|
this.pinned = true;
|
|
90
|
+
this.behind = false;
|
|
55
91
|
const reduced = this.viewport.ownerDocument.defaultView?.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
56
92
|
this.viewport.scrollTo?.({ top: this.viewport.scrollHeight, behavior: reduced ? "instant" : "smooth" });
|
|
57
|
-
this.
|
|
93
|
+
this.notify();
|
|
58
94
|
}
|
|
59
95
|
disconnect() { this.cleanup.forEach(fn => fn()); this.cleanup = []; this.observer?.disconnect(); }
|
|
60
96
|
}
|
|
@@ -28,6 +28,7 @@ export declare const boeMotionEasing: {
|
|
|
28
28
|
readonly standard: "var(--boe-profile-easing-standard, ease)";
|
|
29
29
|
readonly enter: "var(--boe-profile-easing-enter, ease-out)";
|
|
30
30
|
readonly exit: "var(--boe-profile-easing-exit, ease-in)";
|
|
31
|
+
readonly inOut: "var(--boe-profile-easing-in-out, ease-in-out)";
|
|
31
32
|
readonly linear: "var(--boe-profile-easing-linear, linear)";
|
|
32
33
|
};
|
|
33
34
|
export type BoeMotionDuration = (typeof boeMotionDuration)[keyof typeof boeMotionDuration];
|
|
@@ -28,6 +28,7 @@ export const boeMotionEasing = {
|
|
|
28
28
|
standard: "var(--boe-profile-easing-standard, ease)",
|
|
29
29
|
enter: "var(--boe-profile-easing-enter, ease-out)",
|
|
30
30
|
exit: "var(--boe-profile-easing-exit, ease-in)",
|
|
31
|
+
inOut: "var(--boe-profile-easing-in-out, ease-in-out)",
|
|
31
32
|
linear: "var(--boe-profile-easing-linear, linear)",
|
|
32
33
|
};
|
|
33
34
|
/** CSS transition shorthand using the shared vocabulary. */
|
|
@@ -54,6 +54,9 @@ export const boxDefaultDesignProfile = {
|
|
|
54
54
|
primaryFocus: "inset 0 0 0 1px rgb(255 255 255 / 80%), 0 1px 2px rgb(0 0 0 / 10%)",
|
|
55
55
|
},
|
|
56
56
|
motion: {
|
|
57
|
+
arrival: "200ms",
|
|
58
|
+
panel: "320ms",
|
|
59
|
+
stagger: "50ms",
|
|
57
60
|
fast: "120ms",
|
|
58
61
|
interactive: "140ms",
|
|
59
62
|
medium: "160ms",
|
|
@@ -63,6 +66,7 @@ export const boxDefaultDesignProfile = {
|
|
|
63
66
|
easingStandard: "ease",
|
|
64
67
|
easingEnter: "ease-out",
|
|
65
68
|
easingExit: "ease-in",
|
|
69
|
+
easingInOut: "ease-in-out",
|
|
66
70
|
easingLinear: "linear",
|
|
67
71
|
},
|
|
68
72
|
};
|
|
@@ -116,6 +120,9 @@ export const compactNeutralDesignProfile = {
|
|
|
116
120
|
inputInset: "none",
|
|
117
121
|
},
|
|
118
122
|
motion: {
|
|
123
|
+
arrival: "160ms",
|
|
124
|
+
panel: "240ms",
|
|
125
|
+
stagger: "35ms",
|
|
119
126
|
fast: "80ms",
|
|
120
127
|
interactive: "100ms",
|
|
121
128
|
medium: "140ms",
|
|
@@ -123,6 +130,7 @@ export const compactNeutralDesignProfile = {
|
|
|
123
130
|
easingStandard: "cubic-bezier(0.2, 0, 0, 1)",
|
|
124
131
|
easingEnter: "cubic-bezier(0.16, 1, 0.3, 1)",
|
|
125
132
|
easingExit: "cubic-bezier(0.7, 0, 0.84, 0)",
|
|
133
|
+
easingInOut: "cubic-bezier(0.65, 0, 0.35, 1)",
|
|
126
134
|
},
|
|
127
135
|
};
|
|
128
136
|
export const registerBuiltInDesignProfiles = () => {
|
|
@@ -64,6 +64,7 @@ export declare const DESIGN_PROFILE_VARIABLES: {
|
|
|
64
64
|
readonly easingStandard: "--boe-profile-easing-standard";
|
|
65
65
|
readonly easingEnter: "--boe-profile-easing-enter";
|
|
66
66
|
readonly easingExit: "--boe-profile-easing-exit";
|
|
67
|
+
readonly easingInOut: "--boe-profile-easing-in-out";
|
|
67
68
|
readonly easingLinear: "--boe-profile-easing-linear";
|
|
68
69
|
};
|
|
69
70
|
};
|
|
@@ -63,6 +63,7 @@ export const DESIGN_PROFILE_VARIABLES = {
|
|
|
63
63
|
easingStandard: "--boe-profile-easing-standard",
|
|
64
64
|
easingEnter: "--boe-profile-easing-enter",
|
|
65
65
|
easingExit: "--boe-profile-easing-exit",
|
|
66
|
+
easingInOut: "--boe-profile-easing-in-out",
|
|
66
67
|
easingLinear: "--boe-profile-easing-linear",
|
|
67
68
|
},
|
|
68
69
|
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export type StatusKind = "pending" | "active" | "done" | "warning" | "failed" | "skipped" | "approved" | "rejected";
|
|
2
2
|
export declare const toStatusKind: (status: string) => StatusKind;
|
|
3
|
-
export declare const statusLabel: (kind: StatusKind) => string;
|
|
3
|
+
export declare const statusLabel: (kind: StatusKind, labels?: Partial<Record<StatusKind, string>>) => string;
|
|
4
4
|
/** Decorative markup. Pair with visible words or the StatusIcon component. */
|
|
5
5
|
export declare const boeStatusGlyph: (kind: StatusKind) => string;
|
|
6
|
-
export declare const boeStatusStyles = "\n.boe-status { flex: none; vertical-align: middle; fill: none; stroke: currentColor; stroke-width: 1.5; }\n.boe-status[data-kind=\"active\"] { color: var(--boe-token-surface-surface-brand, #0061d5); animation: boe-status-spin .8s linear infinite; }\n.boe-status[data-kind=\"active\"] circle { opacity: .25; }\n.boe-status[data-kind=\"done\"] { color: var(--boe-token-text-status-text-success, #187657); }\n.boe-status[data-kind=\"warning\"] { color: var(--boe-token-text-status-text-warning, #946400); }\n.boe-status[data-kind=\"failed\"] { color: var(--boe-token-text-status-text-error, #c52a46); }\n.boe-status[data-kind=\"skipped\"] circle { stroke-dasharray: 2 2; }\n.boe-status:is([data-kind=\"done\"], [data-kind=\"warning\"], [data-kind=\"failed\"]) circle { fill: currentColor; }\n.boe-status:is([data-kind=\"done\"], [data-kind=\"warning\"], [data-kind=\"failed\"]) path { stroke: var(--boe-token-surface-surface, #fff); stroke-linecap: round; }\n.boe-status[data-kind=\"done\"] { animation: boe-pop 200ms ease-out both; }\n.boe-status[data-kind=\"done\"] path { stroke-dasharray: 20; animation: boe-status-check 200ms ease-out both; }\n";
|
|
6
|
+
export declare const boeStatusStyles = "\n.boe-status { flex: none; vertical-align: middle; fill: none; stroke: currentColor; stroke-width: 1.5; }\n.boe-status[data-kind=\"active\"] { color: var(--boe-token-surface-surface-brand, #0061d5); }\n.boe-status-arc { transform-origin: 8px 8px; animation: boe-status-spin .8s linear infinite; }\n.boe-status[data-kind=\"active\"] circle { opacity: .25; }\n.boe-status[data-kind=\"done\"] { color: var(--boe-token-text-status-text-success, #187657); }\n.boe-status[data-kind=\"warning\"] { color: var(--boe-token-text-status-text-warning, #946400); }\n.boe-status[data-kind=\"failed\"] { color: var(--boe-token-text-status-text-error, #c52a46); }\n.boe-status[data-kind=\"skipped\"] circle { stroke-dasharray: 2 2; }\n.boe-status:is([data-kind=\"done\"], [data-kind=\"warning\"], [data-kind=\"failed\"]) circle { fill: currentColor; }\n.boe-status:is([data-kind=\"done\"], [data-kind=\"warning\"], [data-kind=\"failed\"]) path { stroke: var(--boe-token-surface-surface, #fff); stroke-linecap: round; }\n.boe-status[data-kind=\"done\"] { animation: boe-pop 200ms ease-out both; }\n.boe-status[data-kind=\"done\"] path { stroke-dasharray: 20; animation: boe-status-check 200ms ease-out both; }\n";
|
|
7
|
+
/** Self-contained styles for light-DOM glyphs; safe to insert in a document style element. */
|
|
8
|
+
export declare const boeStatusDocumentStyles = "\n@keyframes boe-rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }\n@keyframes boe-pop { from { opacity: 0; transform: scale(.8); } to { opacity: 1; transform: none; } }\n@keyframes boe-fade-in { from { opacity: 0; } to { opacity: 1; } }\n@keyframes boe-status-check { from { stroke-dashoffset: 20; } to { stroke-dashoffset: 0; } }\n@keyframes boe-status-spin { to { transform: rotate(360deg); } }\n\n.boe-status { flex: none; vertical-align: middle; fill: none; stroke: currentColor; stroke-width: 1.5; }\n.boe-status[data-kind=\"active\"] { color: var(--boe-token-surface-surface-brand, #0061d5); }\n.boe-status-arc { transform-origin: 8px 8px; animation: boe-status-spin .8s linear infinite; }\n.boe-status[data-kind=\"active\"] circle { opacity: .25; }\n.boe-status[data-kind=\"done\"] { color: var(--boe-token-text-status-text-success, #187657); }\n.boe-status[data-kind=\"warning\"] { color: var(--boe-token-text-status-text-warning, #946400); }\n.boe-status[data-kind=\"failed\"] { color: var(--boe-token-text-status-text-error, #c52a46); }\n.boe-status[data-kind=\"skipped\"] circle { stroke-dasharray: 2 2; }\n.boe-status:is([data-kind=\"done\"], [data-kind=\"warning\"], [data-kind=\"failed\"]) circle { fill: currentColor; }\n.boe-status:is([data-kind=\"done\"], [data-kind=\"warning\"], [data-kind=\"failed\"]) path { stroke: var(--boe-token-surface-surface, #fff); stroke-linecap: round; }\n.boe-status[data-kind=\"done\"] { animation: boe-pop 200ms ease-out both; }\n.boe-status[data-kind=\"done\"] path { stroke-dasharray: 20; animation: boe-status-check 200ms ease-out both; }\n\n@media (prefers-reduced-motion: reduce) {\n *, *::before, *::after { animation-duration: 1ms !important; animation-iteration-count: 1 !important;\n animation-delay: 0ms !important; transition-duration: 1ms !important; transition-delay: 0ms !important; scroll-behavior: auto !important; }\n}\n";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { boeEntranceKeyframes, boeReducedMotionPolicy } from "../motion/behaviors.js";
|
|
1
2
|
const mappings = {
|
|
2
3
|
pending: "pending", info: "pending", active: "active", running: "active", in_progress: "active",
|
|
3
4
|
done: "done", succeeded: "done", completed: "done", pass: "done", approved: "approved",
|
|
@@ -5,8 +6,8 @@ const mappings = {
|
|
|
5
6
|
skipped: "skipped", rejected: "rejected",
|
|
6
7
|
};
|
|
7
8
|
export const toStatusKind = (status) => mappings[status] ?? "pending";
|
|
8
|
-
export const statusLabel = (kind) => ({
|
|
9
|
-
pending: "
|
|
9
|
+
export const statusLabel = (kind, labels = {}) => labels[kind] ?? ({
|
|
10
|
+
pending: "Not started", active: "In progress", done: "Done", warning: "Done with a warning",
|
|
10
11
|
failed: "Failed", skipped: "Skipped",
|
|
11
12
|
approved: "Approved", rejected: "Rejected",
|
|
12
13
|
})[kind];
|
|
@@ -16,13 +17,14 @@ export const boeStatusGlyph = (kind) => {
|
|
|
16
17
|
const path = state === "done" || state === "approved" ? '<path d="m4 8 3 3 5-6"/>'
|
|
17
18
|
: state === "rejected" ? '<path d="M4 12 12 4"/>'
|
|
18
19
|
: state === "failed" ? '<path d="m5 5 6 6m0-6-6 6"/>'
|
|
19
|
-
: state === "warning" ? '<path d="
|
|
20
|
-
: state === "active" ? '<path d="M8
|
|
21
|
-
return `<svg class="boe-status" data-kind="${state}" aria-hidden="true" viewBox="0 0 16 16" width="16" height="16"><circle cx="8" cy="8" r="
|
|
20
|
+
: state === "warning" ? '<path d="M8 4.75v3.75M8 11h.01"/>'
|
|
21
|
+
: state === "active" ? '<path class="boe-status-arc" d="M8 1.75a6.25 6.25 0 0 1 6.25 6.25"/>' : "";
|
|
22
|
+
return `<svg class="boe-status" data-kind="${state}" aria-hidden="true" viewBox="0 0 16 16" width="16" height="16"><circle cx="8" cy="8" r="6.25"/>${path}</svg>`;
|
|
22
23
|
};
|
|
23
24
|
export const boeStatusStyles = `
|
|
24
25
|
.boe-status { flex: none; vertical-align: middle; fill: none; stroke: currentColor; stroke-width: 1.5; }
|
|
25
|
-
.boe-status[data-kind="active"] { color: var(--boe-token-surface-surface-brand, #0061d5);
|
|
26
|
+
.boe-status[data-kind="active"] { color: var(--boe-token-surface-surface-brand, #0061d5); }
|
|
27
|
+
.boe-status-arc { transform-origin: 8px 8px; animation: boe-status-spin .8s linear infinite; }
|
|
26
28
|
.boe-status[data-kind="active"] circle { opacity: .25; }
|
|
27
29
|
.boe-status[data-kind="done"] { color: var(--boe-token-text-status-text-success, #187657); }
|
|
28
30
|
.boe-status[data-kind="warning"] { color: var(--boe-token-text-status-text-warning, #946400); }
|
|
@@ -33,3 +35,5 @@ export const boeStatusStyles = `
|
|
|
33
35
|
.boe-status[data-kind="done"] { animation: boe-pop 200ms ease-out both; }
|
|
34
36
|
.boe-status[data-kind="done"] path { stroke-dasharray: 20; animation: boe-status-check 200ms ease-out both; }
|
|
35
37
|
`;
|
|
38
|
+
/** Self-contained styles for light-DOM glyphs; safe to insert in a document style element. */
|
|
39
|
+
export const boeStatusDocumentStyles = `${boeEntranceKeyframes}${boeStatusStyles}${boeReducedMotionPolicy}`;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { applyDesignTokens,
|
|
1
|
+
import { applyDesignTokens, setActiveDesignSystem, } from "../tokens/registry.js";
|
|
2
|
+
import { registerBoxDarkDesignSystem } from "../tokens/box-dark.js";
|
|
3
|
+
import { registerBoxDefaultDesignSystem } from "../tokens/box-defaults.js";
|
|
2
4
|
export const THEME_CHANGE_EVENT = "boe:theme-change";
|
|
3
5
|
export const DEFAULT_THEME_STORAGE_KEY = "boe-theme";
|
|
4
6
|
export const DARK_MODE_MEDIA_QUERY = "(prefers-color-scheme: dark)";
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { RegisteredDesignSystemDefinition } from "./types.js";
|
|
2
|
+
/** Optional preload for hosts that want named icons ready before first render. */
|
|
3
|
+
export declare const preloadBoxDefaultIcons: () => Promise<void>;
|
|
2
4
|
export declare const boxDefaultDesignSystem: RegisteredDesignSystemDefinition;
|
|
3
5
|
export declare const registerBoxDefaultDesignSystem: (options?: {
|
|
4
6
|
setActive?: boolean;
|
|
@@ -1,7 +1,35 @@
|
|
|
1
|
-
import { registerDesignSystem } from "./registry.js";
|
|
2
|
-
import { boxIconography } from "../icons/box-iconography.js";
|
|
1
|
+
import { DESIGN_SYSTEM_CHANGE_EVENT, getActiveDesignSystem, registerDesignSystem } from "./registry.js";
|
|
3
2
|
const iconSvg = (viewBox, body) => `<svg viewBox="${viewBox}" width="1em" height="1em" role="img" aria-hidden="true" focusable="false">${body}</svg>`;
|
|
4
3
|
const illustrationSvg = (viewBox, body) => `<svg viewBox="${viewBox}" width="100%" height="100%" preserveAspectRatio="xMidYMid meet" role="presentation" aria-hidden="true" focusable="false">${body}</svg>`;
|
|
4
|
+
let loadDefaultIcons;
|
|
5
|
+
/** Keep theme setup and token-only components independent of the full icon registry. */
|
|
6
|
+
const lazyBoxIcons = (defaults) => {
|
|
7
|
+
const icons = { ...defaults };
|
|
8
|
+
let loading = null;
|
|
9
|
+
const load = () => {
|
|
10
|
+
loading ??= import("../icons/box-iconography.js")
|
|
11
|
+
.then(({ boxIconography }) => {
|
|
12
|
+
Object.assign(icons, boxIconography, defaults);
|
|
13
|
+
if (typeof globalThis.dispatchEvent === "function" && typeof CustomEvent !== "undefined") {
|
|
14
|
+
globalThis.dispatchEvent(new CustomEvent(DESIGN_SYSTEM_CHANGE_EVENT, {
|
|
15
|
+
detail: { activeDesignSystemName: getActiveDesignSystem()?.name ?? null },
|
|
16
|
+
}));
|
|
17
|
+
}
|
|
18
|
+
})
|
|
19
|
+
.catch(error => { loading = null; throw error; });
|
|
20
|
+
return loading;
|
|
21
|
+
};
|
|
22
|
+
loadDefaultIcons = load;
|
|
23
|
+
return new Proxy(icons, {
|
|
24
|
+
get(target, name, receiver) {
|
|
25
|
+
if (typeof name === "string" && !Object.hasOwn(target, name))
|
|
26
|
+
void load().catch(() => { });
|
|
27
|
+
return Reflect.get(target, name, receiver);
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
/** Optional preload for hosts that want named icons ready before first render. */
|
|
32
|
+
export const preloadBoxDefaultIcons = () => loadDefaultIcons?.() ?? Promise.resolve();
|
|
5
33
|
export const boxDefaultDesignSystem = {
|
|
6
34
|
name: "box-default",
|
|
7
35
|
// Values track Box's modernized "Blueprint" design system
|
|
@@ -40,13 +68,12 @@ export const boxDefaultDesignSystem = {
|
|
|
40
68
|
StrokeStroke: "#e8e8e8",
|
|
41
69
|
StrokeStrokeHover: "#bcbcbc",
|
|
42
70
|
},
|
|
43
|
-
icons: {
|
|
44
|
-
...boxIconography,
|
|
71
|
+
icons: lazyBoxIcons({
|
|
45
72
|
info: iconSvg("0 0 16 16", '<path fill="currentColor" d="M8.5 6.5H6.25a.75.75 0 0 0 0 1.5H7v4.5h-.75a.75.75 0 1 0 0 1.5H10a.75.75 0 1 0 0-1.5h-.75V7.41s.006-.217-.02-.327A.753.753 0 0 0 8.5 6.5ZM7.75 2a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3Z" />'),
|
|
46
73
|
alert: iconSvg("0 0 16 16", '<path fill="currentColor" fill-rule="evenodd" d="M8 1.5a1.4 1.4 0 0 1 1.227.725l5.138 9.317A1.4 1.4 0 0 1 13.138 13.6H2.862a1.4 1.4 0 0 1-1.227-2.058l5.138-9.317A1.4 1.4 0 0 1 8 1.5Zm0 3.1a.75.75 0 0 0-.75.75v3.4a.75.75 0 0 0 1.5 0v-3.4A.75.75 0 0 0 8 4.6Zm0 6.4a.9.9 0 1 0 0 1.8.9.9 0 0 0 0-1.8Z" clip-rule="evenodd" />'),
|
|
47
74
|
"folder-shared": iconSvg("0 0 32 32", '<path fill="#2687FC" fill-rule="evenodd" d="M6 6h6c2 0 1.5 2 4 2h10a3 3 0 0 1 3 3v13a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3V9a3 3 0 0 1 3-3Z" clip-rule="evenodd" /><path fill="#91C2FD" fill-rule="evenodd" d="M26 11a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3V14a3 3 0 0 1 3-3h20Zm-6.999 8c-1.117 0-1.933.543-2.439 1.401.198.464.337.951.414 1.45.066.42.003.809-.165 1.138a1.7 1.7 0 0 0 .193.011h4.002l.14-.006c.63-.054.924-.476.844-.988a5.024 5.024 0 0 0-.258-.997c-.453-1.2-1.367-2.009-2.73-2.009h-.001ZM13 19c-1.364 0-2.278.81-2.731 2.01-.076.202-.137.41-.185.62-.028.123-.053.25-.073.378-.084.54.258.992.992.992h4.002l.14-.006c.63-.054.924-.476.843-.988a5.023 5.023 0 0 0-.257-.997C15.277 19.81 14.363 19 13 19Zm0-4a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3Zm6.001 0a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3Z" clip-rule="evenodd" />'),
|
|
48
75
|
"file-pdf": iconSvg("0 0 32 32", '<path fill="#FFF" d="M6 4a3 3 0 0 1 3-3h9.757a2 2 0 0 1 1.415.586l5.242 5.242A2 2 0 0 1 26 8.243V25a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3V4Z" /><path fill="#D0021B" d="M18 1v6a2 2 0 0 0 2 2h6v16a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3h9Z" opacity="0.12" /><path fill="#D0021B" d="M19 2.414 24.586 8H20a1 1 0 0 1-1-1V2.414Z" /><path fill="#D0021B" d="M9.8 23v-7h2.485c1.526 0 2.415.865 2.415 2.24 0 1.374-.889 2.248-2.415 2.248h-1.03V23H9.8Zm1.455-3.614h.83c.731 0 1.148-.387 1.148-1.146 0-.758-.417-1.137-1.148-1.137h-.83v2.283ZM15.975 23v-7h2.19c2.105 0 3.313 1.273 3.313 3.492 0 2.221-1.208 3.508-3.313 3.508h-2.19Zm1.455-1.22h.597c1.267 0 1.951-.728 1.951-2.288 0-1.557-.684-2.272-1.95-2.272h-.598v4.56ZM22.786 23v-7h4.475v1.22H24.24v1.675h2.796v1.188H24.24V23h-1.454Z" />'),
|
|
49
|
-
},
|
|
76
|
+
}),
|
|
50
77
|
illustrations: {
|
|
51
78
|
"empty-state-folder": illustrationSvg("0 0 140 140", '<g fill="var(--boe-token-surface-illustration-surface-box-neutral, #0061d5)" fill-rule="evenodd" clip-rule="evenodd" opacity="0.1"><path d="M47.11 36H35.383c-1.261 0-2.294.97-2.378 2.198L33 38.36v48.604c0 2.162 1.716 3.926 3.872 4.031l.546.005h.257l.19-.036c1.743-.375 3.062-1.86 3.152-3.663l.005-.197V73.972a.98.98 0 0 1 .017-.18.87.87 0 0 1-.032-.155L41 73.52V56.717c0-4.209 3.7-7.59 8.268-7.713l.26-.004L97 48.999v-2.26c0-3.08-2.463-5.592-5.546-5.707l-.221-.004H54.118a4.402 4.402 0 0 1-3.51-1.738l-.14-.197-1.375-2.042a2.386 2.386 0 0 0-1.8-1.044L47.11 36Z" /><path d="M51 96a7 7 0 1 1 0 14 7 7 0 0 1 0-14Zm47-66c5.523 0 10 4.477 10 10s-4.477 10-10 10-10-4.477-10-10 4.477-10 10-10Z" /></g><path fill="var(--boe-token-surface-illustration-surface-box-neutral, #0061d5)" fill-rule="evenodd" d="M95 90c0-7.18-5.82-13-13-13s-13 5.82-13 13 5.82 13 13 13 13-5.82 13-13Zm-12.268-6.723a1.03 1.03 0 0 0-1.269-.107l-.105.079-.061.057-.057.061-4.99 5.898-.074.098a1.06 1.06 0 0 0 .187 1.384l.098.076c.17.115.371.177.578.177H79l.001 4.921c0 .596.497 1.08 1.11 1.08h3.779c.614 0 1.11-.484 1.11-1.081V91h1.96l.115-.006c.52-.057.925-.503.925-1.045 0-.249-.087-.489-.246-.679l-4.932-5.898-.09-.095Z" clip-rule="evenodd" /><path fill="var(--boe-token-surface-illustration-surface-box-neutral, #0061d5)" d="M44.156 39c.466 0 .844.448.844 1s-.378 1-.844 1h-6.312c-.466 0-.844-.448-.844-1s.378-1 .844-1h6.312Zm41.952 21c.493 0 .892.448.892 1s-.4 1-.892 1H61.892c-.493 0-.892-.448-.892-1s.4-1 .892-1h24.216Z" /><path fill="var(--boe-token-surface-illustration-surface-box-neutral, #0061d5)" fill-rule="evenodd" d="M99 91a6 6 0 0 0 5.996-5.775L105 85l.005-28.283c0-2.983-2.745-5.672-6.005-5.708l-49.473-.019c-3.55 0-6.403 2.476-6.528 5.518l-.004.209c0 10.13.005 20.255.005 30.387a5.817 5.817 0 0 1-1.497 3.897L65 91a1 1 0 0 1 0 2H37c-3.238 0-5.878-2.521-5.996-5.675L31 87.104V38.347c0-2.33 1.85-4.232 4.174-4.342l.212-.005h11.727a4.4 4.4 0 0 1 3.509 1.739l.14.197 1.376 2.043c.407.607 1.073.99 1.799 1.045l.183.007h37.11c4.208 0 7.636 3.316 7.766 7.456l.004.244v2.284c4.358.24 7.863 3.449 7.996 7.464l.004.238V85a8 8 0 0 1-7.75 7.996L99 93a1 1 0 0 1 0-2ZM35.383 36H47.11l.183.007a2.386 2.386 0 0 1 1.8 1.044l1.375 2.042.14.197a4.402 4.402 0 0 0 3.51 1.738h37.115l.221.004c3.083.115 5.546 2.627 5.546 5.707v2.26L49.528 49l-.26.004C44.7 49.127 41 52.508 41 56.717c0 10.129.022 20.258.022 30.387l-.005.197c-.09 1.803-1.409 3.288-3.152 3.663l-.19.036h-.257l-.546-.005C34.716 90.89 33 89.126 33 86.964V38.36l.005-.162A2.374 2.374 0 0 1 35.383 36Z" clip-rule="evenodd" />'),
|
|
52
79
|
// Fanned file cards behind a cloud carrying an upload arrow — the empty
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { DESIGN_SYSTEM_CHANGE_EVENT, SEMANTIC_TOKEN_ALIASES, applyDesignTokens, createDesignTokenStyleText, getActiveDesignSystem, getDesignSystem, listDesignSystems, normalizeDesignTokens, registerDesignSystem, resolveDesignIcon, resolveDesignIllustration, resolveDesignSystemTokens, setActiveDesignSystem, } from "./registry.js";
|
|
2
|
-
export { boxDefaultDesignSystem, registerBoxDefaultDesignSystem } from "./box-defaults.js";
|
|
2
|
+
export { boxDefaultDesignSystem, preloadBoxDefaultIcons, registerBoxDefaultDesignSystem } from "./box-defaults.js";
|
|
3
3
|
export { boxDarkDesignSystem, registerBoxDarkDesignSystem } from "./box-dark.js";
|
|
4
4
|
export { boeBrandInteractiveStyles, boeFocusRingShadow, boeFocusVisibleStyles, boeNeutralInteractiveStyles, } from "./interaction.js";
|
|
5
5
|
export type { ApplyDesignTokensOptions, DesignAssetRenderContext, DesignAssetRenderer, DesignSystemDefinition, DesignTokenInput, DesignTokenMap, RegisteredDesignSystemDefinition, SemanticDesignTokenMap, } from "./types.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { DESIGN_SYSTEM_CHANGE_EVENT, SEMANTIC_TOKEN_ALIASES, applyDesignTokens, createDesignTokenStyleText, getActiveDesignSystem, getDesignSystem, listDesignSystems, normalizeDesignTokens, registerDesignSystem, resolveDesignIcon, resolveDesignIllustration, resolveDesignSystemTokens, setActiveDesignSystem, } from "./registry.js";
|
|
2
|
-
export { boxDefaultDesignSystem, registerBoxDefaultDesignSystem } from "./box-defaults.js";
|
|
2
|
+
export { boxDefaultDesignSystem, preloadBoxDefaultIcons, registerBoxDefaultDesignSystem } from "./box-defaults.js";
|
|
3
3
|
export { boxDarkDesignSystem, registerBoxDarkDesignSystem } from "./box-dark.js";
|
|
4
4
|
export { boeBrandInteractiveStyles, boeFocusRingShadow, boeFocusVisibleStyles, boeNeutralInteractiveStyles, } from "./interaction.js";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { Controller, TypedEventEmitter } from "./core/index.js";
|
|
2
2
|
export type { EventMap, Unsubscribe } from "./core/index.js";
|
|
3
3
|
export type { JsonSchema } from "./core/json-schema.js";
|
|
4
|
-
export { DESIGN_SYSTEM_CHANGE_EVENT, SEMANTIC_TOKEN_ALIASES, applyDesignTokens, boxDarkDesignSystem, boxDefaultDesignSystem, createDesignTokenStyleText, getActiveDesignSystem, getDesignSystem, listDesignSystems, normalizeDesignTokens, registerBoxDarkDesignSystem, registerBoxDefaultDesignSystem, registerDesignSystem, resolveDesignIcon, resolveDesignIllustration, resolveDesignSystemTokens, setActiveDesignSystem, } from "./foundations/tokens/index.js";
|
|
4
|
+
export { DESIGN_SYSTEM_CHANGE_EVENT, SEMANTIC_TOKEN_ALIASES, applyDesignTokens, boxDarkDesignSystem, boxDefaultDesignSystem, createDesignTokenStyleText, getActiveDesignSystem, getDesignSystem, listDesignSystems, normalizeDesignTokens, preloadBoxDefaultIcons, registerBoxDarkDesignSystem, registerBoxDefaultDesignSystem, registerDesignSystem, resolveDesignIcon, resolveDesignIllustration, resolveDesignSystemTokens, setActiveDesignSystem, } from "./foundations/tokens/index.js";
|
|
5
5
|
export type { ApplyDesignTokensOptions, DesignAssetRenderContext, DesignAssetRenderer, DesignSystemDefinition, DesignTokenInput, DesignTokenMap, RegisteredDesignSystemDefinition, SemanticDesignTokenMap, } from "./foundations/tokens/index.js";
|
|
6
6
|
export { DARK_MODE_MEDIA_QUERY, DEFAULT_THEME_STORAGE_KEY, THEME_CHANGE_EVENT, createThemeController, createThemeInitializationScript, } from "./foundations/theming/index.js";
|
|
7
7
|
export type { ResolvedTheme, ThemeChangeDetail, ThemeController, ThemeControllerOptions, ThemeInitializationScriptOptions, ThemePreference, } from "./foundations/theming/index.js";
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Core runtime
|
|
2
2
|
export { Controller, TypedEventEmitter } from "./core/index.js";
|
|
3
3
|
// Foundations
|
|
4
|
-
export { DESIGN_SYSTEM_CHANGE_EVENT, SEMANTIC_TOKEN_ALIASES, applyDesignTokens, boxDarkDesignSystem, boxDefaultDesignSystem, createDesignTokenStyleText, getActiveDesignSystem, getDesignSystem, listDesignSystems, normalizeDesignTokens, registerBoxDarkDesignSystem, registerBoxDefaultDesignSystem, registerDesignSystem, resolveDesignIcon, resolveDesignIllustration, resolveDesignSystemTokens, setActiveDesignSystem, } from "./foundations/tokens/index.js";
|
|
4
|
+
export { DESIGN_SYSTEM_CHANGE_EVENT, SEMANTIC_TOKEN_ALIASES, applyDesignTokens, boxDarkDesignSystem, boxDefaultDesignSystem, createDesignTokenStyleText, getActiveDesignSystem, getDesignSystem, listDesignSystems, normalizeDesignTokens, preloadBoxDefaultIcons, registerBoxDarkDesignSystem, registerBoxDefaultDesignSystem, registerDesignSystem, resolveDesignIcon, resolveDesignIllustration, resolveDesignSystemTokens, setActiveDesignSystem, } from "./foundations/tokens/index.js";
|
|
5
5
|
export { DARK_MODE_MEDIA_QUERY, DEFAULT_THEME_STORAGE_KEY, THEME_CHANGE_EVENT, createThemeController, createThemeInitializationScript, } from "./foundations/theming/index.js";
|
|
6
6
|
export { DESIGN_PROFILE_CHANGE_EVENT, DESIGN_PROFILE_VARIABLES, DEFAULT_DESIGN_PROFILE_STORAGE_KEY, applyDesignProfile, boxDefaultDesignProfile, compactNeutralDesignProfile, createDesignProfileController, createDesignProfileStyleText, getDesignProfile, listDesignProfiles, registerBuiltInDesignProfiles, registerDesignProfile, resolveDesignProfileProperties, } from "./foundations/profiles/index.js";
|
|
7
7
|
export { boxIconography, boxIconographyAliases } from "./foundations/icons/index.js";
|
|
@@ -220,7 +220,7 @@ const elementStyles = `
|
|
|
220
220
|
color: var(--boe-token-text-text-secondary, #6f6f6f);
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
[part="proposal-params"] {
|
|
223
|
+
[part="proposal-params"], [part="proposal-details"] {
|
|
224
224
|
margin: 0;
|
|
225
225
|
display: grid;
|
|
226
226
|
grid-template-columns: auto 1fr;
|
|
@@ -236,6 +236,7 @@ const elementStyles = `
|
|
|
236
236
|
margin: 0;
|
|
237
237
|
color: var(--boe-token-text-text, #1f1e1b);
|
|
238
238
|
}
|
|
239
|
+
.boe-sr-only { position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0; }
|
|
239
240
|
|
|
240
241
|
[part="proposal-actions"] {
|
|
241
242
|
display: flex;
|
|
@@ -373,7 +374,7 @@ const elementStyles = `
|
|
|
373
374
|
export class AgentChat extends BaseElement {
|
|
374
375
|
static tagName = DEFAULT_TAG_NAME;
|
|
375
376
|
static get observedAttributes() {
|
|
376
|
-
return ["agent-name", "heading", "placeholder", "token", "hidden", "hide-citations"];
|
|
377
|
+
return ["agent-name", "heading", "placeholder", "token", "hidden", "hide-citations", "hide-modify"];
|
|
377
378
|
}
|
|
378
379
|
controller = null;
|
|
379
380
|
scope = `boe-chat-${++chatInstance}`;
|
|
@@ -608,6 +609,8 @@ export class AgentChat extends BaseElement {
|
|
|
608
609
|
const failed = proposal.outcome === "failed";
|
|
609
610
|
return `<div part="proposal" aria-live="off" tabindex="-1" id="${this.proposalAnchor(message.id, proposal.id)}" data-proposal-id="${escapeHtml(proposal.id)}" data-decision="${escapeHtml(proposal.decision)}" ${failed ? 'role="alert"' : ""}>
|
|
610
611
|
<span part="decision">${boeStatusGlyph(failed ? "failed" : proposal.decision === "approved" ? "done" : "skipped")}${proposal.decision === "approved" ? failed ? "Approved · didn't complete" : "Approved" : "Rejected"} · <span part="proposal-title">${escapeHtml(proposal.title)}</span></span>
|
|
612
|
+
${proposal.summary ? `<p part="proposal-summary">${escapeHtml(proposal.summary)}</p>` : ""}
|
|
613
|
+
${proposal.details?.length ? `<dl part="proposal-details">${proposal.details.map(detail => `<dt part="param-label">${escapeHtml(detail.label)}</dt><dd part="param-value">${detail.href && isSafeHref(detail.href) ? `<a href="${escapeHtml(detail.href)}" target="_blank" rel="noopener noreferrer">${escapeHtml(detail.value)} <span aria-hidden="true">↗</span><span class="boe-sr-only"> (opens in a new tab)</span></a>` : escapeHtml(detail.value)}</dd>`).join("")}</dl>` : ""}
|
|
611
614
|
${proposal.note ? `<p part="proposal-note">${escapeHtml(proposal.note)}</p>` : ""}
|
|
612
615
|
${failed ? `<button part="retry" data-message-id="${escapeHtml(message.id)}">Try again</button>` : ""}</div>`;
|
|
613
616
|
}
|
|
@@ -622,7 +625,7 @@ export class AgentChat extends BaseElement {
|
|
|
622
625
|
<div part="proposal-actions">
|
|
623
626
|
<button type="button" part="proposal-action" data-action="approve" data-proposal-id="${escapeHtml(proposal.id)}" ${proposal.resolving ? "disabled" : ""} aria-busy="${proposal.resolving === "approved"}">${proposal.resolving === "approved" ? boeStatusGlyph("active") : ""}Approve</button>
|
|
624
627
|
<button type="button" part="proposal-action" data-action="reject" data-proposal-id="${escapeHtml(proposal.id)}" ${proposal.resolving ? "disabled" : ""} aria-busy="${proposal.resolving === "rejected"}">${proposal.resolving === "rejected" ? boeStatusGlyph("active") : ""}Reject</button>
|
|
625
|
-
|
|
628
|
+
${this.hasAttribute("hide-modify") ? "" : `<button type="button" part="proposal-action" data-action="modify" data-proposal-id="${escapeHtml(proposal.id)}" ${proposal.resolving ? "disabled" : ""}>Modify</button>`}
|
|
626
629
|
</div>
|
|
627
630
|
`
|
|
628
631
|
: "";
|
|
@@ -634,6 +637,7 @@ export class AgentChat extends BaseElement {
|
|
|
634
637
|
${params ? `<dl part="proposal-params">${params}</dl>` : ""}
|
|
635
638
|
${proposal.decision ? `<span part="decision">${proposal.decision === "approved" ? "Approved" : "Rejected"}</span>` : ""}
|
|
636
639
|
${proposal.note ? `<p part="proposal-note">${escapeHtml(proposal.note)}</p>` : ""}
|
|
640
|
+
${proposal.resolveError ? `<p part="error" role="alert">${escapeHtml(proposal.resolveError)}</p>` : ""}
|
|
637
641
|
${actions}
|
|
638
642
|
<p part="proposal-note">To change it, reply with the new values.</p>
|
|
639
643
|
</div>
|
|
@@ -768,7 +772,7 @@ export class AgentChat extends BaseElement {
|
|
|
768
772
|
}
|
|
769
773
|
setupListeners() {
|
|
770
774
|
this.jumpEl = this.shadowRoot.querySelector('[part="jump"]');
|
|
771
|
-
this.scrollPin = new ScrollPinController(this.threadEl,
|
|
775
|
+
this.scrollPin = new ScrollPinController(this.threadEl, ({ behind }) => { this.jumpEl.hidden = !behind; });
|
|
772
776
|
this.jumpEl.addEventListener("click", () => this.scrollPin?.jump());
|
|
773
777
|
this.inputEl.addEventListener("compositionstart", () => { this.composing = true; });
|
|
774
778
|
this.inputEl.addEventListener("compositionend", () => { this.composing = false; });
|
|
@@ -817,12 +821,7 @@ export class AgentChat extends BaseElement {
|
|
|
817
821
|
void this.controller?.resolveAction(proposalId, "rejected", undefined, messageId);
|
|
818
822
|
}
|
|
819
823
|
else if (action === "modify") {
|
|
820
|
-
|
|
821
|
-
this.dispatchEvent(new CustomEvent("proposal-modify-requested", {
|
|
822
|
-
bubbles: true,
|
|
823
|
-
composed: true,
|
|
824
|
-
detail: { proposalId },
|
|
825
|
-
}));
|
|
824
|
+
this.dispatchEvent(new CustomEvent("proposal-modify-requested", { bubbles: true, composed: true, detail: { proposalId, messageId } }));
|
|
826
825
|
}
|
|
827
826
|
return;
|
|
828
827
|
}
|
|
@@ -97,6 +97,7 @@ export class AgentChatController extends Controller {
|
|
|
97
97
|
};
|
|
98
98
|
const sequences = new Set();
|
|
99
99
|
let highSequence = 0;
|
|
100
|
+
let invalidSequence = false;
|
|
100
101
|
let done;
|
|
101
102
|
const missing = () => Array.from({ length: highSequence }, (_, i) => i + 1).filter(i => !sequences.has(i));
|
|
102
103
|
const upsert = (items, item) => item.id && items.some(i => i.id === item.id)
|
|
@@ -107,8 +108,10 @@ export class AgentChatController extends Controller {
|
|
|
107
108
|
return;
|
|
108
109
|
}
|
|
109
110
|
if (event.seq !== undefined) {
|
|
110
|
-
if (!Number.isSafeInteger(event.seq) || event.seq < 1 || event.seq > 100000)
|
|
111
|
-
|
|
111
|
+
if (!Number.isSafeInteger(event.seq) || event.seq < 1 || event.seq > 100000) {
|
|
112
|
+
invalidSequence = true;
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
112
115
|
if (sequences.has(event.seq))
|
|
113
116
|
return;
|
|
114
117
|
sequences.add(event.seq);
|
|
@@ -151,7 +154,7 @@ export class AgentChatController extends Controller {
|
|
|
151
154
|
finished = true;
|
|
152
155
|
const gaps = missing();
|
|
153
156
|
patchAgentMessage({ ...patch, endedAt: Date.now(), completeness: {
|
|
154
|
-
status: patch.status === "error" ? "error" : !done || gaps.length ? "incomplete" : done,
|
|
157
|
+
status: patch.status === "error" && done === "error" ? "error" : !done || gaps.length || invalidSequence ? "incomplete" : done,
|
|
155
158
|
missing: gaps,
|
|
156
159
|
} });
|
|
157
160
|
// A superseded send must not clear the newer send's streaming flag.
|
|
@@ -240,9 +243,10 @@ export class AgentChatController extends Controller {
|
|
|
240
243
|
}
|
|
241
244
|
catch (error) {
|
|
242
245
|
const message = error instanceof Error ? error.message : `Agent action ${decision} failed`;
|
|
246
|
+
patch({ resolveError: message });
|
|
243
247
|
this.setState({ ...this.state, error: message });
|
|
244
248
|
this.emit("sendFailed", { message });
|
|
245
|
-
|
|
249
|
+
throw error;
|
|
246
250
|
}
|
|
247
251
|
finally {
|
|
248
252
|
this.resolving.delete(key);
|
|
@@ -6,6 +6,16 @@ export async function* readNdjson(stream, options = {}) {
|
|
|
6
6
|
let buffer = "";
|
|
7
7
|
let finished = false;
|
|
8
8
|
const abort = () => { void reader.cancel(options.signal?.reason); };
|
|
9
|
+
const parse = (line) => {
|
|
10
|
+
try {
|
|
11
|
+
return JSON.parse(line);
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
if (options.onInvalidLine?.(line, error) !== "skip")
|
|
15
|
+
throw error;
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
9
19
|
options.signal?.addEventListener("abort", abort, { once: true });
|
|
10
20
|
try {
|
|
11
21
|
while (true) {
|
|
@@ -19,15 +29,21 @@ export async function* readNdjson(stream, options = {}) {
|
|
|
19
29
|
buffer = buffer.slice(newline + 1);
|
|
20
30
|
if (line.length > limit)
|
|
21
31
|
throw new Error("NDJSON line exceeds limit");
|
|
22
|
-
if (line)
|
|
23
|
-
|
|
32
|
+
if (line) {
|
|
33
|
+
const record = parse(line);
|
|
34
|
+
if (record !== undefined)
|
|
35
|
+
yield record;
|
|
36
|
+
}
|
|
24
37
|
}
|
|
25
38
|
if (buffer.length > limit)
|
|
26
39
|
throw new Error("NDJSON line exceeds limit");
|
|
27
40
|
if (done) {
|
|
28
41
|
finished = true;
|
|
29
|
-
if (buffer.trim())
|
|
30
|
-
|
|
42
|
+
if (buffer.trim()) {
|
|
43
|
+
const record = parse(buffer);
|
|
44
|
+
if (record !== undefined)
|
|
45
|
+
yield record;
|
|
46
|
+
}
|
|
31
47
|
break;
|
|
32
48
|
}
|
|
33
49
|
}
|
|
@@ -39,6 +39,13 @@ export interface AgentActionProposal {
|
|
|
39
39
|
outcome?: "done" | "failed";
|
|
40
40
|
resolving?: AgentActionDecision;
|
|
41
41
|
note?: string;
|
|
42
|
+
details?: Array<{
|
|
43
|
+
label: string;
|
|
44
|
+
value: string;
|
|
45
|
+
href?: string;
|
|
46
|
+
}>;
|
|
47
|
+
/** A failed approval request is kept with its proposal so the error appears at the decision point. */
|
|
48
|
+
resolveError?: string;
|
|
42
49
|
}
|
|
43
50
|
export interface AgentChatMessage {
|
|
44
51
|
id: string;
|
|
@@ -11,7 +11,18 @@ export declare class AgentWorkspace extends BaseElement {
|
|
|
11
11
|
private detailsOpen;
|
|
12
12
|
private initialized;
|
|
13
13
|
private renderedActive;
|
|
14
|
+
private chatIds;
|
|
15
|
+
private lastPanes;
|
|
14
16
|
private sessions;
|
|
17
|
+
/** Host-controlled pane state; mobile drawers remain mutually exclusive. */
|
|
18
|
+
get panes(): {
|
|
19
|
+
chats: boolean;
|
|
20
|
+
details: boolean;
|
|
21
|
+
};
|
|
22
|
+
set panes(value: {
|
|
23
|
+
chats?: boolean;
|
|
24
|
+
details?: boolean;
|
|
25
|
+
});
|
|
15
26
|
get workspaceController(): AgentWorkspaceController | null;
|
|
16
27
|
set workspaceController(value: AgentWorkspaceController | null);
|
|
17
28
|
connectedCallback(): void;
|
|
@@ -19,7 +30,8 @@ export declare class AgentWorkspace extends BaseElement {
|
|
|
19
30
|
private listen;
|
|
20
31
|
private resize;
|
|
21
32
|
private storageKey;
|
|
22
|
-
|
|
33
|
+
toggle(pane: "chats" | "details"): void;
|
|
34
|
+
open(pane: "chats" | "details", open: boolean): void;
|
|
23
35
|
private closeDrawers;
|
|
24
36
|
private syncPanes;
|
|
25
37
|
protected renderTemplate(): void;
|