@unofficialbox/box-open-elements 0.17.0 → 0.19.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 (146) hide show
  1. package/dist/components/actions/button-group.js +6 -0
  2. package/dist/components/actions/button.js +6 -0
  3. package/dist/components/actions/icon-button.js +6 -0
  4. package/dist/components/actions/link-button.js +6 -0
  5. package/dist/components/actions/menu-item.js +6 -0
  6. package/dist/components/actions/menu.js +6 -0
  7. package/dist/components/actions/segmented-control.js +6 -0
  8. package/dist/components/actions/toolbar.js +6 -0
  9. package/dist/components/collections/card.js +6 -0
  10. package/dist/components/collections/carousel.js +6 -0
  11. package/dist/components/collections/datalist-item.js +6 -0
  12. package/dist/components/collections/draggable-list.js +6 -0
  13. package/dist/components/collections/grid-view.js +6 -0
  14. package/dist/components/collections/pagination.js +6 -0
  15. package/dist/components/collections/table.js +6 -0
  16. package/dist/components/collections/thumbnail-card.js +6 -0
  17. package/dist/components/collections/tree-grid.js +6 -0
  18. package/dist/components/collections/tree.js +6 -0
  19. package/dist/components/feedback/alert.js +1 -1
  20. package/dist/components/feedback/badge.js +1 -1
  21. package/dist/components/feedback/badgeable.js +6 -0
  22. package/dist/components/feedback/chip.js +6 -0
  23. package/dist/components/feedback/due-badge.js +6 -0
  24. package/dist/components/feedback/empty-state.js +6 -0
  25. package/dist/components/feedback/error-mask.js +6 -0
  26. package/dist/components/feedback/help-text.js +6 -0
  27. package/dist/components/feedback/indicator.js +1 -1
  28. package/dist/components/feedback/nudge.js +6 -0
  29. package/dist/components/feedback/path.js +6 -0
  30. package/dist/components/feedback/progress-bar.js +6 -0
  31. package/dist/components/feedback/progress-ring.js +6 -0
  32. package/dist/components/feedback/progress-steps.js +6 -0
  33. package/dist/components/feedback/skeleton.js +6 -0
  34. package/dist/components/feedback/spinner.js +6 -0
  35. package/dist/components/feedback/toast.js +1 -1
  36. package/dist/components/files/drop-zone.d.ts +26 -5
  37. package/dist/components/files/drop-zone.js +181 -22
  38. package/dist/components/forms/calendar.js +6 -0
  39. package/dist/components/forms/category-selector.js +6 -0
  40. package/dist/components/forms/checkbox-group.js +6 -0
  41. package/dist/components/forms/checkbox.js +6 -0
  42. package/dist/components/forms/color-picker.js +6 -0
  43. package/dist/components/forms/combobox.js +6 -0
  44. package/dist/components/forms/date-field.js +6 -0
  45. package/dist/components/forms/dropdown.js +6 -0
  46. package/dist/components/forms/dual-listbox.js +6 -0
  47. package/dist/components/forms/fieldset.js +6 -0
  48. package/dist/components/forms/multi-select.js +6 -0
  49. package/dist/components/forms/number-input.js +6 -0
  50. package/dist/components/forms/pill-cloud.js +6 -0
  51. package/dist/components/forms/pill-selector-dropdown.js +6 -0
  52. package/dist/components/forms/radio-group.js +6 -0
  53. package/dist/components/forms/range-slider.js +6 -0
  54. package/dist/components/forms/rating.js +6 -0
  55. package/dist/components/forms/rich-text-input.js +6 -0
  56. package/dist/components/forms/search-field.js +6 -0
  57. package/dist/components/forms/select.js +6 -0
  58. package/dist/components/forms/slider.js +6 -0
  59. package/dist/components/forms/spin-button.js +6 -0
  60. package/dist/components/forms/switch.js +6 -0
  61. package/dist/components/forms/tag-input.js +6 -0
  62. package/dist/components/forms/text-area.js +6 -0
  63. package/dist/components/forms/text-field.js +6 -0
  64. package/dist/components/forms/tile-group.js +1 -1
  65. package/dist/components/forms/time-field.js +6 -0
  66. package/dist/components/identity/avatar.js +6 -0
  67. package/dist/components/identity/contact-datalist-item.js +6 -0
  68. package/dist/components/identity/persona.js +6 -0
  69. package/dist/components/layout/app-shell.js +6 -0
  70. package/dist/components/layout/divider.js +6 -0
  71. package/dist/components/layout/grid.js +1 -1
  72. package/dist/components/layout/nav-sidebar.js +6 -0
  73. package/dist/components/layout/section.js +6 -0
  74. package/dist/components/layout/sidebar-toggle-button.js +6 -0
  75. package/dist/components/layout/split-view.js +6 -0
  76. package/dist/components/navigation/accordion.js +6 -0
  77. package/dist/components/navigation/breadcrumb.js +6 -0
  78. package/dist/components/navigation/tabs.js +6 -0
  79. package/dist/components/output/code-block.js +1 -1
  80. package/dist/components/output/formatted-value.js +1 -1
  81. package/dist/components/overlays/command-palette.js +6 -0
  82. package/dist/components/overlays/context-menu.js +6 -0
  83. package/dist/components/overlays/guide-tooltip.js +6 -0
  84. package/dist/components/overlays/popover.js +6 -0
  85. package/dist/components/overlays/shortcuts-overlay.js +6 -0
  86. package/dist/components/overlays/tooltip.js +6 -0
  87. package/dist/components/visuals/illustration.js +6 -0
  88. package/dist/foundations/tokens/box-defaults.js +36 -0
  89. package/dist/patterns/agent-chat/agent-chat.js +6 -0
  90. package/dist/patterns/audit/activity-density.js +6 -0
  91. package/dist/patterns/audit/audit-log.js +6 -0
  92. package/dist/patterns/comments/comment-thread.js +6 -0
  93. package/dist/patterns/content-explorer/adapters/action-menu.js +6 -0
  94. package/dist/patterns/content-explorer/adapters/breadcrumbs.js +6 -0
  95. package/dist/patterns/content-explorer/adapters/list.js +6 -0
  96. package/dist/patterns/content-explorer/adapters/table.js +6 -0
  97. package/dist/patterns/content-explorer/adapters/toolbar.js +6 -0
  98. package/dist/patterns/content-explorer/content-explorer.js +6 -0
  99. package/dist/patterns/content-picker/content-picker.js +6 -0
  100. package/dist/patterns/content-sidebar/content-sidebar.js +6 -0
  101. package/dist/patterns/content-uploader/content-uploader.d.ts +33 -0
  102. package/dist/patterns/content-uploader/content-uploader.js +181 -16
  103. package/dist/patterns/diff/compare-view.js +6 -0
  104. package/dist/patterns/diff/diff-viewer.js +6 -0
  105. package/dist/patterns/file-request/file-request-builder.js +6 -0
  106. package/dist/patterns/form-wizard/form-wizard.js +6 -0
  107. package/dist/patterns/form-wizard/wizard-summary.js +6 -0
  108. package/dist/patterns/governance/governance-panel.js +6 -0
  109. package/dist/patterns/insights/bar-chart.js +6 -0
  110. package/dist/patterns/insights/chart-panel.js +6 -0
  111. package/dist/patterns/insights/donut-chart.js +6 -0
  112. package/dist/patterns/insights/line-chart.js +6 -0
  113. package/dist/patterns/insights/metric-card.js +6 -0
  114. package/dist/patterns/item/bulk-action-bar.js +6 -0
  115. package/dist/patterns/item/item-details-panel.js +6 -0
  116. package/dist/patterns/item/item-form.js +6 -0
  117. package/dist/patterns/item/preview-header.js +6 -0
  118. package/dist/patterns/lineage/lineage-graph.js +6 -0
  119. package/dist/patterns/lineage/provenance-strip.js +6 -0
  120. package/dist/patterns/metadata/metadata-filter-builder.js +6 -0
  121. package/dist/patterns/metadata/metadata-inspector.js +6 -0
  122. package/dist/patterns/notifications/notification-bell.js +6 -0
  123. package/dist/patterns/notifications/notification-inbox.js +6 -0
  124. package/dist/patterns/preview/annotation-inspector.js +6 -0
  125. package/dist/patterns/preview/annotation-toolbar.js +6 -0
  126. package/dist/patterns/preview/preview-element.js +6 -0
  127. package/dist/patterns/run/run-trace.js +6 -0
  128. package/dist/patterns/search/filter-bar.js +6 -0
  129. package/dist/patterns/search/saved-view-picker.js +6 -0
  130. package/dist/patterns/search/search-results-header.js +6 -0
  131. package/dist/patterns/share/access-stats.js +6 -0
  132. package/dist/patterns/share/collaborator-avatars.js +6 -0
  133. package/dist/patterns/share/invite-collaborators-modal.js +6 -0
  134. package/dist/patterns/share/permission-matrix.js +6 -0
  135. package/dist/patterns/share/presence.js +6 -0
  136. package/dist/patterns/share/share-panel.js +6 -0
  137. package/dist/patterns/share/unified-share-modal.js +6 -0
  138. package/dist/patterns/signature/signature-ceremony.js +6 -0
  139. package/dist/patterns/task/review-queue-item.js +6 -0
  140. package/dist/patterns/task/task-assignment-panel.js +6 -0
  141. package/dist/patterns/timeline/timeline.js +6 -0
  142. package/dist/patterns/versions/version-graph.js +6 -0
  143. package/dist/patterns/versions/version-list.js +6 -0
  144. package/dist/patterns/work-queue/work-queue.js +6 -0
  145. package/dist/patterns/work-queue/workload-board.js +6 -0
  146. package/package.json +1 -1
@@ -4,6 +4,7 @@ import { formatItemSize } from "../content-explorer/adapters/item-summary.js";
4
4
  import { DropZone } from "../../components/files/drop-zone.js";
5
5
  import { ProgressBar } from "../../components/feedback/progress-bar.js";
6
6
  import { BaseElement } from "../../core/index.js";
7
+ import { DESIGN_SYSTEM_CHANGE_EVENT, resolveDesignIllustration, } from "../../foundations/tokens/index.js";
7
8
  import { boeMotionDuration, boeMotionEasing } from "../../foundations/motion/index.js";
8
9
  import { boePanel, boeRadius } from "../../foundations/geometry/index.js";
9
10
  const DEFAULT_TAG_NAME = "box-content-uploader";
@@ -62,6 +63,12 @@ const elementStyles = `
62
63
  font: inherit;
63
64
  }
64
65
 
66
+ /* The host's own display would otherwise beat the UA rule for [hidden],
67
+ leaving the element on screen when a host hides it. */
68
+ :host([hidden]) {
69
+ display: none !important;
70
+ }
71
+
65
72
  [part="panel"] {
66
73
  display: grid;
67
74
  gap: ${boePanel.gap};
@@ -171,10 +178,19 @@ const elementStyles = `
171
178
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--boe-token-surface-surface-brand, #0061d5) 18%, transparent);
172
179
  }
173
180
 
181
+ /* The footer is a bar rather than a caption: Close sits apart on the
182
+ left, the queue-level actions group on the right, as they do in
183
+ box-ui-elements. */
184
+ /* Wraps rather than squeezes: in a narrow column the summary would
185
+ otherwise concertina onto three lines and the button labels break
186
+ mid-phrase. Wrapped, the action group drops to its own row intact. */
174
187
  [part="footer"] {
175
188
  display: flex;
189
+ flex-wrap: wrap;
176
190
  align-items: center;
177
- gap: ${boePanel.gap};
191
+ gap: 0.5rem ${boePanel.gap};
192
+ padding-block-start: ${boePanel.gap};
193
+ border-block-start: 1px solid color-mix(in srgb, var(--boe-token-stroke-stroke, #e8e8e8) 82%, transparent);
178
194
  }
179
195
 
180
196
  [part="footer"][hidden] {
@@ -182,39 +198,81 @@ const elementStyles = `
182
198
  }
183
199
 
184
200
  [part="summary"] {
185
- flex: 1;
201
+ /* Takes the slack but never forces a wrap of its own: it is a status
202
+ line, not a reason for the buttons to be squeezed. */
203
+ flex: 1 1 auto;
204
+ min-inline-size: 0;
186
205
  font-size: 0.85rem;
187
206
  color: var(--boe-token-text-text-secondary, #6f6f6f);
188
207
  }
189
208
 
190
- [part="clear-completed"] {
209
+ [part="footer-actions"] {
210
+ display: flex;
211
+ flex-wrap: wrap;
212
+ align-items: center;
213
+ justify-content: flex-end;
214
+ /* Keeps the group right-aligned once the footer wraps it onto its
215
+ own row. */
216
+ margin-inline-start: auto;
217
+ gap: 0.5rem;
218
+ }
219
+
220
+ [part~="action"] {
191
221
  appearance: none;
192
222
  font: inherit;
193
223
  font-size: 0.875rem;
194
224
  font-weight: 600;
195
- padding: 0.4rem 0.7rem;
225
+ padding: 0.5rem 0.9rem;
196
226
  border-radius: ${boeRadius.control};
197
227
  border: 1px solid var(--boe-token-stroke-stroke, #e8e8e8);
198
228
  background: var(--boe-token-surface-surface, #ffffff);
199
229
  color: var(--boe-token-text-text, #222222);
200
230
  cursor: pointer;
231
+ /* A label that breaks mid-phrase reads as two controls. */
232
+ white-space: nowrap;
233
+ transition:
234
+ background ${boeMotionDuration.interactive} ${boeMotionEasing.standard},
235
+ border-color ${boeMotionDuration.interactive} ${boeMotionEasing.standard};
201
236
  }
202
237
 
203
- [part="clear-completed"]:hover {
238
+ [part~="action"]:hover:not(:disabled) {
204
239
  background: var(--boe-token-surface-surface-hover, #f4f4f4);
205
240
  border-color: var(--boe-token-stroke-stroke-hover, #bcbcbc);
206
241
  }
207
242
 
208
- [part="clear-completed"]:focus-visible {
243
+ [part~="action"]:focus-visible {
209
244
  outline: none;
210
245
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--boe-token-surface-surface-brand, #0061d5) 18%, transparent);
211
246
  }
247
+
248
+ /* Disabled, not removed: the control keeps its place so the footer does
249
+ not reflow as the queue changes, and stays discoverable. */
250
+ [part~="action"]:disabled {
251
+ cursor: not-allowed;
252
+ opacity: 0.5;
253
+ }
254
+
255
+ [part~="action-primary"] {
256
+ border-color: transparent;
257
+ background: var(--boe-token-surface-surface-brand, #0061d5);
258
+ color: var(--boe-token-text-text-on-color, #ffffff);
259
+ }
260
+
261
+ [part~="action-primary"]:hover:not(:disabled) {
262
+ background: color-mix(in srgb, var(--boe-token-surface-surface-brand, #0061d5) 86%, black 14%);
263
+ border-color: transparent;
264
+ }
265
+
266
+ [part="close"][hidden] {
267
+ display: none;
268
+ }
212
269
  `;
213
270
  export class ContentUploader extends BaseElement {
214
271
  static tagName = DEFAULT_TAG_NAME;
215
272
  static get observedAttributes() {
216
273
  return [
217
274
  "auto-start",
275
+ "closable",
218
276
  "concurrency",
219
277
  "drop-label",
220
278
  "drop-message",
@@ -237,6 +295,17 @@ export class ContentUploader extends BaseElement {
237
295
  summaryEl;
238
296
  queueSignature = "";
239
297
  updateScheduled = false;
298
+ closeEl;
299
+ cancelEl;
300
+ uploadEl;
301
+ clearCompletedEl;
302
+ illustrationEl;
303
+ illustrationSignature = "";
304
+ handleDesignSystemChange = () => {
305
+ if (this.isRendered) {
306
+ this.renderIllustration();
307
+ }
308
+ };
240
309
  get folderId() {
241
310
  return this.getAttribute("folder-id");
242
311
  }
@@ -326,14 +395,39 @@ export class ContentUploader extends BaseElement {
326
395
  set directories(value) {
327
396
  this.toggleAttribute("directories", value);
328
397
  }
398
+ /**
399
+ * Show the Close control. On by default, matching box-ui-elements; a host
400
+ * that owns its own dismissal (a drawer with its own close button) sets
401
+ * `closable="false"` rather than styling ours away.
402
+ */
403
+ get closable() {
404
+ return this.getAttribute("closable") !== "false";
405
+ }
406
+ set closable(value) {
407
+ if (value) {
408
+ this.removeAttribute("closable");
409
+ return;
410
+ }
411
+ this.setAttribute("closable", "false");
412
+ }
413
+ /**
414
+ * Headline of the empty state. Defaults to the box-ui-elements wording, and
415
+ * names folders too when they can be uploaded, so the invitation matches what
416
+ * the zone will actually accept.
417
+ */
329
418
  get dropLabel() {
330
- return this.getAttribute("drop-label") ?? "Upload files";
419
+ return (this.getAttribute("drop-label") ??
420
+ (this.directories ? "Drag and drop files and folders" : "Drag and drop files"));
331
421
  }
332
422
  set dropLabel(value) {
333
423
  this.setAttribute("drop-label", value);
334
424
  }
425
+ /**
426
+ * Optional supporting line under the headline. Empty by default: the browse
427
+ * controls say what to do, and a sentence repeating them is noise.
428
+ */
335
429
  get dropMessage() {
336
- return this.getAttribute("drop-message") ?? "Drag files here or click to browse.";
430
+ return this.getAttribute("drop-message") ?? "";
337
431
  }
338
432
  set dropMessage(value) {
339
433
  this.setAttribute("drop-message", value);
@@ -357,6 +451,7 @@ export class ContentUploader extends BaseElement {
357
451
  * else feeds the session config, so changing it re-creates the queue.
358
452
  */
359
453
  static PRESENTATION_ATTRIBUTES = new Set([
454
+ "closable",
360
455
  "directories",
361
456
  "drop-label",
362
457
  "drop-message",
@@ -368,10 +463,12 @@ export class ContentUploader extends BaseElement {
368
463
  super.attributeChangedCallback(name, oldValue, newValue);
369
464
  }
370
465
  connectedCallback() {
466
+ globalThis.addEventListener?.(DESIGN_SYSTEM_CHANGE_EVENT, this.handleDesignSystemChange);
371
467
  super.connectedCallback();
372
468
  this.scheduleStart();
373
469
  }
374
470
  disconnectedCallback() {
471
+ globalThis.removeEventListener?.(DESIGN_SYSTEM_CHANGE_EVENT, this.handleDesignSystemChange);
375
472
  this.teardownController();
376
473
  }
377
474
  addFiles(files) {
@@ -511,11 +608,18 @@ export class ContentUploader extends BaseElement {
511
608
  this.shadowRoot.innerHTML = `
512
609
  <style>${elementStyles}</style>
513
610
  <div part="panel">
514
- <box-drop-zone part="drop-zone"></box-drop-zone>
611
+ <box-drop-zone part="drop-zone" variant="hero">
612
+ <span slot="illustration" part="drop-illustration"></span>
613
+ </box-drop-zone>
515
614
  <ul part="queue" aria-label="Upload queue"></ul>
516
- <footer part="footer" hidden>
615
+ <footer part="footer">
616
+ <button type="button" part="action close">Close</button>
517
617
  <span part="summary" role="status" aria-live="polite"></span>
518
- <button type="button" part="clear-completed">Clear completed</button>
618
+ <span part="footer-actions">
619
+ <button type="button" part="action clear-completed">Clear completed</button>
620
+ <button type="button" part="action cancel">Cancel</button>
621
+ <button type="button" part="action action-primary upload">Upload</button>
622
+ </span>
519
623
  </footer>
520
624
  </div>
521
625
  `;
@@ -523,6 +627,25 @@ export class ContentUploader extends BaseElement {
523
627
  this.queueEl = this.shadowRoot.querySelector('[part="queue"]');
524
628
  this.footerEl = this.shadowRoot.querySelector('[part="footer"]');
525
629
  this.summaryEl = this.shadowRoot.querySelector('[part="summary"]');
630
+ this.closeEl = this.shadowRoot.querySelector('[part~="close"]');
631
+ this.cancelEl = this.shadowRoot.querySelector('[part~="cancel"]');
632
+ this.uploadEl = this.shadowRoot.querySelector('[part~="upload"]');
633
+ this.clearCompletedEl = this.shadowRoot.querySelector('[part~="clear-completed"]');
634
+ this.illustrationEl = this.shadowRoot.querySelector('[part="drop-illustration"]');
635
+ }
636
+ /**
637
+ * Paints the empty-state art from the active design system, so a host that
638
+ * registers its own system gets its own illustration without touching this.
639
+ *
640
+ * Resolved during update rather than at template time: a host may register or
641
+ * switch design systems after the element upgrades, and the art has to follow.
642
+ */
643
+ renderIllustration() {
644
+ const markup = resolveDesignIllustration("upload-cloud") ?? "";
645
+ if (markup !== this.illustrationSignature) {
646
+ this.illustrationSignature = markup;
647
+ this.illustrationEl.innerHTML = markup;
648
+ }
526
649
  }
527
650
  setupListeners() {
528
651
  this.dropZoneEl.addEventListener("files-selected", event => {
@@ -554,9 +677,33 @@ export class ContentUploader extends BaseElement {
554
677
  this.removeItem(itemId);
555
678
  }
556
679
  });
557
- this.footerEl.querySelector('[part="clear-completed"]')?.addEventListener("click", () => {
680
+ this.clearCompletedEl.addEventListener("click", () => {
558
681
  this.clearCompleted();
559
682
  });
683
+ this.uploadEl.addEventListener("click", () => {
684
+ this.start();
685
+ });
686
+ this.cancelEl.addEventListener("click", () => {
687
+ this.cancelAll();
688
+ });
689
+ // The uploader does not own the surface it sits in — a dialog, a drawer, a
690
+ // page — so Close reports the intent and the host decides what closing
691
+ // means. Cancellable, so a host can refuse.
692
+ this.closeEl.addEventListener("click", () => {
693
+ this.dispatchEvent(new CustomEvent("close", { bubbles: true, composed: true, cancelable: true }));
694
+ });
695
+ }
696
+ /** Cancel every item still queued or in flight. Settled items are untouched. */
697
+ cancelAll() {
698
+ const controller = this.controller;
699
+ if (!controller) {
700
+ return;
701
+ }
702
+ for (const item of controller.getState().items) {
703
+ if (item.status === "queued" || item.status === "uploading") {
704
+ controller.cancelItem(item.id);
705
+ }
706
+ }
560
707
  }
561
708
  rebuildQueue(items) {
562
709
  this.queueEl.innerHTML = items
@@ -605,6 +752,7 @@ export class ContentUploader extends BaseElement {
605
752
  if (!this.queueEl) {
606
753
  return;
607
754
  }
755
+ this.renderIllustration();
608
756
  this.dropZoneEl.label = this.dropLabel;
609
757
  this.dropZoneEl.message = this.dropMessage;
610
758
  this.dropZoneEl.directories = this.directories;
@@ -625,12 +773,29 @@ export class ContentUploader extends BaseElement {
625
773
  }
626
774
  this.patchQueueProgress(items);
627
775
  const summary = summarizeUploadQueue(items);
628
- this.footerEl.hidden = summary.total === 0;
629
776
  const active = summary.queued + summary.uploading;
777
+ // The empty state and the queue are alternatives, not neighbours: the
778
+ // illustration is the invitation, and once files are in the queue the list
779
+ // is what a person needs to see. Dropping still works over the list.
780
+ this.dropZoneEl.hidden = summary.total > 0;
781
+ // The footer stays put with its controls disabled rather than appearing
782
+ // when the first file lands — a bar that materialises under the pointer is
783
+ // how people click the wrong thing.
784
+ this.uploadEl.disabled = summary.queued === 0;
785
+ this.cancelEl.disabled = active === 0;
786
+ this.clearCompletedEl.disabled = summary.succeeded + summary.cancelled === 0;
787
+ // Closing mid-upload would abandon transfers in flight, so Close waits.
788
+ // box-ui-elements disables it for any non-empty queue; that would trap a
789
+ // person on a finished queue with no way out, so it is only held while
790
+ // something is actually running.
791
+ this.closeEl.disabled = active > 0;
792
+ this.closeEl.hidden = !this.closable;
630
793
  this.summaryEl.textContent =
631
- active > 0
632
- ? `Uploading ${String(summary.uploading)} · ${String(summary.queued)} queued`
633
- : `${String(summary.succeeded)} of ${String(summary.total)} uploaded${summary.failed ? ` · ${String(summary.failed)} failed` : ""}`;
794
+ summary.total === 0
795
+ ? ""
796
+ : active > 0
797
+ ? `Uploading ${String(summary.uploading)} · ${String(summary.queued)} queued`
798
+ : `${String(summary.succeeded)} of ${String(summary.total)} uploaded${summary.failed ? ` · ${String(summary.failed)} failed` : ""}`;
634
799
  }
635
800
  }
636
801
  DropZone.register();
@@ -18,6 +18,12 @@ const elementStyles = `
18
18
  display: block;
19
19
  }
20
20
 
21
+ /* The host's own display would otherwise beat the UA rule for [hidden],
22
+ leaving the element on screen when a host hides it. */
23
+ :host([hidden]) {
24
+ display: none !important;
25
+ }
26
+
21
27
  /*
22
28
  * The height a host sets on the element has to reach the scrollers, or
23
29
  * the panes size to their content, never overflow, and the scroll lock
@@ -20,6 +20,12 @@ const elementStyles = `
20
20
  font: inherit;
21
21
  }
22
22
 
23
+ /* The host's own display would otherwise beat the UA rule for [hidden],
24
+ leaving the element on screen when a host hides it. */
25
+ :host([hidden]) {
26
+ display: none !important;
27
+ }
28
+
23
29
  [part="panel"] {
24
30
  display: grid;
25
31
  gap: ${boePanel.gap};
@@ -15,6 +15,12 @@ const elementStyles = `
15
15
  font: inherit;
16
16
  }
17
17
 
18
+ /* The host's own display would otherwise beat the UA rule for [hidden],
19
+ leaving the element on screen when a host hides it. */
20
+ :host([hidden]) {
21
+ display: none !important;
22
+ }
23
+
18
24
  [part="builder"] {
19
25
  display: grid;
20
26
  gap: 0.6rem;
@@ -25,6 +25,12 @@ const elementStyles = `
25
25
  font: inherit;
26
26
  }
27
27
 
28
+ /* The host's own display would otherwise beat the UA rule for [hidden],
29
+ leaving the element on screen when a host hides it. */
30
+ :host([hidden]) {
31
+ display: none !important;
32
+ }
33
+
28
34
  [part="wizard"] {
29
35
  display: grid;
30
36
  gap: ${boePanel.gap};
@@ -13,6 +13,12 @@ const elementStyles = `
13
13
  display: block;
14
14
  }
15
15
 
16
+ /* The host's own display would otherwise beat the UA rule for [hidden],
17
+ leaving the element on screen when a host hides it. */
18
+ :host([hidden]) {
19
+ display: none !important;
20
+ }
21
+
16
22
  [part="card"] {
17
23
  border: ${boePanel.border};
18
24
  border-radius: ${boePanel.radius};
@@ -15,6 +15,12 @@ const elementStyles = `
15
15
  font: inherit;
16
16
  }
17
17
 
18
+ /* The host's own display would otherwise beat the UA rule for [hidden],
19
+ leaving the element on screen when a host hides it. */
20
+ :host([hidden]) {
21
+ display: none !important;
22
+ }
23
+
18
24
  [part="panel"] {
19
25
  display: grid;
20
26
  gap: 0.6rem;
@@ -14,6 +14,12 @@ const elementStyles = `
14
14
  font: inherit;
15
15
  }
16
16
 
17
+ /* The host's own display would otherwise beat the UA rule for [hidden],
18
+ leaving the element on screen when a host hides it. */
19
+ :host([hidden]) {
20
+ display: none !important;
21
+ }
22
+
17
23
  [part="panel"] {
18
24
  display: grid;
19
25
  gap: 0.6rem;
@@ -15,6 +15,12 @@ const elementStyles = `
15
15
  font: inherit;
16
16
  }
17
17
 
18
+ /* The host's own display would otherwise beat the UA rule for [hidden],
19
+ leaving the element on screen when a host hides it. */
20
+ :host([hidden]) {
21
+ display: none !important;
22
+ }
23
+
18
24
  [part="panel"] {
19
25
  display: grid;
20
26
  gap: 0.6rem;
@@ -16,6 +16,12 @@ const elementStyles = `
16
16
  font: inherit;
17
17
  }
18
18
 
19
+ /* The host's own display would otherwise beat the UA rule for [hidden],
20
+ leaving the element on screen when a host hides it. */
21
+ :host([hidden]) {
22
+ display: none !important;
23
+ }
24
+
19
25
  [part="panel"] {
20
26
  display: grid;
21
27
  gap: ${boePanel.gap};
@@ -14,6 +14,12 @@ const elementStyles = `
14
14
  font: inherit;
15
15
  }
16
16
 
17
+ /* The host's own display would otherwise beat the UA rule for [hidden],
18
+ leaving the element on screen when a host hides it. */
19
+ :host([hidden]) {
20
+ display: none !important;
21
+ }
22
+
17
23
  [part="panel"] {
18
24
  display: grid;
19
25
  gap: ${boePanel.gap};
@@ -15,6 +15,12 @@ const elementStyles = `
15
15
  font: inherit;
16
16
  }
17
17
 
18
+ /* The host's own display would otherwise beat the UA rule for [hidden],
19
+ leaving the element on screen when a host hides it. */
20
+ :host([hidden]) {
21
+ display: none !important;
22
+ }
23
+
18
24
  [part="card"] {
19
25
  display: grid;
20
26
  gap: ${boePanel.gap};
@@ -24,6 +24,12 @@ const elementStyles = `
24
24
  --_obp-brand-soft: color-mix(in srgb, var(--_obp-brand) 12%, var(--boe-token-surface-surface, #ffffff) 88%);
25
25
  }
26
26
 
27
+ /* The host's own display would otherwise beat the UA rule for [hidden],
28
+ leaving the element on screen when a host hides it. */
29
+ :host([hidden]) {
30
+ display: none !important;
31
+ }
32
+
27
33
  [part="bar"] {
28
34
  display: grid;
29
35
  gap: ${boePanel.gap};
@@ -23,6 +23,12 @@ const elementStyles = `
23
23
  --_obp-brand-soft: color-mix(in srgb, var(--_obp-brand) 12%, var(--boe-token-surface-surface, #ffffff) 88%);
24
24
  }
25
25
 
26
+ /* The host's own display would otherwise beat the UA rule for [hidden],
27
+ leaving the element on screen when a host hides it. */
28
+ :host([hidden]) {
29
+ display: none !important;
30
+ }
31
+
26
32
  [part="panel"] {
27
33
  display: grid;
28
34
  gap: ${boePanel.gap};
@@ -16,6 +16,12 @@ const elementStyles = `
16
16
  font: inherit;
17
17
  }
18
18
 
19
+ /* The host's own display would otherwise beat the UA rule for [hidden],
20
+ leaving the element on screen when a host hides it. */
21
+ :host([hidden]) {
22
+ display: none !important;
23
+ }
24
+
19
25
  [part="form"] {
20
26
  display: grid;
21
27
  gap: ${boePanel.gap};
@@ -23,6 +23,12 @@ const elementStyles = `
23
23
  --_obp-brand-soft: color-mix(in srgb, var(--_obp-brand) 12%, var(--boe-token-surface-surface, #ffffff) 88%);
24
24
  }
25
25
 
26
+ /* The host's own display would otherwise beat the UA rule for [hidden],
27
+ leaving the element on screen when a host hides it. */
28
+ :host([hidden]) {
29
+ display: none !important;
30
+ }
31
+
26
32
  [part="header"] {
27
33
  display: grid;
28
34
  gap: ${boePanel.gap};
@@ -39,6 +39,12 @@ const elementStyles = `
39
39
  font: inherit;
40
40
  }
41
41
 
42
+ /* The host's own display would otherwise beat the UA rule for [hidden],
43
+ leaving the element on screen when a host hides it. */
44
+ :host([hidden]) {
45
+ display: none !important;
46
+ }
47
+
42
48
  section[part="panel"] {
43
49
  display: grid;
44
50
  gap: ${boePanel.gap};
@@ -21,6 +21,12 @@ const elementStyles = `
21
21
  font: inherit;
22
22
  }
23
23
 
24
+ /* The host's own display would otherwise beat the UA rule for [hidden],
25
+ leaving the element on screen when a host hides it. */
26
+ :host([hidden]) {
27
+ display: none !important;
28
+ }
29
+
24
30
  /* Read as a flow diagram rather than a breadcrumb. The anatomy is
25
31
  React Flow's, taken from its stylesheet: nodes are bordered boxes
26
32
  with a small radius (not pills), ports are 6px circles sitting on
@@ -20,6 +20,12 @@ const builderStyles = `
20
20
  font: inherit;
21
21
  }
22
22
 
23
+ /* The host's own display would otherwise beat the UA rule for [hidden],
24
+ leaving the element on screen when a host hides it. */
25
+ :host([hidden]) {
26
+ display: none !important;
27
+ }
28
+
23
29
  [part="builder"] {
24
30
  display: grid;
25
31
  gap: ${boePanel.gap};
@@ -15,6 +15,12 @@ const elementStyles = `
15
15
  font: inherit;
16
16
  }
17
17
 
18
+ /* The host's own display would otherwise beat the UA rule for [hidden],
19
+ leaving the element on screen when a host hides it. */
20
+ :host([hidden]) {
21
+ display: none !important;
22
+ }
23
+
18
24
  [part="inspector"] {
19
25
  display: grid;
20
26
  gap: ${boePanel.gap};
@@ -18,6 +18,12 @@ const elementStyles = `
18
18
  display: inline-block;
19
19
  }
20
20
 
21
+ /* The host's own display would otherwise beat the UA rule for [hidden],
22
+ leaving the element on screen when a host hides it. */
23
+ :host([hidden]) {
24
+ display: none !important;
25
+ }
26
+
21
27
  [part="trigger"] {
22
28
  position: relative;
23
29
  appearance: none;
@@ -21,6 +21,12 @@ const elementStyles = `
21
21
  font: inherit;
22
22
  }
23
23
 
24
+ /* The host's own display would otherwise beat the UA rule for [hidden],
25
+ leaving the element on screen when a host hides it. */
26
+ :host([hidden]) {
27
+ display: none !important;
28
+ }
29
+
24
30
  [part="panel"] {
25
31
  display: grid;
26
32
  grid-template-rows: auto auto 1fr;
@@ -22,6 +22,12 @@ const elementStyles = `
22
22
  font: inherit;
23
23
  }
24
24
 
25
+ /* The host's own display would otherwise beat the UA rule for [hidden],
26
+ leaving the element on screen when a host hides it. */
27
+ :host([hidden]) {
28
+ display: none !important;
29
+ }
30
+
25
31
  [part="panel"] {
26
32
  display: grid;
27
33
  gap: ${boePanel.gap};
@@ -23,6 +23,12 @@ const elementStyles = `
23
23
  font: inherit;
24
24
  }
25
25
 
26
+ /* The host's own display would otherwise beat the UA rule for [hidden],
27
+ leaving the element on screen when a host hides it. */
28
+ :host([hidden]) {
29
+ display: none !important;
30
+ }
31
+
26
32
  [part="toolbar"] {
27
33
  display: grid;
28
34
  gap: 0.5rem;
@@ -23,6 +23,12 @@ const elementStyles = `
23
23
  --_obp-error: var(--boe-token-surface-status-surface-error, #ed3757);
24
24
  }
25
25
 
26
+ /* The host's own display would otherwise beat the UA rule for [hidden],
27
+ leaving the element on screen when a host hides it. */
28
+ :host([hidden]) {
29
+ display: none !important;
30
+ }
31
+
26
32
  [part="shell"] {
27
33
  display: grid;
28
34
  gap: 0.6rem;