@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
@@ -0,0 +1,382 @@
1
+ import { BaseElement } from "../../core/index.js";
2
+ import { basicSetup } from "codemirror";
3
+ import { Compartment, EditorSelection, EditorState, Prec, } from "@codemirror/state";
4
+ import { EditorView, keymap } from "@codemirror/view";
5
+ import { indentWithTab } from "@codemirror/commands";
6
+ import { javascript } from "@codemirror/lang-javascript";
7
+ import { go } from "@codemirror/lang-go";
8
+ import { autocompletion, closeCompletion, startCompletion, } from "@codemirror/autocomplete";
9
+ import { closeSearchPanel } from "@codemirror/search";
10
+ import { lintGutter, setDiagnostics } from "@codemirror/lint";
11
+ import { HighlightStyle, syntaxHighlighting } from "@codemirror/language";
12
+ import { tags } from "@lezer/highlight";
13
+ /** Optional CodeMirror entrypoint. Import `code-editor`, not the root catalog. */
14
+ export class CodeEditor extends BaseElement {
15
+ static tagName = "box-code-editor";
16
+ static get observedAttributes() {
17
+ return ["language", "readonly", "label", "value"];
18
+ }
19
+ valueInternal = "";
20
+ problemsInternal = [];
21
+ completionsInternal = [];
22
+ view;
23
+ languageConfig = new Compartment();
24
+ readonlyConfig = new Compartment();
25
+ completionsConfig = new Compartment();
26
+ timer;
27
+ pending = false;
28
+ syncing = false;
29
+ problemIndex = -1;
30
+ savedSelection = { anchor: 0, head: 0 };
31
+ escapeUntil = 0;
32
+ get value() {
33
+ return this.valueInternal;
34
+ }
35
+ set value(value) {
36
+ if (this.valueInternal === value)
37
+ return;
38
+ this.valueInternal = value;
39
+ if (this.isRendered)
40
+ this.update();
41
+ }
42
+ get language() {
43
+ return this.getAttribute("language") ?? "typescript";
44
+ }
45
+ set language(value) {
46
+ this.setAttribute("language", value);
47
+ }
48
+ get readonly() {
49
+ return this.hasAttribute("readonly");
50
+ }
51
+ set readonly(value) {
52
+ this.toggleAttribute("readonly", value);
53
+ }
54
+ get label() {
55
+ return this.getAttribute("label") ?? "Code editor";
56
+ }
57
+ set label(value) {
58
+ this.setAttribute("label", value);
59
+ }
60
+ get problems() {
61
+ return this.problemsInternal;
62
+ }
63
+ set problems(value) {
64
+ this.problemsInternal = [...value];
65
+ this.problemIndex = -1;
66
+ this.syncProblems();
67
+ }
68
+ get completions() {
69
+ return this.completionsInternal;
70
+ }
71
+ set completions(value) {
72
+ this.completionsInternal = [...value];
73
+ if (this.isRendered)
74
+ this.update();
75
+ }
76
+ get selection() {
77
+ return this.view
78
+ ? {
79
+ anchor: this.view.state.selection.main.anchor,
80
+ head: this.view.state.selection.main.head,
81
+ }
82
+ : this.savedSelection;
83
+ }
84
+ set selection(value) {
85
+ const clamp = (offset) => Math.max(0, Math.min(this.value.length, Number.isFinite(offset) ? offset : 0));
86
+ this.savedSelection = {
87
+ anchor: clamp(value.anchor),
88
+ head: clamp(value.head),
89
+ };
90
+ this.view?.dispatch({
91
+ selection: EditorSelection.single(this.savedSelection.anchor, this.savedSelection.head),
92
+ scrollIntoView: true,
93
+ });
94
+ }
95
+ revealLine(line) {
96
+ if (!this.view)
97
+ return;
98
+ const target = this.view.state.doc.line(Math.max(1, Math.min(this.view.state.doc.lines, Math.floor(line) || 1)));
99
+ this.selection = { anchor: target.from, head: target.from };
100
+ this.view.focus();
101
+ }
102
+ focus() {
103
+ this.view?.focus();
104
+ }
105
+ attributeChangedCallback(name, oldValue, newValue) {
106
+ if (name === "value")
107
+ this.valueInternal = newValue ?? "";
108
+ super.attributeChangedCallback(name, oldValue, newValue);
109
+ }
110
+ connectedCallback() {
111
+ super.connectedCallback();
112
+ }
113
+ disconnectedCallback() {
114
+ this.flushChange();
115
+ this.savedSelection = this.selection;
116
+ this.view?.destroy();
117
+ this.view = undefined;
118
+ }
119
+ renderTemplate() {
120
+ this.shadowRoot.innerHTML = `<style>
121
+ :host{display:block;min-width:0;color:var(--boe-token-text-text,#222);font:inherit}
122
+ :host([hidden]){display:none!important}
123
+ [part=editor]{border:1px solid var(--boe-token-stroke-stroke,#ddd);border-radius:8px;overflow:hidden}
124
+ .cm-editor{background:var(--boe-token-surface-surface,#fff);color:var(--boe-token-text-text,#222)}
125
+ [part=editor]:focus-within{box-shadow:0 0 0 3px var(--boe-token-surface-surface-brand,#0061d5)}
126
+ .cm-editor.cm-focused{outline:none}
127
+ .cm-scroller{max-height:var(--boe-code-editor-height,420px);min-height:160px;overflow:auto;font-family:monospace;font-size:14px;line-height:1.6}
128
+ .cm-gutters,.cm-panels,.cm-tooltip{background:var(--boe-token-surface-surface-secondary,#fbfbfb)!important;color:var(--boe-token-text-text,#222)!important;border-color:var(--boe-token-stroke-stroke,#ddd)!important}
129
+ .cm-cursor{border-left-color:var(--boe-token-text-text,#222)}
130
+ .cm-activeLine,.cm-activeLineGutter,.cm-selectionBackground{background:color-mix(in srgb,var(--boe-token-surface-surface-brand,#0061d5) 12%,transparent)!important}
131
+ .cm-matchingBracket,.cm-selectionMatch{background:color-mix(in srgb,var(--boe-token-surface-surface-brand,#0061d5) 15%,transparent)!important;color:inherit!important}
132
+ .cm-nonmatchingBracket{color:var(--boe-token-text-status-text-error,#b92340)!important}
133
+ .cm-searchMatch{background:color-mix(in srgb,var(--boe-token-text-status-text-warning,#9a6500) 20%,transparent);outline:none}
134
+ .cm-searchMatch-selected,.cm-tooltip-autocomplete ul li[aria-selected=true]{background:var(--boe-token-surface-surface-brand,#0061d5)!important;color:var(--boe-token-text-text-on-brand,#fff)!important}
135
+ .cm-panels input,.cm-panels button,.cm-foldPlaceholder{background:var(--boe-token-surface-surface,#fff);color:var(--boe-token-text-text,#222);border:1px solid var(--boe-token-stroke-stroke,#ddd)}
136
+ .cm-lintRange-error,.cm-lintRange-warning,.cm-lintRange-info{background-image:none;text-decoration-line:underline;text-decoration-style:wavy;text-decoration-thickness:1px;text-underline-offset:3px}
137
+ .cm-lintRange-error,.cm-diagnostic-error{color:inherit;text-decoration-color:var(--boe-token-text-status-text-error,#b92340);border-left-color:var(--boe-token-text-status-text-error,#b92340)}
138
+ .cm-lintRange-warning,.cm-diagnostic-warning{text-decoration-color:var(--boe-token-text-status-text-warning,#9a6500);border-left-color:var(--boe-token-text-status-text-warning,#9a6500)}
139
+ .cm-lintRange-info,.cm-diagnostic-info{text-decoration-color:var(--boe-token-surface-surface-brand,#0061d5);border-left-color:var(--boe-token-surface-surface-brand,#0061d5)}
140
+ .cm-lint-marker-error{background-image:radial-gradient(circle,var(--boe-token-text-status-text-error,#b92340) 45%,transparent 50%)!important}
141
+ .cm-lint-marker-warning{background-image:radial-gradient(circle,var(--boe-token-text-status-text-warning,#9a6500) 45%,transparent 50%)!important}
142
+ .cm-lint-marker-info{background-image:radial-gradient(circle,var(--boe-token-surface-surface-brand,#0061d5) 45%,transparent 50%)!important}
143
+ [part=help],[part=problems]{font-size:13px;color:var(--boe-token-text-text-secondary,#666);margin:8px 0}
144
+ [part=toolbar]{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
145
+ button{font:inherit;color:inherit;background:var(--boe-token-surface-surface,#fff);border:1px solid var(--boe-token-stroke-stroke,#ddd);border-radius:8px;padding:8px;min-height:36px}
146
+ button:focus-visible{outline:3px solid var(--boe-token-surface-surface-brand,#0061d5);outline-offset:2px}
147
+ @media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important;scroll-behavior:auto!important}}
148
+ </style><div part="editor"></div><p part="help" id="editor-help">Press Escape then Tab to leave the editor. Use Control-Space for suggestions.</p><div part="toolbar"><button type="button" data-direction="-1">Previous problem</button><button type="button" data-direction="1">Next problem</button><span part="problems" role="status" aria-live="polite"></span></div>`;
149
+ }
150
+ setupListeners() {
151
+ this.shadowRoot.querySelectorAll("button[data-direction]").forEach((button) => button.addEventListener("click", () => this.navigateProblem(Number(button.dataset.direction))));
152
+ // Keep the advertised escape hatch independent of completion/search keymaps.
153
+ this.shadowRoot.addEventListener("keydown", (event) => {
154
+ const key = event;
155
+ if (!key.target.closest(".cm-content"))
156
+ return;
157
+ if (key.ctrlKey && (key.code === "Space" || key.key === " ")) {
158
+ key.preventDefault();
159
+ key.stopPropagation();
160
+ if (this.view && !this.readonly)
161
+ startCompletion(this.view);
162
+ }
163
+ else if (key.key === "Escape")
164
+ this.escapeUntil = Date.now() + 2000;
165
+ else if (key.key === "Tab" && Date.now() <= this.escapeUntil) {
166
+ key.preventDefault();
167
+ key.stopPropagation();
168
+ this.escapeUntil = 0;
169
+ const target = this.shadowRoot.querySelector("button:not(:disabled)") ?? this.shadowRoot.querySelector("[part=help]");
170
+ target.setAttribute("tabindex", "0");
171
+ target.focus();
172
+ }
173
+ else if (!key.ctrlKey &&
174
+ !key.metaKey &&
175
+ !key.altKey &&
176
+ key.key !== "Shift")
177
+ this.escapeUntil = 0;
178
+ }, { capture: true });
179
+ }
180
+ languageExtension() {
181
+ return this.language === "go"
182
+ ? go()
183
+ : javascript({ typescript: this.language === "typescript" });
184
+ }
185
+ completionExtension() {
186
+ return autocompletion({
187
+ override: [
188
+ (context) => {
189
+ const word = context.matchBefore(/[\w$]+(?:\.[\w$]*)*/);
190
+ if (!word && !context.explicit)
191
+ return null;
192
+ let from = word?.from ?? context.pos;
193
+ // A full SDK name replaces its prefix; a method replaces only the
194
+ // identifier after the receiver's dot (for example flow().st).
195
+ if (word?.text.includes(".") &&
196
+ !this.completionsInternal.some((option) => option.label.startsWith(word.text))) {
197
+ from += word.text.lastIndexOf(".") + 1;
198
+ }
199
+ return { from, options: [...this.completionsInternal] };
200
+ },
201
+ ],
202
+ });
203
+ }
204
+ update() {
205
+ if (!this.view) {
206
+ this.view = new EditorView({
207
+ parent: this.shadowRoot.querySelector("[part=editor]"),
208
+ root: this.shadowRoot,
209
+ state: EditorState.create({
210
+ doc: this.value,
211
+ extensions: [
212
+ basicSetup,
213
+ lintGutter(),
214
+ keymap.of([indentWithTab]),
215
+ Prec.highest(keymap.of([
216
+ {
217
+ key: "Escape",
218
+ run: (view) => {
219
+ closeCompletion(view);
220
+ closeSearchPanel(view);
221
+ view.setTabFocusMode(2000);
222
+ return true;
223
+ },
224
+ },
225
+ ])),
226
+ this.languageConfig.of(this.languageExtension()),
227
+ this.readonlyConfig.of([
228
+ EditorState.readOnly.of(this.readonly),
229
+ EditorView.editable.of(!this.readonly),
230
+ ]),
231
+ this.completionsConfig.of(this.completionExtension()),
232
+ syntaxHighlighting(HighlightStyle.define([
233
+ {
234
+ tag: [
235
+ tags.variableName,
236
+ tags.definition(tags.variableName),
237
+ tags.propertyName,
238
+ tags.operator,
239
+ tags.punctuation,
240
+ ],
241
+ color: "var(--boe-token-text-text,#222)",
242
+ },
243
+ {
244
+ tag: tags.keyword,
245
+ color: "var(--boe-token-surface-surface-brand,#0061d5)",
246
+ },
247
+ {
248
+ tag: [
249
+ tags.typeName,
250
+ tags.className,
251
+ tags.function(tags.variableName),
252
+ ],
253
+ color: "var(--boe-token-surface-surface-brand,#0061d5)",
254
+ },
255
+ {
256
+ tag: tags.string,
257
+ color: "var(--boe-token-text-status-text-success,#138a58)",
258
+ },
259
+ {
260
+ tag: tags.comment,
261
+ color: "var(--boe-token-text-text-secondary,#666)",
262
+ },
263
+ {
264
+ tag: tags.number,
265
+ color: "var(--boe-token-text-status-text-warning,#9a6500)",
266
+ },
267
+ {
268
+ tag: [tags.bool, tags.null, tags.atom],
269
+ color: "var(--boe-token-text-status-text-warning,#9a6500)",
270
+ },
271
+ ])),
272
+ EditorView.updateListener.of((update) => {
273
+ if (update.docChanged && !this.syncing) {
274
+ this.valueInternal = update.state.doc.toString();
275
+ this.pending = true;
276
+ clearTimeout(this.timer);
277
+ this.timer = setTimeout(() => this.flushChange(), 200);
278
+ }
279
+ }),
280
+ EditorView.domEventHandlers({
281
+ blur: () => {
282
+ this.flushChange();
283
+ return false;
284
+ },
285
+ }),
286
+ ],
287
+ }),
288
+ });
289
+ this.selection = this.savedSelection;
290
+ }
291
+ else {
292
+ this.syncing = true;
293
+ try {
294
+ if (this.view.state.doc.toString() !== this.value) {
295
+ clearTimeout(this.timer);
296
+ this.pending = false;
297
+ this.view.dispatch({
298
+ changes: {
299
+ from: 0,
300
+ to: this.view.state.doc.length,
301
+ insert: this.value,
302
+ },
303
+ });
304
+ }
305
+ this.view.dispatch({
306
+ effects: [
307
+ this.languageConfig.reconfigure(this.languageExtension()),
308
+ this.readonlyConfig.reconfigure([
309
+ EditorState.readOnly.of(this.readonly),
310
+ EditorView.editable.of(!this.readonly),
311
+ ]),
312
+ this.completionsConfig.reconfigure(this.completionExtension()),
313
+ ],
314
+ });
315
+ }
316
+ finally {
317
+ this.syncing = false;
318
+ }
319
+ }
320
+ this.view.contentDOM.setAttribute("aria-label", this.label);
321
+ this.view.contentDOM.setAttribute("tabindex", "0");
322
+ this.view.contentDOM.setAttribute("aria-describedby", "editor-help");
323
+ this.syncProblems();
324
+ }
325
+ flushChange() {
326
+ clearTimeout(this.timer);
327
+ if (!this.pending)
328
+ return;
329
+ this.pending = false;
330
+ this.dispatchEvent(new CustomEvent("value-changed", {
331
+ detail: { value: this.value },
332
+ bubbles: true,
333
+ composed: true,
334
+ }));
335
+ }
336
+ diagnostics() {
337
+ if (!this.view)
338
+ return [];
339
+ const doc = this.view.state.doc;
340
+ return this.problems
341
+ .filter((problem) => Number.isInteger(problem.line) &&
342
+ problem.line >= 1 &&
343
+ problem.line <= doc.lines)
344
+ .map((problem) => {
345
+ const line = doc.line(problem.line);
346
+ const column = Number.isFinite(problem.col) ? problem.col : 1;
347
+ const endColumn = Number.isFinite(problem.endCol)
348
+ ? problem.endCol
349
+ : column + 1;
350
+ const from = line.from + Math.max(0, Math.min(line.length, column - 1));
351
+ const to = Math.max(from, Math.min(line.to, line.from + endColumn - 1));
352
+ return { from, to, message: problem.message, severity: problem.tone };
353
+ });
354
+ }
355
+ syncProblems() {
356
+ if (!this.view)
357
+ return;
358
+ const diagnostics = this.diagnostics();
359
+ this.view.dispatch(setDiagnostics(this.view.state, diagnostics));
360
+ this.shadowRoot.querySelector("[part=problems]").textContent =
361
+ `${diagnostics.length} problem${diagnostics.length === 1 ? "" : "s"}`;
362
+ this.shadowRoot.querySelectorAll("button[data-direction]").forEach((button) => (button.disabled = diagnostics.length === 0));
363
+ }
364
+ navigateProblem(direction) {
365
+ const diagnostics = this.diagnostics();
366
+ if (!diagnostics.length)
367
+ return;
368
+ this.problemIndex =
369
+ this.problemIndex < 0
370
+ ? direction < 0
371
+ ? diagnostics.length - 1
372
+ : 0
373
+ : (this.problemIndex + (direction < 0 ? -1 : 1) + diagnostics.length) %
374
+ diagnostics.length;
375
+ const problem = diagnostics[this.problemIndex];
376
+ this.selection = { anchor: problem.from, head: problem.to };
377
+ this.focus();
378
+ this.shadowRoot.querySelector("[part=problems]").textContent =
379
+ `Problem ${this.problemIndex + 1} of ${diagnostics.length}: ${problem.message}`;
380
+ }
381
+ }
382
+ CodeEditor.register();
@@ -1,5 +1,5 @@
1
1
  import { FormAssociatedElement, boeFormFieldErrorStyles, formErrorMessageMarkup, } from "../../core/index.js";
2
- import { boeNeutralInteractiveStyles } from "../../foundations/tokens/index.js";
2
+ import { boeNeutralInteractiveStyles } from "../../foundations/tokens/interaction.js";
3
3
  import { boeMotionDuration, boeMotionEasing } from "../../foundations/motion/index.js";
4
4
  import { boeOverlay, boeRadius } from "../../foundations/geometry/index.js";
5
5
  import { parsePlacement, trackAnchor, } from "../../foundations/overlay/index.js";
@@ -1,5 +1,5 @@
1
1
  import { FormAssociatedElement, boeFormFieldErrorStyles, boeFormFieldSupportStyles, formDescriptionMarkup, formErrorMessageMarkup, } from "../../core/index.js";
2
- import { boeNeutralInteractiveStyles } from "../../foundations/tokens/index.js";
2
+ import { boeNeutralInteractiveStyles } from "../../foundations/tokens/interaction.js";
3
3
  import { boeMotionDuration, boeMotionEasing } from "../../foundations/motion/index.js";
4
4
  import { boeRadius } from "../../foundations/geometry/index.js";
5
5
  const DEFAULT_TAG_NAME = "box-date-field";
@@ -1,7 +1,7 @@
1
1
  import { FormAssociatedElement, boeFormFieldErrorStyles, formErrorMessageMarkup, } from "../../core/index.js";
2
2
  import { boeControl, boeOverlay, boeRadius, boeSpace } from "../../foundations/geometry/index.js";
3
3
  import { FocusRestore, applyRovingTabindex, focusRovingItem, nextRovingIndex, } from "../../foundations/a11y/index.js";
4
- import { boeFocusVisibleStyles, boeNeutralInteractiveStyles, } from "../../foundations/tokens/index.js";
4
+ import { boeFocusVisibleStyles, boeNeutralInteractiveStyles, } from "../../foundations/tokens/interaction.js";
5
5
  import { boeMotionDuration, boeMotionEasing } from "../../foundations/motion/index.js";
6
6
  import { parsePlacement, trackAnchor, } from "../../foundations/overlay/index.js";
7
7
  const DEFAULT_TAG_NAME = "box-dropdown";
@@ -1,5 +1,5 @@
1
1
  import { FormAssociatedElement, boeFormFieldErrorStyles, formDataFromNamedValues, formErrorMessageMarkup, stringValuesFromFormValue, } from "../../core/index.js";
2
- import { boeFocusRingShadow, boeFocusVisibleStyles, } from "../../foundations/tokens/index.js";
2
+ import { boeFocusRingShadow, boeFocusVisibleStyles, } from "../../foundations/tokens/interaction.js";
3
3
  import { boeMotionDuration, boeMotionEasing } from "../../foundations/motion/index.js";
4
4
  import { boeRadius } from "../../foundations/geometry/index.js";
5
5
  const DEFAULT_TAG_NAME = "box-multi-select";
@@ -1,5 +1,5 @@
1
1
  import { FormAssociatedElement, boeFormFieldErrorStyles, boeFormFieldSupportStyles, formDescriptionMarkup, formErrorMessageMarkup, } from "../../core/index.js";
2
- import { boeNeutralInteractiveStyles } from "../../foundations/tokens/index.js";
2
+ import { boeNeutralInteractiveStyles } from "../../foundations/tokens/interaction.js";
3
3
  import { boeMotionDuration, boeMotionEasing } from "../../foundations/motion/index.js";
4
4
  import { boeControl, boeRadius } from "../../foundations/geometry/index.js";
5
5
  const DEFAULT_TAG_NAME = "box-number-input";
@@ -35,6 +35,9 @@ const numberInputStyles = `
35
35
  }
36
36
 
37
37
  [part="input"] {
38
+ width: 100%;
39
+ min-width: 0;
40
+ box-sizing: border-box;
38
41
  font: inherit;
39
42
  color: var(--boe-token-text-text, #222222);
40
43
  padding: 0.45rem 0.7rem;
@@ -64,7 +67,7 @@ export class NumberInput extends FormAssociatedElement {
64
67
  static tagName = DEFAULT_TAG_NAME;
65
68
  static get observedAttributes() {
66
69
  return [
67
- ...FormAssociatedElement.formObservedAttributes,
70
+ ...FormAssociatedElement.fieldObservedAttributes,
68
71
  "disabled",
69
72
  "label",
70
73
  "max",
@@ -1,5 +1,5 @@
1
1
  import { FORM_ERROR_MESSAGE_ID, FormAssociatedElement, boeFormFieldErrorStyles, formErrorMessageMarkup, } from "../../core/index.js";
2
- import { boeFocusRingShadow, boeFocusVisibleStyles, } from "../../foundations/tokens/index.js";
2
+ import { boeFocusRingShadow, boeFocusVisibleStyles, } from "../../foundations/tokens/interaction.js";
3
3
  import { boeMotionDuration, boeMotionEasing } from "../../foundations/motion/index.js";
4
4
  import { boeRadius } from "../../foundations/geometry/index.js";
5
5
  const DEFAULT_TAG_NAME = "box-radio-group";
@@ -1,5 +1,5 @@
1
1
  import { FormAssociatedElement, boeFormFieldErrorStyles, formDataFromRange, formErrorMessageMarkup, rangeFromFormValue, } from "../../core/index.js";
2
- import { boeFocusVisibleStyles } from "../../foundations/tokens/index.js";
2
+ import { boeFocusVisibleStyles } from "../../foundations/tokens/interaction.js";
3
3
  const DEFAULT_TAG_NAME = "box-range-slider";
4
4
  const parseNumber = (value, fallback) => {
5
5
  if (value == null || value === "") {
@@ -1,5 +1,5 @@
1
1
  import { FormAssociatedElement, boeFormFieldErrorStyles, formErrorMessageMarkup, } from "../../core/index.js";
2
- import { boeFocusVisibleStyles } from "../../foundations/tokens/index.js";
2
+ import { boeFocusVisibleStyles } from "../../foundations/tokens/interaction.js";
3
3
  const DEFAULT_TAG_NAME = "box-slider";
4
4
  const parseNumber = (value, fallback) => {
5
5
  if (value == null || value === "") {
@@ -1,6 +1,6 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
2
  import { boeRadius } from "../../foundations/geometry/index.js";
3
- import { boeFocusRingShadow } from "../../foundations/tokens/index.js";
3
+ import { boeFocusRingShadow } from "../../foundations/tokens/interaction.js";
4
4
  const DEFAULT_TAG_NAME = "box-tile-group";
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 { boeMotionDuration, boeMotionEasing } from "../../foundations/motion/index.js";
4
4
  import { boeRadius } from "../../foundations/geometry/index.js";
5
5
  const DEFAULT_TAG_NAME = "box-sidebar-toggle-button";
@@ -1,6 +1,6 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
2
  import { boeRadius } from "../../foundations/geometry/index.js";
3
- import { boeNeutralInteractiveStyles } from "../../foundations/tokens/index.js";
3
+ import { boeNeutralInteractiveStyles } from "../../foundations/tokens/interaction.js";
4
4
  const DEFAULT_TAG_NAME = "box-accordion";
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 { boeControl, boeRadius, boeSpace } from "../../foundations/geometry/index.js";
3
- import { boeFocusVisibleStyles, } from "../../foundations/tokens/index.js";
3
+ import { boeFocusVisibleStyles, } from "../../foundations/tokens/interaction.js";
4
4
  import { boeMotionDuration, boeMotionEasing } from "../../foundations/motion/index.js";
5
5
  const DEFAULT_TAG_NAME = "box-tabs";
6
6
  const escapeHtml = (value) => value
@@ -1,6 +1,6 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
2
  import { boeRadius } from "../../foundations/geometry/index.js";
3
- import { boeFocusVisibleStyles } from "../../foundations/tokens/index.js";
3
+ import { boeFocusVisibleStyles } from "../../foundations/tokens/interaction.js";
4
4
  const DEFAULT_TAG_NAME = "box-code-block";
5
5
  const COPY_ICON = `<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" focusable="false"><rect x="5.5" y="5.5" width="8" height="8" rx="1.5"/><path d="M10.5 3.5v-1a1 1 0 00-1-1h-7a1 1 0 00-1 1v7a1 1 0 001 1h1"/></svg>`;
6
6
  const COPIED_ICON = `<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" focusable="false"><path d="M3 8.5l3.2 3.2L13 5"/></svg>`;
@@ -2,7 +2,7 @@ import { BaseElement } from "../../core/index.js";
2
2
  import { dismissModal, promoteModal } from "../../foundations/overlay/index.js";
3
3
  import { FocusRestore, trapTabKey } from "../../foundations/a11y/index.js";
4
4
  import { boeControl, boeOverlay, boeRadius, boeSpace } from "../../foundations/geometry/index.js";
5
- import { boeBrandInteractiveStyles, boeNeutralInteractiveStyles, } from "../../foundations/tokens/index.js";
5
+ import { boeBrandInteractiveStyles, boeNeutralInteractiveStyles, } from "../../foundations/tokens/interaction.js";
6
6
  const DEFAULT_TAG_NAME = "box-dialog";
7
7
  const dialogStyles = `
8
8
  :host {
@@ -2,7 +2,7 @@ import { BaseElement } from "../../core/index.js";
2
2
  import { FocusRestore, trapTabKey } from "../../foundations/a11y/index.js";
3
3
  import { dismissModal, promoteModal } from "../../foundations/overlay/index.js";
4
4
  import { boeControl, boeOverlay, boePanel, boeRadius, boeSpace, } from "../../foundations/geometry/index.js";
5
- import { boeNeutralInteractiveStyles } from "../../foundations/tokens/index.js";
5
+ import { boeNeutralInteractiveStyles } from "../../foundations/tokens/interaction.js";
6
6
  const DEFAULT_TAG_NAME = "box-drawer";
7
7
  const drawerStyles = `
8
8
  :host {
@@ -1,7 +1,7 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
2
  import { dismissPopover, promotePopover } from "../../foundations/overlay/index.js";
3
3
  import { boeControl, boeOverlay, boeRadius, boeSpace } from "../../foundations/geometry/index.js";
4
- import { boeNeutralInteractiveStyles } from "../../foundations/tokens/index.js";
4
+ import { boeNeutralInteractiveStyles } from "../../foundations/tokens/interaction.js";
5
5
  import { boeMotionDuration, boeMotionEasing } from "../../foundations/motion/index.js";
6
6
  import { parsePlacement, trackAnchor, } from "../../foundations/overlay/index.js";
7
7
  const DEFAULT_TAG_NAME = "box-guide-tooltip";
@@ -2,7 +2,7 @@ import { BaseElement } from "../../core/index.js";
2
2
  import { dismissPopover, promotePopover } from "../../foundations/overlay/index.js";
3
3
  import { FocusRestore, getTabbableElements } from "../../foundations/a11y/index.js";
4
4
  import { boeControl, boeOverlay, boeRadius } from "../../foundations/geometry/index.js";
5
- import { boeNeutralInteractiveStyles } from "../../foundations/tokens/index.js";
5
+ import { boeNeutralInteractiveStyles } from "../../foundations/tokens/interaction.js";
6
6
  import { boeMotionDuration, boeMotionEasing } from "../../foundations/motion/index.js";
7
7
  import { parsePlacement, trackAnchor, } from "../../foundations/overlay/index.js";
8
8
  const DEFAULT_TAG_NAME = "box-popover";
@@ -1,7 +1,7 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
2
  import { dismissPopover, promotePopover } from "../../foundations/overlay/index.js";
3
3
  import { boeRadius } from "../../foundations/geometry/index.js";
4
- import { boeNeutralInteractiveStyles } from "../../foundations/tokens/index.js";
4
+ import { boeNeutralInteractiveStyles } from "../../foundations/tokens/interaction.js";
5
5
  import { parsePlacement, trackAnchor, } from "../../foundations/overlay/index.js";
6
6
  const DEFAULT_TAG_NAME = "box-tooltip";
7
7
  const DEFAULT_TRIGGER_LABEL = "More information";
@@ -30,6 +30,7 @@ export declare const boeFormFieldErrorStyles = "\n :host([invalid]) [part=\"inp
30
30
  export declare const FORM_ERROR_MESSAGE_ID = "boe-field-error";
31
31
  export declare const formErrorMessageMarkup: () => string;
32
32
  export declare const FORM_DESCRIPTION_ID = "boe-field-description";
33
+ export declare const FORM_LABEL_ID = "boe-field-label";
33
34
  /** Optional help text rendered under the label (shown only when `description` is set). */
34
35
  export declare const formDescriptionMarkup: () => string;
35
36
  /**
@@ -125,6 +125,7 @@ export const boeFormFieldErrorStyles = `
125
125
  export const FORM_ERROR_MESSAGE_ID = "boe-field-error";
126
126
  export const formErrorMessageMarkup = () => `<p part="error-message" id="${FORM_ERROR_MESSAGE_ID}" role="alert" hidden></p>`;
127
127
  export const FORM_DESCRIPTION_ID = "boe-field-description";
128
+ export const FORM_LABEL_ID = "boe-field-label";
128
129
  /** Optional help text rendered under the label (shown only when `description` is set). */
129
130
  export const formDescriptionMarkup = () => `<p part="description" id="${FORM_DESCRIPTION_ID}" hidden></p>`;
130
131
  /**
@@ -302,6 +303,7 @@ export class FormAssociatedElement extends BaseElement {
302
303
  const required = this.required;
303
304
  const description = this.description;
304
305
  if (labelEl) {
306
+ labelEl.id = FORM_LABEL_ID;
305
307
  const existing = labelEl.querySelector(".boe-required-mark");
306
308
  if (required && !existing) {
307
309
  const mark = document.createElement("span");
@@ -315,6 +317,7 @@ export class FormAssociatedElement extends BaseElement {
315
317
  }
316
318
  }
317
319
  if (control) {
320
+ control.setAttribute("aria-labelledby", FORM_LABEL_ID);
318
321
  control.toggleAttribute("required", required);
319
322
  control.setAttribute("aria-required", String(required));
320
323
  if (description) {
@@ -0,0 +1 @@
1
+ export * from "../components/forms/code-editor.js";
@@ -0,0 +1 @@
1
+ export * from "../components/forms/code-editor.js";