@unofficialbox/box-open-elements 0.10.0 → 0.11.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 (39) hide show
  1. package/dist/components/feedback/alert.js +1 -16
  2. package/dist/components/feedback/path.d.ts +84 -0
  3. package/dist/components/feedback/path.js +455 -0
  4. package/dist/components/feedback/skeleton.d.ts +70 -0
  5. package/dist/components/feedback/skeleton.js +231 -1
  6. package/dist/components/feedback/toast.d.ts +38 -0
  7. package/dist/components/feedback/toast.js +189 -13
  8. package/dist/components/feedback/tone.d.ts +16 -0
  9. package/dist/components/feedback/tone.js +31 -0
  10. package/dist/components/layout/grid.d.ts +41 -0
  11. package/dist/components/layout/grid.js +152 -0
  12. package/dist/element-maps.d.ts +5 -3
  13. package/dist/entries/grid.d.ts +1 -0
  14. package/dist/entries/grid.js +1 -0
  15. package/dist/entries/path.d.ts +1 -0
  16. package/dist/entries/path.js +1 -0
  17. package/dist/foundations/layout/grid.d.ts +70 -0
  18. package/dist/foundations/layout/grid.js +84 -0
  19. package/dist/foundations/layout/index.d.ts +1 -0
  20. package/dist/foundations/layout/index.js +3 -0
  21. package/dist/index.d.ts +4 -1
  22. package/dist/index.js +5 -1
  23. package/dist/patterns/audit/audit-log.js +0 -1
  24. package/dist/patterns/lineage/lineage-graph.d.ts +7 -0
  25. package/dist/patterns/lineage/lineage-graph.js +67 -6
  26. package/dist/patterns/lineage/provenance-strip.js +106 -15
  27. package/dist/patterns/notifications/notification-inbox.js +2 -18
  28. package/dist/patterns/timeline/timeline.js +44 -12
  29. package/dist/patterns/versions/graph-arrows.d.ts +22 -0
  30. package/dist/patterns/versions/graph-arrows.js +13 -0
  31. package/dist/patterns/versions/index.d.ts +1 -0
  32. package/dist/patterns/versions/index.js +1 -0
  33. package/dist/patterns/versions/version-graph.d.ts +7 -0
  34. package/dist/patterns/versions/version-graph.js +54 -6
  35. package/package.json +1 -1
  36. package/dist/components/feedback/stage-path.d.ts +0 -44
  37. package/dist/components/feedback/stage-path.js +0 -235
  38. package/dist/entries/stage-path.d.ts +0 -1
  39. package/dist/entries/stage-path.js +0 -1
@@ -0,0 +1,31 @@
1
+ /**
2
+ * The status vocabulary shared by the feedback surfaces.
3
+ *
4
+ * `box-alert` and `box-toast` both state their tone in words for screen
5
+ * readers, and both must say the *same* words: a reader who hears "In progress"
6
+ * from an alert should not hear "Inprogress" from a toast reporting the same
7
+ * thing. One definition is what keeps them in step.
8
+ */
9
+ /**
10
+ * The tone as a word, for assistive technology.
11
+ *
12
+ * Tone is otherwise carried by fill and glyph, neither of which reaches a
13
+ * screen reader. An unrecognised tone is title-cased rather than dropped —
14
+ * a host that invents a tone should still get something spoken.
15
+ */
16
+ export const toneAccessibleLabel = (tone) => {
17
+ switch (tone) {
18
+ case "success":
19
+ return "Success";
20
+ case "error":
21
+ return "Error";
22
+ case "warning":
23
+ return "Warning";
24
+ case "inprogress":
25
+ return "In progress";
26
+ case "info":
27
+ return "Info";
28
+ default:
29
+ return tone.charAt(0).toUpperCase() + tone.slice(1);
30
+ }
31
+ };
@@ -0,0 +1,41 @@
1
+ import { BaseElement } from "../../core/index.js";
2
+ /**
3
+ * Adobe Spectrum's responsive grid, for laying out arbitrary content.
4
+ *
5
+ * Twelve columns by default, with gutters stepping 16 → 24 → 32 → 40 → 48px
6
+ * across Spectrum's breakpoints. Children declare their own placement:
7
+ *
8
+ * ```html
9
+ * <box-grid columns="12">
10
+ * <article data-span="8">Main</article>
11
+ * <aside data-span="4">Sidebar</aside>
12
+ * <footer data-span="6" data-offset="3">Centred</footer>
13
+ * </box-grid>
14
+ * ```
15
+ *
16
+ * Placement lives on the children rather than in a payload on the host,
17
+ * because the children are arbitrary content the author already writes — an
18
+ * `items` array would have to address them positionally and would silently
19
+ * mis-place everything the moment one was inserted.
20
+ *
21
+ * `data-offset` sets an explicit `grid-column-start`. That is the author's
22
+ * stated intent here, unlike `box-skeleton`, which generates its own regions
23
+ * and uses spacers so auto-placement is not disturbed.
24
+ */
25
+ export declare class Grid extends BaseElement {
26
+ static readonly tagName: string;
27
+ static get observedAttributes(): string[];
28
+ private gridEl;
29
+ /** Columns in the grid. Defaults to Spectrum's twelve. */
30
+ get columns(): number;
31
+ set columns(value: number);
32
+ /**
33
+ * Height of one row. Unset by default: a layout grid's rows should be as
34
+ * tall as their content, and pinning them would crop it.
35
+ */
36
+ get rowHeight(): string;
37
+ set rowHeight(value: string);
38
+ protected renderTemplate(): void;
39
+ protected setupListeners(): void;
40
+ protected update(): void;
41
+ }
@@ -0,0 +1,152 @@
1
+ import { BaseElement } from "../../core/index.js";
2
+ import { BOE_GRID_COLUMNS, BOE_GRID_GUTTER_PROPERTY, boeGridGutterStyles, resolveGridCount, } from "../../foundations/layout/index.js";
3
+ const DEFAULT_TAG_NAME = "box-grid";
4
+ /**
5
+ * How far a child's placement attributes are honoured.
6
+ *
7
+ * Placement is expressed in CSS rules generated per value, not computed per
8
+ * element, so the ceiling is a real limit rather than a guess. Twenty-four
9
+ * covers a twelve-column grid used at double density without emitting rules
10
+ * nobody will match.
11
+ */
12
+ const MAX_TRACKS = 24;
13
+ /**
14
+ * Placement rules, one per value.
15
+ *
16
+ * A slotted child cannot be given a computed `grid-column` without writing to
17
+ * the light DOM, which is the host's tree, not ours. Generating a rule per
18
+ * value keeps placement declarative and leaves the author's markup untouched.
19
+ *
20
+ * `grid-column-start` and `grid-column-end` are set by separate rules on
21
+ * purpose: they compose, so offset and span combine without needing a rule for
22
+ * every offset × span pair.
23
+ */
24
+ const placementRules = () => {
25
+ const rules = [];
26
+ for (let value = 1; value <= MAX_TRACKS; value += 1) {
27
+ rules.push(` ::slotted([data-span="${value}"]) { grid-column-end: span ${value}; }`);
28
+ rules.push(` ::slotted([data-row-span="${value}"]) { grid-row: span ${value}; }`);
29
+ }
30
+ for (let value = 1; value < MAX_TRACKS; value += 1) {
31
+ // An offset of N starts the region at column N + 1.
32
+ rules.push(` ::slotted([data-offset="${value}"]) { grid-column-start: ${value + 1}; }`);
33
+ }
34
+ return rules.join("\n");
35
+ };
36
+ const elementStyles = `
37
+ :host {
38
+ display: block;
39
+ color: inherit;
40
+ font: inherit;
41
+ }
42
+
43
+ :host([hidden]) {
44
+ display: none;
45
+ }
46
+
47
+ ${boeGridGutterStyles(":host")}
48
+
49
+ [part="grid"] {
50
+ display: grid;
51
+ grid-template-columns: repeat(var(--boe-grid-columns, ${BOE_GRID_COLUMNS}), minmax(0, 1fr));
52
+ gap: var(${BOE_GRID_GUTTER_PROPERTY});
53
+ }
54
+
55
+ /* Rows are only constrained when the author asks for them; otherwise each
56
+ row is as tall as its content, which is what a layout grid should do.
57
+ Spectrum's layout regions have no intrinsic height either — at minimum
58
+ they are as tall as the components inside them. */
59
+ :host([row-height]) [part="grid"] {
60
+ grid-auto-rows: var(--boe-grid-row-height);
61
+ }
62
+
63
+ /* Without this the slot itself is the grid item and every child lands in one
64
+ cell. display: contents dissolves it, so the assigned children become the
65
+ grid's own items. */
66
+ slot {
67
+ display: contents;
68
+ }
69
+
70
+ /* A region with no placement attributes occupies one column, so a bare list
71
+ of children reads as an even row. */
72
+ ::slotted(*) {
73
+ grid-column-end: span 1;
74
+ }
75
+
76
+ ${placementRules()}
77
+ `;
78
+ /**
79
+ * Adobe Spectrum's responsive grid, for laying out arbitrary content.
80
+ *
81
+ * Twelve columns by default, with gutters stepping 16 → 24 → 32 → 40 → 48px
82
+ * across Spectrum's breakpoints. Children declare their own placement:
83
+ *
84
+ * ```html
85
+ * <box-grid columns="12">
86
+ * <article data-span="8">Main</article>
87
+ * <aside data-span="4">Sidebar</aside>
88
+ * <footer data-span="6" data-offset="3">Centred</footer>
89
+ * </box-grid>
90
+ * ```
91
+ *
92
+ * Placement lives on the children rather than in a payload on the host,
93
+ * because the children are arbitrary content the author already writes — an
94
+ * `items` array would have to address them positionally and would silently
95
+ * mis-place everything the moment one was inserted.
96
+ *
97
+ * `data-offset` sets an explicit `grid-column-start`. That is the author's
98
+ * stated intent here, unlike `box-skeleton`, which generates its own regions
99
+ * and uses spacers so auto-placement is not disturbed.
100
+ */
101
+ export class Grid extends BaseElement {
102
+ static tagName = DEFAULT_TAG_NAME;
103
+ static get observedAttributes() {
104
+ return ["columns", "row-height"];
105
+ }
106
+ gridEl;
107
+ /** Columns in the grid. Defaults to Spectrum's twelve. */
108
+ get columns() {
109
+ return resolveGridCount(this.getAttribute("columns"), BOE_GRID_COLUMNS);
110
+ }
111
+ set columns(value) {
112
+ this.setAttribute("columns", String(value));
113
+ }
114
+ /**
115
+ * Height of one row. Unset by default: a layout grid's rows should be as
116
+ * tall as their content, and pinning them would crop it.
117
+ */
118
+ get rowHeight() {
119
+ return this.getAttribute("row-height") ?? "";
120
+ }
121
+ set rowHeight(value) {
122
+ if (value) {
123
+ this.setAttribute("row-height", value);
124
+ return;
125
+ }
126
+ this.removeAttribute("row-height");
127
+ }
128
+ renderTemplate() {
129
+ if (!this.shadowRoot) {
130
+ return;
131
+ }
132
+ this.shadowRoot.innerHTML = `<style>${elementStyles}</style><div part="grid"><slot></slot></div>`;
133
+ this.gridEl = this.shadowRoot.querySelector('[part="grid"]');
134
+ }
135
+ setupListeners() {
136
+ // Layout only: placement is declared by the children and applied in CSS.
137
+ }
138
+ update() {
139
+ if (!this.gridEl) {
140
+ return;
141
+ }
142
+ this.gridEl.style.setProperty("--boe-grid-columns", String(this.columns));
143
+ // Via the CSSOM rather than interpolated into markup. Note that custom
144
+ // properties are *not* validated the way a standard property like `width`
145
+ // is — they accept almost any token sequence — so this does not sanitise
146
+ // the value. What makes it safe is that the value never reaches an HTML
147
+ // string: a nonsensical one makes `grid-auto-rows` invalid at computed-value
148
+ // time, which falls back to `auto`, and rows simply size to their content.
149
+ this.gridEl.style.setProperty("--boe-grid-row-height", this.rowHeight);
150
+ }
151
+ }
152
+ Grid.register();
@@ -48,6 +48,7 @@ import type { DateField } from "./components/forms/date-field.js";
48
48
  import type { Dialog } from "./components/overlays/dialog.js";
49
49
  import type { DiffViewer } from "./patterns/diff/diff-viewer.js";
50
50
  import type { Divider } from "./components/layout/divider.js";
51
+ import type { Grid } from "./components/layout/grid.js";
51
52
  import type { DonutChart } from "./patterns/insights/donut-chart.js";
52
53
  import type { DraggableList } from "./components/collections/draggable-list.js";
53
54
  import type { Drawer } from "./components/overlays/drawer.js";
@@ -124,7 +125,7 @@ import type { Slider } from "./components/forms/slider.js";
124
125
  import type { SpinButton } from "./components/forms/spin-button.js";
125
126
  import type { Spinner } from "./components/feedback/spinner.js";
126
127
  import type { SplitView } from "./components/layout/split-view.js";
127
- import type { StagePath } from "./components/feedback/stage-path.js";
128
+ import type { Path } from "./components/feedback/path.js";
128
129
  import type { Switch } from "./components/forms/switch.js";
129
130
  import type { Table } from "./components/collections/table.js";
130
131
  import type { Tabs } from "./components/navigation/tabs.js";
@@ -189,6 +190,7 @@ declare global {
189
190
  "box-dialog": Dialog;
190
191
  "box-diff-viewer": DiffViewer;
191
192
  "box-divider": Divider;
193
+ "box-grid": Grid;
192
194
  "box-donut-chart": DonutChart;
193
195
  "box-draggable-list": DraggableList;
194
196
  "box-drawer": Drawer;
@@ -265,7 +267,7 @@ declare global {
265
267
  "box-spin-button": SpinButton;
266
268
  "box-spinner": Spinner;
267
269
  "box-split-view": SplitView;
268
- "box-stage-path": StagePath;
270
+ "box-path": Path;
269
271
  "box-switch": Switch;
270
272
  "box-table": Table;
271
273
  "box-tabs": Tabs;
@@ -289,4 +291,4 @@ declare global {
289
291
  }
290
292
  }
291
293
  /** Every element tag the library registers, for host-side narrowing. */
292
- export type BoxElementTagName = "box-access-stats" | "box-accordion" | "box-activity-density" | "box-agent-chat" | "box-alert" | "box-annotation-inspector" | "box-annotation-thread" | "box-annotation-toolbar" | "box-app-shell" | "box-audit-log" | "box-avatar" | "box-badge" | "box-badgeable" | "box-bar-chart" | "box-breadcrumb" | "box-bulk-action-bar" | "box-button" | "box-button-group" | "box-calendar" | "box-card" | "box-carousel" | "box-category-selector" | "box-chart-panel" | "box-checkbox" | "box-checkbox-group" | "box-chip" | "box-collaborator-avatars" | "box-color-picker" | "box-combobox" | "box-command-palette" | "box-compare-view" | "box-contact-datalist-item" | "box-content-explorer" | "box-content-picker" | "box-content-sidebar" | "box-content-uploader" | "box-context-menu" | "box-datalist-item" | "box-date-field" | "box-dialog" | "box-diff-viewer" | "box-divider" | "box-donut-chart" | "box-draggable-list" | "box-drawer" | "box-drop-zone" | "box-dropdown" | "box-dual-listbox" | "box-due-badge" | "box-empty-state" | "box-error-mask" | "box-explorer-action-menu" | "box-explorer-breadcrumbs" | "box-explorer-items" | "box-explorer-list" | "box-explorer-table" | "box-explorer-toolbar" | "box-fieldset" | "box-file-request-builder" | "box-filter-bar" | "box-form-wizard" | "box-governance-panel" | "box-grid-view" | "box-guide-tooltip" | "box-help-text" | "box-icon-button" | "box-illustration" | "box-invite-collaborators-modal" | "box-item-details-panel" | "box-item-form" | "box-line-chart" | "box-lineage-graph" | "box-link-button" | "box-menu" | "box-menu-item" | "box-metadata-filter-builder" | "box-metadata-inspector" | "box-metric-card" | "box-multi-select" | "box-nav-sidebar" | "box-notification-bell" | "box-notification-inbox" | "box-nudge" | "box-number-input" | "box-pagination" | "box-permission-matrix" | "box-persona" | "box-pill-cloud" | "box-pill-selector-dropdown" | "box-popover" | "box-presence" | "box-preview-element" | "box-preview-header" | "box-progress-bar" | "box-progress-ring" | "box-progress-steps" | "box-provenance-strip" | "box-radio-group" | "box-range-slider" | "box-rating" | "box-review-queue-item" | "box-rich-text-input" | "box-run-trace" | "box-saved-view-picker" | "box-search-field" | "box-search-results-header" | "box-section" | "box-segmented-control" | "box-select" | "box-share-panel" | "box-shortcuts-overlay" | "box-sidebar-toggle-button" | "box-signature-ceremony" | "box-skeleton" | "box-slider" | "box-spin-button" | "box-spinner" | "box-split-view" | "box-stage-path" | "box-switch" | "box-table" | "box-tabs" | "box-tag-input" | "box-task-assignment-panel" | "box-text-area" | "box-text-field" | "box-thumbnail-card" | "box-time-field" | "box-timeline" | "box-toast" | "box-tooltip" | "box-tree" | "box-tree-grid" | "box-unified-share-modal" | "box-version-graph" | "box-version-list" | "box-wizard-summary" | "box-work-queue" | "box-workload-board";
294
+ export type BoxElementTagName = "box-access-stats" | "box-accordion" | "box-activity-density" | "box-agent-chat" | "box-alert" | "box-annotation-inspector" | "box-annotation-thread" | "box-annotation-toolbar" | "box-app-shell" | "box-audit-log" | "box-avatar" | "box-badge" | "box-badgeable" | "box-bar-chart" | "box-breadcrumb" | "box-bulk-action-bar" | "box-button" | "box-button-group" | "box-calendar" | "box-card" | "box-carousel" | "box-category-selector" | "box-chart-panel" | "box-checkbox" | "box-checkbox-group" | "box-chip" | "box-collaborator-avatars" | "box-color-picker" | "box-combobox" | "box-command-palette" | "box-compare-view" | "box-contact-datalist-item" | "box-content-explorer" | "box-content-picker" | "box-content-sidebar" | "box-content-uploader" | "box-context-menu" | "box-datalist-item" | "box-date-field" | "box-dialog" | "box-diff-viewer" | "box-divider" | "box-grid" | "box-donut-chart" | "box-draggable-list" | "box-drawer" | "box-drop-zone" | "box-dropdown" | "box-dual-listbox" | "box-due-badge" | "box-empty-state" | "box-error-mask" | "box-explorer-action-menu" | "box-explorer-breadcrumbs" | "box-explorer-items" | "box-explorer-list" | "box-explorer-table" | "box-explorer-toolbar" | "box-fieldset" | "box-file-request-builder" | "box-filter-bar" | "box-form-wizard" | "box-governance-panel" | "box-grid-view" | "box-guide-tooltip" | "box-help-text" | "box-icon-button" | "box-illustration" | "box-invite-collaborators-modal" | "box-item-details-panel" | "box-item-form" | "box-line-chart" | "box-lineage-graph" | "box-link-button" | "box-menu" | "box-menu-item" | "box-metadata-filter-builder" | "box-metadata-inspector" | "box-metric-card" | "box-multi-select" | "box-nav-sidebar" | "box-notification-bell" | "box-notification-inbox" | "box-nudge" | "box-number-input" | "box-pagination" | "box-permission-matrix" | "box-persona" | "box-pill-cloud" | "box-pill-selector-dropdown" | "box-popover" | "box-presence" | "box-preview-element" | "box-preview-header" | "box-progress-bar" | "box-progress-ring" | "box-progress-steps" | "box-provenance-strip" | "box-radio-group" | "box-range-slider" | "box-rating" | "box-review-queue-item" | "box-rich-text-input" | "box-run-trace" | "box-saved-view-picker" | "box-search-field" | "box-search-results-header" | "box-section" | "box-segmented-control" | "box-select" | "box-share-panel" | "box-shortcuts-overlay" | "box-sidebar-toggle-button" | "box-signature-ceremony" | "box-skeleton" | "box-slider" | "box-spin-button" | "box-spinner" | "box-split-view" | "box-path" | "box-switch" | "box-table" | "box-tabs" | "box-tag-input" | "box-task-assignment-panel" | "box-text-area" | "box-text-field" | "box-thumbnail-card" | "box-time-field" | "box-timeline" | "box-toast" | "box-tooltip" | "box-tree" | "box-tree-grid" | "box-unified-share-modal" | "box-version-graph" | "box-version-list" | "box-wizard-summary" | "box-work-queue" | "box-workload-board";
@@ -0,0 +1 @@
1
+ export * from "../components/layout/grid.js";
@@ -0,0 +1 @@
1
+ export * from "../components/layout/grid.js";
@@ -0,0 +1 @@
1
+ export * from "../components/feedback/path.js";
@@ -0,0 +1 @@
1
+ export * from "../components/feedback/path.js";
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Adobe Spectrum's responsive grid, as a foundation.
3
+ *
4
+ * Two surfaces build on this: `box-grid`, which lays out slotted content, and
5
+ * `box-skeleton`'s grid variant, which fills the same regions with shimmer
6
+ * bars. They must agree on what a column is worth and how wide a gutter is at
7
+ * a given viewport, so the model lives here rather than in either of them.
8
+ */
9
+ /**
10
+ * Columns in the grid.
11
+ *
12
+ * Twelve divides by 2, 3, 4 and 6, so halves, thirds, quarters and
13
+ * sidebar-plus-content all land on whole columns.
14
+ */
15
+ export declare const BOE_GRID_COLUMNS = 12;
16
+ /**
17
+ * Spectrum's breakpoints and their gutters.
18
+ *
19
+ * Breakpoints are min-widths, so a viewport between two of them inherits the
20
+ * smaller one's dimensions. Gutters are fixed values per breakpoint rather
21
+ * than a proportion of the grid — that is Spectrum's rule, and it is why the
22
+ * gutter cannot simply be a percentage.
23
+ */
24
+ export declare const BOE_GRID_BREAKPOINTS: readonly {
25
+ minWidth: number;
26
+ gutter: number;
27
+ }[];
28
+ /** The custom property every grid surface reads its gutter from. */
29
+ export declare const BOE_GRID_GUTTER_PROPERTY = "--boe-grid-gutter";
30
+ /**
31
+ * The gutter scale as CSS, scoped to a selector.
32
+ *
33
+ * Emitted rather than hand-written in each component so the two cannot drift,
34
+ * and so adding a breakpoint is one edit. A consumer overriding the property
35
+ * replaces the whole scale in one declaration.
36
+ */
37
+ export declare const boeGridGutterStyles: (selector?: string) => string;
38
+ /**
39
+ * One region of the grid: a block spanning some columns and rows, optionally
40
+ * pushed right by an offset. Spectrum calls these layout regions.
41
+ */
42
+ export interface BoeGridPlacement {
43
+ /** Columns to span. Clamped to what is left after `offset`. */
44
+ span?: number;
45
+ /** Rows to span. Clamped to the grid's `rows`, so a region cannot exceed it. */
46
+ rowSpan?: number;
47
+ /** Empty columns before this region. Clamped to leave room for one column. */
48
+ offset?: number;
49
+ }
50
+ /** A resolved region: every field present, every value in range. */
51
+ export interface ResolvedBoeGridPlacement {
52
+ span: number;
53
+ rowSpan: number;
54
+ offset: number;
55
+ }
56
+ /** Attribute payloads are author input — validate every record. */
57
+ export declare const isBoeGridPlacementRecord: (value: unknown) => value is BoeGridPlacement;
58
+ /**
59
+ * Fit a region to the grid.
60
+ *
61
+ * Every value is clamped rather than rejected. A layout that renders slightly
62
+ * wrong is recoverable; one that vanishes because a number was out of range is
63
+ * not, and the caller usually cannot tell which region was dropped. The clamps
64
+ * are what confine a region to the totals the author declared: a span of 9 in a
65
+ * three-column grid becomes 3, and a `rowSpan` of 5 in a three-row grid
66
+ * becomes 3.
67
+ */
68
+ export declare const resolveBoeGridPlacement: (item: BoeGridPlacement, columns: number, rows: number) => ResolvedBoeGridPlacement;
69
+ /** Parse a positive integer attribute, falling back when it is absent or junk. */
70
+ export declare const resolveGridCount: (raw: string | null, fallback: number) => number;
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Adobe Spectrum's responsive grid, as a foundation.
3
+ *
4
+ * Two surfaces build on this: `box-grid`, which lays out slotted content, and
5
+ * `box-skeleton`'s grid variant, which fills the same regions with shimmer
6
+ * bars. They must agree on what a column is worth and how wide a gutter is at
7
+ * a given viewport, so the model lives here rather than in either of them.
8
+ */
9
+ /**
10
+ * Columns in the grid.
11
+ *
12
+ * Twelve divides by 2, 3, 4 and 6, so halves, thirds, quarters and
13
+ * sidebar-plus-content all land on whole columns.
14
+ */
15
+ export const BOE_GRID_COLUMNS = 12;
16
+ /**
17
+ * Spectrum's breakpoints and their gutters.
18
+ *
19
+ * Breakpoints are min-widths, so a viewport between two of them inherits the
20
+ * smaller one's dimensions. Gutters are fixed values per breakpoint rather
21
+ * than a proportion of the grid — that is Spectrum's rule, and it is why the
22
+ * gutter cannot simply be a percentage.
23
+ */
24
+ export const BOE_GRID_BREAKPOINTS = [
25
+ { minWidth: 0, gutter: 16 },
26
+ { minWidth: 768, gutter: 24 },
27
+ { minWidth: 1280, gutter: 32 },
28
+ { minWidth: 1768, gutter: 40 },
29
+ { minWidth: 2160, gutter: 48 },
30
+ ];
31
+ /** The custom property every grid surface reads its gutter from. */
32
+ export const BOE_GRID_GUTTER_PROPERTY = "--boe-grid-gutter";
33
+ /**
34
+ * The gutter scale as CSS, scoped to a selector.
35
+ *
36
+ * Emitted rather than hand-written in each component so the two cannot drift,
37
+ * and so adding a breakpoint is one edit. A consumer overriding the property
38
+ * replaces the whole scale in one declaration.
39
+ */
40
+ export const boeGridGutterStyles = (selector = ":host") => BOE_GRID_BREAKPOINTS.map(({ minWidth, gutter }) => {
41
+ const declaration = `${selector} {\n ${BOE_GRID_GUTTER_PROPERTY}: ${gutter}px;\n }`;
42
+ return minWidth === 0
43
+ ? ` ${declaration}`
44
+ : ` @media (min-width: ${minWidth}px) {\n ${declaration}\n }`;
45
+ }).join("\n\n");
46
+ /** Attribute payloads are author input — validate every record. */
47
+ export const isBoeGridPlacementRecord = (value) => {
48
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
49
+ return false;
50
+ }
51
+ const item = value;
52
+ // Absent is fine — each field has a default. Present-but-not-a-number is not:
53
+ // it means the host built the payload wrong, and silently substituting a
54
+ // default would hide that.
55
+ return ["span", "rowSpan", "offset"].every(key => {
56
+ const raw = item[key];
57
+ return raw === undefined || (typeof raw === "number" && Number.isFinite(raw));
58
+ });
59
+ };
60
+ const clamp = (value, min, max) => Math.min(Math.max(Math.trunc(value), min), max);
61
+ /**
62
+ * Fit a region to the grid.
63
+ *
64
+ * Every value is clamped rather than rejected. A layout that renders slightly
65
+ * wrong is recoverable; one that vanishes because a number was out of range is
66
+ * not, and the caller usually cannot tell which region was dropped. The clamps
67
+ * are what confine a region to the totals the author declared: a span of 9 in a
68
+ * three-column grid becomes 3, and a `rowSpan` of 5 in a three-row grid
69
+ * becomes 3.
70
+ */
71
+ export const resolveBoeGridPlacement = (item, columns, rows) => {
72
+ // Leave at least one column for the region itself.
73
+ const offset = clamp(item.offset ?? 0, 0, Math.max(columns - 1, 0));
74
+ return {
75
+ offset,
76
+ span: clamp(item.span ?? 1, 1, Math.max(columns - offset, 1)),
77
+ rowSpan: clamp(item.rowSpan ?? 1, 1, Math.max(rows, 1)),
78
+ };
79
+ };
80
+ /** Parse a positive integer attribute, falling back when it is absent or junk. */
81
+ export const resolveGridCount = (raw, fallback) => {
82
+ const parsed = Number.parseInt(raw ?? "", 10);
83
+ return Number.isFinite(parsed) ? Math.max(parsed, 1) : fallback;
84
+ };
@@ -0,0 +1 @@
1
+ export * from "./grid.js";
@@ -0,0 +1,3 @@
1
+ // Adobe Spectrum's responsive grid: columns, breakpoint gutters, and the
2
+ // clamping that confines a region to the totals its host declared.
3
+ export * from "./grid.js";
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export type { ResolvedTheme, ThemeChangeDetail, ThemeController, ThemeController
8
8
  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";
9
9
  export type { ApplyDesignProfileOptions, DesignProfileChangeDetail, DesignProfileController, DesignProfileControllerOptions, DesignProfileDefinition, DesignProfileDensity, DesignProfileElevation, DesignProfileMotion, DesignProfileRadius, DesignProfileSpacing, DesignProfileTypography, } from "./foundations/profiles/index.js";
10
10
  export { boxIconography, boxIconographyAliases } from "./foundations/icons/index.js";
11
+ export * from "./foundations/layout/index.js";
11
12
  export { anchorFloating, parsePlacement, resolvePosition, trackAnchor, } from "./foundations/overlay/index.js";
12
13
  export type { OverlayAlign, OverlayPlacement, OverlaySide, PositionOptions, PositionResult, } from "./foundations/overlay/index.js";
13
14
  export * from "./components/actions/button.js";
@@ -42,10 +43,11 @@ export * from "./components/feedback/progress-ring.js";
42
43
  export * from "./components/feedback/progress-steps.js";
43
44
  export * from "./components/feedback/skeleton.js";
44
45
  export * from "./components/feedback/spinner.js";
45
- export * from "./components/feedback/stage-path.js";
46
+ export * from "./components/feedback/path.js";
46
47
  export * from "./components/feedback/toast.js";
47
48
  export * from "./components/files/drop-zone.js";
48
49
  export * from "./components/identity/avatar.js";
50
+ export * from "./components/identity/contact-datalist-item.js";
49
51
  export * from "./components/identity/persona.js";
50
52
  export * from "./components/navigation/accordion.js";
51
53
  export * from "./components/navigation/breadcrumb.js";
@@ -80,6 +82,7 @@ export * from "./components/forms/text-area.js";
80
82
  export * from "./components/forms/text-field.js";
81
83
  export * from "./components/layout/app-shell.js";
82
84
  export * from "./components/layout/divider.js";
85
+ export * from "./components/layout/grid.js";
83
86
  export * from "./components/layout/nav-sidebar.js";
84
87
  export * from "./components/layout/section.js";
85
88
  export * from "./components/layout/sidebar-toggle-button.js";
package/dist/index.js CHANGED
@@ -5,6 +5,8 @@ export { DESIGN_SYSTEM_CHANGE_EVENT, SEMANTIC_TOKEN_ALIASES, applyDesignTokens,
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";
8
+ // Foundations: Adobe Spectrum's responsive grid (shared by box-grid and box-skeleton)
9
+ export * from "./foundations/layout/index.js";
8
10
  // Foundations: viewport-aware overlay positioning (for building custom overlays)
9
11
  export { anchorFloating, parsePlacement, resolvePosition, trackAnchor, } from "./foundations/overlay/index.js";
10
12
  // Components: actions
@@ -42,12 +44,13 @@ export * from "./components/feedback/progress-ring.js";
42
44
  export * from "./components/feedback/progress-steps.js";
43
45
  export * from "./components/feedback/skeleton.js";
44
46
  export * from "./components/feedback/spinner.js";
45
- export * from "./components/feedback/stage-path.js";
47
+ export * from "./components/feedback/path.js";
46
48
  export * from "./components/feedback/toast.js";
47
49
  // Components: files
48
50
  export * from "./components/files/drop-zone.js";
49
51
  // Components: identity
50
52
  export * from "./components/identity/avatar.js";
53
+ export * from "./components/identity/contact-datalist-item.js";
51
54
  export * from "./components/identity/persona.js";
52
55
  // Components: navigation
53
56
  export * from "./components/navigation/accordion.js";
@@ -86,6 +89,7 @@ export * from "./components/forms/text-field.js";
86
89
  // Components: layout
87
90
  export * from "./components/layout/app-shell.js";
88
91
  export * from "./components/layout/divider.js";
92
+ export * from "./components/layout/grid.js";
89
93
  export * from "./components/layout/nav-sidebar.js";
90
94
  export * from "./components/layout/section.js";
91
95
  export * from "./components/layout/sidebar-toggle-button.js";
@@ -221,7 +221,6 @@ const elementStyles = `
221
221
  gap: 0.25rem;
222
222
  padding: 0.5rem 0.65rem;
223
223
  border-top: 1px solid color-mix(in srgb, var(--boe-token-stroke-stroke, #e8e8e8) 55%, transparent);
224
- border-left: 3px solid var(--audit-tone, transparent);
225
224
  }
226
225
 
227
226
  [part="event-topline"] {
@@ -1,4 +1,5 @@
1
1
  import type { LineageNode } from "./types.js";
2
+ import type { GraphArrows } from "../versions/graph-arrows.js";
2
3
  import { BaseElement } from "../../core/index.js";
3
4
  /**
4
5
  * Provenance DAG for clause lineage (opportunity 2): source clause →
@@ -13,6 +14,12 @@ import { BaseElement } from "../../core/index.js";
13
14
  export declare class LineageGraph extends BaseElement {
14
15
  static readonly tagName: string;
15
16
  static get observedAttributes(): string[];
17
+ /**
18
+ * Which ends of each edge carry an arrowhead. Defaults to `end`, the head on
19
+ * the derived node, because the layout builds edges source → derived.
20
+ */
21
+ get arrows(): GraphArrows;
22
+ set arrows(value: GraphArrows);
16
23
  private nodesValue;
17
24
  private rovingId;
18
25
  private hostEl;