@kerfjs/ui 5.0.0-beta.53 → 5.0.0-beta.55

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 (152) hide show
  1. package/README.md +4 -2
  2. package/ai/application-ui-diagnostic-ids-v1.json +1 -0
  3. package/ai/component-catalog-v2.json +138 -5
  4. package/ai/component-catalog-v2.schema.json +2 -1
  5. package/ai/component-catalog.json +208 -16
  6. package/ai/public-api-signatures-v1.md +462 -39
  7. package/ai/skill.md +28 -20
  8. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  9. package/analyzer/index.mjs +48 -0
  10. package/analyzer/loud-pairs.d.mts +49 -0
  11. package/analyzer/loud-pairs.mjs +357 -0
  12. package/dist/app-tab.d.ts +7 -5
  13. package/dist/app-tab.js +1 -1
  14. package/dist/browser/popup-menu.js +3 -0
  15. package/dist/catalog-resources.d.ts +1 -1
  16. package/dist/catalog.d.ts +10 -4
  17. package/dist/catalog.js +243 -300
  18. package/dist/catalog.js.map +1 -1
  19. package/dist/{chunk-7IUSV4XG.js → chunk-24PHKUR3.js} +2 -2
  20. package/dist/chunk-24PHKUR3.js.map +1 -0
  21. package/dist/{chunk-EKYZCRCX.js → chunk-3CGQ7ZNO.js} +54 -22
  22. package/dist/chunk-3CGQ7ZNO.js.map +1 -0
  23. package/dist/{chunk-UKKSMZYT.js → chunk-46263QLK.js} +51 -1
  24. package/dist/chunk-46263QLK.js.map +1 -0
  25. package/dist/chunk-4BIMLITI.js +92 -0
  26. package/dist/chunk-4BIMLITI.js.map +1 -0
  27. package/dist/{chunk-NDUGJ4TU.js → chunk-5NDQABWK.js} +1 -1
  28. package/dist/{chunk-NDUGJ4TU.js.map → chunk-5NDQABWK.js.map} +1 -1
  29. package/dist/{chunk-ZK5EGVFP.js → chunk-5OLVUEND.js} +12 -2
  30. package/dist/chunk-5OLVUEND.js.map +1 -0
  31. package/dist/{chunk-CMUIXJZM.js → chunk-BSKEH3UC.js} +2 -2
  32. package/dist/{chunk-CMUIXJZM.js.map → chunk-BSKEH3UC.js.map} +1 -1
  33. package/dist/chunk-EAX2GSS4.js +384 -0
  34. package/dist/chunk-EAX2GSS4.js.map +1 -0
  35. package/dist/chunk-KH6VUGHU.js +399 -0
  36. package/dist/chunk-KH6VUGHU.js.map +1 -0
  37. package/dist/{chunk-BJJKFVWW.js → chunk-LZXQVUGN.js} +2 -2
  38. package/dist/chunk-LZXQVUGN.js.map +1 -0
  39. package/dist/chunk-N7FHFNT6.js +55 -0
  40. package/dist/chunk-N7FHFNT6.js.map +1 -0
  41. package/dist/{chunk-CCMKJWLX.js → chunk-NE5JAOQS.js} +7 -7
  42. package/dist/chunk-NE5JAOQS.js.map +1 -0
  43. package/dist/chunk-PSHUSWQH.js +18 -0
  44. package/dist/chunk-PSHUSWQH.js.map +1 -0
  45. package/dist/{chunk-KPNTVB7A.js → chunk-R754MHXX.js} +3 -3
  46. package/dist/{chunk-KPNTVB7A.js.map → chunk-R754MHXX.js.map} +1 -1
  47. package/dist/{chunk-HJKRCKDR.js → chunk-RNRUVPJ3.js} +4 -2
  48. package/dist/chunk-RNRUVPJ3.js.map +1 -0
  49. package/dist/{chunk-VOCPXGQN.js → chunk-VHADGP3B.js} +9 -8
  50. package/dist/chunk-VHADGP3B.js.map +1 -0
  51. package/dist/chunk-XQV2B4IL.js +14 -0
  52. package/dist/chunk-XQV2B4IL.js.map +1 -0
  53. package/dist/collapsible-panel.d.ts +46 -15
  54. package/dist/collapsible-panel.js +42 -10
  55. package/dist/collapsible-panel.js.map +1 -1
  56. package/dist/floating-toolbar.d.ts +5 -2
  57. package/dist/floating-toolbar.js +1 -1
  58. package/dist/index.d.ts +1 -0
  59. package/dist/index.js +20 -18
  60. package/dist/list-header.js +1 -1
  61. package/dist/list-inset-text.d.ts +7 -1
  62. package/dist/list-inset-text.js +2 -1
  63. package/dist/panel-toolbar-BFQxFITu.d.ts +52 -0
  64. package/dist/popup-menu-register.d.ts +9 -0
  65. package/dist/popup-menu-register.js +30 -0
  66. package/dist/popup-menu-register.js.map +1 -0
  67. package/dist/popup-menu.d.ts +71 -0
  68. package/dist/popup-menu.js +3 -0
  69. package/dist/popup-menu.js.map +1 -0
  70. package/dist/resizable-region.d.ts +4 -1
  71. package/dist/resizable-region.js +1 -1
  72. package/dist/split-view.js +1 -1
  73. package/dist/state-banner.js +1 -1
  74. package/dist/styles/catalog/components/catalog-example.css +0 -16
  75. package/dist/styles/catalog/components/catalog-stage.css +8 -13
  76. package/dist/styles/catalog/components/catalog.css +8 -18
  77. package/dist/styles/catalog.css +0 -5
  78. package/dist/styles/collapsible-panel.css +88 -10
  79. package/dist/styles/floating-toolbar.css +11 -6
  80. package/dist/styles/popup-menu.css +12 -0
  81. package/dist/styles/resizable-region.css +81 -13
  82. package/dist/styles/state-banner.css +13 -4
  83. package/dist/styles/styles.css +1 -0
  84. package/dist/styles/tab-bar.css +31 -3
  85. package/dist/styles/toolbar-control-group.css +13 -0
  86. package/dist/styles/toolbar.css +43 -2
  87. package/dist/styles/workbench.css +503 -10
  88. package/dist/text.js +1 -1
  89. package/dist/token-search-field.d.ts +10 -1
  90. package/dist/token-search-field.js +1 -1
  91. package/dist/{types-CEsieBZi.d.ts → types-D6vzj-VT.d.ts} +15 -0
  92. package/dist/wire-catalog.d.ts +13 -1
  93. package/dist/wire-catalog.js +18 -3
  94. package/dist/wire-catalog.js.map +1 -1
  95. package/dist/wire-resizable-regions.d.ts +2 -1
  96. package/dist/wire-resizable-regions.js +2 -1
  97. package/dist/wire-sidebar.js +6 -3
  98. package/dist/wire-sidebar.js.map +1 -1
  99. package/dist/wire-tab-bars.js +1 -1
  100. package/dist/wire-token-search-fields.js +1 -1
  101. package/dist/wire-workbench.d.ts +109 -0
  102. package/dist/wire-workbench.js +6 -0
  103. package/dist/wire-workbench.js.map +1 -0
  104. package/dist/workbench.d.ts +166 -6
  105. package/dist/workbench.js +11 -104
  106. package/dist/workbench.js.map +1 -1
  107. package/docs/accessibility.md +66 -10
  108. package/docs/app-layouts.md +12 -1
  109. package/docs/catalog.md +27 -9
  110. package/docs/collapsible-panel.md +114 -1
  111. package/docs/component-contract.md +2 -2
  112. package/docs/component-selection.md +41 -23
  113. package/docs/design/templates/state-banner/danger-dark.svg +1 -1
  114. package/docs/design/templates/state-banner/danger.svg +1 -1
  115. package/docs/design/templates/state-banner/info-dark.svg +1 -1
  116. package/docs/design/templates/state-banner/info.svg +1 -1
  117. package/docs/design/templates/state-banner/success-dark.svg +1 -1
  118. package/docs/design/templates/state-banner/success.svg +1 -1
  119. package/docs/design/templates/state-banner/warning-dark.svg +1 -1
  120. package/docs/design/templates/state-banner/warning.svg +1 -1
  121. package/docs/design/templates/state-banner-dark.svg +1 -1
  122. package/docs/design/templates/state-banner.svg +1 -1
  123. package/docs/document-baseline.md +4 -0
  124. package/docs/layout.md +10 -1
  125. package/docs/recipes.md +48 -39
  126. package/docs/surface-scaffold.md +1 -1
  127. package/docs/type-contracts.md +2 -1
  128. package/docs/ui-analyzer.md +94 -19
  129. package/docs/ui-doctor.md +6 -0
  130. package/docs/ux-demo.md +7 -3
  131. package/docs/webawesome-theme.md +11 -2
  132. package/docs/workbench.md +388 -8
  133. package/llms.txt +13 -8
  134. package/package.json +17 -2
  135. package/ux-demo/recipes/app-shell.tsx +141 -223
  136. package/ux-demo/recipes/collapsible-sidebar.tsx +48 -78
  137. package/ux-demo/recipes/list-detail-dialog.tsx +150 -54
  138. package/ux-demo/recipes/mount-recipe.ts +0 -5
  139. package/ux-demo/recipes/types.ts +0 -1
  140. package/dist/chunk-7IUSV4XG.js.map +0 -1
  141. package/dist/chunk-BJJKFVWW.js.map +0 -1
  142. package/dist/chunk-CCMKJWLX.js.map +0 -1
  143. package/dist/chunk-EKYZCRCX.js.map +0 -1
  144. package/dist/chunk-HJKRCKDR.js.map +0 -1
  145. package/dist/chunk-UKKSMZYT.js.map +0 -1
  146. package/dist/chunk-VOCPXGQN.js.map +0 -1
  147. package/dist/chunk-ZK5EGVFP.js.map +0 -1
  148. package/dist/styles/catalog/components/catalog-detail.css +0 -35
  149. package/dist/styles/catalog/components/catalog-resource-footer.css +0 -37
  150. package/dist/styles/catalog/components/catalog-secondary-sections.css +0 -38
  151. package/dist/styles/catalog/components/catalog-section-list.css +0 -22
  152. package/dist/styles/catalog/components/catalog-sidebar.css +0 -82
@@ -1,5 +1,8 @@
1
1
  .kui-workbench {
2
2
  position: relative;
3
+ /* The rail and drawer overlays and the restore controls stack within the
4
+ Workbench, never against the page around it. */
5
+ isolation: isolate;
3
6
  display: flex;
4
7
  min-width: 0;
5
8
  min-height: 0;
@@ -39,6 +42,9 @@
39
42
  var(--kui-workbench-rail-width, 17.5rem) +
40
43
  var(--_kui-workbench-rail-safe-inset)
41
44
  );
45
+ /* The size is the whole track, separator border included, in or out of
46
+ flow and whatever box model the app defaults to. */
47
+ box-sizing: border-box;
42
48
  flex: 0 0 var(--_kui-workbench-rail-extent);
43
49
  min-width: 0;
44
50
  overflow: hidden;
@@ -69,7 +75,10 @@
69
75
  border-color: transparent;
70
76
  }
71
77
 
78
+ /* The center is the overlay drawer's containing block, so a drawer that
79
+ leaves the flow still covers exactly the work-area column it docks under. */
72
80
  .kui-workbench__center {
81
+ position: relative;
73
82
  --kui-edge-inset-block-start: var(--_kui-workbench-safe-block-start);
74
83
  --kui-edge-inset-block-end: var(--_kui-workbench-safe-block-end);
75
84
  --kui-edge-inset-inline-start: var(--_kui-workbench-safe-inline-start);
@@ -178,6 +187,20 @@
178
187
  --kui-edge-inset-inline-end: 0px;
179
188
  }
180
189
 
190
+ /* A region whose only child is a Pane or layout lets it fill the region, so a
191
+ composed toolbar's footer (or the app's own) sits at the region's bottom
192
+ edge rather than under short content. */
193
+ :is(.kui-workbench__main, .kui-workbench__panel-content)
194
+ > :is(
195
+ [data-component="pane"],
196
+ [data-component="nav-stack"],
197
+ [data-component="split-view"],
198
+ [data-component="workbench"],
199
+ [data-component="tab-scaffold"]
200
+ ):only-child {
201
+ height: 100%;
202
+ }
203
+
181
204
  /* Bottom drawer — the vertical analogue of a rail. */
182
205
  .kui-workbench__drawer {
183
206
  --kui-edge-inset-block-start: 0px;
@@ -185,6 +208,7 @@
185
208
  var(--kui-workbench-drawer-height, 13.75rem) +
186
209
  var(--_kui-workbench-safe-block-end)
187
210
  );
211
+ box-sizing: border-box;
188
212
  position: relative;
189
213
  flex: 0 0 var(--_kui-workbench-drawer-extent);
190
214
  min-height: 0;
@@ -253,16 +277,197 @@
253
277
  transform: translateY(100%);
254
278
  }
255
279
 
280
+ /* Opt-in resizable panels. The size lives in the resize wiring's track
281
+ property, which the wiring updates live during a drag, so the rail width or
282
+ drawer height follows it; collapsing leaves it alone, so the panel expands
283
+ back to the size it had. These rules precede the presentation rules below,
284
+ which must keep winning for overlay and hidden panels. */
285
+ .kui-workbench__rail[data-resizable="true"] {
286
+ --kui-workbench-rail-width: var(--kui-resizable-region-size);
287
+ position: relative;
288
+ }
289
+
290
+ .kui-workbench__drawer[data-resizable="true"] {
291
+ --kui-workbench-drawer-height: var(--kui-resizable-region-size);
292
+ }
293
+
294
+ /* The work area keeps a minimum width beside the rails (the Workbench's
295
+ `mainMinSize`) and a minimum height above the drawer (`mainMinHeight`),
296
+ never larger than the Workbench itself. Inline panels, fixed or resizable,
297
+ give way instead: when the container narrows the rails shrink in proportion
298
+ to their sizes, when it gets shorter the drawer shrinks, and their content
299
+ follows the shown size. The wiring stops a resize where the work area would
300
+ drop below the minimum. */
301
+ .kui-workbench[data-main-min-size] > .kui-workbench__center {
302
+ min-width: min(var(--_kui-workbench-main-min-width), 100%);
303
+ }
304
+
305
+ .kui-workbench[data-main-min-height]
306
+ > .kui-workbench__center
307
+ > .kui-workbench__main {
308
+ min-height: min(var(--_kui-workbench-main-min-height), 100%);
309
+ }
310
+
311
+ .kui-workbench__rail[data-presentation="inline"]:not([data-collapsed="true"]),
312
+ .kui-workbench__drawer[data-presentation="inline"]:not(
313
+ [data-collapsed="true"]
314
+ ) {
315
+ flex-shrink: 1;
316
+ }
317
+
318
+ /* Low specificity, so a responsive overlay (below) restores the fixed size. */
319
+ .kui-workbench__rail:where(
320
+ [data-presentation="inline"]:not([data-collapsed="true"])
321
+ )
322
+ > .kui-workbench__panel-content {
323
+ width: 100%;
324
+ }
325
+
326
+ .kui-workbench__drawer:where(
327
+ [data-presentation="inline"]:not([data-collapsed="true"])
328
+ )
329
+ > .kui-workbench__panel-content {
330
+ height: 100%;
331
+ }
332
+
333
+ /* The panel clips its sliding content, so a scrolling panel scrolls its
334
+ content box instead of itself: the separator handle is a child of the panel
335
+ and must not scroll away with the content. */
336
+ .kui-workbench__rail[data-resizable="true"][data-content-overflow="auto"],
337
+ .kui-workbench__drawer[data-resizable="true"][data-content-overflow="auto"] {
338
+ overflow: hidden;
339
+ }
340
+
341
+ .kui-workbench__rail[data-resizable="true"][data-content-overflow="auto"]
342
+ > .kui-workbench__panel-content,
343
+ .kui-workbench__drawer[data-resizable="true"][data-content-overflow="auto"]
344
+ > .kui-workbench__panel-content {
345
+ overflow: auto;
346
+ }
347
+
348
+ /* The separator handle: the 20px hit target and dormant grip a
349
+ ResizableRegion handle has. The panel's own border stays the visible
350
+ separator line. By default the target sits wholly inside the panel, at its
351
+ inner edge, because the panel clips its sliding content. */
352
+ .kui-workbench__handle {
353
+ position: absolute;
354
+ z-index: 3;
355
+ display: grid;
356
+ color: var(--kui-color-neutral-on-quiet);
357
+ place-items: center;
358
+ touch-action: none;
359
+ }
360
+
361
+ .kui-workbench__rail > .kui-workbench__handle {
362
+ inset-block: 0;
363
+ width: 20px;
364
+ cursor: col-resize;
365
+ }
366
+
367
+ .kui-workbench__rail--left > .kui-workbench__handle {
368
+ inset-inline-end: 0;
369
+ }
370
+
371
+ .kui-workbench__rail--right > .kui-workbench__handle {
372
+ inset-inline-start: 0;
373
+ }
374
+
375
+ .kui-workbench__drawer > .kui-workbench__handle {
376
+ inset-inline: 0;
377
+ inset-block-start: 0;
378
+ height: 20px;
379
+ cursor: row-resize;
380
+ }
381
+
382
+ .kui-workbench__rail[data-collapsed="true"] > .kui-workbench__handle,
383
+ .kui-workbench__drawer[data-collapsed="true"] > .kui-workbench__handle,
384
+ .kui-workbench__rail:not([data-presentation="inline"]) > .kui-workbench__handle,
385
+ .kui-workbench__drawer:not([data-presentation="inline"])
386
+ > .kui-workbench__handle {
387
+ display: none;
388
+ }
389
+
390
+ /* Where the engine can extend a clip past the panel's edge, an expanded
391
+ panel lets exactly the handle's outer half through, so the hit target
392
+ straddles the separator like a ResizableRegion handle does. Collapsing drops
393
+ the margin again before the content slides out. */
394
+ @supports (overflow-clip-margin: 10px) {
395
+ .kui-workbench__rail[data-resizable="true"]:not(
396
+ [data-collapsed="true"],
397
+ [data-content-overflow="visible"]
398
+ ),
399
+ .kui-workbench__drawer[data-resizable="true"]:not(
400
+ [data-collapsed="true"],
401
+ [data-content-overflow="visible"]
402
+ ) {
403
+ overflow: clip;
404
+ overflow-clip-margin: 10px;
405
+ }
406
+
407
+ .kui-workbench__rail--left[data-resizable="true"] > .kui-workbench__handle {
408
+ inset-inline-end: -10px;
409
+ }
410
+
411
+ .kui-workbench__rail--right[data-resizable="true"] > .kui-workbench__handle {
412
+ inset-inline-start: -10px;
413
+ }
414
+
415
+ .kui-workbench__drawer[data-resizable="true"] > .kui-workbench__handle {
416
+ inset-block-start: -10px;
417
+ }
418
+ }
419
+
420
+ .kui-workbench__handle:hover,
421
+ .kui-workbench__handle:focus-visible {
422
+ color: var(--kui-color-text-link);
423
+ }
424
+
425
+ /* The ring stays wholly inside the handle's box, as a ResizableRegion
426
+ handle's does. */
427
+ .kui-workbench__handle:focus-visible {
428
+ border-radius: var(--kui-radius-s);
429
+ outline: var(--kui-focus-ring);
430
+ outline-offset: -3px;
431
+ }
432
+
433
+ .kui-workbench__handle-icon {
434
+ position: relative;
435
+ display: grid;
436
+ width: 0.9rem;
437
+ height: 0.9rem;
438
+ opacity: 0;
439
+ pointer-events: none;
440
+ place-items: center;
441
+ }
442
+
443
+ .kui-workbench__handle-icon > svg {
444
+ width: 100%;
445
+ height: 100%;
446
+ }
447
+
448
+ .kui-workbench__handle:hover .kui-workbench__handle-icon,
449
+ .kui-workbench__handle:focus-visible .kui-workbench__handle-icon {
450
+ opacity: 1;
451
+ }
452
+
453
+ /* Overlay stacking order: both rails stack above the bottom drawer, one below
454
+ the overlay z-index, as inline rails span the Workbench's full height beside
455
+ the drawer's column; the right rail stacks above the left (document order).
456
+ Restore controls stack below every overlay (see .kui-workbench__restore). */
256
457
  .kui-workbench__rail[data-presentation="overlay"],
257
458
  .kui-workbench__drawer[data-presentation="overlay"] {
258
459
  position: absolute;
259
460
  z-index: var(--kui-workbench-overlay-z, 41);
260
- max-width: var(--kui-workbench-overlay-max-width, 85vw);
261
- max-height: var(--kui-workbench-overlay-max-height, 85vh);
262
461
  box-shadow: var(--kui-shadow-l);
263
462
  }
264
463
 
464
+ /* An out-of-flow rail sizes to its content plus its border, so it takes its
465
+ extent explicitly, as its in-flow flex basis does, border included. Each
466
+ overlay maximum caps only the panel's own axis: a rail spans the
467
+ Workbench's full height and a drawer its full width. */
265
468
  .kui-workbench__rail[data-presentation="overlay"] {
469
+ width: var(--_kui-workbench-rail-extent);
470
+ max-width: var(--kui-workbench-overlay-max-width, 85vw);
266
471
  inset-block: 0;
267
472
  }
268
473
 
@@ -274,41 +479,312 @@
274
479
  inset-inline-end: 0;
275
480
  }
276
481
 
482
+ /* The drawer's content is absolutely positioned against its bottom edge, so
483
+ an out-of-flow drawer has no content height of its own: it takes its extent
484
+ explicitly, as the in-flow track does through its flex basis. */
277
485
  .kui-workbench__drawer[data-presentation="overlay"] {
486
+ z-index: calc(var(--kui-workbench-overlay-z, 41) - 1);
487
+ height: var(--_kui-workbench-drawer-extent);
488
+ max-height: var(--kui-workbench-overlay-max-height, 85vh);
278
489
  inset-inline: 0;
279
490
  inset-block-end: 0;
280
491
  }
281
492
 
493
+ /* A collapsed overlay keeps its box for the slide-out, so it drops its surface
494
+ and shadow; the sliding content carries the surface instead. */
282
495
  .kui-workbench__rail[data-presentation="overlay"][data-collapsed="true"],
283
496
  .kui-workbench__drawer[data-presentation="overlay"][data-collapsed="true"] {
497
+ background: transparent;
498
+ box-shadow: none;
284
499
  pointer-events: none;
285
500
  }
286
501
 
502
+ /* Overlay content fills the rail inside its separator border, so it is
503
+ clamped with the rail and carries the surface through the slide-out. */
504
+ .kui-workbench__rail[data-presentation="overlay"]
505
+ > .kui-workbench__panel-content {
506
+ width: 100%;
507
+ background: var(--kui-color-surface);
508
+ }
509
+
510
+ /* The overlay content fills the drawer box below its separator border, so it
511
+ is clamped with the box and carries the surface through the slide-out. */
512
+ .kui-workbench__drawer[data-presentation="overlay"]
513
+ > .kui-workbench__panel-content {
514
+ height: 100%;
515
+ background: var(--kui-color-surface);
516
+ }
517
+
287
518
  .kui-workbench__rail[data-presentation="hidden"],
288
519
  .kui-workbench__drawer[data-presentation="hidden"] {
289
520
  display: none;
290
521
  }
291
522
 
523
+ /* Responsive overlay panels. A rail or the drawer with `responsiveOverlayAt`
524
+ presents as an overlay — out of flow, over the work area, without a
525
+ separator — below the Workbench's own container breakpoint (`narrow`: 704px
526
+ or less, `compact`: 448px or less, as `ResizableRegion`'s
527
+ `responsiveFillAt`), and inline above it. The Workbench becomes a named
528
+ inline-size container only when a panel opts in. The work area keeps its
529
+ safe-area inset under an overlay panel. */
530
+ .kui-workbench:has(
531
+ > .kui-workbench__rail[data-responsive-overlay-at],
532
+ > .kui-workbench__center > .kui-workbench__drawer[data-responsive-overlay-at]
533
+ ) {
534
+ container: kui-workbench / inline-size;
535
+ }
536
+
537
+ @container kui-workbench (max-width: 44rem) {
538
+ .kui-workbench__rail[data-responsive-overlay-at="narrow"] {
539
+ position: absolute;
540
+ z-index: var(--kui-workbench-overlay-z, 41);
541
+ width: var(--_kui-workbench-rail-extent);
542
+ max-width: var(--kui-workbench-overlay-max-width, 85vw);
543
+ inset-block: 0;
544
+ box-shadow: var(--kui-shadow-l);
545
+ }
546
+
547
+ .kui-workbench__rail--left[data-responsive-overlay-at="narrow"] {
548
+ inset-inline-start: 0;
549
+ }
550
+
551
+ .kui-workbench__rail--right[data-responsive-overlay-at="narrow"] {
552
+ inset-inline-end: 0;
553
+ }
554
+
555
+ .kui-workbench__rail[data-responsive-overlay-at="narrow"][data-collapsed="true"] {
556
+ background: transparent;
557
+ box-shadow: none;
558
+ pointer-events: none;
559
+ }
560
+
561
+ .kui-workbench__rail[data-responsive-overlay-at="narrow"]
562
+ > .kui-workbench__panel-content {
563
+ width: 100%;
564
+ background: var(--kui-color-surface);
565
+ }
566
+
567
+ .kui-workbench__rail[data-responsive-overlay-at="narrow"]
568
+ > .kui-workbench__handle {
569
+ display: none;
570
+ }
571
+
572
+ .kui-workbench:has(
573
+ > .kui-workbench__rail--left[data-responsive-overlay-at="narrow"][data-presentation="inline"]
574
+ )
575
+ > .kui-workbench__center {
576
+ --kui-edge-inset-inline-start: var(--_kui-workbench-safe-inline-start);
577
+ }
578
+
579
+ .kui-workbench:has(
580
+ > .kui-workbench__rail--right[data-responsive-overlay-at="narrow"][data-presentation="inline"]
581
+ )
582
+ > .kui-workbench__center {
583
+ --kui-edge-inset-inline-end: var(--_kui-workbench-safe-inline-end);
584
+ }
585
+
586
+ .kui-workbench__drawer[data-responsive-overlay-at="narrow"] {
587
+ position: absolute;
588
+ anchor-name: none;
589
+ z-index: calc(var(--kui-workbench-overlay-z, 41) - 1);
590
+ height: var(--_kui-workbench-drawer-extent);
591
+ max-height: var(--kui-workbench-overlay-max-height, 85vh);
592
+ inset-inline: 0;
593
+ inset-block-end: 0;
594
+ box-shadow: var(--kui-shadow-l);
595
+ }
596
+
597
+ .kui-workbench__drawer[data-responsive-overlay-at="narrow"][data-collapsed="true"] {
598
+ background: transparent;
599
+ box-shadow: none;
600
+ pointer-events: none;
601
+ }
602
+
603
+ .kui-workbench__drawer[data-responsive-overlay-at="narrow"]
604
+ > .kui-workbench__panel-content {
605
+ height: 100%;
606
+ background: var(--kui-color-surface);
607
+ }
608
+
609
+ .kui-workbench__drawer[data-responsive-overlay-at="narrow"]
610
+ > .kui-workbench__handle {
611
+ display: none;
612
+ }
613
+
614
+ .kui-workbench__main:has(
615
+ ~ .kui-workbench__drawer[data-responsive-overlay-at="narrow"][data-presentation="inline"]
616
+ ) {
617
+ --kui-edge-inset-block-end: var(--_kui-workbench-safe-block-end);
618
+ }
619
+ }
620
+
621
+ @container kui-workbench (max-width: 28rem) {
622
+ .kui-workbench__rail[data-responsive-overlay-at="compact"] {
623
+ position: absolute;
624
+ z-index: var(--kui-workbench-overlay-z, 41);
625
+ width: var(--_kui-workbench-rail-extent);
626
+ max-width: var(--kui-workbench-overlay-max-width, 85vw);
627
+ inset-block: 0;
628
+ box-shadow: var(--kui-shadow-l);
629
+ }
630
+
631
+ .kui-workbench__rail--left[data-responsive-overlay-at="compact"] {
632
+ inset-inline-start: 0;
633
+ }
634
+
635
+ .kui-workbench__rail--right[data-responsive-overlay-at="compact"] {
636
+ inset-inline-end: 0;
637
+ }
638
+
639
+ .kui-workbench__rail[data-responsive-overlay-at="compact"][data-collapsed="true"] {
640
+ background: transparent;
641
+ box-shadow: none;
642
+ pointer-events: none;
643
+ }
644
+
645
+ .kui-workbench__rail[data-responsive-overlay-at="compact"]
646
+ > .kui-workbench__panel-content {
647
+ width: 100%;
648
+ background: var(--kui-color-surface);
649
+ }
650
+
651
+ .kui-workbench__rail[data-responsive-overlay-at="compact"]
652
+ > .kui-workbench__handle {
653
+ display: none;
654
+ }
655
+
656
+ .kui-workbench:has(
657
+ > .kui-workbench__rail--left[data-responsive-overlay-at="compact"][data-presentation="inline"]
658
+ )
659
+ > .kui-workbench__center {
660
+ --kui-edge-inset-inline-start: var(--_kui-workbench-safe-inline-start);
661
+ }
662
+
663
+ .kui-workbench:has(
664
+ > .kui-workbench__rail--right[data-responsive-overlay-at="compact"][data-presentation="inline"]
665
+ )
666
+ > .kui-workbench__center {
667
+ --kui-edge-inset-inline-end: var(--_kui-workbench-safe-inline-end);
668
+ }
669
+
670
+ .kui-workbench__drawer[data-responsive-overlay-at="compact"] {
671
+ position: absolute;
672
+ anchor-name: none;
673
+ z-index: calc(var(--kui-workbench-overlay-z, 41) - 1);
674
+ height: var(--_kui-workbench-drawer-extent);
675
+ max-height: var(--kui-workbench-overlay-max-height, 85vh);
676
+ inset-inline: 0;
677
+ inset-block-end: 0;
678
+ box-shadow: var(--kui-shadow-l);
679
+ }
680
+
681
+ .kui-workbench__drawer[data-responsive-overlay-at="compact"][data-collapsed="true"] {
682
+ background: transparent;
683
+ box-shadow: none;
684
+ pointer-events: none;
685
+ }
686
+
687
+ .kui-workbench__drawer[data-responsive-overlay-at="compact"]
688
+ > .kui-workbench__panel-content {
689
+ height: 100%;
690
+ background: var(--kui-color-surface);
691
+ }
692
+
693
+ .kui-workbench__drawer[data-responsive-overlay-at="compact"]
694
+ > .kui-workbench__handle {
695
+ display: none;
696
+ }
697
+
698
+ .kui-workbench__main:has(
699
+ ~ .kui-workbench__drawer[data-responsive-overlay-at="compact"][data-presentation="inline"]
700
+ ) {
701
+ --kui-edge-inset-block-end: var(--_kui-workbench-safe-block-end);
702
+ }
703
+ }
704
+
705
+ /* A collapsed panel's restore control floats in a corner of the Workbench
706
+ itself, never of the viewport, so an embedded Workbench cannot float it over
707
+ page chrome outside it. It is inset from the corner plus the unsafe area of
708
+ each edge that corner reaches. The drawer's control sits in the work-area
709
+ column it restores (the center is its containing block), inset from the
710
+ edges that column still reaches, so it never lands on an expanded rail.
711
+ It belongs to the layer beneath the overlays, two below the overlay
712
+ z-index: an open overlay covers it as it covers the rest of the work area,
713
+ so no other panel's control floats over the overlay's content. A collapsed
714
+ overlay drops its pointer events, so the control stays usable beneath it. */
292
715
  .kui-workbench__restore {
293
- position: fixed;
294
- z-index: var(--kui-workbench-restore-z, 42);
716
+ --_kui-workbench-restore-inset: var(
717
+ --kui-workbench-restore-inset,
718
+ 1rem
719
+ );
720
+ /* The corner owns the inset, so a FloatingToolbar composed here floats
721
+ from this point instead of adding its own inset on top. */
722
+ --kui-floating-toolbar-inset: 0px;
723
+ position: absolute;
724
+ z-index: var(
725
+ --kui-workbench-restore-z,
726
+ calc(var(--kui-workbench-overlay-z, 41) - 2)
727
+ );
295
728
  inset-block-end: calc(
296
- var(--kui-workbench-restore-inset, 1rem) +
297
- var(--kui-safe-area-block-end, env(safe-area-inset-bottom, 0px))
729
+ var(--_kui-workbench-restore-inset) + var(--_kui-workbench-safe-block-end)
298
730
  );
299
731
  }
300
732
 
301
733
  .kui-workbench__restore[data-position="bottom-start"] {
302
734
  inset-inline-start: calc(
303
- var(--kui-workbench-restore-inset, 1rem) +
304
- var(--kui-safe-area-inline-start, env(safe-area-inset-left, 0px))
735
+ var(--_kui-workbench-restore-inset) +
736
+ var(--_kui-workbench-safe-inline-start)
305
737
  );
306
738
  }
307
739
 
308
740
  .kui-workbench__restore[data-position="bottom-end"] {
309
741
  inset-inline-end: calc(
310
- var(--kui-workbench-restore-inset, 1rem) +
311
- var(--kui-safe-area-inline-end, env(safe-area-inset-right, 0px))
742
+ var(--_kui-workbench-restore-inset) + var(--_kui-workbench-safe-inline-end)
743
+ );
744
+ }
745
+
746
+ /* An expanded inline bottom drawer owns the bottom of the work-area column,
747
+ which reaches the Workbench's bottom corners once a rail collapses, so a
748
+ collapsed rail's control floats the restore inset above the drawer's top
749
+ edge instead of over it — the standalone CollapsiblePanel rule, scoped to
750
+ this Workbench so a nested Workbench or an enclosing layout never sees its
751
+ drawer. The drawer publishes that edge only while it is expanded and in
752
+ flow: an overlay drawer, static or responsive (see the container queries
753
+ above), covers the control as every open overlay does. Without anchor
754
+ positioning the control keeps the Workbench corner. */
755
+ .kui-workbench {
756
+ anchor-scope: --kui-restore-drawer;
757
+ }
758
+
759
+ .kui-workbench__drawer:where(
760
+ [data-presentation="inline"]:not([data-collapsed="true"])
761
+ ) {
762
+ anchor-name: --kui-restore-drawer;
763
+ }
764
+
765
+ .kui-workbench > .kui-workbench__restore {
766
+ position-visibility: always;
767
+ inset-block-end: calc(
768
+ var(--_kui-workbench-restore-inset) +
769
+ anchor(--kui-restore-drawer top, var(--_kui-workbench-safe-block-end))
770
+ );
771
+ }
772
+
773
+ .kui-workbench__center > .kui-workbench__restore {
774
+ inset-block-end: calc(
775
+ var(--_kui-workbench-restore-inset) + var(--kui-edge-inset-block-end)
776
+ );
777
+ }
778
+
779
+ .kui-workbench__center > .kui-workbench__restore[data-position="bottom-start"] {
780
+ inset-inline-start: calc(
781
+ var(--_kui-workbench-restore-inset) + var(--kui-edge-inset-inline-start)
782
+ );
783
+ }
784
+
785
+ .kui-workbench__center > .kui-workbench__restore[data-position="bottom-end"] {
786
+ inset-inline-end: calc(
787
+ var(--_kui-workbench-restore-inset) + var(--kui-edge-inset-inline-end)
312
788
  );
313
789
  }
314
790
 
@@ -317,3 +793,20 @@
317
793
  transition: none;
318
794
  }
319
795
  }
796
+
797
+ /* On a compact (phone-sized) Workbench an overlay rail fills the Workbench
798
+ less a dismiss margin on the side away from its edge, so a press beside it
799
+ closes it (the wiring's outside press); `compactOverlay: "full"` fills the
800
+ Workbench. The rail's resize and configured size stop applying there. */
801
+ @container kui-workbench (max-width: 28rem) {
802
+ .kui-workbench__rail[data-responsive-overlay-at] {
803
+ width: calc(
804
+ 100% - var(--kui-workbench-overlay-dismiss-margin, 2.75rem)
805
+ );
806
+ max-width: none;
807
+ }
808
+
809
+ .kui-workbench__rail[data-responsive-overlay-at][data-compact-overlay="full"] {
810
+ width: 100%;
811
+ }
812
+ }
package/dist/text.js CHANGED
@@ -1,3 +1,3 @@
1
- export { Text } from './chunk-7IUSV4XG.js';
1
+ export { Text } from './chunk-24PHKUR3.js';
2
2
 
3
3
  //# sourceMappingURL=text.js.map
@@ -20,6 +20,15 @@ interface TokenSearchFieldBaseProps {
20
20
  label: string;
21
21
  query?: string;
22
22
  tokens?: readonly TokenSearchToken[];
23
+ /**
24
+ * Editor identity for a programmatic text replacement. The editor's text is
25
+ * DOM-owned between token changes, so a new `query` with the same tokens
26
+ * does not re-render it (that would reset the caret on every keystroke).
27
+ * Change `revision` when the app replaces the text itself — reseeding a
28
+ * persistent dialog's field on reopen, applying a saved search — and the
29
+ * editor is rebuilt from `query` and `tokens`.
30
+ */
31
+ revision?: string | number;
23
32
  placeholder?: string;
24
33
  tokenPlaceholder?: string;
25
34
  disabled?: boolean;
@@ -55,7 +64,7 @@ interface TokenSearchFieldValue {
55
64
  query: string;
56
65
  tokens: TokenSearchToken[];
57
66
  }
58
- declare function TokenSearchField({ id, label, query, tokens, placeholder, tokenPlaceholder, disabled, autofocus, collapsible, expanded, expandAction, expandLabel, leading, trailing, presentation, editAction, removeAction, clearAction, clearLabel, className, editorAttributes, slot, }: TokenSearchFieldProps): kerfjs.SafeHtml;
67
+ declare function TokenSearchField({ id, label, query, tokens, revision, placeholder, tokenPlaceholder, disabled, autofocus, collapsible, expanded, expandAction, expandLabel, leading, trailing, presentation, editAction, removeAction, clearAction, clearLabel, className, editorAttributes, slot, }: TokenSearchFieldProps): kerfjs.SafeHtml;
59
68
  /** Read editable text and ordered token offsets from a rendered TokenSearchField editor. */
60
69
  declare function readTokenSearchField(editor: HTMLElement, knownTokens?: readonly TokenSearchToken[]): TokenSearchFieldValue;
61
70
  /** Focus an editor and place its caret at a text offset, skipping atomic token chips. */
@@ -1,4 +1,4 @@
1
- export { TokenSearchField, placeTokenSearchCaret, readTokenSearchField } from './chunk-HJKRCKDR.js';
1
+ export { TokenSearchField, placeTokenSearchCaret, readTokenSearchField } from './chunk-RNRUVPJ3.js';
2
2
 
3
3
 
4
4
  //# sourceMappingURL=token-search-field.js.map
@@ -44,6 +44,11 @@ type CatalogStageRootAttributes = Readonly<Record<`data-${string}`, string | und
44
44
  'data-catalog-stage'?: never;
45
45
  }>;
46
46
  interface CatalogProps {
47
+ /**
48
+ * The catalog's `id` (default `kui-catalog`). Its Workbench derives the
49
+ * sidebar's id from it (`<id>-left-rail`), which `wireCatalog` wires.
50
+ */
51
+ id?: string;
47
52
  brand: CatalogBrand;
48
53
  sections: readonly CatalogSection[];
49
54
  active: string;
@@ -61,6 +66,16 @@ interface CatalogProps {
61
66
  toggleSidebarAction?: string;
62
67
  toggleThemeAction?: string;
63
68
  toggleSecondaryAction?: string;
69
+ /**
70
+ * Whether the entry toolbar stays pinned above the preview (`fixed`,
71
+ * default) or scrolls away with it (`scroll`).
72
+ */
73
+ headerPlacement?: 'fixed' | 'scroll';
74
+ /**
75
+ * Whether the status and resource footer stays pinned below the preview
76
+ * (`fixed`, default) or scrolls with it (`scroll`).
77
+ */
78
+ footerPlacement?: 'fixed' | 'scroll';
64
79
  className?: string;
65
80
  /** Native named-slot assignment when composed inside a web component. */
66
81
  slot?: string;
@@ -1,3 +1,5 @@
1
+ import { Signal } from 'kerfjs';
2
+
1
3
  interface WireCatalogOptions {
2
4
  /** Invoked with the entry id when a sidebar item or a related-entry option is chosen. */
3
5
  onSelect: (id: string) => void;
@@ -18,6 +20,16 @@ interface WireCatalogOptions {
18
20
  toggleSidebarAction?: string;
19
21
  toggleThemeAction?: string;
20
22
  toggleSecondaryAction?: string;
23
+ /**
24
+ * The sidebar's app-owned collapsed flag. With it, the catalog's Workbench
25
+ * sidebar is wired like any Workbench rail: it becomes a transient overlay
26
+ * on a small screen (collapsed as the breakpoint applies, closed on Escape
27
+ * or a press outside, focus handed back), and choosing an entry from the
28
+ * open overlay closes it.
29
+ */
30
+ collapsed?: Signal<boolean>;
31
+ /** The Catalog's `id`, when it is not the default `kui-catalog`. */
32
+ id?: string;
21
33
  }
22
34
  interface CatalogRevealOptions {
23
35
  /** Scroll alignment within the sidebar. Default `'nearest'`. */
@@ -52,6 +64,6 @@ declare function wireCatalogGeometryOverlay(root: HTMLElement): () => void;
52
64
  * them in the callbacks; optionally mirror the active id into the URL via `urlParam`.
53
65
  * Returns a disposer.
54
66
  */
55
- declare function wireCatalog(root: HTMLElement, { onSelect, onToggleSidebar, onToggleTheme, onToggleSecondary, urlParam, revealSelection, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, }: WireCatalogOptions): () => void;
67
+ declare function wireCatalog(root: HTMLElement, { onSelect, onToggleSidebar, onToggleTheme, onToggleSecondary, urlParam, revealSelection, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, collapsed, id: catalogId, }: WireCatalogOptions): () => void;
56
68
 
57
69
  export { type CatalogRevealOptions, type WireCatalogOptions, revealCatalogEntry, wireCatalog, wireCatalogGeometryOverlay };