@unofficialbox/box-open-elements 0.23.0 → 0.25.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 (54) hide show
  1. package/README.md +15 -13
  2. package/dist/components/actions/button.d.ts +1 -0
  3. package/dist/components/actions/button.js +16 -3
  4. package/dist/components/actions/segmented-control.d.ts +1 -0
  5. package/dist/components/actions/segmented-control.js +20 -6
  6. package/dist/components/feedback/alert.js +1 -1
  7. package/dist/components/feedback/progress-bar.js +2 -2
  8. package/dist/components/forms/checkbox.d.ts +1 -0
  9. package/dist/components/forms/checkbox.js +6 -2
  10. package/dist/components/forms/code-editor.d.ts +86 -0
  11. package/dist/components/forms/code-editor.js +447 -0
  12. package/dist/components/forms/combobox.js +7 -8
  13. package/dist/components/forms/number-input.d.ts +1 -0
  14. package/dist/components/forms/number-input.js +8 -2
  15. package/dist/components/forms/select.d.ts +1 -0
  16. package/dist/components/forms/select.js +3 -1
  17. package/dist/components/forms/text-area.js +5 -7
  18. package/dist/components/forms/text-field.d.ts +1 -0
  19. package/dist/components/forms/text-field.js +2 -0
  20. package/dist/components/navigation/accordion.d.ts +7 -0
  21. package/dist/components/navigation/accordion.js +31 -8
  22. package/dist/components/output/code-block.js +3 -1
  23. package/dist/components/overlays/drawer.js +2 -2
  24. package/dist/core/form-associated.d.ts +1 -0
  25. package/dist/core/form-associated.js +3 -0
  26. package/dist/entries/code-editor.d.ts +1 -0
  27. package/dist/entries/code-editor.js +1 -0
  28. package/dist/foundations/geometry/tokens.d.ts +2 -2
  29. package/dist/foundations/geometry/tokens.js +3 -3
  30. package/dist/foundations/icons/box-iconography.generated.js +1 -0
  31. package/dist/foundations/icons/glyphs/constants.d.ts +472 -0
  32. package/dist/foundations/icons/glyphs/constants.js +473 -0
  33. package/dist/foundations/icons/glyphs/index.d.ts +1 -1
  34. package/dist/foundations/icons/glyphs/index.js +1 -1
  35. package/dist/index.d.ts +1 -0
  36. package/dist/index.js +1 -0
  37. package/dist/patterns/flow-builder/flow-builder.d.ts +7 -1
  38. package/dist/patterns/flow-builder/flow-builder.js +32 -15
  39. package/dist/patterns/flow-builder/model.d.ts +2 -0
  40. package/dist/patterns/flow-builder/model.js +3 -3
  41. package/dist/patterns/flow-builder/primitives.d.ts +1 -0
  42. package/dist/patterns/flow-builder/primitives.js +5 -4
  43. package/dist/patterns/insights/metric-card.js +2 -2
  44. package/dist/patterns/process-modeler/bridge.d.ts +10 -0
  45. package/dist/patterns/process-modeler/bridge.js +173 -0
  46. package/dist/patterns/process-modeler/geometry.d.ts +18 -0
  47. package/dist/patterns/process-modeler/geometry.js +307 -0
  48. package/dist/patterns/process-modeler/index.d.ts +4 -0
  49. package/dist/patterns/process-modeler/index.js +4 -0
  50. package/dist/patterns/process-modeler/model.d.ts +135 -0
  51. package/dist/patterns/process-modeler/model.js +113 -0
  52. package/dist/patterns/process-modeler/process-modeler.d.ts +130 -0
  53. package/dist/patterns/process-modeler/process-modeler.js +1507 -0
  54. package/package.json +21 -3
@@ -0,0 +1,447 @@
1
+ import { BaseElement } from "../../core/index.js";
2
+ import { basicSetup } from "codemirror";
3
+ import { Compartment, EditorSelection, EditorState, Prec, Transaction, } from "@codemirror/state";
4
+ import { Decoration, 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", "wrap"];
18
+ }
19
+ valueInternal = "";
20
+ problemsInternal = [];
21
+ completionsInternal = [];
22
+ view;
23
+ languageConfig = new Compartment();
24
+ readonlyConfig = new Compartment();
25
+ completionsConfig = new Compartment();
26
+ wrapConfig = new Compartment();
27
+ highlightsConfig = new Compartment();
28
+ highlightsInternal = [];
29
+ source;
30
+ timer;
31
+ pending = false;
32
+ syncing = false;
33
+ problemIndex = -1;
34
+ savedSelection = { anchor: 0, head: 0 };
35
+ escapeUntil = 0;
36
+ get value() {
37
+ return this.valueInternal;
38
+ }
39
+ set value(value) {
40
+ if (this.valueInternal === value)
41
+ return;
42
+ this.valueInternal = value;
43
+ if (this.isRendered)
44
+ this.update();
45
+ }
46
+ /** Host replacements are silent and excluded from the typing undo stack. */
47
+ setValue(value, options = {}) {
48
+ if (!options.addToHistory || !this.view) {
49
+ this.value = value;
50
+ return;
51
+ }
52
+ clearTimeout(this.timer);
53
+ this.pending = false;
54
+ this.syncing = true;
55
+ try {
56
+ this.view.dispatch({ changes: { from: 0, to: this.view.state.doc.length, insert: value } });
57
+ this.valueInternal = value;
58
+ }
59
+ finally {
60
+ this.syncing = false;
61
+ }
62
+ this.syncProblems();
63
+ }
64
+ get wrap() { return this.hasAttribute("wrap"); }
65
+ set wrap(value) { this.toggleAttribute("wrap", value); }
66
+ get completionSource() { return this.source; }
67
+ set completionSource(value) { this.source = value; if (this.isRendered)
68
+ this.update(); }
69
+ get highlights() { return this.highlightsInternal.map(range => ({ ...range })); }
70
+ set highlights(value) { this.highlightsInternal = value.map(range => ({ ...range })); if (this.isRendered)
71
+ this.update(); }
72
+ highlightExtension() {
73
+ return EditorView.decorations.of(view => {
74
+ const doc = view.state.doc;
75
+ const lines = new Set();
76
+ for (const range of this.highlightsInternal) {
77
+ if (!Number.isFinite(range.from) || !Number.isFinite(range.to))
78
+ continue;
79
+ const from = Math.max(0, Math.min(doc.length, range.from));
80
+ const to = Math.max(from, Math.min(doc.length, range.to));
81
+ for (let line = doc.lineAt(from).number; line <= doc.lineAt(Math.max(from, to - 1)).number; line++) {
82
+ lines.add(doc.line(line).from);
83
+ }
84
+ }
85
+ return Decoration.set([...lines].sort((a, b) => a - b).map(from => Decoration.line({ class: "boe-code-highlight", attributes: { part: "highlight" } }).range(from)));
86
+ });
87
+ }
88
+ get language() {
89
+ return this.getAttribute("language") ?? "typescript";
90
+ }
91
+ set language(value) {
92
+ this.setAttribute("language", value);
93
+ }
94
+ get readonly() {
95
+ return this.hasAttribute("readonly");
96
+ }
97
+ set readonly(value) {
98
+ this.toggleAttribute("readonly", value);
99
+ }
100
+ get label() {
101
+ return this.getAttribute("label") ?? "Code editor";
102
+ }
103
+ set label(value) {
104
+ this.setAttribute("label", value);
105
+ }
106
+ get problems() {
107
+ return this.problemsInternal;
108
+ }
109
+ set problems(value) {
110
+ this.problemsInternal = [...value];
111
+ this.problemIndex = -1;
112
+ this.syncProblems();
113
+ }
114
+ get completions() {
115
+ return this.completionsInternal;
116
+ }
117
+ set completions(value) {
118
+ this.completionsInternal = [...value];
119
+ if (this.isRendered)
120
+ this.update();
121
+ }
122
+ get selection() {
123
+ return this.view
124
+ ? {
125
+ anchor: this.view.state.selection.main.anchor,
126
+ head: this.view.state.selection.main.head,
127
+ }
128
+ : this.savedSelection;
129
+ }
130
+ set selection(value) {
131
+ const clamp = (offset) => Math.max(0, Math.min(this.value.length, Number.isFinite(offset) ? offset : 0));
132
+ this.savedSelection = {
133
+ anchor: clamp(value.anchor),
134
+ head: clamp(value.head),
135
+ };
136
+ this.view?.dispatch({
137
+ selection: EditorSelection.single(this.savedSelection.anchor, this.savedSelection.head),
138
+ scrollIntoView: true,
139
+ });
140
+ }
141
+ revealLine(line, options = {}) {
142
+ if (!this.view)
143
+ return;
144
+ const target = this.view.state.doc.line(Math.max(1, Math.min(this.view.state.doc.lines, Math.floor(line) || 1)));
145
+ this.selection = { anchor: target.from, head: target.from };
146
+ if (options.center)
147
+ this.view.dispatch({ effects: EditorView.scrollIntoView(target.from, { y: "center" }) });
148
+ this.view.focus();
149
+ }
150
+ focus() {
151
+ this.view?.focus();
152
+ }
153
+ attributeChangedCallback(name, oldValue, newValue) {
154
+ if (name === "value")
155
+ this.valueInternal = newValue ?? "";
156
+ super.attributeChangedCallback(name, oldValue, newValue);
157
+ }
158
+ connectedCallback() {
159
+ super.connectedCallback();
160
+ }
161
+ disconnectedCallback() {
162
+ this.flushChange();
163
+ this.savedSelection = this.selection;
164
+ this.view?.destroy();
165
+ this.view = undefined;
166
+ }
167
+ renderTemplate() {
168
+ this.shadowRoot.innerHTML = `<style>
169
+ :host{display:block;min-width:0;color:var(--boe-token-text-text,#222);font:inherit}
170
+ :host([hidden]){display:none!important}
171
+ [part=editor]{border:1px solid var(--boe-token-stroke-stroke,#ddd);border-radius:8px;overflow:hidden}
172
+ .cm-editor{background:var(--boe-token-surface-surface,#fff);color:var(--boe-token-text-text,#222)}
173
+ [part=editor]:focus-within{box-shadow:0 0 0 3px var(--boe-token-surface-surface-brand,#0061d5)}
174
+ .cm-editor.cm-focused{outline:none}
175
+ .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}
176
+ .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}
177
+ .cm-cursor{border-left-color:var(--boe-token-text-text,#222)}
178
+ .cm-activeLine,.cm-activeLineGutter,.cm-selectionBackground{background:color-mix(in srgb,var(--boe-token-surface-surface-brand,#0061d5) 12%,transparent)!important}
179
+ .boe-code-highlight{background:var(--boe-code-highlight-background,color-mix(in srgb,var(--boe-token-surface-surface-brand,#0061d5) 10%,transparent))!important;box-shadow:inset 3px 0 var(--boe-token-surface-surface-brand,#0061d5)}
180
+ .cm-matchingBracket,.cm-selectionMatch{background:color-mix(in srgb,var(--boe-token-surface-surface-brand,#0061d5) 15%,transparent)!important;color:inherit!important}
181
+ .cm-nonmatchingBracket{color:var(--boe-token-text-status-text-error,#b92340)!important}
182
+ .cm-searchMatch{background:color-mix(in srgb,var(--boe-token-text-status-text-warning,#9a6500) 20%,transparent);outline:none}
183
+ .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}
184
+ .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)}
185
+ .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}
186
+ .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)}
187
+ .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)}
188
+ .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)}
189
+ .cm-lint-marker-error{background-image:radial-gradient(circle,var(--boe-token-text-status-text-error,#b92340) 45%,transparent 50%)!important}
190
+ .cm-lint-marker-warning{background-image:radial-gradient(circle,var(--boe-token-text-status-text-warning,#9a6500) 45%,transparent 50%)!important}
191
+ .cm-lint-marker-info{background-image:radial-gradient(circle,var(--boe-token-surface-surface-brand,#0061d5) 45%,transparent 50%)!important}
192
+ [part=help],[part=problems]{font-size:13px;color:var(--boe-token-text-text-secondary,#666);margin:8px 0}
193
+ [part=toolbar]{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
194
+ 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}
195
+ button:focus-visible{outline:3px solid var(--boe-token-surface-surface-brand,#0061d5);outline-offset:2px}
196
+ @media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important;scroll-behavior:auto!important}}
197
+ </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>`;
198
+ }
199
+ setupListeners() {
200
+ this.shadowRoot.querySelectorAll("button[data-direction]").forEach((button) => button.addEventListener("click", () => this.navigateProblem(Number(button.dataset.direction))));
201
+ // Keep the advertised escape hatch independent of completion/search keymaps.
202
+ this.shadowRoot.addEventListener("keydown", (event) => {
203
+ const key = event;
204
+ if (!key.target.closest(".cm-content"))
205
+ return;
206
+ if (key.ctrlKey && (key.code === "Space" || key.key === " ")) {
207
+ key.preventDefault();
208
+ key.stopPropagation();
209
+ if (this.view && !this.readonly)
210
+ startCompletion(this.view);
211
+ }
212
+ else if (key.key === "Escape")
213
+ this.escapeUntil = Date.now() + 2000;
214
+ else if (key.key === "Tab" && Date.now() <= this.escapeUntil) {
215
+ key.preventDefault();
216
+ key.stopPropagation();
217
+ this.escapeUntil = 0;
218
+ const target = this.shadowRoot.querySelector("button:not(:disabled)") ?? this.shadowRoot.querySelector("[part=help]");
219
+ target.setAttribute("tabindex", "0");
220
+ target.focus();
221
+ }
222
+ else if (!key.ctrlKey &&
223
+ !key.metaKey &&
224
+ !key.altKey &&
225
+ key.key !== "Shift")
226
+ this.escapeUntil = 0;
227
+ }, { capture: true });
228
+ }
229
+ languageExtension() {
230
+ return this.language === "go"
231
+ ? go()
232
+ : javascript({ typescript: this.language === "typescript" });
233
+ }
234
+ completionExtension() {
235
+ if (this.source)
236
+ return autocompletion({ override: [this.source] });
237
+ return autocompletion({
238
+ override: [
239
+ (context) => {
240
+ const word = context.matchBefore(/[\w$]+(?:\.[\w$]*)*/);
241
+ if (!word && !context.explicit)
242
+ return null;
243
+ let from = word?.from ?? context.pos;
244
+ // A full SDK name replaces its prefix; a method replaces only the
245
+ // identifier after the receiver's dot (for example flow().st).
246
+ if (word?.text.includes(".") &&
247
+ !this.completionsInternal.some((option) => option.label.startsWith(word.text))) {
248
+ from += word.text.lastIndexOf(".") + 1;
249
+ }
250
+ return { from, options: [...this.completionsInternal] };
251
+ },
252
+ ],
253
+ });
254
+ }
255
+ update() {
256
+ if (!this.view) {
257
+ this.view = new EditorView({
258
+ parent: this.shadowRoot.querySelector("[part=editor]"),
259
+ root: this.shadowRoot,
260
+ state: EditorState.create({
261
+ doc: this.value,
262
+ extensions: [
263
+ basicSetup,
264
+ lintGutter(),
265
+ keymap.of([indentWithTab]),
266
+ Prec.highest(keymap.of([
267
+ {
268
+ key: "Escape",
269
+ run: (view) => {
270
+ closeCompletion(view);
271
+ closeSearchPanel(view);
272
+ view.setTabFocusMode(2000);
273
+ return true;
274
+ },
275
+ },
276
+ ])),
277
+ this.languageConfig.of(this.languageExtension()),
278
+ this.readonlyConfig.of([
279
+ EditorState.readOnly.of(this.readonly),
280
+ EditorView.editable.of(!this.readonly),
281
+ ]),
282
+ this.completionsConfig.of(this.completionExtension()),
283
+ this.wrapConfig.of(this.wrap ? EditorView.lineWrapping : []),
284
+ this.highlightsConfig.of(this.highlightExtension()),
285
+ syntaxHighlighting(HighlightStyle.define([
286
+ {
287
+ tag: [
288
+ tags.variableName,
289
+ tags.definition(tags.variableName),
290
+ tags.propertyName,
291
+ tags.operator,
292
+ tags.punctuation,
293
+ ],
294
+ color: "var(--boe-token-text-text,#222)",
295
+ },
296
+ {
297
+ tag: tags.keyword,
298
+ color: "var(--boe-token-surface-surface-brand,#0061d5)",
299
+ },
300
+ {
301
+ tag: [
302
+ tags.typeName,
303
+ tags.className,
304
+ tags.function(tags.variableName),
305
+ ],
306
+ color: "var(--boe-token-surface-surface-brand,#0061d5)",
307
+ },
308
+ {
309
+ tag: tags.string,
310
+ color: "var(--boe-token-text-status-text-success,#138a58)",
311
+ },
312
+ {
313
+ tag: tags.comment,
314
+ color: "var(--boe-token-text-text-secondary,#666)",
315
+ },
316
+ {
317
+ tag: tags.number,
318
+ color: "var(--boe-token-text-status-text-warning,#9a6500)",
319
+ },
320
+ {
321
+ tag: [tags.bool, tags.null, tags.atom],
322
+ color: "var(--boe-token-text-status-text-warning,#9a6500)",
323
+ },
324
+ ])),
325
+ EditorView.updateListener.of((update) => {
326
+ if (update.selectionSet && !this.syncing && !update.startState.selection.eq(update.state.selection)) {
327
+ const { anchor, head } = update.state.selection.main;
328
+ this.dispatchEvent(new CustomEvent("selection-changed", { detail: { anchor, head }, bubbles: true, composed: true }));
329
+ }
330
+ if (update.docChanged && !this.syncing) {
331
+ this.valueInternal = update.state.doc.toString();
332
+ this.pending = true;
333
+ clearTimeout(this.timer);
334
+ this.timer = setTimeout(() => this.flushChange(), 200);
335
+ }
336
+ }),
337
+ EditorView.domEventHandlers({
338
+ blur: () => {
339
+ this.flushChange();
340
+ return false;
341
+ },
342
+ }),
343
+ ],
344
+ }),
345
+ });
346
+ this.selection = this.savedSelection;
347
+ }
348
+ else {
349
+ this.syncing = true;
350
+ try {
351
+ if (this.view.state.doc.toString() !== this.value) {
352
+ clearTimeout(this.timer);
353
+ this.pending = false;
354
+ this.view.dispatch({
355
+ annotations: Transaction.addToHistory.of(false),
356
+ changes: {
357
+ from: 0,
358
+ to: this.view.state.doc.length,
359
+ insert: this.value,
360
+ },
361
+ });
362
+ }
363
+ this.view.dispatch({
364
+ effects: [
365
+ this.languageConfig.reconfigure(this.languageExtension()),
366
+ this.readonlyConfig.reconfigure([
367
+ EditorState.readOnly.of(this.readonly),
368
+ EditorView.editable.of(!this.readonly),
369
+ ]),
370
+ this.completionsConfig.reconfigure(this.completionExtension()),
371
+ this.wrapConfig.reconfigure(this.wrap ? EditorView.lineWrapping : []),
372
+ this.highlightsConfig.reconfigure(this.highlightExtension()),
373
+ ],
374
+ });
375
+ }
376
+ finally {
377
+ this.syncing = false;
378
+ }
379
+ }
380
+ this.view.contentDOM.setAttribute("aria-label", this.label);
381
+ this.view.contentDOM.setAttribute("tabindex", "0");
382
+ this.view.contentDOM.setAttribute("aria-describedby", "editor-help");
383
+ this.syncProblems();
384
+ }
385
+ flushChange() {
386
+ clearTimeout(this.timer);
387
+ if (!this.pending)
388
+ return;
389
+ this.pending = false;
390
+ this.dispatchEvent(new CustomEvent("value-changed", {
391
+ detail: { value: this.value },
392
+ bubbles: true,
393
+ composed: true,
394
+ }));
395
+ }
396
+ diagnostics() {
397
+ if (!this.view)
398
+ return [];
399
+ const doc = this.view.state.doc;
400
+ return this.problems
401
+ .filter((problem) => Number.isFinite(problem.from) || (Number.isInteger(problem.line) &&
402
+ problem.line >= 1 &&
403
+ problem.line <= doc.lines))
404
+ .map((problem) => {
405
+ if (Number.isFinite(problem.from)) {
406
+ const from = Math.max(0, Math.min(doc.length, Math.floor(problem.from)));
407
+ const to = Math.max(from, Math.min(doc.length, Number.isFinite(problem.to) ? Math.floor(problem.to) : from + 1));
408
+ return { from, to, message: problem.message, severity: problem.tone };
409
+ }
410
+ const line = doc.line(problem.line);
411
+ const column = Number.isFinite(problem.col) ? problem.col : 1;
412
+ const endColumn = Number.isFinite(problem.endCol)
413
+ ? problem.endCol
414
+ : column + 1;
415
+ const from = line.from + Math.max(0, Math.min(line.length, column - 1));
416
+ const to = Math.max(from, Math.min(line.to, line.from + endColumn - 1));
417
+ return { from, to, message: problem.message, severity: problem.tone };
418
+ });
419
+ }
420
+ syncProblems() {
421
+ if (!this.view)
422
+ return;
423
+ const diagnostics = this.diagnostics();
424
+ this.view.dispatch(setDiagnostics(this.view.state, diagnostics));
425
+ this.shadowRoot.querySelector("[part=problems]").textContent =
426
+ `${diagnostics.length} problem${diagnostics.length === 1 ? "" : "s"}`;
427
+ this.shadowRoot.querySelectorAll("button[data-direction]").forEach((button) => (button.disabled = diagnostics.length === 0));
428
+ }
429
+ navigateProblem(direction) {
430
+ const diagnostics = this.diagnostics();
431
+ if (!diagnostics.length)
432
+ return;
433
+ this.problemIndex =
434
+ this.problemIndex < 0
435
+ ? direction < 0
436
+ ? diagnostics.length - 1
437
+ : 0
438
+ : (this.problemIndex + (direction < 0 ? -1 : 1) + diagnostics.length) %
439
+ diagnostics.length;
440
+ const problem = diagnostics[this.problemIndex];
441
+ this.selection = { anchor: problem.from, head: problem.to };
442
+ this.focus();
443
+ this.shadowRoot.querySelector("[part=problems]").textContent =
444
+ `Problem ${this.problemIndex + 1} of ${diagnostics.length}: ${problem.message}`;
445
+ }
446
+ }
447
+ CodeEditor.register();
@@ -1,7 +1,7 @@
1
1
  import { FormAssociatedElement, boeFormFieldErrorStyles, formErrorMessageMarkup, } from "../../core/index.js";
2
2
  import { boeNeutralInteractiveStyles } from "../../foundations/tokens/interaction.js";
3
3
  import { boeMotionDuration, boeMotionEasing } from "../../foundations/motion/index.js";
4
- import { boeOverlay, boeRadius } from "../../foundations/geometry/index.js";
4
+ import { boeControl, boeOverlay, boeRadius } from "../../foundations/geometry/index.js";
5
5
  import { parsePlacement, trackAnchor, } from "../../foundations/overlay/index.js";
6
6
  const DEFAULT_TAG_NAME = "box-combobox";
7
7
  const escapeHtml = (value) => value
@@ -29,11 +29,9 @@ const comboboxStyles = `
29
29
  }
30
30
 
31
31
  [part="label"] {
32
- font-size: 0.8rem;
32
+ font-size: ${boeControl.fontSize};
33
33
  font-weight: 700;
34
- letter-spacing: 0.08em;
35
- text-transform: uppercase;
36
- color: var(--boe-token-text-text-secondary, #6f6f6f);
34
+ color: var(--boe-token-text-text, #222222);
37
35
  }
38
36
 
39
37
  [part="control"] {
@@ -48,7 +46,7 @@ const comboboxStyles = `
48
46
  font: inherit;
49
47
  color: var(--boe-token-text-text, #222222);
50
48
  padding: 0.45rem 0.7rem;
51
- border: 1px solid color-mix(in srgb, var(--boe-token-stroke-stroke, #e8e8e8) 78%, var(--boe-token-surface-surface, #ffffff) 22%);
49
+ border: 1px solid ${boeControl.inputBorder};
52
50
  border-radius: ${boeRadius.control};
53
51
  background: var(--boe-token-surface-surface, #ffffff);
54
52
  transition:
@@ -62,6 +60,7 @@ const comboboxStyles = `
62
60
  }
63
61
 
64
62
  ${boeNeutralInteractiveStyles('[part="input"]')}
63
+ [part="input"]:hover:not(:disabled) { border-color: ${boeControl.inputBorder}; }
65
64
 
66
65
  [part="input"]:focus-visible {
67
66
  border-color: var(--boe-token-surface-surface-brand, #0061d5);
@@ -126,8 +125,8 @@ const comboboxStyles = `
126
125
  padding: 6px 10px 2px;
127
126
  font-size: 0.72rem;
128
127
  font-weight: 700;
129
- letter-spacing: 0.06em;
130
- text-transform: uppercase;
128
+ letter-spacing: normal;
129
+ text-transform: none;
131
130
  color: var(--boe-token-text-text-secondary, #6f6f6f);
132
131
  }
133
132
 
@@ -5,6 +5,7 @@ export declare class NumberInput extends FormAssociatedElement {
5
5
  static get observedAttributes(): string[];
6
6
  private valueInternal;
7
7
  private inputEl;
8
+ focus(options?: FocusOptions): void;
8
9
  private labelEl;
9
10
  private errorEl;
10
11
  private descriptionEl;
@@ -35,10 +35,13 @@ 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;
41
- border: 1px solid color-mix(in srgb, var(--boe-token-stroke-stroke, #e8e8e8) 78%, var(--boe-token-surface-surface, #ffffff) 22%);
44
+ border: 1px solid ${boeControl.inputBorder};
42
45
  border-radius: ${boeRadius.control};
43
46
  background: var(--boe-token-surface-surface, #ffffff);
44
47
  transition:
@@ -52,6 +55,7 @@ const numberInputStyles = `
52
55
  }
53
56
 
54
57
  ${boeNeutralInteractiveStyles('[part="input"]')}
58
+ [part="input"]:hover:not(:disabled) { border-color: ${boeControl.inputBorder}; }
55
59
 
56
60
  [part="input"]:focus-visible {
57
61
  border-color: var(--boe-token-surface-surface-brand, #0061d5);
@@ -64,7 +68,7 @@ export class NumberInput extends FormAssociatedElement {
64
68
  static tagName = DEFAULT_TAG_NAME;
65
69
  static get observedAttributes() {
66
70
  return [
67
- ...FormAssociatedElement.formObservedAttributes,
71
+ ...FormAssociatedElement.fieldObservedAttributes,
68
72
  "disabled",
69
73
  "label",
70
74
  "max",
@@ -76,6 +80,8 @@ export class NumberInput extends FormAssociatedElement {
76
80
  }
77
81
  valueInternal = 0;
78
82
  inputEl;
83
+ focus(options) { if (!this.disabled)
84
+ this.inputEl?.focus(options); }
79
85
  labelEl;
80
86
  errorEl;
81
87
  descriptionEl;
@@ -17,6 +17,7 @@ export declare class Select extends FormAssociatedElement {
17
17
  private valueInternal;
18
18
  private valuesInternal;
19
19
  private selectEl;
20
+ focus(options?: FocusOptions): void;
20
21
  private labelEl;
21
22
  private descriptionEl;
22
23
  private errorEl;
@@ -64,7 +64,7 @@ const selectStyles = `
64
64
  }
65
65
 
66
66
  [part="select"]:hover:not(:disabled) {
67
- border-color: var(--boe-token-stroke-stroke-hover, #bcbcbc);
67
+ border-color: ${boeControl.inputBorder};
68
68
  }
69
69
 
70
70
  [part="select"]:focus-visible {
@@ -150,6 +150,8 @@ export class Select extends FormAssociatedElement {
150
150
  valueInternal = "";
151
151
  valuesInternal = [];
152
152
  selectEl;
153
+ focus(options) { if (!this.disabled)
154
+ this.selectEl?.focus(options); }
153
155
  labelEl;
154
156
  descriptionEl;
155
157
  errorEl;
@@ -1,6 +1,6 @@
1
1
  import { FormAssociatedElement, boeFormFieldErrorStyles, formErrorMessageMarkup, } from "../../core/index.js";
2
2
  import { boeMotionDuration, boeMotionEasing } from "../../foundations/motion/index.js";
3
- import { boeRadius } from "../../foundations/geometry/index.js";
3
+ import { boeControl, boeRadius } from "../../foundations/geometry/index.js";
4
4
  const DEFAULT_TAG_NAME = "box-text-area";
5
5
  const textAreaStyles = `
6
6
  :host {
@@ -21,11 +21,9 @@ const textAreaStyles = `
21
21
  }
22
22
 
23
23
  [part="label"] {
24
- font-size: 0.8rem;
24
+ font-size: ${boeControl.fontSize};
25
25
  font-weight: 700;
26
- letter-spacing: 0.08em;
27
- text-transform: uppercase;
28
- color: var(--boe-token-text-text-secondary, #6f6f6f);
26
+ color: var(--boe-token-text-text, #222222);
29
27
  }
30
28
 
31
29
  [part="textarea"] {
@@ -33,7 +31,7 @@ const textAreaStyles = `
33
31
  font: inherit;
34
32
  color: var(--boe-token-text-text, #222222);
35
33
  padding: 0.45rem 0.7rem;
36
- border: 1px solid color-mix(in srgb, var(--boe-token-stroke-stroke, #e8e8e8) 78%, var(--boe-token-surface-surface, #ffffff) 22%);
34
+ border: 1px solid ${boeControl.inputBorder};
37
35
  border-radius: ${boeRadius.control};
38
36
  background: var(--boe-token-surface-surface, #ffffff);
39
37
  resize: vertical;
@@ -49,7 +47,7 @@ const textAreaStyles = `
49
47
  }
50
48
 
51
49
  [part="textarea"]:hover:not(:disabled) {
52
- border-color: var(--boe-token-stroke-stroke-hover, #bcbcbc);
50
+ border-color: ${boeControl.inputBorder};
53
51
  }
54
52
 
55
53
  [part="textarea"]:focus-visible {
@@ -10,6 +10,7 @@ export declare class TextField extends FormAssociatedElement {
10
10
  private valueInternal;
11
11
  private revealed;
12
12
  private inputEl;
13
+ focus(options?: FocusOptions): void;
13
14
  private labelEl;
14
15
  private descriptionEl;
15
16
  private errorEl;
@@ -178,6 +178,8 @@ export class TextField extends FormAssociatedElement {
178
178
  valueInternal = "";
179
179
  revealed = false;
180
180
  inputEl;
181
+ focus(options) { if (!this.disabled)
182
+ this.inputEl?.focus(options); }
181
183
  labelEl;
182
184
  descriptionEl;
183
185
  errorEl;
@@ -1,6 +1,7 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
2
  type BoxAccordionItem = {
3
3
  content?: string;
4
+ summary?: string;
4
5
  label: string;
5
6
  value: string;
6
7
  };
@@ -11,6 +12,12 @@ export declare class Accordion extends BaseElement {
11
12
  get borderless(): boolean;
12
13
  set borderless(value: boolean);
13
14
  private valueInternal;
15
+ private valuesInternal;
16
+ get multiple(): boolean;
17
+ set multiple(value: boolean);
18
+ get values(): string[];
19
+ set values(value: string[]);
20
+ private isOpen;
14
21
  private lastItemsJson;
15
22
  private accordionEl;
16
23
  get label(): string;