@threadlabs/looma 0.10.12 → 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 (112) hide show
  1. package/components/shared/editor.js +2 -26
  2. package/components/shared/icons.js +53 -0
  3. package/components/ui-avatar-group/ui-avatar-group.html +6 -6
  4. package/components/ui-avatar-group/ui-avatar-group.js +1 -1
  5. package/components/ui-breadcrumb-item/ui-breadcrumb-item.html +60 -0
  6. package/components/ui-breadcrumbs/ui-breadcrumbs.html +31 -0
  7. package/components/ui-card/ui-card.html +55 -0
  8. package/components/ui-combobox/ui-combobox.js +2 -2
  9. package/components/ui-context-menu/ui-context-menu.js +4 -4
  10. package/components/ui-cover/ui-cover.html +36 -0
  11. package/components/ui-description-item/ui-description-item.html +46 -0
  12. package/components/ui-description-list/ui-description-list.html +37 -0
  13. package/components/ui-icon/ui-icon.js +1 -1
  14. package/components/ui-menu/ui-menu.js +3 -3
  15. package/components/ui-page-header/ui-page-header.html +97 -0
  16. package/components/ui-radio/ui-radio.js +1 -1
  17. package/components/ui-radio-group/ui-radio-group.js +1 -1
  18. package/components/ui-section/ui-section.html +108 -0
  19. package/components/ui-spinner/ui-spinner.html +48 -0
  20. package/components/ui-status-message/ui-status-message.html +84 -0
  21. package/components/ui-text/ui-text.html +96 -0
  22. package/components/ui-tree/ui-tree.js +2 -2
  23. package/components/ui-tree-item/ui-tree-item.js +3 -3
  24. package/dist/index.js +1 -1
  25. package/editor/icons.d.ts +5 -0
  26. package/editor/index.js +6 -1
  27. package/package.json +1 -1
  28. package/styles/ui-avatar-group.css +6 -6
  29. package/styles/ui-breadcrumb-item.css +57 -0
  30. package/styles/ui-breadcrumbs.css +32 -0
  31. package/styles/ui-card.css +51 -0
  32. package/styles/ui-cover.css +35 -0
  33. package/styles/ui-description-item.css +43 -0
  34. package/styles/ui-description-list.css +38 -0
  35. package/styles/ui-page-header.css +89 -0
  36. package/styles/ui-section.css +94 -0
  37. package/styles/ui-spinner.css +42 -0
  38. package/styles/ui-status-message.css +72 -0
  39. package/styles/ui-text.css +85 -0
  40. package/vanilla/UiBreadcrumbItem.d.ts +14 -0
  41. package/vanilla/UiBreadcrumbItem.js +38 -0
  42. package/vanilla/UiBreadcrumbs.d.ts +14 -0
  43. package/vanilla/UiBreadcrumbs.js +39 -0
  44. package/vanilla/UiCard.d.ts +17 -0
  45. package/vanilla/UiCard.js +32 -0
  46. package/vanilla/UiCover.d.ts +14 -0
  47. package/vanilla/UiCover.js +28 -0
  48. package/vanilla/UiDescriptionItem.d.ts +14 -0
  49. package/vanilla/UiDescriptionItem.js +39 -0
  50. package/vanilla/UiDescriptionList.d.ts +14 -0
  51. package/vanilla/UiDescriptionList.js +28 -0
  52. package/vanilla/UiPageHeader.d.ts +14 -0
  53. package/vanilla/UiPageHeader.js +78 -0
  54. package/vanilla/UiSection.d.ts +16 -0
  55. package/vanilla/UiSection.js +64 -0
  56. package/vanilla/UiSpinner.d.ts +15 -0
  57. package/vanilla/UiSpinner.js +23 -0
  58. package/vanilla/UiStatusMessage.d.ts +16 -0
  59. package/vanilla/UiStatusMessage.js +53 -0
  60. package/vanilla/UiText.d.ts +20 -0
  61. package/vanilla/UiText.js +38 -0
  62. package/vanilla/index.js +11 -0
  63. package/vue/UiAvatarGroup.vue +6 -6
  64. package/vue/UiBreadcrumbItem.d.ts +18 -0
  65. package/vue/UiBreadcrumbItem.js +2 -0
  66. package/vue/UiBreadcrumbItem.vue +101 -0
  67. package/vue/UiBreadcrumbs.d.ts +18 -0
  68. package/vue/UiBreadcrumbs.js +2 -0
  69. package/vue/UiBreadcrumbs.vue +45 -0
  70. package/vue/UiCard.d.ts +24 -0
  71. package/vue/UiCard.js +2 -0
  72. package/vue/UiCard.vue +82 -0
  73. package/vue/UiCover.d.ts +18 -0
  74. package/vue/UiCover.js +2 -0
  75. package/vue/UiCover.vue +57 -0
  76. package/vue/UiDescriptionItem.d.ts +18 -0
  77. package/vue/UiDescriptionItem.js +2 -0
  78. package/vue/UiDescriptionItem.vue +58 -0
  79. package/vue/UiDescriptionList.d.ts +18 -0
  80. package/vue/UiDescriptionList.js +2 -0
  81. package/vue/UiDescriptionList.vue +62 -0
  82. package/vue/UiIconButton.d.ts +1 -1
  83. package/vue/UiPageHeader.d.ts +26 -0
  84. package/vue/UiPageHeader.js +2 -0
  85. package/vue/UiPageHeader.vue +118 -0
  86. package/vue/UiSection.d.ts +26 -0
  87. package/vue/UiSection.js +2 -0
  88. package/vue/UiSection.vue +128 -0
  89. package/vue/UiSpinner.d.ts +10 -0
  90. package/vue/UiSpinner.js +2 -0
  91. package/vue/UiSpinner.vue +87 -0
  92. package/vue/UiStatusMessage.d.ts +24 -0
  93. package/vue/UiStatusMessage.js +2 -0
  94. package/vue/UiStatusMessage.vue +121 -0
  95. package/vue/UiText.d.ts +30 -0
  96. package/vue/UiText.js +2 -0
  97. package/vue/UiText.vue +125 -0
  98. package/vue/chunks/UiAvatarGroup.js +1 -1
  99. package/vue/chunks/UiBreadcrumbItem.js +50 -0
  100. package/vue/chunks/UiBreadcrumbs.js +19 -0
  101. package/vue/chunks/UiCard.js +31 -0
  102. package/vue/chunks/UiCover.js +21 -0
  103. package/vue/chunks/UiDescriptionItem.js +16 -0
  104. package/vue/chunks/UiDescriptionList.js +21 -0
  105. package/vue/chunks/UiPageHeader.js +35 -0
  106. package/vue/chunks/UiSection.js +34 -0
  107. package/vue/chunks/UiSpinner.js +64 -0
  108. package/vue/chunks/UiStatusMessage.js +54 -0
  109. package/vue/chunks/UiText.js +40 -0
  110. package/vue/components.css +521 -29
  111. package/vue/index.d.ts +11 -0
  112. package/vue/index.js +13 -2
@@ -0,0 +1,40 @@
1
+ import { t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper.js";
2
+ import { computed, createBlock, defineComponent, mergeProps, openBlock, renderSlot, resolveDynamicComponent, withCtx } from "vue";
3
+ //#endregion
4
+ //#region .build/vue/UiText.vue
5
+ var UiText_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
6
+ inheritAttrs: false,
7
+ __name: "UiText",
8
+ props: {
9
+ as: { default: "p" },
10
+ align: { default: "start" },
11
+ size: { default: "inherit" },
12
+ tone: { default: "default" },
13
+ truncate: {
14
+ type: Boolean,
15
+ default: false
16
+ },
17
+ variant: { default: "body" },
18
+ weight: { default: "inherit" }
19
+ },
20
+ setup(__props) {
21
+ const props = __props;
22
+ /** The values the styles' :host-state() rules test. */
23
+ const hostState = computed(() => [
24
+ props.size && `size size=${props.size}`,
25
+ props.tone && `tone tone=${props.tone}`,
26
+ props.weight && `weight weight=${props.weight}`,
27
+ props.variant && `variant variant=${props.variant}`,
28
+ props.truncate && "truncate",
29
+ props.align && `align align=${props.align}`
30
+ ].filter(Boolean).join(" "));
31
+ return (_ctx, _cache) => {
32
+ return openBlock(), createBlock(resolveDynamicComponent(__props.as), mergeProps({ "data-component": "ui-text" }, _ctx.$attrs, { "data-ui-text-state": hostState.value || void 0 }), {
33
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default", {}, void 0, true)]),
34
+ _: 3
35
+ }, 16, ["data-ui-text-state"]);
36
+ };
37
+ }
38
+ }), [["__scopeId", "data-v-70a75450"]]);
39
+ //#endregion
40
+ export { UiText_default as t };
@@ -63,11 +63,11 @@
63
63
  display: none;
64
64
  }
65
65
 
66
- [data-component~="ui-avatar-group"][data-v-9d727004] {
67
- /* Avatars separate with a tight, crisp edge, matching Looma's 1px borders rather than the
68
- * diffuse elevation overlays use. */
69
- --_overlap-shadow: -2px 0 2px -1px rgba(0, 0, 0, 0.22);
70
- --_edge-ring: 0 0 0 1px rgba(0, 0, 0, 0.08);
66
+ [data-component~="ui-avatar-group"][data-v-6c48e0e3] {
67
+ /* Each avatar is ringed in the surface colour, so where one overlaps the next it reads as a
68
+ * whole circle set on top, not a shape cut into the one beneath. */
69
+ --_overlap-shadow: 0 0 0 0 transparent;
70
+ --_edge-ring: 0 0 0 2px var(--ui-surface);
71
71
 
72
72
  display: flex;
73
73
  align-items: center;
@@ -77,16 +77,16 @@
77
77
 
78
78
  /* Overlap and the separating shadow are applied by the controller: slotted avatars are nested
79
79
  * component roots outside this style scope. */
80
- [data-v-9d727004-s] {
81
- margin-inline-start: -0.625rem;
80
+ [data-v-6c48e0e3-s] {
81
+ margin-inline-start: -0.5rem;
82
82
  flex-shrink: 0;
83
83
  border-radius: 999px;
84
84
  }
85
- [data-v-9d727004-s]:first-child {
85
+ [data-v-6c48e0e3-s]:first-child {
86
86
  margin-inline-start: 0;
87
87
  }
88
- .overflow[data-v-9d727004] {
89
- margin-inline-start: -0.625rem;
88
+ .overflow[data-v-6c48e0e3] {
89
+ margin-inline-start: -0.5rem;
90
90
  display: inline-flex;
91
91
  align-items: center;
92
92
  justify-content: center;
@@ -104,12 +104,12 @@
104
104
  font-weight: 600;
105
105
  flex-shrink: 0;
106
106
  }
107
- .overflow[hidden][data-v-9d727004] {
107
+ .overflow[hidden][data-v-6c48e0e3] {
108
108
  display: none;
109
109
  }
110
110
 
111
111
  /* A component that sets its display still honours the hidden attribute on its root. */
112
- [data-component~="ui-avatar-group"][hidden][data-v-9d727004] {
112
+ [data-component~="ui-avatar-group"][hidden][data-v-6c48e0e3] {
113
113
  display: none;
114
114
  }
115
115
 
@@ -229,6 +229,89 @@
229
229
  display: none;
230
230
  }
231
231
 
232
+ [data-component~="ui-icon"][data-v-3d48bd86] {
233
+ display: inline-flex;
234
+ flex: none;
235
+ inline-size: var(--ui-icon-size, 1em);
236
+ block-size: var(--ui-icon-size, 1em);
237
+ }
238
+ svg[data-v-3d48bd86] {
239
+ inline-size: 100%;
240
+ block-size: 100%;
241
+ stroke-width: var(--ui-icon-stroke-width, 2);
242
+ }
243
+
244
+ /* A component that sets its display still honours the hidden attribute on its root. */
245
+ [data-component~="ui-icon"][hidden][data-v-3d48bd86] {
246
+ display: none;
247
+ }
248
+
249
+ /* One step in a ui-breadcrumbs trail: a link up to that place, or the current view. A chevron leads
250
+ every step but the first. An icon slotted before the name sits with it. */
251
+ [data-component~="ui-breadcrumb-item"][data-v-9de59def] {
252
+ display: inline-flex;
253
+ align-items: center;
254
+ gap: var(--ui-space-2);
255
+ min-inline-size: 0;
256
+ }
257
+ .separator[data-v-9de59def] {
258
+ display: inline-flex;
259
+ color: var(--ui-text-muted);
260
+ font-size: var(--ui-font-size-xs);
261
+ }
262
+ [data-component~="ui-breadcrumb-item"]:first-child .separator[data-v-9de59def] {
263
+ display: none;
264
+ }
265
+ .content[data-v-9de59def] {
266
+ display: inline-flex;
267
+ align-items: center;
268
+ gap: var(--ui-space-1);
269
+ min-inline-size: 0;
270
+ }
271
+ .content > a[data-v-9de59def-s] {
272
+ display: inline-flex;
273
+ align-items: center;
274
+ gap: var(--ui-space-1);
275
+ color: var(--ui-text-secondary);
276
+ text-decoration: none;
277
+ }
278
+ .content > a[data-v-9de59def-s]:hover {
279
+ color: var(--ui-text-primary);
280
+ text-decoration: underline;
281
+ }
282
+ [data-component~="ui-breadcrumb-item"][data-ui-breadcrumb-item-state~="current"] .content[data-v-9de59def] {
283
+ color: var(--ui-text-primary);
284
+ font-weight: var(--ui-font-medium);
285
+ }
286
+
287
+ /* A component that sets its display still honours the hidden attribute on its root. */
288
+ [data-component~="ui-breadcrumb-item"][hidden][data-v-9de59def] {
289
+ display: none;
290
+ }
291
+
292
+ /* Where a view sits: a trail of ui-breadcrumb-item, from the top down to the current view. It wraps
293
+ rather than scrolls, so every step stays reachable. */
294
+ [data-component~="ui-breadcrumbs"][data-v-0d86d58e] {
295
+ display: block;
296
+ min-inline-size: 0;
297
+ color: var(--ui-text-muted);
298
+ font-size: var(--ui-font-size-sm);
299
+ }
300
+ ol[data-v-0d86d58e] {
301
+ display: flex;
302
+ flex-wrap: wrap;
303
+ align-items: center;
304
+ gap: var(--ui-space-1) var(--ui-space-2);
305
+ margin: 0;
306
+ padding: 0;
307
+ list-style: none;
308
+ }
309
+
310
+ /* A component that sets its display still honours the hidden attribute on its root. */
311
+ [data-component~="ui-breadcrumbs"][hidden][data-v-0d86d58e] {
312
+ display: none;
313
+ }
314
+
232
315
  [data-component~="ui-button"][data-v-0c121308] {
233
316
  --_hue: var(--ui-accent);
234
317
  --_hue-hover: var(--ui-accent-hover);
@@ -549,6 +632,44 @@
549
632
  display: none;
550
633
  }
551
634
 
635
+ /* A surface that groups content. Its children stack with even space between them, so a card
636
+ needs no layout of its own. */
637
+ [data-component~="ui-card"][data-v-d00c53f0] {
638
+ display: flex;
639
+ flex-direction: column;
640
+ gap: var(--ui-space-4);
641
+ box-sizing: border-box;
642
+ min-inline-size: 0;
643
+ padding: var(--ui-space-5);
644
+ border: 1px solid var(--ui-border-default);
645
+ border-radius: var(--ui-radius-lg);
646
+ background: var(--ui-surface-raised);
647
+ color: var(--ui-text-primary);
648
+ }
649
+ [data-component~="ui-card"][data-ui-card-state~="padding=sm"][data-v-d00c53f0] {
650
+ gap: var(--ui-space-2);
651
+ padding: var(--ui-space-3);
652
+ }
653
+ [data-component~="ui-card"][data-ui-card-state~="padding=lg"][data-v-d00c53f0] {
654
+ padding: var(--ui-space-6);
655
+ }
656
+ [data-component~="ui-card"][data-ui-card-state~="variant=subtle"][data-v-d00c53f0] {
657
+ border-color: transparent;
658
+ background: var(--ui-surface-muted);
659
+ }
660
+ [data-component~="ui-card"][data-ui-card-state~="variant=elevated"][data-v-d00c53f0] {
661
+ border-color: var(--ui-border-subtle);
662
+ box-shadow: var(--ui-shadow-lg);
663
+ }
664
+ [data-component~="ui-card"][data-ui-card-state~="tone=danger"][data-v-d00c53f0] {
665
+ border-color: var(--ui-danger);
666
+ }
667
+
668
+ /* A component that sets its display still honours the hidden attribute on its root. */
669
+ [data-component~="ui-card"][hidden][data-v-d00c53f0] {
670
+ display: none;
671
+ }
672
+
552
673
  [data-component~="ui-checkbox"][data-v-9c9d1eaa] {
553
674
  display: inline-flex;
554
675
  align-items: flex-start;
@@ -1131,6 +1252,93 @@ button[data-v-0bd7ecc4] {
1131
1252
  display: none;
1132
1253
  }
1133
1254
 
1255
+ /* A layout primitive that centres its content in the space, both ways, with room around it: the
1256
+ frame for a view that is one card or one message. */
1257
+ [data-component~="ui-cover"][data-v-f341d85e] {
1258
+ display: flex;
1259
+ flex-direction: column;
1260
+ align-items: center;
1261
+ justify-content: center;
1262
+ gap: var(--ui-space-6);
1263
+ box-sizing: border-box;
1264
+ min-block-size: 100dvh;
1265
+ padding: var(--ui-space-6) var(--ui-space-4);
1266
+ }
1267
+ [data-component~="ui-cover"][data-ui-cover-state~="size=fill"][data-v-f341d85e] {
1268
+ flex: 1;
1269
+ min-block-size: 100%;
1270
+ }
1271
+ [data-component~="ui-cover"] > [data-v-f341d85e-s] {
1272
+ max-inline-size: 100%;
1273
+ }
1274
+
1275
+ /* A component that sets its display still honours the hidden attribute on its root. */
1276
+ [data-component~="ui-cover"][hidden][data-v-f341d85e] {
1277
+ display: none;
1278
+ }
1279
+
1280
+ /* One term and its value in a ui-description-list, laid out by the list's layout. */
1281
+ [data-component~="ui-description-item"][data-v-2d94bc9f] {
1282
+ display: var(--_ui-description-display, grid);
1283
+ grid-column: var(--_ui-description-column, 1 / -1);
1284
+ grid-template-columns: subgrid;
1285
+ flex-direction: column;
1286
+ align-items: var(--_ui-description-align, baseline);
1287
+ gap: var(--ui-space-1) var(--ui-space-6);
1288
+ min-inline-size: 0;
1289
+ padding: var(--_ui-description-padding, 0);
1290
+ border-width: var(--_ui-description-border-width, 0);
1291
+ border-style: solid;
1292
+ border-color: var(--ui-border-default);
1293
+ border-radius: var(--ui-radius-md);
1294
+ font-size: var(--ui-font-size-sm);
1295
+ }
1296
+ dt[data-v-2d94bc9f] {
1297
+ color: var(--ui-text-muted);
1298
+ }
1299
+ dd[data-v-2d94bc9f] {
1300
+ margin: 0;
1301
+ min-inline-size: 0;
1302
+ color: var(--ui-text-primary);
1303
+ font-weight: var(--ui-font-medium);
1304
+ font-size: var(--_ui-description-value-size, inherit);
1305
+ text-align: start;
1306
+ overflow-wrap: anywhere;
1307
+ }
1308
+
1309
+ /* A component that sets its display still honours the hidden attribute on its root. */
1310
+ [data-component~="ui-description-item"][hidden][data-v-2d94bc9f] {
1311
+ display: none;
1312
+ }
1313
+
1314
+ /* Named values: a term and what it is, for each item (ui-description-item). */
1315
+ /* Rows line every term up in one column and every value in the next, through subgrid. */
1316
+ [data-component~="ui-description-list"][data-v-0519dd0f] {
1317
+ display: grid;
1318
+ grid-template-columns: minmax(6rem, max-content) minmax(0, 1fr);
1319
+ gap: var(--ui-space-2) var(--ui-space-6);
1320
+ min-inline-size: 0;
1321
+ margin: 0;
1322
+ }
1323
+
1324
+ /* Tiles pass their shape to the items through private properties, which cross into each item. */
1325
+ [data-component~="ui-description-list"][data-ui-description-list-state~="layout=tiles"][data-v-0519dd0f] {
1326
+ --_ui-description-display: flex;
1327
+ --_ui-description-column: auto;
1328
+ --_ui-description-align: flex-start;
1329
+ --_ui-description-value-size: var(--ui-font-size-lg);
1330
+ --_ui-description-padding: var(--ui-space-3);
1331
+ --_ui-description-border-width: 1px;
1332
+ display: grid;
1333
+ grid-template-columns: repeat(auto-fill, minmax(min(100%, 10rem), 1fr));
1334
+ gap: var(--ui-space-3);
1335
+ }
1336
+
1337
+ /* A component that sets its display still honours the hidden attribute on its root. */
1338
+ [data-component~="ui-description-list"][hidden][data-v-0519dd0f] {
1339
+ display: none;
1340
+ }
1341
+
1134
1342
  [data-component~="ui-dialog"][data-v-0fd6654c] {
1135
1343
  position: fixed;
1136
1344
  inset: 0;
@@ -1691,23 +1899,6 @@ from {
1691
1899
  display: none;
1692
1900
  }
1693
1901
 
1694
- [data-component~="ui-icon"][data-v-3d48bd86] {
1695
- display: inline-flex;
1696
- flex: none;
1697
- inline-size: var(--ui-icon-size, 1em);
1698
- block-size: var(--ui-icon-size, 1em);
1699
- }
1700
- svg[data-v-3d48bd86] {
1701
- inline-size: 100%;
1702
- block-size: 100%;
1703
- stroke-width: var(--ui-icon-stroke-width, 2);
1704
- }
1705
-
1706
- /* A component that sets its display still honours the hidden attribute on its root. */
1707
- [data-component~="ui-icon"][hidden][data-v-3d48bd86] {
1708
- display: none;
1709
- }
1710
-
1711
1902
  [data-component~="ui-editor-slash-menu"][data-v-dcc1f07d] {
1712
1903
  user-select: none;
1713
1904
  }
@@ -3201,6 +3392,77 @@ svg[data-v-bcedd63e-s] {
3201
3392
  display: none;
3202
3393
  }
3203
3394
 
3395
+ /* The top of a view: its title (the page's one h1), with an optional icon or mark before it, a
3396
+ short eyebrow above it, a line or two of description under it, and the view's own actions at
3397
+ the end. Every view titles itself the same way, at the same size. */
3398
+ [data-component~="ui-page-header"][data-v-8dcefe30] {
3399
+ display: flex;
3400
+ flex-wrap: wrap;
3401
+ align-items: center;
3402
+ gap: var(--ui-space-3) var(--ui-space-4);
3403
+ min-inline-size: 0;
3404
+ }
3405
+ .leading[data-v-8dcefe30] {
3406
+ display: inline-flex;
3407
+ flex: none;
3408
+ align-self: center;
3409
+ color: var(--ui-text-muted);
3410
+ font-size: var(--ui-font-size-2xl);
3411
+ }
3412
+ .copy[data-v-8dcefe30] {
3413
+ display: flex;
3414
+ flex: 1 1 16rem;
3415
+ flex-direction: column;
3416
+ gap: var(--ui-space-1);
3417
+ min-inline-size: 0;
3418
+ }
3419
+ .eyebrow[data-v-8dcefe30] {
3420
+ color: var(--ui-text-muted);
3421
+ font-size: var(--ui-font-size-xs);
3422
+ font-weight: var(--ui-font-semibold);
3423
+ letter-spacing: 0.06em;
3424
+ text-transform: uppercase;
3425
+ }
3426
+ .title[data-v-8dcefe30] {
3427
+ margin: 0;
3428
+ color: var(--ui-text-primary);
3429
+ font-size: var(--ui-font-size-2xl);
3430
+ font-weight: var(--ui-font-bold, 700);
3431
+ line-height: var(--ui-line-height-tight);
3432
+ overflow-wrap: anywhere;
3433
+ }
3434
+ .description[data-v-8dcefe30] {
3435
+ color: var(--ui-text-secondary);
3436
+ font-size: var(--ui-font-size-md);
3437
+ line-height: var(--ui-line-height);
3438
+ }
3439
+ .actions[data-v-8dcefe30] {
3440
+ display: inline-flex;
3441
+ flex: none;
3442
+ flex-wrap: wrap;
3443
+ align-items: center;
3444
+ gap: var(--ui-space-2);
3445
+ }
3446
+ [data-component~="ui-page-header"][data-ui-page-header-state~="align=center"][data-v-8dcefe30] {
3447
+ flex-direction: column;
3448
+ text-align: center;
3449
+ }
3450
+ [data-component~="ui-page-header"][data-ui-page-header-state~="align=center"] .copy[data-v-8dcefe30] {
3451
+ align-items: center;
3452
+ flex-basis: auto;
3453
+ }
3454
+ .leading[data-v-8dcefe30]:empty,
3455
+ .eyebrow[data-v-8dcefe30]:empty,
3456
+ .description[data-v-8dcefe30]:empty,
3457
+ .actions[data-v-8dcefe30]:empty {
3458
+ display: none;
3459
+ }
3460
+
3461
+ /* A component that sets its display still honours the hidden attribute on its root. */
3462
+ [data-component~="ui-page-header"][hidden][data-v-8dcefe30] {
3463
+ display: none;
3464
+ }
3465
+
3204
3466
  [data-component~="ui-popover"][data-v-00194c85] {
3205
3467
  box-sizing: border-box;
3206
3468
  max-inline-size: min(
@@ -3674,6 +3936,80 @@ dialog[data-v-2ba71171] {
3674
3936
  display: none;
3675
3937
  }
3676
3938
 
3939
+ /* A part of a view: a heading, an optional line under it, actions for the whole section at its
3940
+ end, and the content. Sections space themselves out through the Stack around them. */
3941
+ [data-component~="ui-section"][data-v-4d1e5a3a] {
3942
+ display: flex;
3943
+ flex-direction: column;
3944
+ gap: var(--ui-space-4);
3945
+ min-inline-size: 0;
3946
+ }
3947
+ [data-component~="ui-section"][data-ui-section-state~="variant=card"][data-v-4d1e5a3a] {
3948
+ padding: var(--ui-space-5);
3949
+ border: 1px solid var(--ui-border-default);
3950
+ border-radius: var(--ui-radius-lg);
3951
+ background: var(--ui-surface-raised);
3952
+ }
3953
+ [data-component~="ui-section"][data-ui-section-state~="variant=divided"][data-v-4d1e5a3a] {
3954
+ padding-block-start: var(--ui-space-6);
3955
+ border-block-start: 1px solid var(--ui-border-default);
3956
+ }
3957
+ [data-component~="ui-section"][data-ui-section-state~="variant=card"][data-ui-section-state~="tone=danger"][data-v-4d1e5a3a] {
3958
+ border-color: var(--ui-danger);
3959
+ }
3960
+ .head[data-v-4d1e5a3a] {
3961
+ display: flex;
3962
+ flex-wrap: wrap;
3963
+ align-items: flex-start;
3964
+ justify-content: space-between;
3965
+ gap: var(--ui-space-2) var(--ui-space-4);
3966
+ }
3967
+ .copy[data-v-4d1e5a3a] {
3968
+ display: flex;
3969
+ flex: 1 1 16rem;
3970
+ flex-direction: column;
3971
+ gap: var(--ui-space-1);
3972
+ min-inline-size: 0;
3973
+ }
3974
+ .heading[data-v-4d1e5a3a] {
3975
+ margin: 0;
3976
+ color: var(--ui-text-primary);
3977
+ font-size: var(--ui-font-size-lg);
3978
+ font-weight: var(--ui-font-semibold);
3979
+ line-height: var(--ui-line-height-tight);
3980
+ }
3981
+ [data-component~="ui-section"][data-ui-section-state~="tone=danger"] .heading[data-v-4d1e5a3a] {
3982
+ color: var(--ui-danger);
3983
+ }
3984
+ .description[data-v-4d1e5a3a] {
3985
+ color: var(--ui-text-secondary);
3986
+ font-size: var(--ui-font-size-sm);
3987
+ line-height: var(--ui-line-height);
3988
+ }
3989
+ .actions[data-v-4d1e5a3a] {
3990
+ display: inline-flex;
3991
+ flex-wrap: wrap;
3992
+ gap: var(--ui-space-2);
3993
+ }
3994
+ .body[data-v-4d1e5a3a] {
3995
+ display: flex;
3996
+ flex-direction: column;
3997
+ gap: var(--ui-space-4);
3998
+ min-inline-size: 0;
3999
+ }
4000
+ .description[data-v-4d1e5a3a]:empty,
4001
+ .actions[data-v-4d1e5a3a]:empty {
4002
+ display: none;
4003
+ }
4004
+ .head[data-v-4d1e5a3a]:has(.heading[hidden]):has(.description:empty):has(.actions:empty) {
4005
+ display: none;
4006
+ }
4007
+
4008
+ /* A component that sets its display still honours the hidden attribute on its root. */
4009
+ [data-component~="ui-section"][hidden][data-v-4d1e5a3a] {
4010
+ display: none;
4011
+ }
4012
+
3677
4013
  [data-component~="ui-select"][data-v-f9be4ab9] {
3678
4014
  box-sizing: border-box;
3679
4015
  display: inline-block;
@@ -3923,6 +4259,35 @@ hr[aria-orientation="vertical"][data-v-357ad177] {
3923
4259
  display: none;
3924
4260
  }
3925
4261
 
4262
+ /* Something is on its way. It turns in the current text colour; with reduced motion it holds still,
4263
+ and the label (or the text beside it) still says what is happening. */
4264
+ [data-component~="ui-spinner"][data-v-3472d01c] {
4265
+ display: inline-flex;
4266
+ flex: none;
4267
+ color: currentColor;
4268
+ font-size: var(--ui-font-size-lg);
4269
+ line-height: 1;
4270
+ animation: ui-spinner-turn-3472d01c 0.8s linear infinite;
4271
+ }
4272
+ [data-component~="ui-spinner"][data-ui-spinner-state~="size=sm"][data-v-3472d01c] {
4273
+ font-size: var(--ui-font-size-md);
4274
+ }
4275
+ @keyframes ui-spinner-turn-3472d01c {
4276
+ to {
4277
+ transform: rotate(1turn);
4278
+ }
4279
+ }
4280
+ @media (prefers-reduced-motion: reduce) {
4281
+ [data-component~="ui-spinner"][data-v-3472d01c] {
4282
+ animation: none;
4283
+ }
4284
+ }
4285
+
4286
+ /* A component that sets its display still honours the hidden attribute on its root. */
4287
+ [data-component~="ui-spinner"][hidden][data-v-3472d01c] {
4288
+ display: none;
4289
+ }
4290
+
3926
4291
  [data-component~="ui-stack"][data-v-e8d52a11] {
3927
4292
  --_layout-gap: var(--ui-space-4);
3928
4293
  display: flex;
@@ -3972,6 +4337,62 @@ hr[aria-orientation="vertical"][data-v-357ad177] {
3972
4337
  display: none;
3973
4338
  }
3974
4339
 
4340
+ /* The one way a view says it is loading, has nothing yet, or failed, with an optional next step.
4341
+ Every view says it the same way, in the same place, at the same size. */
4342
+ [data-component~="ui-status-message"][data-v-a56387a4] {
4343
+ display: flex;
4344
+ flex-wrap: wrap;
4345
+ align-items: center;
4346
+ gap: var(--ui-space-2) var(--ui-space-4);
4347
+ padding-block: var(--ui-space-4);
4348
+ color: var(--ui-text-muted);
4349
+ font-size: var(--ui-font-size-md);
4350
+ line-height: var(--ui-line-height);
4351
+ }
4352
+ [data-component~="ui-status-message"][data-ui-status-message-state~="kind=error"][data-v-a56387a4] {
4353
+ color: var(--ui-danger);
4354
+ }
4355
+ [data-component~="ui-status-message"][data-ui-status-message-state~="layout=panel"][data-v-a56387a4] {
4356
+ padding: var(--ui-space-6);
4357
+ border: 1px dashed var(--ui-border-default);
4358
+ border-radius: var(--ui-radius-lg);
4359
+ }
4360
+ [data-component~="ui-status-message"][data-ui-status-message-state~="layout=fill"][data-v-a56387a4] {
4361
+ flex: 1;
4362
+ flex-direction: column;
4363
+ justify-content: center;
4364
+ min-block-size: 50vh;
4365
+ text-align: center;
4366
+ }
4367
+ .copy[data-v-a56387a4] {
4368
+ display: flex;
4369
+ flex: 1 1 12rem;
4370
+ flex-direction: column;
4371
+ gap: var(--ui-space-1);
4372
+ min-inline-size: 0;
4373
+ }
4374
+ [data-component~="ui-status-message"][data-ui-status-message-state~="layout=fill"] .copy[data-v-a56387a4] {
4375
+ flex: none;
4376
+ align-items: center;
4377
+ }
4378
+ .heading[data-v-a56387a4] {
4379
+ color: var(--ui-text-primary);
4380
+ font-weight: var(--ui-font-semibold);
4381
+ }
4382
+ .action[data-v-a56387a4] {
4383
+ display: inline-flex;
4384
+ flex-wrap: wrap;
4385
+ gap: var(--ui-space-2);
4386
+ }
4387
+ .action[data-v-a56387a4]:empty {
4388
+ display: none;
4389
+ }
4390
+
4391
+ /* A component that sets its display still honours the hidden attribute on its root. */
4392
+ [data-component~="ui-status-message"][hidden][data-v-a56387a4] {
4393
+ display: none;
4394
+ }
4395
+
3975
4396
  [data-component~="ui-switch"][data-v-26ab3add] {
3976
4397
  display: inline-flex;
3977
4398
  align-items: flex-start;
@@ -4221,6 +4642,77 @@ input[data-v-26ab3add], input[data-v-26ab3add]::after {
4221
4642
  display: none;
4222
4643
  }
4223
4644
 
4645
+ /* Running text, set on the type scale and in a tone that says what it is, so a view never styles
4646
+ text of its own. The root is a paragraph unless as= names a span, div, small, strong, or label. */
4647
+ [data-component~="ui-text"][data-v-70a75450] {
4648
+ margin: 0;
4649
+ min-inline-size: 0;
4650
+ color: var(--ui-text-primary);
4651
+ text-align: start;
4652
+ }
4653
+ [data-component~="ui-text"][data-ui-text-state~="size=xs"][data-v-70a75450] {
4654
+ font-size: var(--ui-font-size-xs);
4655
+ line-height: var(--ui-line-height);
4656
+ }
4657
+ [data-component~="ui-text"][data-ui-text-state~="size=sm"][data-v-70a75450] {
4658
+ font-size: var(--ui-font-size-sm);
4659
+ line-height: var(--ui-line-height);
4660
+ }
4661
+ [data-component~="ui-text"][data-ui-text-state~="size=md"][data-v-70a75450] {
4662
+ font-size: var(--ui-font-size-md);
4663
+ line-height: var(--ui-line-height);
4664
+ }
4665
+ [data-component~="ui-text"][data-ui-text-state~="size=lg"][data-v-70a75450] {
4666
+ font-size: var(--ui-font-size-lg);
4667
+ line-height: var(--ui-line-height-relaxed);
4668
+ }
4669
+ [data-component~="ui-text"][data-ui-text-state~="tone=secondary"][data-v-70a75450] {
4670
+ color: var(--ui-text-secondary);
4671
+ }
4672
+ [data-component~="ui-text"][data-ui-text-state~="tone=muted"][data-v-70a75450] {
4673
+ color: var(--ui-text-muted);
4674
+ }
4675
+ [data-component~="ui-text"][data-ui-text-state~="tone=accent"][data-v-70a75450] {
4676
+ color: var(--ui-accent-active);
4677
+ }
4678
+ [data-component~="ui-text"][data-ui-text-state~="tone=danger"][data-v-70a75450] {
4679
+ color: var(--ui-danger);
4680
+ }
4681
+ [data-component~="ui-text"][data-ui-text-state~="tone=success"][data-v-70a75450] {
4682
+ color: var(--ui-success);
4683
+ }
4684
+ [data-component~="ui-text"][data-ui-text-state~="weight=normal"][data-v-70a75450] {
4685
+ font-weight: var(--ui-font-normal);
4686
+ }
4687
+ [data-component~="ui-text"][data-ui-text-state~="weight=medium"][data-v-70a75450] {
4688
+ font-weight: var(--ui-font-medium);
4689
+ }
4690
+ [data-component~="ui-text"][data-ui-text-state~="weight=semibold"][data-v-70a75450] {
4691
+ font-weight: var(--ui-font-semibold);
4692
+ }
4693
+ [data-component~="ui-text"][data-ui-text-state~="variant=eyebrow"][data-v-70a75450] {
4694
+ font-size: var(--ui-font-size-xs);
4695
+ font-weight: var(--ui-font-semibold);
4696
+ letter-spacing: 0.06em;
4697
+ text-transform: uppercase;
4698
+ }
4699
+ [data-component~="ui-text"][data-ui-text-state~="variant=code"][data-v-70a75450] {
4700
+ font-family: var(--ui-font-family-mono);
4701
+ }
4702
+ [data-component~="ui-text"][data-ui-text-state~="truncate"][data-v-70a75450] {
4703
+ overflow: hidden;
4704
+ text-overflow: ellipsis;
4705
+ white-space: nowrap;
4706
+ }
4707
+ [data-component~="ui-text"][data-ui-text-state~="align=center"][data-v-70a75450] {
4708
+ text-align: center;
4709
+ }
4710
+
4711
+ /* A component that sets its display still honours the hidden attribute on its root. */
4712
+ [data-component~="ui-text"][hidden][data-v-70a75450] {
4713
+ display: none;
4714
+ }
4715
+
4224
4716
  [data-component~="ui-textarea"][data-v-0352d397] {
4225
4717
  box-sizing: border-box;
4226
4718
  display: inline-block;