@kerfjs/ui 5.0.0-beta.111 → 5.0.0-beta.113

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 (93) hide show
  1. package/README.md +2 -0
  2. package/ai/component-catalog.json +152 -6
  3. package/ai/component-composition.json +111 -1
  4. package/ai/components/README.md +2 -0
  5. package/ai/components/backdrop-image.md +1 -0
  6. package/ai/components/content-item.md +1 -0
  7. package/ai/components/editor-frame.md +80 -0
  8. package/ai/components/summary-row.md +5 -2
  9. package/ai/components/value-preview.md +75 -0
  10. package/ai/public-api-signatures-v1.md +124 -14
  11. package/ai/skill.md +13 -0
  12. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  13. package/dist/backdrop-image.d.ts +3 -0
  14. package/dist/backdrop-image.js +1 -1
  15. package/dist/browser/editor-frame.js +3 -0
  16. package/dist/browser/value-preview.js +3 -0
  17. package/dist/catalog.js +4 -3
  18. package/dist/catalog.js.map +1 -1
  19. package/dist/{chunk-JCCN3U6X.js → chunk-2J7XKAZX.js} +3 -2
  20. package/dist/chunk-2J7XKAZX.js.map +1 -0
  21. package/dist/{chunk-WD6KABEU.js → chunk-3KFMLOTH.js} +3 -2
  22. package/dist/chunk-3KFMLOTH.js.map +1 -0
  23. package/dist/{chunk-ATGAJVZ6.js → chunk-3OP66VXU.js} +64 -4
  24. package/dist/chunk-3OP66VXU.js.map +1 -0
  25. package/dist/{chunk-ZNROKDSZ.js → chunk-3V4OCDTL.js} +2 -8
  26. package/dist/chunk-3V4OCDTL.js.map +1 -0
  27. package/dist/{chunk-3GLYIIFR.js → chunk-3WWX2O4G.js} +3 -2
  28. package/dist/chunk-3WWX2O4G.js.map +1 -0
  29. package/dist/{chunk-SOBRGH7T.js → chunk-5CLMV5YU.js} +5 -2
  30. package/dist/chunk-5CLMV5YU.js.map +1 -0
  31. package/dist/chunk-F653O57X.js +41 -0
  32. package/dist/chunk-F653O57X.js.map +1 -0
  33. package/dist/{chunk-4UB5Z3ZZ.js → chunk-K67XBCHG.js} +8 -4
  34. package/dist/chunk-K67XBCHG.js.map +1 -0
  35. package/dist/chunk-OK7FUK7U.js +9 -0
  36. package/dist/chunk-OK7FUK7U.js.map +1 -0
  37. package/dist/{chunk-VGECEXM6.js → chunk-S3DCRI2M.js} +21 -4
  38. package/dist/chunk-S3DCRI2M.js.map +1 -0
  39. package/dist/chunk-V6N3YLTM.js +56 -0
  40. package/dist/chunk-V6N3YLTM.js.map +1 -0
  41. package/dist/content-item.d.ts +2 -0
  42. package/dist/content-item.js +1 -1
  43. package/dist/editor-frame.d.ts +41 -0
  44. package/dist/editor-frame.js +3 -0
  45. package/dist/editor-frame.js.map +1 -0
  46. package/dist/index.d.ts +2 -0
  47. package/dist/index.js +24 -21
  48. package/dist/list-action-row.js +2 -1
  49. package/dist/list-detail-dialog.js +2 -2
  50. package/dist/list-item.js +2 -1
  51. package/dist/styles/backdrop-image.css +6 -0
  52. package/dist/styles/components/actions/popup-menu/popup-menu.css +1 -1
  53. package/dist/styles/components/collections/summary-row/summary-row.css +7 -3
  54. package/dist/styles/components/data-display/value-preview/value-preview.css +18 -0
  55. package/dist/styles/components/surfaces/backdrop-image/backdrop-image.css +6 -0
  56. package/dist/styles/components/surfaces/editor-frame/editor-frame.css +121 -0
  57. package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +16 -0
  58. package/dist/styles/editor-frame.css +121 -0
  59. package/dist/styles/foundation.css +5 -0
  60. package/dist/styles/popup-menu.css +1 -1
  61. package/dist/styles/styles.css +2 -0
  62. package/dist/styles/summary-row.css +7 -3
  63. package/dist/styles/surface-scaffold.css +16 -0
  64. package/dist/styles/value-preview.css +18 -0
  65. package/dist/summary-row.d.ts +20 -11
  66. package/dist/summary-row.js +2 -1
  67. package/dist/surface-scaffold-register.js +1 -1
  68. package/dist/surface-scaffold.d.ts +26 -2
  69. package/dist/surface-scaffold.js +2 -2
  70. package/dist/value-preview.d.ts +21 -0
  71. package/dist/value-preview.js +3 -0
  72. package/dist/value-preview.js.map +1 -0
  73. package/dist/wire-catalog.js +1 -1
  74. package/dist/wire-content-items.js +34 -8
  75. package/dist/wire-content-items.js.map +1 -1
  76. package/dist/workbench-dialog.js +2 -2
  77. package/docs/component-contract.md +28 -5
  78. package/docs/component-selection.md +15 -0
  79. package/docs/editor-frame.md +47 -0
  80. package/docs/investigations/content-item-media-scroll-performance.md +46 -0
  81. package/docs/layout.md +10 -1
  82. package/docs/surface-scaffold.md +46 -0
  83. package/docs/value-preview.md +16 -0
  84. package/llms.txt +7 -1
  85. package/package.json +13 -1
  86. package/dist/chunk-3GLYIIFR.js.map +0 -1
  87. package/dist/chunk-4UB5Z3ZZ.js.map +0 -1
  88. package/dist/chunk-ATGAJVZ6.js.map +0 -1
  89. package/dist/chunk-JCCN3U6X.js.map +0 -1
  90. package/dist/chunk-SOBRGH7T.js.map +0 -1
  91. package/dist/chunk-VGECEXM6.js.map +0 -1
  92. package/dist/chunk-WD6KABEU.js.map +0 -1
  93. package/dist/chunk-ZNROKDSZ.js.map +0 -1
@@ -52,6 +52,22 @@
52
52
  light-dark(rgb(29 29 31 / 0.34), rgb(0 0 0 / 0.6))
53
53
  );
54
54
  }
55
+ .kui-dialog-surface[data-stack-active="false"] {
56
+ pointer-events: none;
57
+ transform: translateY(var(--_kui-dialog-surface-stack-offset, 0px));
58
+ }
59
+ .kui-dialog-surface[data-stack-position] {
60
+ --_kui-dialog-surface-gutter: 1.5rem;
61
+ }
62
+ .kui-dialog-surface[data-stack-active="false"]::backdrop {
63
+ background: transparent;
64
+ }
65
+ @media screen and (max-width: 48rem) {
66
+ .kui-dialog-surface[data-stack-position] {
67
+ --_kui-dialog-surface-gutter: 1rem;
68
+ transform: none;
69
+ }
70
+ }
55
71
  /* Room for phones whose viewport height ignores the browser chrome. */
56
72
  @media screen and (max-width: 26.25rem) {
57
73
  .kui-dialog-surface {
@@ -0,0 +1,121 @@
1
+ .kui-editor-frame {
2
+ display: flex;
3
+ width: min(100%, var(--_kui-editor-frame-max-width, 42rem));
4
+ height: var(--_kui-editor-frame-height, 20rem);
5
+ min-width: 0;
6
+ min-height: 0;
7
+ box-sizing: border-box;
8
+ overflow: hidden;
9
+ border: 1px solid var(--kui-color-neutral-border-normal);
10
+ border-radius: var(--kui-radius-l);
11
+ color: var(--kui-color-neutral-on-normal);
12
+ background: var(--kui-color-surface);
13
+ flex-direction: column;
14
+ }
15
+
16
+ .kui-editor-frame__toolbar {
17
+ flex: none;
18
+ }
19
+
20
+ .kui-editor-frame__surface {
21
+ display: flex;
22
+ min-width: 0;
23
+ min-height: 0;
24
+ padding: 1rem;
25
+ flex: 1 1 auto;
26
+ flex-direction: column;
27
+ }
28
+
29
+ .kui-editor-frame[data-mode="source"] > .kui-editor-frame__surface {
30
+ overflow: hidden;
31
+ }
32
+
33
+ .kui-editor-frame[data-mode="preview"] > .kui-editor-frame__surface {
34
+ overflow: auto;
35
+ }
36
+
37
+ .kui-editor-frame[data-mode="source"] > .kui-editor-frame__surface > textarea {
38
+ display: block;
39
+ width: 100%;
40
+ min-width: 0;
41
+ min-height: 0;
42
+ box-sizing: border-box;
43
+ padding: 0;
44
+ overflow: auto;
45
+ border: 0;
46
+ outline: 0;
47
+ color: inherit;
48
+ background: transparent;
49
+ flex: 1 1 auto;
50
+ font: inherit;
51
+ line-height: 1.6;
52
+ resize: none;
53
+ }
54
+
55
+ .kui-editor-frame[data-inset="flush"] > .kui-editor-frame__surface {
56
+ padding: 0;
57
+ }
58
+
59
+ .kui-editor-frame[data-appearance="embedded"]:not([data-expanded="true"]) {
60
+ width: 100%;
61
+ height: auto;
62
+ overflow: visible;
63
+ border: 0;
64
+ border-radius: 0;
65
+ background: transparent;
66
+ }
67
+
68
+ .kui-editor-frame[data-appearance="embedded"]:not([data-expanded="true"])
69
+ > .kui-editor-frame__surface {
70
+ min-height: 3rem;
71
+ padding: 0.75rem;
72
+ overflow: visible;
73
+ }
74
+
75
+ .kui-editor-frame[data-appearance="embedded"]:not(
76
+ [data-expanded="true"]
77
+ )[data-inset="flush"]
78
+ > .kui-editor-frame__surface {
79
+ padding: 0;
80
+ }
81
+
82
+ .kui-editor-frame[data-appearance="embedded"]:not(
83
+ [data-expanded="true"]
84
+ )[data-mode="source"]
85
+ > .kui-editor-frame__surface
86
+ > textarea {
87
+ height: var(--_kui-editor-frame-source-height, auto);
88
+ min-height: 3rem;
89
+ padding: 0;
90
+ overflow: auto;
91
+ flex: none;
92
+ resize: vertical;
93
+ }
94
+
95
+ .kui-editor-frame[data-appearance="embedded"]:not(
96
+ [data-expanded="true"]
97
+ )[data-mode="source"][data-source-autosize="true"]
98
+ > .kui-editor-frame__surface
99
+ > textarea {
100
+ field-sizing: content;
101
+ resize: none;
102
+ }
103
+
104
+ @supports not (field-sizing: content) {
105
+ .kui-editor-frame[data-appearance="embedded"]:not(
106
+ [data-expanded="true"]
107
+ )[data-mode="source"][data-source-autosize="true"]
108
+ > .kui-editor-frame__surface
109
+ > textarea {
110
+ resize: vertical;
111
+ }
112
+ }
113
+
114
+ .kui-editor-frame[data-expanded="true"] {
115
+ position: fixed;
116
+ z-index: 40;
117
+ inset: 2rem;
118
+ width: auto;
119
+ height: auto;
120
+ box-shadow: var(--kui-shadow-l);
121
+ }
@@ -661,6 +661,11 @@
661
661
  --wa-color-brand-on-quiet: oklch(
662
662
  from var(--_kui-tint-brand-source) min(l, 0.45) c h
663
663
  );
664
+ /* The global on-fill blue is too light over saturated light tints when
665
+ the app does not supply an accent. Keep compact info badges at AA. */
666
+ --kui-color-brand-on-fill: oklch(
667
+ from var(--_kui-tint-brand-source) min(l, 0.3) c h
668
+ );
664
669
  }
665
670
 
666
671
  [data-kui-tint="dark"] {
@@ -402,7 +402,7 @@
402
402
  > .kui-popup-menu {
403
403
  margin: -2px;
404
404
  }
405
- .kui-toolbar-control-group:is([data-single="true"], [data-content="mixed"])
405
+ .kui-toolbar-control-group[data-content="mixed"]
406
406
  > .kui-popup-menu
407
407
  > .kui-popup-menu__trigger {
408
408
  min-width: max-content;
@@ -56,3 +56,5 @@
56
56
  @import "./summary-row.css";
57
57
  @import "./empty-state.css";
58
58
  @import "./value-table.css";
59
+ @import "./value-preview.css";
60
+ @import "./editor-frame.css";
@@ -1,4 +1,4 @@
1
- /* A selectable summary: a full-width option on the base surface, a container
1
+ /* A summary surface: a full-width option or static group on the base surface, a container
2
2
  for its own compaction, with a hairline divider below each list row. */
3
3
  .kui-summary-row {
4
4
  --_kui-summary-row-rail: transparent;
@@ -18,7 +18,7 @@
18
18
  border-radius: 0;
19
19
  color: var(--kui-color-text);
20
20
  background: var(--kui-color-surface);
21
- cursor: pointer;
21
+ cursor: default;
22
22
  outline: none;
23
23
  container-type: inline-size;
24
24
  user-select: none;
@@ -47,7 +47,11 @@
47
47
  contain-intrinsic-size: auto 4.5rem;
48
48
  }
49
49
 
50
- .kui-summary-row:hover {
50
+ .kui-summary-row[role="option"] {
51
+ cursor: pointer;
52
+ }
53
+
54
+ .kui-summary-row[role="option"]:hover {
51
55
  border-color: var(--kui-color-brand-border-normal);
52
56
  }
53
57
 
@@ -52,6 +52,22 @@
52
52
  light-dark(rgb(29 29 31 / 0.34), rgb(0 0 0 / 0.6))
53
53
  );
54
54
  }
55
+ .kui-dialog-surface[data-stack-active="false"] {
56
+ pointer-events: none;
57
+ transform: translateY(var(--_kui-dialog-surface-stack-offset, 0px));
58
+ }
59
+ .kui-dialog-surface[data-stack-position] {
60
+ --_kui-dialog-surface-gutter: 1.5rem;
61
+ }
62
+ .kui-dialog-surface[data-stack-active="false"]::backdrop {
63
+ background: transparent;
64
+ }
65
+ @media screen and (max-width: 48rem) {
66
+ .kui-dialog-surface[data-stack-position] {
67
+ --_kui-dialog-surface-gutter: 1rem;
68
+ transform: none;
69
+ }
70
+ }
55
71
  /* Room for phones whose viewport height ignores the browser chrome. */
56
72
  @media screen and (max-width: 26.25rem) {
57
73
  .kui-dialog-surface {
@@ -0,0 +1,18 @@
1
+ .kui-value-preview {
2
+ display: block;
3
+ box-sizing: border-box;
4
+ min-width: 0;
5
+ min-height: var(--_kui-value-preview-min-height, 3rem);
6
+ max-height: var(--_kui-value-preview-max-height, 6rem);
7
+ overflow: auto;
8
+ color: var(--kui-color-text);
9
+ font-size: var(--kui-font-xs);
10
+ line-height: 1.4;
11
+ white-space: pre-wrap;
12
+ overflow-wrap: anywhere;
13
+ }
14
+
15
+ .kui-value-preview:focus-visible {
16
+ outline: var(--kui-focus-ring);
17
+ outline-offset: -2px;
18
+ }
@@ -14,7 +14,7 @@ type SummaryRowRootAttributes = Readonly<Record<`data-${string}`, string | undef
14
14
  'data-selected'?: never;
15
15
  'data-dimmed'?: never;
16
16
  }>;
17
- interface SummaryRowProps {
17
+ interface SummaryRowBaseProps {
18
18
  /** The identity line: an identifier, inline status glyphs, and the title. */
19
19
  title: KerfUiContent;
20
20
  /** Optional leading glyph, such as a category icon. */
@@ -29,7 +29,7 @@ interface SummaryRowProps {
29
29
  titleLines?: number;
30
30
  /** A leading state rail in a semantic tone (Up Next, blocked, …). */
31
31
  rail?: SemanticTone;
32
- /** Selected state, exposed as `aria-selected`. */
32
+ /** Selected visual state; also exposed as `aria-selected` for an option. */
33
33
  selected?: boolean;
34
34
  /** Dim a finished or cut item; hover and selection restore it. */
35
35
  dimmed?: boolean;
@@ -37,20 +37,29 @@ interface SummaryRowProps {
37
37
  listEdge?: SummaryRowListEdge;
38
38
  /** Skip rendering while off screen in long lists (`content-visibility`). */
39
39
  deferRendering?: boolean;
40
- /** Accessible name when the visible content is not a good one. */
41
- ariaLabel?: string;
42
40
  id?: string;
43
41
  className?: string;
44
- /** Safe `data-*` identity (an item id or delegated action) on the option. */
42
+ /** Safe `data-*` identity (an item id or delegated action) on the root. */
45
43
  rootAttributes?: SummaryRowRootAttributes;
46
44
  }
45
+ type SummaryRowProps = SummaryRowBaseProps & ({
46
+ /** Selectable option, the default; place it in a labeled listbox. */
47
+ semanticRole?: 'option';
48
+ /** Native HTML drag source on this option root, in row or card form. */
49
+ draggable?: boolean;
50
+ /** Accessible name when the visible content is not a good one. */
51
+ ariaLabel?: string;
52
+ } | {
53
+ /** Static labeled group; nested actions own focus and activation. */
54
+ semanticRole: 'group';
55
+ draggable?: never;
56
+ ariaLabel: string;
57
+ });
47
58
  /**
48
- * A selectable, keyboard-focusable summary of one item, as a list row or a
49
- * board card: an optional leading glyph and state rail, a clamped identity line
50
- * with trailing quiet metadata, and a wrapping metadata line. It is a
51
- * `role="option"`; place rows in a labeled `role="listbox"` and own selection
52
- * and keyboard movement in the application.
59
+ * A list row or board card with a clamped identity line, metadata, and state
60
+ * rail. The default is a focusable `role="option"` for a labeled listbox;
61
+ * `semanticRole="group"` gives a static labeled row for nested actions.
53
62
  */
54
- declare function SummaryRow({ title, leading, trailingMeta, metadata, presentation, titleLines, rail, selected, dimmed, listEdge, deferRendering, ariaLabel, id, className, rootAttributes, }: SummaryRowProps): SafeHtml;
63
+ declare function SummaryRow({ title, leading, trailingMeta, metadata, presentation, titleLines, rail, selected, dimmed, listEdge, deferRendering, semanticRole, draggable, ariaLabel, id, className, rootAttributes, }: SummaryRowProps): SafeHtml;
55
64
 
56
65
  export { SummaryRow, type SummaryRowListEdge, type SummaryRowPresentation, type SummaryRowProps };
@@ -1,4 +1,5 @@
1
- export { SummaryRow } from './chunk-4UB5Z3ZZ.js';
1
+ export { SummaryRow } from './chunk-K67XBCHG.js';
2
+
2
3
 
3
4
 
4
5
  //# sourceMappingURL=summary-row.js.map
@@ -1,4 +1,4 @@
1
- import { installDialogSurfaces } from './chunk-ATGAJVZ6.js';
1
+ import { installDialogSurfaces } from './chunk-3OP66VXU.js';
2
2
 
3
3
 
4
4
  // src/components/surfaces/surface-scaffold/register/surface-scaffold-register.ts
@@ -22,6 +22,15 @@ declare function openDialog(dialog: HTMLDialogElement): void;
22
22
  * `close` event fires once it has closed.
23
23
  */
24
24
  declare function closeDialog(dialog: HTMLDialogElement): void;
25
+ /**
26
+ * Reconcile one controlled stack after rendering its DialogSurface layers.
27
+ * Opening back-to-front establishes native top-layer order; unchanged layers
28
+ * keep their DOM nodes and focus. The application owns `stack.open` and handles
29
+ * `kui-request-close` to update that state before calling this again.
30
+ */
31
+ declare function syncDialogStack(root: ParentNode): void;
32
+ /** Follow a controlled stack's render updates until the returned stop runs. */
33
+ declare function wireDialogStack(root: ParentNode): () => void;
25
34
 
26
35
  type DialogSurfaceSize = 'small' | 'medium' | 'large';
27
36
  /**
@@ -81,6 +90,19 @@ type DialogSurfaceName = {
81
90
  labelledBy: string;
82
91
  };
83
92
  type DialogSurfaceProps = DialogSurfaceName & DialogSurfaceOptions;
93
+ /** Controlled state of one native modal layer inside a `wireDialogStack` root. */
94
+ interface DialogSurfaceStack {
95
+ /** Whether this layer belongs in the native top layer. */
96
+ open: boolean;
97
+ /** The one frontmost open layer; it owns modal focus and accessibility. */
98
+ active: boolean;
99
+ /** One-based order from the back to the front. */
100
+ position: number;
101
+ /** Number of layers in the stack, including closed layers still rendered. */
102
+ count: number;
103
+ /** Optional vertical offset for an inactive layer; omitted on phones. */
104
+ offset?: CssLength;
105
+ }
84
106
  interface DialogSurfaceOptions {
85
107
  /** The dialog's id, for `openDialog(document.getElementById(id))`. */
86
108
  id?: string;
@@ -100,6 +122,8 @@ interface DialogSurfaceOptions {
100
122
  alert?: boolean;
101
123
  /** The body content. */
102
124
  children: KerfUiContent;
125
+ /** Controlled modal stack state; call `wireDialogStack` on the containing root. */
126
+ stack?: DialogSurfaceStack;
103
127
  /**
104
128
  * Header title content in place of the `label` text, such as an xl
105
129
  * `ToolbarText` with a description. The dialog keeps its `label` (or
@@ -214,7 +238,7 @@ interface DialogSurfaceOptions {
214
238
  * floating header and footer measurement, the bottom sheet's keyboard
215
239
  * clearance and grabber, and re-render resilience while open.
216
240
  */
217
- declare function DialogSurface({ id, label, labelledBy, describedBy, alert, heading, headerActions, footer, withoutHeader, lightDismiss, closeLabel, closeEmphasis, children, size, presentation, preferredWidth, bodyInset, footerInset, viewportGutter, maxHeight, height, minHeight, resizable, enterMotion, exitMotion, bodyLayout, headerPresentation, footerPresentation, footerOffset, rootAttributes, className, slot, }: DialogSurfaceProps): kerfjs.SafeHtml;
241
+ declare function DialogSurface({ id, label, labelledBy, describedBy, alert, heading, headerActions, footer, withoutHeader, lightDismiss, closeLabel, closeEmphasis, children, stack, size, presentation, preferredWidth, bodyInset, footerInset, viewportGutter, maxHeight, height, minHeight, resizable, enterMotion, exitMotion, bodyLayout, headerPresentation, footerPresentation, footerOffset, rootAttributes, className, slot, }: DialogSurfaceProps): kerfjs.SafeHtml;
218
242
  /** Where a PopoverDialogSurface appears: the top layer, or in flow. */
219
243
  type PopoverDialogSurfacePresentation = 'overlay' | 'embedded';
220
244
  /** Application `data-*` metadata on the surface root. */
@@ -281,4 +305,4 @@ interface PopupSurfaceProps {
281
305
  /** Configure recurring Web Awesome dropdown-menu geometry without consumer ::part() CSS. */
282
306
  declare function PopupSurface({ children, inset, className, slot, }: PopupSurfaceProps): kerfjs.SafeHtml;
283
307
 
284
- export { type DialogCloseSource, type DialogRequestCloseDetail, DialogSurface, type DialogSurfaceBodyLayout, type DialogSurfaceCloseEmphasis, type DialogSurfaceFooterPresentation, type DialogSurfaceHeaderPresentation, type DialogSurfaceHeight, type DialogSurfaceMaxHeight, type DialogSurfaceName, type DialogSurfaceOptions, type DialogSurfacePresentation, type DialogSurfaceProps, type DialogSurfaceRootAttributes, type DialogSurfaceSheetMotion, type DialogSurfaceSize, PopoverDialogSurface, type PopoverDialogSurfaceDataAttributes, type PopoverDialogSurfacePresentation, type PopoverDialogSurfaceProps, PopupSurface, type PopupSurfaceInset, type PopupSurfaceProps, type SurfaceInset, closeDialog, openDialog };
308
+ export { type DialogCloseSource, type DialogRequestCloseDetail, DialogSurface, type DialogSurfaceBodyLayout, type DialogSurfaceCloseEmphasis, type DialogSurfaceFooterPresentation, type DialogSurfaceHeaderPresentation, type DialogSurfaceHeight, type DialogSurfaceMaxHeight, type DialogSurfaceName, type DialogSurfaceOptions, type DialogSurfacePresentation, type DialogSurfaceProps, type DialogSurfaceRootAttributes, type DialogSurfaceSheetMotion, type DialogSurfaceSize, type DialogSurfaceStack, PopoverDialogSurface, type PopoverDialogSurfaceDataAttributes, type PopoverDialogSurfacePresentation, type PopoverDialogSurfaceProps, PopupSurface, type PopupSurfaceInset, type PopupSurfaceProps, type SurfaceInset, closeDialog, openDialog, syncDialogStack, wireDialogStack };
@@ -1,5 +1,5 @@
1
- export { DialogSurface, PopoverDialogSurface, PopupSurface } from './chunk-VGECEXM6.js';
2
- export { closeDialog, openDialog } from './chunk-ATGAJVZ6.js';
1
+ export { DialogSurface, PopoverDialogSurface, PopupSurface } from './chunk-S3DCRI2M.js';
2
+ export { closeDialog, openDialog, syncDialogStack, wireDialogStack } from './chunk-3OP66VXU.js';
3
3
 
4
4
 
5
5
 
@@ -0,0 +1,21 @@
1
+ import * as kerfjs from 'kerfjs';
2
+ import { CssLength } from './css-values.js';
3
+
4
+ interface ValuePreviewProps {
5
+ /** Accessible name for the keyboard-scrollable value. */
6
+ label: string;
7
+ /** Literal plain-text value, including newlines and long unbroken text. */
8
+ value: string;
9
+ /** Minimum height; defaults to 48px. */
10
+ minHeight?: CssLength;
11
+ /** Maximum height before the value scrolls; defaults to 96px. */
12
+ maxHeight?: CssLength;
13
+ id?: string;
14
+ className?: string;
15
+ /** Native named-slot assignment when composed inside a web component. */
16
+ slot?: string;
17
+ }
18
+ /** Read-only, bounded multiline text for a containing surface such as SunkenPanel. */
19
+ declare function ValuePreview({ label, value, minHeight, maxHeight, id, className, slot, }: ValuePreviewProps): kerfjs.SafeHtml;
20
+
21
+ export { ValuePreview, type ValuePreviewProps };
@@ -0,0 +1,3 @@
1
+ export { ValuePreview } from './chunk-F653O57X.js';
2
+
3
+ //# sourceMappingURL=value-preview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"value-preview.js"}
@@ -1,6 +1,6 @@
1
1
  import { wireWorkbench } from './chunk-WPNIKZMJ.js';
2
-
3
2
  import { wireScrollDividers } from './chunk-OZ6X76G5.js';
3
+
4
4
  import { loadUxReviewProject } from './chunk-6C6DLP3W.js';
5
5
 
6
6
  import { readSearchField } from './chunk-VEME3D7K.js';
@@ -8,15 +8,20 @@ function wireContentItemMedia(root) {
8
8
  const scheme = media?.dataset.tintScheme;
9
9
  if (!scheme) return;
10
10
  if (enabled) {
11
- card.setAttribute("data-kui-tint", scheme);
12
- card.classList.add(`wa-${scheme}`);
13
- if (media?.hasAttribute("data-tint-accent")) {
11
+ if (card.dataset.kuiTint !== scheme)
12
+ card.setAttribute("data-kui-tint", scheme);
13
+ if (!card.classList.contains(`wa-${scheme}`))
14
+ card.classList.add(`wa-${scheme}`);
15
+ if (media?.hasAttribute("data-tint-accent") && !card.hasAttribute("data-kui-tint-accent")) {
14
16
  card.setAttribute("data-kui-tint-accent", "");
15
17
  }
16
18
  } else {
17
- card.removeAttribute("data-kui-tint");
18
- card.removeAttribute("data-kui-tint-accent");
19
- card.classList.remove("wa-light", "wa-dark");
19
+ if (card.hasAttribute("data-kui-tint"))
20
+ card.removeAttribute("data-kui-tint");
21
+ if (card.hasAttribute("data-kui-tint-accent"))
22
+ card.removeAttribute("data-kui-tint-accent");
23
+ if (card.classList.contains("wa-light") || card.classList.contains("wa-dark"))
24
+ card.classList.remove("wa-light", "wa-dark");
20
25
  }
21
26
  };
22
27
  const sync = (card) => {
@@ -41,12 +46,33 @@ function wireContentItemMedia(root) {
41
46
  const card = target.closest(CARD);
42
47
  if (card && root.contains(card)) sync(card);
43
48
  };
44
- const observer = new MutationObserver(all);
49
+ const observer = new MutationObserver((records) => {
50
+ if (records.some((record) => record.type === "childList")) {
51
+ all();
52
+ return;
53
+ }
54
+ const cards = /* @__PURE__ */ new Set();
55
+ for (const record of records) {
56
+ const target = record.target;
57
+ if (target instanceof Element) {
58
+ const card = target.closest(CARD);
59
+ if (card && root.contains(card)) cards.add(card);
60
+ }
61
+ }
62
+ cards.forEach(sync);
63
+ });
45
64
  observer.observe(root, {
46
65
  childList: true,
47
66
  subtree: true,
48
67
  attributes: true,
49
- attributeFilter: ["src", "srcset"]
68
+ attributeFilter: [
69
+ "src",
70
+ "srcset",
71
+ "data-media-state",
72
+ "data-kui-tint",
73
+ "data-kui-tint-accent",
74
+ "class"
75
+ ]
50
76
  });
51
77
  root.addEventListener("load", onImage, true);
52
78
  root.addEventListener("error", onImage, true);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/surfaces/content-item/wiring/wire-content-item-media.ts","../src/components/surfaces/content-item/wiring/wire-content-items.ts"],"names":[],"mappings":"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","file":"wire-content-items.js","sourcesContent":["const CARD = '[data-component=\"content-item\"][data-media-state]';\nconst LEAD = '.kui-content-item__media .kui-backdrop-image__media';\nconst BLURRED = '.kui-content-item__media .kui-backdrop-image__blurred';\n\n/** Image state uses one load/error listener pair and one observer per feed root. */\nexport function wireContentItemMedia(root: HTMLElement): () => void {\n const tint = (card: HTMLElement, enabled: boolean) => {\n const media = card.querySelector<HTMLElement>('.kui-content-item__media');\n const scheme = media?.dataset.tintScheme;\n if (!scheme) return;\n if (enabled) {\n card.setAttribute('data-kui-tint', scheme);\n card.classList.add(`wa-${scheme}`);\n if (media?.hasAttribute('data-tint-accent')) {\n card.setAttribute('data-kui-tint-accent', '');\n }\n } else {\n card.removeAttribute('data-kui-tint');\n card.removeAttribute('data-kui-tint-accent');\n card.classList.remove('wa-light', 'wa-dark');\n }\n };\n const sync = (card: HTMLElement) => {\n const lead = card.querySelector<HTMLImageElement>(LEAD);\n if (!lead) return;\n const state = !lead.complete\n ? 'pending'\n : lead.naturalWidth > 0\n ? 'ready'\n : 'error';\n if (card.dataset.mediaState !== state) card.dataset.mediaState = state;\n tint(card, state !== 'error');\n const blurred = card.querySelector<HTMLImageElement>(BLURRED);\n if (blurred?.complete && blurred.naturalWidth === 0)\n blurred.dataset.imageError = 'true';\n else blurred?.removeAttribute('data-image-error');\n };\n const all = () => {\n if (root.matches(CARD)) sync(root);\n root.querySelectorAll<HTMLElement>(CARD).forEach(sync);\n };\n const onImage = (event: Event) => {\n const target = event.target;\n if (!(target instanceof Element) || !target.matches(`${LEAD}, ${BLURRED}`))\n return;\n const card = target.closest<HTMLElement>(CARD);\n if (card && root.contains(card)) sync(card);\n };\n const observer = new MutationObserver(all);\n observer.observe(root, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['src', 'srcset'],\n });\n root.addEventListener('load', onImage, true);\n root.addEventListener('error', onImage, true);\n all();\n return () => {\n observer.disconnect();\n root.removeEventListener('load', onImage, true);\n root.removeEventListener('error', onImage, true);\n };\n}\n","import { wireContentItemMedia } from './wire-content-item-media.js';\n\nconst ITEM_SELECTOR =\n '[data-component=\"content-item\"][data-interactive=\"true\"]';\nconst NESTED_CONTROL_SELECTOR =\n 'button, a[href], input, select, textarea, [contenteditable=\"true\"], [role=\"button\"]';\nconst MULTI_GRID_SELECTOR = '[role=\"grid\"][aria-multiselectable=\"true\"]';\nconst MULTI_ROW_SELECTOR = `${ITEM_SELECTOR}[data-selection-mode=\"multiple\"]`;\n\n/** The enabled selectable rows of one multi-select grid, in order. */\nfunction gridRows(grid: Element): HTMLElement[] {\n return Array.from(\n grid.querySelectorAll<HTMLElement>(\n `${MULTI_ROW_SELECTOR}:not([data-disabled=\"true\"])`,\n ),\n ).filter((row) => row.closest(MULTI_GRID_SELECTOR) === grid);\n}\n\nfunction nextTile(\n item: HTMLElement,\n rows: HTMLElement[],\n key: string,\n): HTMLElement | undefined {\n const current = item.getBoundingClientRect();\n const centerX = current.left + current.width / 2;\n const candidates = rows\n .filter((row) => row !== item)\n .map((row) => {\n const rect = row.getBoundingClientRect();\n return { row, x: rect.left + rect.width / 2, y: rect.top };\n });\n const sameLine = (y: number) => Math.abs(y - current.top) < 1;\n const directed = candidates.filter(({ x, y }) => {\n switch (key) {\n case 'ArrowLeft':\n return sameLine(y) && x < centerX;\n case 'ArrowRight':\n return sameLine(y) && x > centerX;\n case 'ArrowUp':\n return y < current.top - 1;\n default:\n return y > current.top + 1;\n }\n });\n directed.sort((a, b) => {\n if (key === 'ArrowLeft') return b.x - a.x;\n if (key === 'ArrowRight') return a.x - b.x;\n const vertical = Math.abs(a.y - current.top) - Math.abs(b.y - current.top);\n return vertical || Math.abs(a.x - centerX) - Math.abs(b.x - centerX);\n });\n return directed[0]?.row;\n}\n\nfunction actionItem(root: HTMLElement, event: Event) {\n const target = event.target;\n if (!(target instanceof Element)) return null;\n const item = target.closest<HTMLElement>(ITEM_SELECTOR);\n if (!item || !root.contains(item) || item.dataset.disabled === 'true')\n return null;\n // Composed events expose native controls inside a custom element's shadow\n // root even though event.target is retargeted to its host here.\n for (const node of event.composedPath()) {\n if (node === item) break;\n if (node instanceof Element && node.matches(NESTED_CONTROL_SELECTOR))\n return null;\n }\n return item;\n}\n\n/** True when a card action originated on the card rather than a nested control. */\nexport function isContentItemActivation(\n event: Event,\n item: HTMLElement,\n): boolean {\n return actionItem(item, event) === item;\n}\n\ntype ActivationModifiers = Pick<\n KeyboardEvent,\n 'shiftKey' | 'ctrlKey' | 'metaKey'\n>;\n\n/**\n * Activate an item with a click that carries the activating key's modifier\n * state, so one delegated click handler serves pointer and keyboard\n * multi-selection alike (Shift extends a range, Cmd/Ctrl toggles one item).\n */\nfunction activate(item: HTMLElement, modifiers: ActivationModifiers) {\n item.dispatchEvent(\n new MouseEvent('click', {\n bubbles: true,\n cancelable: true,\n composed: true,\n view: item.ownerDocument.defaultView,\n shiftKey: modifiers.shiftKey,\n ctrlKey: modifiers.ctrlKey,\n metaKey: modifiers.metaKey,\n }),\n );\n}\n\n/**\n * Give interactive ContentItems native-like Enter/Space activation with one\n * delegated listener pair. Space activates on release and is cancelled if\n * focus moves; the item's own `data-action` still goes through the app's\n * ordinary delegated click handler. The activation click mirrors the Shift,\n * Ctrl, and Meta state of the activating key (Space uses the state at press),\n * so the click handler can read `shiftKey` / `metaKey` / `ctrlKey` for\n * keyboard range and toggle selection. Alt-modified keys are left to the\n * platform. Returns a disposer.\n */\nexport function wireContentItems(root: HTMLElement): () => void {\n const stopMedia = wireContentItemMedia(root);\n // Roving tabindex: each multi-select grid is one Tab stop, on the last\n // focused row, else the first selected, else the first enabled row.\n const activeRows = new WeakMap<Element, HTMLElement>();\n const rove = (grid: Element) => {\n const rows = gridRows(grid);\n const remembered = activeRows.get(grid);\n const stop =\n remembered && rows.includes(remembered)\n ? remembered\n : (rows.find((row) => row.getAttribute('aria-selected') === 'true') ??\n rows[0]);\n for (const row of rows) {\n const want = row === stop ? '0' : '-1';\n if (row.getAttribute('tabindex') !== want)\n row.setAttribute('tabindex', want);\n }\n };\n const grids = () =>\n [\n ...(root.matches(MULTI_GRID_SELECTOR) ? [root] : []),\n ...root.querySelectorAll(MULTI_GRID_SELECTOR),\n ] as Element[];\n // A re-render resets every row's tabindex to its template value, so the\n // roving stop is restored after each change (deduplicated per task).\n let roving = false;\n const scheduleRove = () => {\n if (roving) return;\n roving = true;\n globalThis.queueMicrotask(() => {\n roving = false;\n for (const grid of grids()) rove(grid);\n });\n };\n const View = root.ownerDocument.defaultView;\n const observer =\n View && 'MutationObserver' in View\n ? new View.MutationObserver(scheduleRove)\n : null;\n observer?.observe(root, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['tabindex', 'aria-selected', 'data-disabled'],\n });\n for (const grid of grids()) rove(grid);\n\n const focusin = (event: FocusEvent) => {\n const target = event.target;\n if (!(target instanceof Element)) return;\n const row = target.closest<HTMLElement>(MULTI_ROW_SELECTOR);\n const grid = row?.closest(MULTI_GRID_SELECTOR);\n if (!row || !grid || !root.contains(grid)) return;\n activeRows.set(grid, row);\n rove(grid);\n };\n\n let pendingSpace: {\n item: HTMLElement;\n modifiers: ActivationModifiers;\n } | null = null;\n\n const clearSpace = () => {\n pendingSpace?.item.removeAttribute('data-kui-pressed');\n pendingSpace = null;\n };\n\n const keydown = (event: KeyboardEvent) => {\n if (event.defaultPrevented || event.altKey) return;\n const item = actionItem(root, event);\n if (!item) return;\n const commandKey = event.ctrlKey || event.metaKey;\n if (\n !commandKey &&\n item.dataset.selectionMode === 'multiple' &&\n [\n 'ArrowDown',\n 'ArrowUp',\n 'ArrowLeft',\n 'ArrowRight',\n 'Home',\n 'End',\n ].includes(event.key)\n ) {\n const grid = item.closest(MULTI_GRID_SELECTOR);\n if (!grid) return;\n const rows = gridRows(grid);\n const index = rows.indexOf(item);\n if (index < 0) return;\n const isTileGrid = grid.getAttribute('data-component') === 'grid';\n let next: HTMLElement | undefined;\n switch (event.key) {\n case 'Home':\n next = rows[0];\n break;\n case 'End':\n next = rows[rows.length - 1];\n break;\n case 'ArrowDown':\n case 'ArrowUp':\n next = isTileGrid\n ? nextTile(item, rows, event.key)\n : rows[index + (event.key === 'ArrowDown' ? 1 : -1)];\n break;\n case 'ArrowLeft':\n case 'ArrowRight':\n next = isTileGrid ? nextTile(item, rows, event.key) : undefined;\n break;\n }\n if (next) {\n event.preventDefault();\n next.focus();\n }\n return;\n }\n if (event.key === 'Enter') {\n event.preventDefault();\n activate(item, event);\n return;\n }\n if (event.key === ' ' || event.key === 'Spacebar') {\n event.preventDefault();\n if (event.repeat) return;\n clearSpace();\n pendingSpace = {\n item,\n modifiers: {\n shiftKey: event.shiftKey,\n ctrlKey: event.ctrlKey,\n metaKey: event.metaKey,\n },\n };\n item.setAttribute('data-kui-pressed', 'true');\n }\n };\n\n const keyup = (event: KeyboardEvent) => {\n if (event.key !== ' ' && event.key !== 'Spacebar') return;\n if (!pendingSpace) return;\n const { item, modifiers } = pendingSpace;\n event.preventDefault();\n clearSpace();\n if (\n item === actionItem(root, event) &&\n item.ownerDocument.activeElement === item\n )\n activate(item, modifiers);\n };\n\n const focusout = (event: FocusEvent) => {\n if (event.target === pendingSpace?.item) clearSpace();\n };\n\n root.addEventListener('keydown', keydown);\n root.addEventListener('keyup', keyup);\n root.addEventListener('focusout', focusout);\n root.addEventListener('focusin', focusin);\n return () => {\n stopMedia();\n clearSpace();\n observer?.disconnect();\n root.removeEventListener('focusin', focusin);\n root.removeEventListener('keydown', keydown);\n root.removeEventListener('keyup', keyup);\n root.removeEventListener('focusout', focusout);\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/components/surfaces/content-item/wiring/wire-content-item-media.ts","../src/components/surfaces/content-item/wiring/wire-content-items.ts"],"names":[],"mappings":";AAAA,IAAM,IAAA,GAAO,mDAAA;AACb,IAAM,IAAA,GAAO,qDAAA;AACb,IAAM,OAAA,GAAU,uDAAA;AAGT,SAAS,qBAAqB,IAAA,EAA+B;AAClE,EAAA,MAAM,IAAA,GAAO,CAAC,IAAA,EAAmB,OAAA,KAAqB;AACpD,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,aAAA,CAA2B,0BAA0B,CAAA;AACxE,IAAA,MAAM,MAAA,GAAS,OAAO,OAAA,CAAQ,UAAA;AAC9B,IAAA,IAAI,CAAC,MAAA,EAAQ;AACb,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,IAAI,IAAA,CAAK,QAAQ,OAAA,KAAY,MAAA;AAC3B,QAAA,IAAA,CAAK,YAAA,CAAa,iBAAiB,MAAM,CAAA;AAC3C,MAAA,IAAI,CAAC,IAAA,CAAK,SAAA,CAAU,QAAA,CAAS,CAAA,GAAA,EAAM,MAAM,CAAA,CAAE,CAAA;AACzC,QAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,CAAA,GAAA,EAAM,MAAM,CAAA,CAAE,CAAA;AACnC,MAAA,IACE,KAAA,EAAO,aAAa,kBAAkB,CAAA,IACtC,CAAC,IAAA,CAAK,YAAA,CAAa,sBAAsB,CAAA,EACzC;AACA,QAAA,IAAA,CAAK,YAAA,CAAa,wBAAwB,EAAE,CAAA;AAAA,MAC9C;AAAA,IACF,CAAA,MAAO;AACL,MAAA,IAAI,IAAA,CAAK,aAAa,eAAe,CAAA;AACnC,QAAA,IAAA,CAAK,gBAAgB,eAAe,CAAA;AACtC,MAAA,IAAI,IAAA,CAAK,aAAa,sBAAsB,CAAA;AAC1C,QAAA,IAAA,CAAK,gBAAgB,sBAAsB,CAAA;AAC7C,MAAA,IACE,IAAA,CAAK,UAAU,QAAA,CAAS,UAAU,KAClC,IAAA,CAAK,SAAA,CAAU,SAAS,SAAS,CAAA;AAEjC,QAAA,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,UAAA,EAAY,SAAS,CAAA;AAAA,IAC/C;AAAA,EACF,CAAA;AACA,EAAA,MAAM,IAAA,GAAO,CAAC,IAAA,KAAsB;AAClC,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,aAAA,CAAgC,IAAI,CAAA;AACtD,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,MAAM,KAAA,GAAQ,CAAC,IAAA,CAAK,QAAA,GAChB,YACA,IAAA,CAAK,YAAA,GAAe,IAClB,OAAA,GACA,OAAA;AACN,IAAA,IAAI,KAAK,OAAA,CAAQ,UAAA,KAAe,KAAA,EAAO,IAAA,CAAK,QAAQ,UAAA,GAAa,KAAA;AACjE,IAAA,IAAA,CAAK,IAAA,EAAM,UAAU,OAAO,CAAA;AAC5B,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,aAAA,CAAgC,OAAO,CAAA;AAC5D,IAAA,IAAI,OAAA,EAAS,QAAA,IAAY,OAAA,CAAQ,YAAA,KAAiB,CAAA;AAChD,MAAA,OAAA,CAAQ,QAAQ,UAAA,GAAa,MAAA;AAAA,SAC1B,OAAA,EAAS,gBAAgB,kBAAkB,CAAA;AAAA,EAClD,CAAA;AACA,EAAA,MAAM,MAAM,MAAM;AAChB,IAAA,IAAI,IAAA,CAAK,OAAA,CAAQ,IAAI,CAAA,OAAQ,IAAI,CAAA;AACjC,IAAA,IAAA,CAAK,gBAAA,CAA8B,IAAI,CAAA,CAAE,OAAA,CAAQ,IAAI,CAAA;AAAA,EACvD,CAAA;AACA,EAAA,MAAM,OAAA,GAAU,CAAC,KAAA,KAAiB;AAChC,IAAA,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,IAAA,IAAI,EAAE,MAAA,YAAkB,OAAA,CAAA,IAAY,CAAC,MAAA,CAAO,QAAQ,CAAA,EAAG,IAAI,CAAA,EAAA,EAAK,OAAO,CAAA,CAAE,CAAA;AACvE,MAAA;AACF,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,OAAA,CAAqB,IAAI,CAAA;AAC7C,IAAA,IAAI,QAAQ,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,OAAQ,IAAI,CAAA;AAAA,EAC5C,CAAA;AAGA,EAAA,MAAM,QAAA,GAAW,IAAI,gBAAA,CAAiB,CAAC,OAAA,KAAY;AACjD,IAAA,IAAI,QAAQ,IAAA,CAAK,CAAC,WAAW,MAAA,CAAO,IAAA,KAAS,WAAW,CAAA,EAAG;AACzD,MAAA,GAAA,EAAI;AACJ,MAAA;AAAA,IACF;AACA,IAAA,MAAM,KAAA,uBAAY,GAAA,EAAiB;AACnC,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,MAAA,MAAM,SAAS,MAAA,CAAO,MAAA;AACtB,MAAA,IAAI,kBAAkB,OAAA,EAAS;AAC7B,QAAA,MAAM,IAAA,GAAO,MAAA,CAAO,OAAA,CAAqB,IAAI,CAAA;AAC7C,QAAA,IAAI,QAAQ,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,EAAG,KAAA,CAAM,IAAI,IAAI,CAAA;AAAA,MACjD;AAAA,IACF;AACA,IAAA,KAAA,CAAM,QAAQ,IAAI,CAAA;AAAA,EACpB,CAAC,CAAA;AACD,EAAA,QAAA,CAAS,QAAQ,IAAA,EAAM;AAAA,IACrB,SAAA,EAAW,IAAA;AAAA,IACX,OAAA,EAAS,IAAA;AAAA,IACT,UAAA,EAAY,IAAA;AAAA,IACZ,eAAA,EAAiB;AAAA,MACf,KAAA;AAAA,MACA,QAAA;AAAA,MACA,kBAAA;AAAA,MACA,eAAA;AAAA,MACA,sBAAA;AAAA,MACA;AAAA;AACF,GACD,CAAA;AACD,EAAA,IAAA,CAAK,gBAAA,CAAiB,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AAC3C,EAAA,IAAA,CAAK,gBAAA,CAAiB,OAAA,EAAS,OAAA,EAAS,IAAI,CAAA;AAC5C,EAAA,GAAA,EAAI;AACJ,EAAA,OAAO,MAAM;AACX,IAAA,QAAA,CAAS,UAAA,EAAW;AACpB,IAAA,IAAA,CAAK,mBAAA,CAAoB,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AAC9C,IAAA,IAAA,CAAK,mBAAA,CAAoB,OAAA,EAAS,OAAA,EAAS,IAAI,CAAA;AAAA,EACjD,CAAA;AACF;;;AC/FA,IAAM,aAAA,GACJ,0DAAA;AACF,IAAM,uBAAA,GACJ,qFAAA;AACF,IAAM,mBAAA,GAAsB,4CAAA;AAC5B,IAAM,kBAAA,GAAqB,GAAG,aAAa,CAAA,gCAAA,CAAA;AAG3C,SAAS,SAAS,IAAA,EAA8B;AAC9C,EAAA,OAAO,KAAA,CAAM,IAAA;AAAA,IACX,IAAA,CAAK,gBAAA;AAAA,MACH,GAAG,kBAAkB,CAAA,4BAAA;AAAA;AACvB,GACF,CAAE,OAAO,CAAC,GAAA,KAAQ,IAAI,OAAA,CAAQ,mBAAmB,MAAM,IAAI,CAAA;AAC7D;AAEA,SAAS,QAAA,CACP,IAAA,EACA,IAAA,EACA,GAAA,EACyB;AACzB,EAAA,MAAM,OAAA,GAAU,KAAK,qBAAA,EAAsB;AAC3C,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,IAAA,GAAO,OAAA,CAAQ,KAAA,GAAQ,CAAA;AAC/C,EAAA,MAAM,UAAA,GAAa,IAAA,CAChB,MAAA,CAAO,CAAC,GAAA,KAAQ,QAAQ,IAAI,CAAA,CAC5B,GAAA,CAAI,CAAC,GAAA,KAAQ;AACZ,IAAA,MAAM,IAAA,GAAO,IAAI,qBAAA,EAAsB;AACvC,IAAA,OAAO,EAAE,GAAA,EAAK,CAAA,EAAG,IAAA,CAAK,IAAA,GAAO,KAAK,KAAA,GAAQ,CAAA,EAAG,CAAA,EAAG,IAAA,CAAK,GAAA,EAAI;AAAA,EAC3D,CAAC,CAAA;AACH,EAAA,MAAM,QAAA,GAAW,CAAC,CAAA,KAAc,IAAA,CAAK,IAAI,CAAA,GAAI,OAAA,CAAQ,GAAG,CAAA,GAAI,CAAA;AAC5D,EAAA,MAAM,WAAW,UAAA,CAAW,MAAA,CAAO,CAAC,EAAE,CAAA,EAAG,GAAE,KAAM;AAC/C,IAAA,QAAQ,GAAA;AAAK,MACX,KAAK,WAAA;AACH,QAAA,OAAO,QAAA,CAAS,CAAC,CAAA,IAAK,CAAA,GAAI,OAAA;AAAA,MAC5B,KAAK,YAAA;AACH,QAAA,OAAO,QAAA,CAAS,CAAC,CAAA,IAAK,CAAA,GAAI,OAAA;AAAA,MAC5B,KAAK,SAAA;AACH,QAAA,OAAO,CAAA,GAAI,QAAQ,GAAA,GAAM,CAAA;AAAA,MAC3B;AACE,QAAA,OAAO,CAAA,GAAI,QAAQ,GAAA,GAAM,CAAA;AAAA;AAC7B,EACF,CAAC,CAAA;AACD,EAAA,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM;AACtB,IAAA,IAAI,GAAA,KAAQ,WAAA,EAAa,OAAO,CAAA,CAAE,IAAI,CAAA,CAAE,CAAA;AACxC,IAAA,IAAI,GAAA,KAAQ,YAAA,EAAc,OAAO,CAAA,CAAE,IAAI,CAAA,CAAE,CAAA;AACzC,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,CAAA,GAAI,OAAA,CAAQ,GAAG,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,CAAA,GAAI,QAAQ,GAAG,CAAA;AACzE,IAAA,OAAO,QAAA,IAAY,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,CAAA,GAAI,OAAO,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,CAAA,GAAI,OAAO,CAAA;AAAA,EACrE,CAAC,CAAA;AACD,EAAA,OAAO,QAAA,CAAS,CAAC,CAAA,EAAG,GAAA;AACtB;AAEA,SAAS,UAAA,CAAW,MAAmB,KAAA,EAAc;AACnD,EAAA,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,EAAA,IAAI,EAAE,MAAA,YAAkB,OAAA,CAAA,EAAU,OAAO,IAAA;AACzC,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,OAAA,CAAqB,aAAa,CAAA;AACtD,EAAA,IAAI,CAAC,QAAQ,CAAC,IAAA,CAAK,SAAS,IAAI,CAAA,IAAK,IAAA,CAAK,OAAA,CAAQ,QAAA,KAAa,MAAA;AAC7D,IAAA,OAAO,IAAA;AAGT,EAAA,KAAA,MAAW,IAAA,IAAQ,KAAA,CAAM,YAAA,EAAa,EAAG;AACvC,IAAA,IAAI,SAAS,IAAA,EAAM;AACnB,IAAA,IAAI,IAAA,YAAgB,OAAA,IAAW,IAAA,CAAK,OAAA,CAAQ,uBAAuB,CAAA;AACjE,MAAA,OAAO,IAAA;AAAA,EACX;AACA,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,uBAAA,CACd,OACA,IAAA,EACS;AACT,EAAA,OAAO,UAAA,CAAW,IAAA,EAAM,KAAK,CAAA,KAAM,IAAA;AACrC;AAYA,SAAS,QAAA,CAAS,MAAmB,SAAA,EAAgC;AACnE,EAAA,IAAA,CAAK,aAAA;AAAA,IACH,IAAI,WAAW,OAAA,EAAS;AAAA,MACtB,OAAA,EAAS,IAAA;AAAA,MACT,UAAA,EAAY,IAAA;AAAA,MACZ,QAAA,EAAU,IAAA;AAAA,MACV,IAAA,EAAM,KAAK,aAAA,CAAc,WAAA;AAAA,MACzB,UAAU,SAAA,CAAU,QAAA;AAAA,MACpB,SAAS,SAAA,CAAU,OAAA;AAAA,MACnB,SAAS,SAAA,CAAU;AAAA,KACpB;AAAA,GACH;AACF;AAYO,SAAS,iBAAiB,IAAA,EAA+B;AAC9D,EAAA,MAAM,SAAA,GAAY,qBAAqB,IAAI,CAAA;AAG3C,EAAA,MAAM,UAAA,uBAAiB,OAAA,EAA8B;AACrD,EAAA,MAAM,IAAA,GAAO,CAAC,IAAA,KAAkB;AAC9B,IAAA,MAAM,IAAA,GAAO,SAAS,IAAI,CAAA;AAC1B,IAAA,MAAM,UAAA,GAAa,UAAA,CAAW,GAAA,CAAI,IAAI,CAAA;AACtC,IAAA,MAAM,OACJ,UAAA,IAAc,IAAA,CAAK,SAAS,UAAU,CAAA,GAClC,aACC,IAAA,CAAK,IAAA,CAAK,CAAC,GAAA,KAAQ,IAAI,YAAA,CAAa,eAAe,MAAM,MAAM,CAAA,IAChE,KAAK,CAAC,CAAA;AACZ,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,MAAM,IAAA,GAAO,GAAA,KAAQ,IAAA,GAAO,GAAA,GAAM,IAAA;AAClC,MAAA,IAAI,GAAA,CAAI,YAAA,CAAa,UAAU,CAAA,KAAM,IAAA;AACnC,QAAA,GAAA,CAAI,YAAA,CAAa,YAAY,IAAI,CAAA;AAAA,IACrC;AAAA,EACF,CAAA;AACA,EAAA,MAAM,QAAQ,MACZ;AAAA,IACE,GAAI,KAAK,OAAA,CAAQ,mBAAmB,IAAI,CAAC,IAAI,IAAI,EAAC;AAAA,IAClD,GAAG,IAAA,CAAK,gBAAA,CAAiB,mBAAmB;AAAA,GAC9C;AAGF,EAAA,IAAI,MAAA,GAAS,KAAA;AACb,EAAA,MAAM,eAAe,MAAM;AACzB,IAAA,IAAI,MAAA,EAAQ;AACZ,IAAA,MAAA,GAAS,IAAA;AACT,IAAA,UAAA,CAAW,eAAe,MAAM;AAC9B,MAAA,MAAA,GAAS,KAAA;AACT,MAAA,KAAA,MAAW,IAAA,IAAQ,KAAA,EAAM,EAAG,IAAA,CAAK,IAAI,CAAA;AAAA,IACvC,CAAC,CAAA;AAAA,EACH,CAAA;AACA,EAAA,MAAM,IAAA,GAAO,KAAK,aAAA,CAAc,WAAA;AAChC,EAAA,MAAM,QAAA,GACJ,QAAQ,kBAAA,IAAsB,IAAA,GAC1B,IAAI,IAAA,CAAK,gBAAA,CAAiB,YAAY,CAAA,GACtC,IAAA;AACN,EAAA,QAAA,EAAU,QAAQ,IAAA,EAAM;AAAA,IACtB,SAAA,EAAW,IAAA;AAAA,IACX,OAAA,EAAS,IAAA;AAAA,IACT,UAAA,EAAY,IAAA;AAAA,IACZ,eAAA,EAAiB,CAAC,UAAA,EAAY,eAAA,EAAiB,eAAe;AAAA,GAC/D,CAAA;AACD,EAAA,KAAA,MAAW,IAAA,IAAQ,KAAA,EAAM,EAAG,IAAA,CAAK,IAAI,CAAA;AAErC,EAAA,MAAM,OAAA,GAAU,CAAC,KAAA,KAAsB;AACrC,IAAA,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,IAAA,IAAI,EAAE,kBAAkB,OAAA,CAAA,EAAU;AAClC,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,OAAA,CAAqB,kBAAkB,CAAA;AAC1D,IAAA,MAAM,IAAA,GAAO,GAAA,EAAK,OAAA,CAAQ,mBAAmB,CAAA;AAC7C,IAAA,IAAI,CAAC,OAAO,CAAC,IAAA,IAAQ,CAAC,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,EAAG;AAC3C,IAAA,UAAA,CAAW,GAAA,CAAI,MAAM,GAAG,CAAA;AACxB,IAAA,IAAA,CAAK,IAAI,CAAA;AAAA,EACX,CAAA;AAEA,EAAA,IAAI,YAAA,GAGO,IAAA;AAEX,EAAA,MAAM,aAAa,MAAM;AACvB,IAAA,YAAA,EAAc,IAAA,CAAK,gBAAgB,kBAAkB,CAAA;AACrD,IAAA,YAAA,GAAe,IAAA;AAAA,EACjB,CAAA;AAEA,EAAA,MAAM,OAAA,GAAU,CAAC,KAAA,KAAyB;AACxC,IAAA,IAAI,KAAA,CAAM,gBAAA,IAAoB,KAAA,CAAM,MAAA,EAAQ;AAC5C,IAAA,MAAM,IAAA,GAAO,UAAA,CAAW,IAAA,EAAM,KAAK,CAAA;AACnC,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,MAAM,UAAA,GAAa,KAAA,CAAM,OAAA,IAAW,KAAA,CAAM,OAAA;AAC1C,IAAA,IACE,CAAC,UAAA,IACD,IAAA,CAAK,OAAA,CAAQ,kBAAkB,UAAA,IAC/B;AAAA,MACE,WAAA;AAAA,MACA,SAAA;AAAA,MACA,WAAA;AAAA,MACA,YAAA;AAAA,MACA,MAAA;AAAA,MACA;AAAA,KACF,CAAE,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA,EACpB;AACA,MAAA,MAAM,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,mBAAmB,CAAA;AAC7C,MAAA,IAAI,CAAC,IAAA,EAAM;AACX,MAAA,MAAM,IAAA,GAAO,SAAS,IAAI,CAAA;AAC1B,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,OAAA,CAAQ,IAAI,CAAA;AAC/B,MAAA,IAAI,QAAQ,CAAA,EAAG;AACf,MAAA,MAAM,UAAA,GAAa,IAAA,CAAK,YAAA,CAAa,gBAAgB,CAAA,KAAM,MAAA;AAC3D,MAAA,IAAI,IAAA;AACJ,MAAA,QAAQ,MAAM,GAAA;AAAK,QACjB,KAAK,MAAA;AACH,UAAA,IAAA,GAAO,KAAK,CAAC,CAAA;AACb,UAAA;AAAA,QACF,KAAK,KAAA;AACH,UAAA,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA;AAC3B,UAAA;AAAA,QACF,KAAK,WAAA;AAAA,QACL,KAAK,SAAA;AACH,UAAA,IAAA,GAAO,UAAA,GACH,QAAA,CAAS,IAAA,EAAM,IAAA,EAAM,KAAA,CAAM,GAAG,CAAA,GAC9B,IAAA,CAAK,KAAA,IAAS,KAAA,CAAM,GAAA,KAAQ,WAAA,GAAc,IAAI,EAAA,CAAG,CAAA;AACrD,UAAA;AAAA,QACF,KAAK,WAAA;AAAA,QACL,KAAK,YAAA;AACH,UAAA,IAAA,GAAO,aAAa,QAAA,CAAS,IAAA,EAAM,IAAA,EAAM,KAAA,CAAM,GAAG,CAAA,GAAI,MAAA;AACtD,UAAA;AAAA;AAEJ,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,KAAA,CAAM,cAAA,EAAe;AACrB,QAAA,IAAA,CAAK,KAAA,EAAM;AAAA,MACb;AACA,MAAA;AAAA,IACF;AACA,IAAA,IAAI,KAAA,CAAM,QAAQ,OAAA,EAAS;AACzB,MAAA,KAAA,CAAM,cAAA,EAAe;AACrB,MAAA,QAAA,CAAS,MAAM,KAAK,CAAA;AACpB,MAAA;AAAA,IACF;AACA,IAAA,IAAI,KAAA,CAAM,GAAA,KAAQ,GAAA,IAAO,KAAA,CAAM,QAAQ,UAAA,EAAY;AACjD,MAAA,KAAA,CAAM,cAAA,EAAe;AACrB,MAAA,IAAI,MAAM,MAAA,EAAQ;AAClB,MAAA,UAAA,EAAW;AACX,MAAA,YAAA,GAAe;AAAA,QACb,IAAA;AAAA,QACA,SAAA,EAAW;AAAA,UACT,UAAU,KAAA,CAAM,QAAA;AAAA,UAChB,SAAS,KAAA,CAAM,OAAA;AAAA,UACf,SAAS,KAAA,CAAM;AAAA;AACjB,OACF;AACA,MAAA,IAAA,CAAK,YAAA,CAAa,oBAAoB,MAAM,CAAA;AAAA,IAC9C;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,KAAA,GAAQ,CAAC,KAAA,KAAyB;AACtC,IAAA,IAAI,KAAA,CAAM,GAAA,KAAQ,GAAA,IAAO,KAAA,CAAM,QAAQ,UAAA,EAAY;AACnD,IAAA,IAAI,CAAC,YAAA,EAAc;AACnB,IAAA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAU,GAAI,YAAA;AAC5B,IAAA,KAAA,CAAM,cAAA,EAAe;AACrB,IAAA,UAAA,EAAW;AACX,IAAA,IACE,SAAS,UAAA,CAAW,IAAA,EAAM,KAAK,CAAA,IAC/B,IAAA,CAAK,cAAc,aAAA,KAAkB,IAAA;AAErC,MAAA,QAAA,CAAS,MAAM,SAAS,CAAA;AAAA,EAC5B,CAAA;AAEA,EAAA,MAAM,QAAA,GAAW,CAAC,KAAA,KAAsB;AACtC,IAAA,IAAI,KAAA,CAAM,MAAA,KAAW,YAAA,EAAc,IAAA,EAAM,UAAA,EAAW;AAAA,EACtD,CAAA;AAEA,EAAA,IAAA,CAAK,gBAAA,CAAiB,WAAW,OAAO,CAAA;AACxC,EAAA,IAAA,CAAK,gBAAA,CAAiB,SAAS,KAAK,CAAA;AACpC,EAAA,IAAA,CAAK,gBAAA,CAAiB,YAAY,QAAQ,CAAA;AAC1C,EAAA,IAAA,CAAK,gBAAA,CAAiB,WAAW,OAAO,CAAA;AACxC,EAAA,OAAO,MAAM;AACX,IAAA,SAAA,EAAU;AACV,IAAA,UAAA,EAAW;AACX,IAAA,QAAA,EAAU,UAAA,EAAW;AACrB,IAAA,IAAA,CAAK,mBAAA,CAAoB,WAAW,OAAO,CAAA;AAC3C,IAAA,IAAA,CAAK,mBAAA,CAAoB,WAAW,OAAO,CAAA;AAC3C,IAAA,IAAA,CAAK,mBAAA,CAAoB,SAAS,KAAK,CAAA;AACvC,IAAA,IAAA,CAAK,mBAAA,CAAoB,YAAY,QAAQ,CAAA;AAAA,EAC/C,CAAA;AACF","file":"wire-content-items.js","sourcesContent":["const CARD = '[data-component=\"content-item\"][data-media-state]';\nconst LEAD = '.kui-content-item__media .kui-backdrop-image__media';\nconst BLURRED = '.kui-content-item__media .kui-backdrop-image__blurred';\n\n/** Image state uses one load/error listener pair and one observer per feed root. */\nexport function wireContentItemMedia(root: HTMLElement): () => void {\n const tint = (card: HTMLElement, enabled: boolean) => {\n const media = card.querySelector<HTMLElement>('.kui-content-item__media');\n const scheme = media?.dataset.tintScheme;\n if (!scheme) return;\n if (enabled) {\n if (card.dataset.kuiTint !== scheme)\n card.setAttribute('data-kui-tint', scheme);\n if (!card.classList.contains(`wa-${scheme}`))\n card.classList.add(`wa-${scheme}`);\n if (\n media?.hasAttribute('data-tint-accent') &&\n !card.hasAttribute('data-kui-tint-accent')\n ) {\n card.setAttribute('data-kui-tint-accent', '');\n }\n } else {\n if (card.hasAttribute('data-kui-tint'))\n card.removeAttribute('data-kui-tint');\n if (card.hasAttribute('data-kui-tint-accent'))\n card.removeAttribute('data-kui-tint-accent');\n if (\n card.classList.contains('wa-light') ||\n card.classList.contains('wa-dark')\n )\n card.classList.remove('wa-light', 'wa-dark');\n }\n };\n const sync = (card: HTMLElement) => {\n const lead = card.querySelector<HTMLImageElement>(LEAD);\n if (!lead) return;\n const state = !lead.complete\n ? 'pending'\n : lead.naturalWidth > 0\n ? 'ready'\n : 'error';\n if (card.dataset.mediaState !== state) card.dataset.mediaState = state;\n tint(card, state !== 'error');\n const blurred = card.querySelector<HTMLImageElement>(BLURRED);\n if (blurred?.complete && blurred.naturalWidth === 0)\n blurred.dataset.imageError = 'true';\n else blurred?.removeAttribute('data-image-error');\n };\n const all = () => {\n if (root.matches(CARD)) sync(root);\n root.querySelectorAll<HTMLElement>(CARD).forEach(sync);\n };\n const onImage = (event: Event) => {\n const target = event.target;\n if (!(target instanceof Element) || !target.matches(`${LEAD}, ${BLURRED}`))\n return;\n const card = target.closest<HTMLElement>(CARD);\n if (card && root.contains(card)) sync(card);\n };\n // Morph can restore template attributes without changing an image node or\n // firing a second load/error event. Reconcile its writes against native state.\n const observer = new MutationObserver((records) => {\n if (records.some((record) => record.type === 'childList')) {\n all();\n return;\n }\n const cards = new Set<HTMLElement>();\n for (const record of records) {\n const target = record.target;\n if (target instanceof Element) {\n const card = target.closest<HTMLElement>(CARD);\n if (card && root.contains(card)) cards.add(card);\n }\n }\n cards.forEach(sync);\n });\n observer.observe(root, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\n 'src',\n 'srcset',\n 'data-media-state',\n 'data-kui-tint',\n 'data-kui-tint-accent',\n 'class',\n ],\n });\n root.addEventListener('load', onImage, true);\n root.addEventListener('error', onImage, true);\n all();\n return () => {\n observer.disconnect();\n root.removeEventListener('load', onImage, true);\n root.removeEventListener('error', onImage, true);\n };\n}\n","import { wireContentItemMedia } from './wire-content-item-media.js';\n\nconst ITEM_SELECTOR =\n '[data-component=\"content-item\"][data-interactive=\"true\"]';\nconst NESTED_CONTROL_SELECTOR =\n 'button, a[href], input, select, textarea, [contenteditable=\"true\"], [role=\"button\"]';\nconst MULTI_GRID_SELECTOR = '[role=\"grid\"][aria-multiselectable=\"true\"]';\nconst MULTI_ROW_SELECTOR = `${ITEM_SELECTOR}[data-selection-mode=\"multiple\"]`;\n\n/** The enabled selectable rows of one multi-select grid, in order. */\nfunction gridRows(grid: Element): HTMLElement[] {\n return Array.from(\n grid.querySelectorAll<HTMLElement>(\n `${MULTI_ROW_SELECTOR}:not([data-disabled=\"true\"])`,\n ),\n ).filter((row) => row.closest(MULTI_GRID_SELECTOR) === grid);\n}\n\nfunction nextTile(\n item: HTMLElement,\n rows: HTMLElement[],\n key: string,\n): HTMLElement | undefined {\n const current = item.getBoundingClientRect();\n const centerX = current.left + current.width / 2;\n const candidates = rows\n .filter((row) => row !== item)\n .map((row) => {\n const rect = row.getBoundingClientRect();\n return { row, x: rect.left + rect.width / 2, y: rect.top };\n });\n const sameLine = (y: number) => Math.abs(y - current.top) < 1;\n const directed = candidates.filter(({ x, y }) => {\n switch (key) {\n case 'ArrowLeft':\n return sameLine(y) && x < centerX;\n case 'ArrowRight':\n return sameLine(y) && x > centerX;\n case 'ArrowUp':\n return y < current.top - 1;\n default:\n return y > current.top + 1;\n }\n });\n directed.sort((a, b) => {\n if (key === 'ArrowLeft') return b.x - a.x;\n if (key === 'ArrowRight') return a.x - b.x;\n const vertical = Math.abs(a.y - current.top) - Math.abs(b.y - current.top);\n return vertical || Math.abs(a.x - centerX) - Math.abs(b.x - centerX);\n });\n return directed[0]?.row;\n}\n\nfunction actionItem(root: HTMLElement, event: Event) {\n const target = event.target;\n if (!(target instanceof Element)) return null;\n const item = target.closest<HTMLElement>(ITEM_SELECTOR);\n if (!item || !root.contains(item) || item.dataset.disabled === 'true')\n return null;\n // Composed events expose native controls inside a custom element's shadow\n // root even though event.target is retargeted to its host here.\n for (const node of event.composedPath()) {\n if (node === item) break;\n if (node instanceof Element && node.matches(NESTED_CONTROL_SELECTOR))\n return null;\n }\n return item;\n}\n\n/** True when a card action originated on the card rather than a nested control. */\nexport function isContentItemActivation(\n event: Event,\n item: HTMLElement,\n): boolean {\n return actionItem(item, event) === item;\n}\n\ntype ActivationModifiers = Pick<\n KeyboardEvent,\n 'shiftKey' | 'ctrlKey' | 'metaKey'\n>;\n\n/**\n * Activate an item with a click that carries the activating key's modifier\n * state, so one delegated click handler serves pointer and keyboard\n * multi-selection alike (Shift extends a range, Cmd/Ctrl toggles one item).\n */\nfunction activate(item: HTMLElement, modifiers: ActivationModifiers) {\n item.dispatchEvent(\n new MouseEvent('click', {\n bubbles: true,\n cancelable: true,\n composed: true,\n view: item.ownerDocument.defaultView,\n shiftKey: modifiers.shiftKey,\n ctrlKey: modifiers.ctrlKey,\n metaKey: modifiers.metaKey,\n }),\n );\n}\n\n/**\n * Give interactive ContentItems native-like Enter/Space activation with one\n * delegated listener pair. Space activates on release and is cancelled if\n * focus moves; the item's own `data-action` still goes through the app's\n * ordinary delegated click handler. The activation click mirrors the Shift,\n * Ctrl, and Meta state of the activating key (Space uses the state at press),\n * so the click handler can read `shiftKey` / `metaKey` / `ctrlKey` for\n * keyboard range and toggle selection. Alt-modified keys are left to the\n * platform. Returns a disposer.\n */\nexport function wireContentItems(root: HTMLElement): () => void {\n const stopMedia = wireContentItemMedia(root);\n // Roving tabindex: each multi-select grid is one Tab stop, on the last\n // focused row, else the first selected, else the first enabled row.\n const activeRows = new WeakMap<Element, HTMLElement>();\n const rove = (grid: Element) => {\n const rows = gridRows(grid);\n const remembered = activeRows.get(grid);\n const stop =\n remembered && rows.includes(remembered)\n ? remembered\n : (rows.find((row) => row.getAttribute('aria-selected') === 'true') ??\n rows[0]);\n for (const row of rows) {\n const want = row === stop ? '0' : '-1';\n if (row.getAttribute('tabindex') !== want)\n row.setAttribute('tabindex', want);\n }\n };\n const grids = () =>\n [\n ...(root.matches(MULTI_GRID_SELECTOR) ? [root] : []),\n ...root.querySelectorAll(MULTI_GRID_SELECTOR),\n ] as Element[];\n // A re-render resets every row's tabindex to its template value, so the\n // roving stop is restored after each change (deduplicated per task).\n let roving = false;\n const scheduleRove = () => {\n if (roving) return;\n roving = true;\n globalThis.queueMicrotask(() => {\n roving = false;\n for (const grid of grids()) rove(grid);\n });\n };\n const View = root.ownerDocument.defaultView;\n const observer =\n View && 'MutationObserver' in View\n ? new View.MutationObserver(scheduleRove)\n : null;\n observer?.observe(root, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['tabindex', 'aria-selected', 'data-disabled'],\n });\n for (const grid of grids()) rove(grid);\n\n const focusin = (event: FocusEvent) => {\n const target = event.target;\n if (!(target instanceof Element)) return;\n const row = target.closest<HTMLElement>(MULTI_ROW_SELECTOR);\n const grid = row?.closest(MULTI_GRID_SELECTOR);\n if (!row || !grid || !root.contains(grid)) return;\n activeRows.set(grid, row);\n rove(grid);\n };\n\n let pendingSpace: {\n item: HTMLElement;\n modifiers: ActivationModifiers;\n } | null = null;\n\n const clearSpace = () => {\n pendingSpace?.item.removeAttribute('data-kui-pressed');\n pendingSpace = null;\n };\n\n const keydown = (event: KeyboardEvent) => {\n if (event.defaultPrevented || event.altKey) return;\n const item = actionItem(root, event);\n if (!item) return;\n const commandKey = event.ctrlKey || event.metaKey;\n if (\n !commandKey &&\n item.dataset.selectionMode === 'multiple' &&\n [\n 'ArrowDown',\n 'ArrowUp',\n 'ArrowLeft',\n 'ArrowRight',\n 'Home',\n 'End',\n ].includes(event.key)\n ) {\n const grid = item.closest(MULTI_GRID_SELECTOR);\n if (!grid) return;\n const rows = gridRows(grid);\n const index = rows.indexOf(item);\n if (index < 0) return;\n const isTileGrid = grid.getAttribute('data-component') === 'grid';\n let next: HTMLElement | undefined;\n switch (event.key) {\n case 'Home':\n next = rows[0];\n break;\n case 'End':\n next = rows[rows.length - 1];\n break;\n case 'ArrowDown':\n case 'ArrowUp':\n next = isTileGrid\n ? nextTile(item, rows, event.key)\n : rows[index + (event.key === 'ArrowDown' ? 1 : -1)];\n break;\n case 'ArrowLeft':\n case 'ArrowRight':\n next = isTileGrid ? nextTile(item, rows, event.key) : undefined;\n break;\n }\n if (next) {\n event.preventDefault();\n next.focus();\n }\n return;\n }\n if (event.key === 'Enter') {\n event.preventDefault();\n activate(item, event);\n return;\n }\n if (event.key === ' ' || event.key === 'Spacebar') {\n event.preventDefault();\n if (event.repeat) return;\n clearSpace();\n pendingSpace = {\n item,\n modifiers: {\n shiftKey: event.shiftKey,\n ctrlKey: event.ctrlKey,\n metaKey: event.metaKey,\n },\n };\n item.setAttribute('data-kui-pressed', 'true');\n }\n };\n\n const keyup = (event: KeyboardEvent) => {\n if (event.key !== ' ' && event.key !== 'Spacebar') return;\n if (!pendingSpace) return;\n const { item, modifiers } = pendingSpace;\n event.preventDefault();\n clearSpace();\n if (\n item === actionItem(root, event) &&\n item.ownerDocument.activeElement === item\n )\n activate(item, modifiers);\n };\n\n const focusout = (event: FocusEvent) => {\n if (event.target === pendingSpace?.item) clearSpace();\n };\n\n root.addEventListener('keydown', keydown);\n root.addEventListener('keyup', keyup);\n root.addEventListener('focusout', focusout);\n root.addEventListener('focusin', focusin);\n return () => {\n stopMedia();\n clearSpace();\n observer?.disconnect();\n root.removeEventListener('focusin', focusin);\n root.removeEventListener('keydown', keydown);\n root.removeEventListener('keyup', keyup);\n root.removeEventListener('focusout', focusout);\n };\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { DialogSurface } from './chunk-VGECEXM6.js';
2
- export { closeDialog, openDialog } from './chunk-ATGAJVZ6.js';
1
+ import { DialogSurface } from './chunk-S3DCRI2M.js';
2
+ export { closeDialog, openDialog } from './chunk-3OP66VXU.js';
3
3
 
4
4
  import { Workbench } from './chunk-YPAQFBMN.js';
5
5