@unofficialbox/box-open-elements 0.10.0 → 0.12.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 (50) hide show
  1. package/dist/components/feedback/alert.js +2 -22
  2. package/dist/components/feedback/nudge.js +0 -1
  3. package/dist/components/feedback/path.d.ts +84 -0
  4. package/dist/components/feedback/path.js +455 -0
  5. package/dist/components/feedback/skeleton.d.ts +70 -0
  6. package/dist/components/feedback/skeleton.js +231 -1
  7. package/dist/components/feedback/toast.d.ts +37 -0
  8. package/dist/components/feedback/toast.js +182 -17
  9. package/dist/components/feedback/tone.d.ts +16 -0
  10. package/dist/components/feedback/tone.js +31 -0
  11. package/dist/components/layout/grid.d.ts +41 -0
  12. package/dist/components/layout/grid.js +152 -0
  13. package/dist/element-maps.d.ts +7 -3
  14. package/dist/entries/comment-thread.d.ts +1 -0
  15. package/dist/entries/comment-thread.js +1 -0
  16. package/dist/entries/grid.d.ts +1 -0
  17. package/dist/entries/grid.js +1 -0
  18. package/dist/entries/path.d.ts +1 -0
  19. package/dist/entries/path.js +1 -0
  20. package/dist/foundations/layout/grid.d.ts +70 -0
  21. package/dist/foundations/layout/grid.js +84 -0
  22. package/dist/foundations/layout/index.d.ts +1 -0
  23. package/dist/foundations/layout/index.js +3 -0
  24. package/dist/index.d.ts +5 -1
  25. package/dist/index.js +6 -1
  26. package/dist/patterns/audit/audit-log.js +0 -1
  27. package/dist/patterns/comments/comment-thread.d.ts +79 -0
  28. package/dist/patterns/comments/comment-thread.js +561 -0
  29. package/dist/patterns/comments/index.d.ts +2 -0
  30. package/dist/patterns/comments/index.js +5 -0
  31. package/dist/patterns/comments/types.d.ts +39 -0
  32. package/dist/patterns/comments/types.js +8 -0
  33. package/dist/patterns/lineage/lineage-graph.d.ts +7 -0
  34. package/dist/patterns/lineage/lineage-graph.js +67 -6
  35. package/dist/patterns/lineage/provenance-strip.js +106 -15
  36. package/dist/patterns/notifications/notification-inbox.js +2 -18
  37. package/dist/patterns/preview/annotation-thread.d.ts +67 -48
  38. package/dist/patterns/preview/annotation-thread.js +96 -440
  39. package/dist/patterns/timeline/timeline.js +44 -12
  40. package/dist/patterns/versions/graph-arrows.d.ts +22 -0
  41. package/dist/patterns/versions/graph-arrows.js +13 -0
  42. package/dist/patterns/versions/index.d.ts +1 -0
  43. package/dist/patterns/versions/index.js +1 -0
  44. package/dist/patterns/versions/version-graph.d.ts +7 -0
  45. package/dist/patterns/versions/version-graph.js +54 -6
  46. package/package.json +1 -1
  47. package/dist/components/feedback/stage-path.d.ts +0 -44
  48. package/dist/components/feedback/stage-path.js +0 -235
  49. package/dist/entries/stage-path.d.ts +0 -1
  50. package/dist/entries/stage-path.js +0 -1
@@ -1,14 +1,84 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
+ import type { BoeGridPlacement, ResolvedBoeGridPlacement } from "../../foundations/layout/index.js";
3
+ /**
4
+ * Shape of the placeholder.
5
+ *
6
+ * `box` is a single rectangle sized by `width`/`height` — the original
7
+ * behaviour, and still the default. `line` is a stack of text lines. `grid` is
8
+ * a column layout whose regions stand in for cards, tiles or panels.
9
+ */
10
+ export type SkeletonVariant = "box" | "line" | "grid";
11
+ /**
12
+ * Narrow an author-supplied variant, falling back to `box`.
13
+ *
14
+ * A typo should render the original single rectangle rather than an empty
15
+ * element: every multi-part branch is scoped to a known value.
16
+ */
17
+ export declare const resolveSkeletonVariant: (value: string | null | undefined) => SkeletonVariant;
18
+ /**
19
+ * The columns in Adobe Spectrum's responsive grid.
20
+ *
21
+ * Delegated to the layout foundation that `box-grid` also builds on: a
22
+ * skeleton stands in for a real layout, so if the two disagreed about what a
23
+ * column is worth the placeholder would stop matching what replaces it.
24
+ */
25
+ export declare const SKELETON_DEFAULT_COLUMNS = 12;
26
+ /** One region of the grid, in Spectrum's terms. */
27
+ export type SkeletonGridItem = BoeGridPlacement;
28
+ /** A resolved region: every field present, every value in range. */
29
+ export type ResolvedSkeletonGridItem = ResolvedBoeGridPlacement;
30
+ /** Attribute payloads are author input — validate every record. */
31
+ export declare const isSkeletonGridItemRecord: (value: unknown) => value is BoeGridPlacement;
32
+ /**
33
+ * Fit a region to the grid, clamping every value to the declared totals.
34
+ *
35
+ * Still exported here because it is part of this component's published
36
+ * surface; the behaviour now lives in the foundation.
37
+ */
38
+ export declare const resolveSkeletonGridItem: (item: BoeGridPlacement, columns: number, rows: number) => ResolvedBoeGridPlacement;
2
39
  export declare class Skeleton extends BaseElement {
3
40
  static readonly tagName: string;
4
41
  static get observedAttributes(): string[];
5
42
  private skeletonEl;
43
+ private rootEl;
6
44
  private appliedWidth;
7
45
  private appliedHeight;
46
+ private renderedVariant;
47
+ private itemsRaw;
48
+ private itemsCache;
8
49
  get width(): string;
9
50
  set width(value: string);
10
51
  get height(): string;
11
52
  set height(value: string);
53
+ /** Shape of the placeholder. An unknown value falls back to `box`. */
54
+ get variant(): SkeletonVariant;
55
+ set variant(value: SkeletonVariant);
56
+ /** Lines drawn by the `line` variant. Values below 1 render a single line. */
57
+ get lines(): number;
58
+ set lines(value: number);
59
+ /** Columns in the `grid` variant. Defaults to Spectrum's twelve. */
60
+ get columns(): number;
61
+ set columns(value: number);
62
+ /** Rows in the `grid` variant. Also the ceiling for any region's `rowSpan`. */
63
+ get rows(): number;
64
+ set rows(value: number);
65
+ /** Height of one grid row; a region spanning two is twice this plus a gutter. */
66
+ get rowHeight(): string;
67
+ set rowHeight(value: string);
68
+ /**
69
+ * Regions of the `grid` variant, in order.
70
+ *
71
+ * With none given the grid is filled with single-column regions — `rows` ×
72
+ * `columns` of them — so `rows` and `columns` alone describe a uniform grid.
73
+ */
74
+ get items(): SkeletonGridItem[];
75
+ set items(value: SkeletonGridItem[]);
76
+ /** The grid's regions as rendered: clamped to `columns` and `rows`. */
77
+ get resolvedItems(): ResolvedSkeletonGridItem[];
12
78
  protected renderTemplate(): void;
13
79
  protected update(): void;
80
+ /** Render the `line` or `grid` variant, which draw many bars rather than one. */
81
+ private updateGroup;
82
+ private renderLines;
83
+ private renderGrid;
14
84
  }
@@ -1,12 +1,48 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
2
  import { boeRadius } from "../../foundations/geometry/index.js";
3
+ import { BOE_GRID_COLUMNS, BOE_GRID_GUTTER_PROPERTY, boeGridGutterStyles, isBoeGridPlacementRecord, resolveBoeGridPlacement, resolveGridCount, } from "../../foundations/layout/index.js";
3
4
  import { boeMotionDuration, boeMotionEasing, boeReducedMotionStyles, } from "../../foundations/motion/index.js";
4
5
  const DEFAULT_TAG_NAME = "box-skeleton";
6
+ const SKELETON_VARIANTS = new Set(["box", "line", "grid"]);
7
+ /**
8
+ * Narrow an author-supplied variant, falling back to `box`.
9
+ *
10
+ * A typo should render the original single rectangle rather than an empty
11
+ * element: every multi-part branch is scoped to a known value.
12
+ */
13
+ export const resolveSkeletonVariant = (value) => SKELETON_VARIANTS.has(value) ? value : "box";
14
+ /**
15
+ * The columns in Adobe Spectrum's responsive grid.
16
+ *
17
+ * Delegated to the layout foundation that `box-grid` also builds on: a
18
+ * skeleton stands in for a real layout, so if the two disagreed about what a
19
+ * column is worth the placeholder would stop matching what replaces it.
20
+ */
21
+ export const SKELETON_DEFAULT_COLUMNS = BOE_GRID_COLUMNS;
22
+ /** Attribute payloads are author input — validate every record. */
23
+ export const isSkeletonGridItemRecord = isBoeGridPlacementRecord;
24
+ /**
25
+ * Fit a region to the grid, clamping every value to the declared totals.
26
+ *
27
+ * Still exported here because it is part of this component's published
28
+ * surface; the behaviour now lives in the foundation.
29
+ */
30
+ export const resolveSkeletonGridItem = resolveBoeGridPlacement;
5
31
  const skeletonStyles = `
6
32
  :host {
7
33
  display: inline-block;
8
34
  color: inherit;
9
35
  font: inherit;
36
+
37
+ }
38
+
39
+ ${boeGridGutterStyles(":host")}
40
+
41
+ /* The multi-part variants are layout, so they take the full width they are
42
+ given rather than shrink-wrapping like the single box. */
43
+ :host([variant="line"]),
44
+ :host([variant="grid"]) {
45
+ display: block;
10
46
  }
11
47
 
12
48
  [part="skeleton"] {
@@ -22,6 +58,38 @@ const skeletonStyles = `
22
58
  animation: boe-skeleton-shimmer ${boeMotionDuration.shimmer} ${boeMotionEasing.standard} infinite;
23
59
  }
24
60
 
61
+ [part="lines"] {
62
+ display: flex;
63
+ flex-direction: column;
64
+ gap: 0.55rem;
65
+ }
66
+
67
+ [part="lines"] [part="skeleton"] {
68
+ display: block;
69
+ inline-size: 100%;
70
+ }
71
+
72
+ /* The last line stops short, the way a paragraph's does. Without it a stack
73
+ of equal bars reads as a table rather than as text. */
74
+ [part="lines"] [part="skeleton"]:last-child:not(:only-child) {
75
+ inline-size: 62%;
76
+ }
77
+
78
+ [part="grid"] {
79
+ display: grid;
80
+ grid-template-columns: repeat(var(--boe-skeleton-columns, ${BOE_GRID_COLUMNS}), minmax(0, 1fr));
81
+ grid-auto-rows: var(--boe-skeleton-row-height, 48px);
82
+ gap: var(${BOE_GRID_GUTTER_PROPERTY});
83
+ }
84
+
85
+ /* Offsets are spacers rather than an explicit grid-column-start, so they
86
+ compose with auto-placement instead of fighting it: an explicit start makes
87
+ the item hunt for a row where that exact column is free, which reorders the
88
+ regions the author listed. */
89
+ [part="grid-offset"] {
90
+ visibility: hidden;
91
+ }
92
+
25
93
  @keyframes boe-skeleton-shimmer {
26
94
  0% {
27
95
  background-position: 100% 0;
@@ -37,11 +105,15 @@ const skeletonStyles = `
37
105
  export class Skeleton extends BaseElement {
38
106
  static tagName = DEFAULT_TAG_NAME;
39
107
  static get observedAttributes() {
40
- return ["height", "width"];
108
+ return ["columns", "height", "items", "lines", "row-height", "rows", "variant", "width"];
41
109
  }
42
110
  skeletonEl;
111
+ rootEl;
43
112
  appliedWidth = "";
44
113
  appliedHeight = "";
114
+ renderedVariant = null;
115
+ itemsRaw = null;
116
+ itemsCache = [];
45
117
  get width() {
46
118
  return this.getAttribute("width") ?? "100%";
47
119
  }
@@ -54,6 +126,85 @@ export class Skeleton extends BaseElement {
54
126
  set height(value) {
55
127
  this.setAttribute("height", value);
56
128
  }
129
+ /** Shape of the placeholder. An unknown value falls back to `box`. */
130
+ get variant() {
131
+ return resolveSkeletonVariant(this.getAttribute("variant"));
132
+ }
133
+ set variant(value) {
134
+ this.setAttribute("variant", value);
135
+ }
136
+ /** Lines drawn by the `line` variant. Values below 1 render a single line. */
137
+ get lines() {
138
+ const parsed = Number.parseInt(this.getAttribute("lines") ?? "", 10);
139
+ return Number.isFinite(parsed) ? Math.max(parsed, 1) : 3;
140
+ }
141
+ set lines(value) {
142
+ this.setAttribute("lines", String(value));
143
+ }
144
+ /** Columns in the `grid` variant. Defaults to Spectrum's twelve. */
145
+ get columns() {
146
+ return resolveGridCount(this.getAttribute("columns"), BOE_GRID_COLUMNS);
147
+ }
148
+ set columns(value) {
149
+ this.setAttribute("columns", String(value));
150
+ }
151
+ /** Rows in the `grid` variant. Also the ceiling for any region's `rowSpan`. */
152
+ get rows() {
153
+ return resolveGridCount(this.getAttribute("rows"), 1);
154
+ }
155
+ set rows(value) {
156
+ this.setAttribute("rows", String(value));
157
+ }
158
+ /** Height of one grid row; a region spanning two is twice this plus a gutter. */
159
+ get rowHeight() {
160
+ return this.getAttribute("row-height") ?? "48px";
161
+ }
162
+ set rowHeight(value) {
163
+ this.setAttribute("row-height", value);
164
+ }
165
+ /**
166
+ * Regions of the `grid` variant, in order.
167
+ *
168
+ * With none given the grid is filled with single-column regions — `rows` ×
169
+ * `columns` of them — so `rows` and `columns` alone describe a uniform grid.
170
+ */
171
+ get items() {
172
+ const raw = this.getAttribute("items");
173
+ if (!raw) {
174
+ return [];
175
+ }
176
+ if (raw !== this.itemsRaw) {
177
+ this.itemsRaw = raw;
178
+ try {
179
+ const parsed = JSON.parse(raw);
180
+ this.itemsCache =
181
+ Array.isArray(parsed) && parsed.every(isSkeletonGridItemRecord)
182
+ ? parsed
183
+ : [];
184
+ }
185
+ catch {
186
+ this.itemsCache = [];
187
+ }
188
+ }
189
+ return [...this.itemsCache];
190
+ }
191
+ set items(value) {
192
+ if (value.length) {
193
+ this.setAttribute("items", JSON.stringify(value));
194
+ return;
195
+ }
196
+ this.removeAttribute("items");
197
+ }
198
+ /** The grid's regions as rendered: clamped to `columns` and `rows`. */
199
+ get resolvedItems() {
200
+ const columns = this.columns;
201
+ const rows = this.rows;
202
+ const declared = this.items;
203
+ const source = declared.length
204
+ ? declared
205
+ : Array.from({ length: rows * columns }, () => ({}));
206
+ return source.map(item => resolveSkeletonGridItem(item, columns, rows));
207
+ }
57
208
  renderTemplate() {
58
209
  if (!this.shadowRoot) {
59
210
  return;
@@ -65,8 +216,29 @@ export class Skeleton extends BaseElement {
65
216
  this.skeletonEl = this.shadowRoot.querySelector('[part="skeleton"]');
66
217
  this.appliedWidth = "";
67
218
  this.appliedHeight = "";
219
+ this.renderedVariant = "box";
68
220
  }
69
221
  update() {
222
+ if (!this.shadowRoot) {
223
+ return;
224
+ }
225
+ const variant = this.variant;
226
+ if (variant !== "box") {
227
+ this.updateGroup(variant);
228
+ return;
229
+ }
230
+ if (this.renderedVariant !== "box") {
231
+ // Coming back from a multi-part variant: restore the single box that the
232
+ // width/height path writes into.
233
+ this.shadowRoot.innerHTML = `
234
+ <style>${skeletonStyles}</style>
235
+ <span part="skeleton" style="display:inline-block;" aria-hidden="true"></span>
236
+ `;
237
+ this.skeletonEl = this.shadowRoot.querySelector('[part="skeleton"]');
238
+ this.appliedWidth = "";
239
+ this.appliedHeight = "";
240
+ this.renderedVariant = "box";
241
+ }
70
242
  if (!this.skeletonEl) {
71
243
  return;
72
244
  }
@@ -85,5 +257,63 @@ export class Skeleton extends BaseElement {
85
257
  this.appliedHeight = nextHeight;
86
258
  }
87
259
  }
260
+ /** Render the `line` or `grid` variant, which draw many bars rather than one. */
261
+ updateGroup(variant) {
262
+ const shadowRoot = this.shadowRoot;
263
+ if (this.renderedVariant !== variant) {
264
+ shadowRoot.innerHTML = `
265
+ <style>${skeletonStyles}</style>
266
+ <div part="${variant === "line" ? "lines" : "grid"}" aria-hidden="true"></div>
267
+ `;
268
+ this.rootEl = shadowRoot.querySelector(`[part="${variant === "line" ? "lines" : "grid"}"]`);
269
+ this.renderedVariant = variant;
270
+ this.appliedWidth = "";
271
+ this.appliedHeight = "";
272
+ }
273
+ if (variant === "line") {
274
+ this.renderLines();
275
+ return;
276
+ }
277
+ this.renderGrid();
278
+ }
279
+ renderLines() {
280
+ const count = this.lines;
281
+ const height = this.height;
282
+ // Reuse the bars already there: only the count changes between renders, and
283
+ // replacing every node would restart the shimmer on each update.
284
+ while (this.rootEl.childElementCount > count) {
285
+ this.rootEl.lastElementChild.remove();
286
+ }
287
+ while (this.rootEl.childElementCount < count) {
288
+ const line = document.createElement("span");
289
+ line.setAttribute("part", "skeleton");
290
+ this.rootEl.append(line);
291
+ }
292
+ for (const child of Array.from(this.rootEl.children)) {
293
+ // Via the CSSOM, for the same reason the box variant does: the value is
294
+ // author input and setProperty drops anything that is not a length.
295
+ child.style.setProperty("height", height);
296
+ }
297
+ }
298
+ renderGrid() {
299
+ this.rootEl.style.setProperty("--boe-skeleton-columns", String(this.columns));
300
+ this.rootEl.style.setProperty("--boe-skeleton-row-height", this.rowHeight);
301
+ // Rebuilt rather than patched: a change to items can alter every region's
302
+ // span and offset, so there is no stable identity to reuse.
303
+ this.rootEl.replaceChildren();
304
+ for (const item of this.resolvedItems) {
305
+ if (item.offset > 0) {
306
+ const spacer = document.createElement("span");
307
+ spacer.setAttribute("part", "grid-offset");
308
+ spacer.style.setProperty("grid-column", `span ${item.offset}`);
309
+ this.rootEl.append(spacer);
310
+ }
311
+ const region = document.createElement("span");
312
+ region.setAttribute("part", "skeleton");
313
+ region.style.setProperty("grid-column", `span ${item.span}`);
314
+ region.style.setProperty("grid-row", `span ${item.rowSpan}`);
315
+ this.rootEl.append(region);
316
+ }
317
+ }
88
318
  }
89
319
  Skeleton.register();
@@ -1,11 +1,25 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
+ /**
3
+ * Whether the toast clears itself.
4
+ *
5
+ * `dismissible` auto-dismisses after `duration` and can also be closed by hand;
6
+ * `sticky` stays until the reader closes it, whatever `duration` says. Both
7
+ * carry the close control — a toast the reader cannot get rid of is a trap.
8
+ */
9
+ export type ToastMode = "dismissible" | "sticky";
10
+ /** Narrow an author-supplied mode, falling back to `dismissible`. */
11
+ export declare const resolveToastMode: (value: string | null | undefined) => ToastMode;
2
12
  export declare class Toast extends BaseElement {
3
13
  static readonly tagName: string;
4
14
  static get observedAttributes(): string[];
5
15
  private openValue;
6
16
  private timeoutId;
7
17
  private toastEl;
18
+ private iconEl;
19
+ private headingEl;
20
+ private toneLabelEl;
8
21
  private messageEl;
22
+ private renderedTone;
9
23
  private actionSlot;
10
24
  private dismissEl;
11
25
  /** Auto-dismiss delay in ms for the declarative `open` path. 0 = sticky. */
@@ -16,6 +30,29 @@ export declare class Toast extends BaseElement {
16
30
  private scheduleAutoDismiss;
17
31
  get message(): string;
18
32
  set message(value: string);
33
+ /**
34
+ * Optional bold line above the message — "Upload failed" over "3 of 12 files
35
+ * could not be read". Named to match `box-alert`, which established the
36
+ * heading-plus-message shape in this family. Salesforce calls it `label`.
37
+ */
38
+ get heading(): string;
39
+ set heading(value: string);
40
+ /**
41
+ * @deprecated Every toast is borderless now, so this does nothing.
42
+ *
43
+ * Kept because it shipped in 0.11.0 and removing it would break hosts that
44
+ * set it for no benefit — what they asked for is what they already get. The
45
+ * attribute is still reflected so those hosts read back what they wrote.
46
+ */
47
+ get borderless(): boolean;
48
+ set borderless(value: boolean);
49
+ /**
50
+ * Whether the toast clears itself. `sticky` overrides any `duration`: a
51
+ * caller that has said "this one stays" should not have it taken away by a
52
+ * duration set elsewhere.
53
+ */
54
+ get mode(): ToastMode;
55
+ set mode(value: ToastMode);
19
56
  get tone(): string;
20
57
  set tone(value: string);
21
58
  disconnectedCallback(): void;