@kerfjs/ui 5.0.0-beta.100 → 5.0.0-beta.101
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.
- package/README.md +3 -1
- package/ai/component-catalog.json +214 -18
- package/ai/component-composition.json +216 -8
- package/ai/components/README.md +2 -0
- package/ai/components/backdrop-image.md +84 -0
- package/ai/components/nav-stack.md +6 -1
- package/ai/components/pane.md +11 -1
- package/ai/components/recipe-media-detail.md +57 -0
- package/ai/components/surface-scaffold.md +13 -6
- package/ai/components/tab-navigator.md +6 -1
- package/ai/components/toolbar-control-group.md +1 -0
- package/ai/public-api-signatures-v1.md +356 -32
- package/ai/skill.md +53 -5
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/dist/backdrop-image.d.ts +132 -0
- package/dist/backdrop-image.js +5 -0
- package/dist/backdrop-image.js.map +1 -0
- package/dist/browser/backdrop-image.js +3 -0
- package/dist/catalog-resources.d.ts +2 -2
- package/dist/catalog.d.ts +2 -2
- package/dist/catalog.js +10 -9
- package/dist/catalog.js.map +1 -1
- package/dist/{chunk-QIG4IGUP.js → chunk-2PXZBFEC.js} +3 -1
- package/dist/chunk-2PXZBFEC.js.map +1 -0
- package/dist/{chunk-T4WJ5VGP.js → chunk-3SKAEPPZ.js} +2 -2
- package/dist/{chunk-T4WJ5VGP.js.map → chunk-3SKAEPPZ.js.map} +1 -1
- package/dist/chunk-5NQF35VO.js +67 -0
- package/dist/chunk-5NQF35VO.js.map +1 -0
- package/dist/{chunk-CMETHPKR.js → chunk-6E2H2E5A.js} +29 -8
- package/dist/chunk-6E2H2E5A.js.map +1 -0
- package/dist/{chunk-PIVY32AE.js → chunk-BYFTHA4I.js} +16 -3
- package/dist/chunk-BYFTHA4I.js.map +1 -0
- package/dist/{chunk-HGV7J4T6.js → chunk-EKHDLBRP.js} +1 -1
- package/dist/chunk-EKHDLBRP.js.map +1 -0
- package/dist/{chunk-QROYYGWU.js → chunk-FNZQOUZ5.js} +2 -2
- package/dist/{chunk-QROYYGWU.js.map → chunk-FNZQOUZ5.js.map} +1 -1
- package/dist/{chunk-EOO6PYGF.js → chunk-IXLUZHGT.js} +4 -4
- package/dist/{chunk-EOO6PYGF.js.map → chunk-IXLUZHGT.js.map} +1 -1
- package/dist/{chunk-UMKV7YVQ.js → chunk-LPHU44S3.js} +5 -1
- package/dist/chunk-LPHU44S3.js.map +1 -0
- package/dist/{chunk-INI4WDWC.js → chunk-M5KZ26VV.js} +27 -4
- package/dist/chunk-M5KZ26VV.js.map +1 -0
- package/dist/{chunk-TLMMFQWM.js → chunk-NS762OVM.js} +3 -3
- package/dist/{chunk-TLMMFQWM.js.map → chunk-NS762OVM.js.map} +1 -1
- package/dist/{chunk-CXZXHZTR.js → chunk-OZ6X76G5.js} +34 -1
- package/dist/chunk-OZ6X76G5.js.map +1 -0
- package/dist/{chunk-YOA5W5ZH.js → chunk-PKL6QJKK.js} +31 -3
- package/dist/chunk-PKL6QJKK.js.map +1 -0
- package/dist/chunk-QTSMHH5J.js +85 -0
- package/dist/chunk-QTSMHH5J.js.map +1 -0
- package/dist/chunk-SCDWURBO.js +136 -0
- package/dist/chunk-SCDWURBO.js.map +1 -0
- package/dist/{chunk-RHD7RKGI.js → chunk-SIW64V65.js} +3 -3
- package/dist/{chunk-RHD7RKGI.js.map → chunk-SIW64V65.js.map} +1 -1
- package/dist/chunk-SQ5DH66U.js +37 -0
- package/dist/chunk-SQ5DH66U.js.map +1 -0
- package/dist/{chunk-PYBBYSZ3.js → chunk-YBWQR2OK.js} +5 -5
- package/dist/{chunk-PYBBYSZ3.js.map → chunk-YBWQR2OK.js.map} +1 -1
- package/dist/{chunk-3GLYIIFR.js → chunk-ZYU5WRC3.js} +2 -2
- package/dist/{chunk-3GLYIIFR.js.map → chunk-ZYU5WRC3.js.map} +1 -1
- package/dist/collapsible-panel.js +3 -2
- package/dist/collapsible-panel.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +24 -20
- package/dist/list-action-row.js +1 -1
- package/dist/list-header.js +1 -1
- package/dist/list-item.js +1 -1
- package/dist/{nav-stack-VXTumzKa.d.ts → nav-stack-CU_0dKtI.d.ts} +41 -5
- package/dist/nav-stack.d.ts +4 -4
- package/dist/nav-stack.js +2 -1
- package/dist/pane.d.ts +76 -4
- package/dist/pane.js +2 -1
- package/dist/select.js +1 -1
- package/dist/split-view.d.ts +4 -4
- package/dist/split-view.js +3 -2
- package/dist/split-view.js.map +1 -1
- package/dist/state-banner.js +1 -1
- package/dist/styles/backdrop-image.css +241 -0
- package/dist/styles/components/actions/toolbar/toolbar.css +9 -0
- package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +128 -0
- package/dist/styles/components/layout/pane/pane.css +121 -1
- package/dist/styles/components/navigation/nav-stack/nav-stack.css +207 -6
- package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +121 -3
- package/dist/styles/components/surfaces/backdrop-image/backdrop-image.css +241 -0
- package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +166 -2
- package/dist/styles/foundation.css +165 -8
- package/dist/styles/nav-stack.css +207 -6
- package/dist/styles/overlay-sheet.css +211 -0
- package/dist/styles/pane.css +121 -1
- package/dist/styles/styles.css +1 -0
- package/dist/styles/surface-scaffold.css +166 -2
- package/dist/styles/tab-navigator.css +121 -3
- package/dist/styles/toolbar-control-group.css +128 -0
- package/dist/styles/toolbar.css +9 -0
- package/dist/styles/webawesome.css +10 -0
- package/dist/surface-scaffold-register.d.ts +3 -2
- package/dist/surface-scaffold-register.js +113 -10
- package/dist/surface-scaffold-register.js.map +1 -1
- package/dist/surface-scaffold.d.ts +38 -5
- package/dist/surface-scaffold.js +1 -1
- package/dist/tab-navigator.d.ts +43 -3
- package/dist/tab-navigator.js +35 -6
- package/dist/tab-navigator.js.map +1 -1
- package/dist/toolbar-control-group.d.ts +13 -2
- package/dist/toolbar-control-group.js +1 -1
- package/dist/toolbar-text.d.ts +6 -1
- package/dist/toolbar-text.js +1 -1
- package/dist/toolbar.d.ts +1 -0
- package/dist/wire-catalog.d.ts +2 -2
- package/dist/wire-catalog.js +1 -1
- package/dist/wire-nav-stack.js +29 -3
- package/dist/wire-nav-stack.js.map +1 -1
- package/dist/wire-overlay-sheets.d.ts +20 -0
- package/dist/wire-overlay-sheets.js +4 -0
- package/dist/wire-overlay-sheets.js.map +1 -0
- package/dist/wire-scroll-dividers.js +1 -1
- package/dist/wire-token-search-fields.js +1 -1
- package/dist/workbench.d.ts +2 -2
- package/dist/workbench.js +2 -1
- package/docs/accessibility.md +35 -0
- package/docs/app-layouts.md +13 -0
- package/docs/backdrop-image.md +128 -0
- package/docs/component-contract.md +2 -0
- package/docs/component-selection.md +11 -2
- package/docs/design/templates/toolbar-control-group/glass-dark.svg +1 -0
- package/docs/design/templates/toolbar-control-group/glass.svg +1 -0
- package/docs/design/templates/toolbar-control-group-dark.svg +1 -1
- package/docs/design/templates/toolbar-control-group.svg +1 -1
- package/docs/design/templates.md +8 -0
- package/docs/layout.md +135 -5
- package/docs/manual-test-plan.md +29 -0
- package/docs/nav-stack.md +37 -1
- package/docs/recipes.md +24 -0
- package/docs/surface-scaffold.md +149 -3
- package/docs/tab-navigator.md +36 -0
- package/docs/ux-demo.md +11 -1
- package/llms.txt +42 -4
- package/package.json +13 -1
- package/ux-demo/recipes/loaders.ts +2 -0
- package/ux-demo/recipes/media-detail.tsx +272 -0
- package/dist/chunk-CMETHPKR.js.map +0 -1
- package/dist/chunk-CXZXHZTR.js.map +0 -1
- package/dist/chunk-HGV7J4T6.js.map +0 -1
- package/dist/chunk-INI4WDWC.js.map +0 -1
- package/dist/chunk-PIVY32AE.js.map +0 -1
- package/dist/chunk-QIG4IGUP.js.map +0 -1
- package/dist/chunk-UMKV7YVQ.js.map +0 -1
- package/dist/chunk-YOA5W5ZH.js.map +0 -1
package/ai/skill.md
CHANGED
|
@@ -59,6 +59,48 @@ twice through a wrapper, a second background, or an unnecessary override.
|
|
|
59
59
|
Check the resulting contrast in both color schemes, especially over a custom
|
|
60
60
|
backdrop. See `../docs/webawesome-theme.md#contextual-transparency`.
|
|
61
61
|
|
|
62
|
+
### Clear chrome over imagery
|
|
63
|
+
|
|
64
|
+
For a header or bar laid over imagery (an Apple-Music-style detail page), use
|
|
65
|
+
the `clear` presentation (`Pane headerPresentation`, `NavStack
|
|
66
|
+
chromePresentation` / `bottomToolbarPresentation`, `TabNavigator
|
|
67
|
+
barPresentation`) instead of making `overlay` chrome transparent with CSS.
|
|
68
|
+
Put its controls in `ToolbarControlGroup material="glass"` groups, and add
|
|
69
|
+
`scrollEdge="material"` (or `"surface"`, with `scrollEdgeDistance`, default
|
|
70
|
+
60px) to fade a backing in gradually as content scrolls beneath the bar (it
|
|
71
|
+
stays clear otherwise); give the opening `BackdropImage` `underChrome` so its artwork runs beneath the clear header. A clear bar draws no divider and turns opaque under reduced
|
|
72
|
+
transparency, increased contrast, and forced colors on its own.
|
|
73
|
+
|
|
74
|
+
### Core dialogs as bottom sheets
|
|
75
|
+
|
|
76
|
+
For a `kerfjs/overlay` `confirm` / `prompt` / `form` / `choice` (or `overlay()`)
|
|
77
|
+
with `presentation: 'bottom-sheet'`, import `@kerfjs/ui/overlay-sheet.css` once
|
|
78
|
+
instead of writing sheet CSS, pass `exitClass: 'kui-overlay-sheet-exit'` with an
|
|
79
|
+
`exitDuration` for the slide out, and compose the content through the dialog's
|
|
80
|
+
`render` slot (on kerfjs 4.x, with native buttons for the wired controls). For a sheet the person
|
|
81
|
+
can resize, add the `kui-overlay-sheet-resizable` class
|
|
82
|
+
(`className: 'kerf-overlay kui-overlay-sheet-resizable'`) and call
|
|
83
|
+
`wireOverlaySheets()` from `@kerfjs/ui/wire-overlay-sheets` once per container,
|
|
84
|
+
instead of building a grabber.
|
|
85
|
+
|
|
86
|
+
### App-chosen surface colors
|
|
87
|
+
|
|
88
|
+
For a surface in its own color (a media page in its artwork's color), set the
|
|
89
|
+
typed `background` prop instead of CSS: `Pane` (also `PaneConfig`, so Workbench
|
|
90
|
+
panels, CollapsiblePanel, and NavStack view panes forward it), `NavStack`,
|
|
91
|
+
`TabNavigator`, and each `TabNavigatorTab`. Pass a `@kerfjs/ui/css-values`
|
|
92
|
+
color (`uiColor(...)`, `fillColor(...)`, `colorVar(...)`); it replaces the
|
|
93
|
+
default or sunken fill, overlay chrome keeps its material, and forced colors
|
|
94
|
+
paint `Canvas`. Never select `.kui-pane` or a layout class to recolor it. You
|
|
95
|
+
own the contrast of the content over the color.
|
|
96
|
+
|
|
97
|
+
For a region that takes on a color, such as a media page in its artwork's
|
|
98
|
+
color, set `tint={{ color, scheme }}` on the same components (and
|
|
99
|
+
`TabNavigatorTab`, `PaneConfig`) instead: you declare whether the color is a
|
|
100
|
+
`'light'` or `'dark'` surface, and the scope re-derives surface, text, quiet
|
|
101
|
+
text, link, fills, and chrome material from it with lightness clamped to keep
|
|
102
|
+
text at WCAG AA. Add `accent` to re-derive the brand ramp (loud fills, links, focus ring) from the artwork's vivid color with the same AA clamps. Never restyle tokens by hand inside a tinted region.
|
|
103
|
+
|
|
62
104
|
## Components own their styles; configure, never override
|
|
63
105
|
|
|
64
106
|
This is the rule every Kerf UI surface follows, and applications and
|
|
@@ -260,6 +302,7 @@ Quick routing:
|
|
|
260
302
|
| Exclusive choice | `TabBar`, `SegmentedControl`, or `Select` | Tabs switch tabpanels; segments expose a few choices; `ChoiceChips` keeps a larger visible set as wrapping pills (`multiple` for any number); Select handles a longer value list. |
|
|
261
303
|
| Status or absent content | `StateBanner` or `EmptyState` | `StateBanner` accepts an optional terse, tone-tinted `badge` beside its title for a count or compact status; do not rely on color alone. Web Awesome callouts suit ecosystem content; toasts are transient and never the only record of important state. |
|
|
262
304
|
| Compact metadata | `Badge` | Configure status, count, category, or metadata presentation with tone, appearance, shape, and size props. For new content without a count use `size="dot"` (no children) with a `label` or `ariaHidden`. Cap long app-supplied text with `maxWidth` (a `CssLength`); it truncates with an ellipsis and the full string becomes the `title`. Do not build badges with application CSS or use them as interactive controls. |
|
|
305
|
+
| Hero image atop a scrolling view | `BackdropImage` | Lags the scroll (`parallax`), blurs progressively (`blur`, an opacity cross-fade to a once-blurred copy), dissolves into a typed `fadeTo` color that also paints the content below, and carries `overlay` content; Kerf owns the compositor-only scroll timeline and the reduced-motion, static-effects, and reduced-transparency fallbacks. Never hand-roll scroll listeners, `background-attachment: fixed`, or mask gradients. |
|
|
263
306
|
| Loading placeholder | a component's `placeholder` prop, or `Skeleton` | Set `placeholder` on a value-bearing component (`Select`, `ListHeader`, `ListItem`, `ValueTableRow`, `SegmentedControl`, `StateBanner`, `AppTab`, `ToolbarText`, `ListActionRow`) to render its real chrome with value slots as subtle **unanimated** skeletons and interactivity disabled; only unknown values change, so a placeholder is never dimmed or styled as disabled (a control whose own `disabled` / `trailingActionDisabled` / choice `disabled` / `actionDisabled` prop is set keeps its live disabled tone via the reserved `data-kui-disabled` marker) — do not hand-rebuild an empty state. Component-drawn chrome stays live too: a `ListItem` or `ListActionRow` placeholder keeps its `busy` spinner while its `status` text (and a `ListItem`'s `trailing` content, always a value) becomes a skeleton. `Skeleton` is the standalone block for a custom slot. A known `AppTab` that is still opening takes `pending` instead: it keeps its name (quiet, and as its accessible name) and the same geometry, shows your `trailing` spinner, and stays selectable (close and drag disabled) so your panel can show placeholders until it loads. Use `LoadingSpinner` for known busy activity, not a skeleton; never animate a skeleton; prefer it over `wa-skeleton`. |
|
|
264
307
|
| Adjustable or asymmetric columns | `ResizableRegion` or CSS grid | Use `ResizableRegion` only for a user-operable controlled separator, CSS grid for asymmetric/intrinsic tracks, and `Grid` for static equal-width tracks. |
|
|
265
308
|
| Structured or ordinary search | `TokenSearchField` or an input | Use token search only when text and ordered filter chips form one editor. |
|
|
@@ -279,7 +322,8 @@ selection set and each tile's nested controls.
|
|
|
279
322
|
adds 8px. Text insets win on any overlapping side, matching Row and List.
|
|
280
323
|
|
|
281
324
|
For a complete shell, sidebar, workspace header, list-detail dialog, composer
|
|
282
|
-
form, list-state lifecycle,
|
|
325
|
+
form, list-state lifecycle, mixed-control toolbar, or a media detail page
|
|
326
|
+
(clear chrome, tint, and artwork), start from the runnable
|
|
283
327
|
reference in [`docs/recipes.md`](../docs/recipes.md). Preserve its production
|
|
284
328
|
primitives and semantic ownership; replace application state, policy, and copy.
|
|
285
329
|
|
|
@@ -320,7 +364,7 @@ Hard rules:
|
|
|
320
364
|
4. Wire `data-action` hooks from one stable root with `delegate()` or `delegateActions()` and retain disposers.
|
|
321
365
|
5. Configure components through their typed props; components own their own styles (see "Components own their styles; configure, never override" above). Use the opinionated `--kui-color-*` semantic ramps for theming, not to reshape a component. Use `pop` only for attractive non-status emphasis such as featured, novel, or celebratory content; never substitute it for info, success, warning, or danger. Set a theme token only at the narrowest useful scope, and never where an equivalent prop exists. `publicClasses` exist for diagnostics, tooling, tests, and package-owned composition, not application styling. Never target a Kerf or Web Awesome component from application CSS; add missing configuration to the owner.
|
|
322
366
|
6. `Select` is pure until the app explicitly imports `@kerfjs/ui/select/register`; once registered, an icon-only `Select` (and, via `@kerfjs/ui/popup-menu/register`, an icon-only `PopupMenu`) shows an `aria-hidden` help tag repeating its accessible name (and a Select's current choice) on hover and keyboard focus, hidden while its popup is open — never add a `title` or your own tooltip to these triggers. The same installer tags an icon-only `<button>` or link in a `ToolbarControlGroup` named by `aria-label` (no visible text, no `title`); a toolbar with such buttons but no registered Select or PopupMenu imports `@kerfjs/ui/help-tags/register` once. Name those buttons with `aria-label`, not `title`: a `title` keeps the browser tooltip and skips the tag. Do not import Web Awesome's full registration bundle. When an app writes direct `wa-*` JSX, add `import type {} from '@kerfjs/ui/webawesome'` for the catalog-supported intrinsic-element declarations, import the CSS-only `@kerfjs/ui/webawesome.css` theme once, and keep importing individual Web Awesome component modules so their JavaScript remains tree-shakeable. The type boundary emits no code and registers nothing. Pass icon-bearing `choices` and `renderSelected` content normally: `Select` preserves its slotted option icons across Kerf rerenders and keys selected content by the controlled value, so app wrappers must not add competing morph-control attributes. Give it a visible `label` or an `ariaLabel` for a visually hidden name; the nonempty visible label takes precedence and the package names the actual shadow combobox, including `renderSelected`, without adding label geometry. Use `hint` for persistent supporting text below the control and `placeholderText` only for the empty value inside the closed control; loading placeholders retain the hint. For any number of choices set `multiple` with an array `value`: the popup stays open while choices toggle and closes on an outside press or Escape, the closed control summarizes the chosen labels, and `change` reports the value array; do not add app code to keep it open or to render tags. For a toolbar filter menu, add `selectedPresentation="icon-only"` plus a fixed `triggerIcon` (such as a funnel `LucideIcon`): the trigger shows that icon, a count badge while any choice is chosen, and ends its accessible name with the chosen labels ("Filter by label: Bug, Docs"); do not render your own count badge or rewrite the name. When testing name or description, target the element with the `combobox` role rather than the `wa-select` wrapper. Web Awesome's hint attribute and explicit hint slot both describe that shadow combobox across supported engines; do not add an `aria-description` mirror or application shadow-DOM patch.
|
|
323
|
-
7. Decorative icons are hidden; controls are named; focus is visible; state never relies on color alone; reduced motion and increased contrast remain usable. `DisclosureArrow` defaults to an 18px root-scaled visual; size it with its typed `size` prop (`size={remify(24)}`); it never becomes the interaction or accessible-name owner. Put it in an owning native control with a stable accessible name and controlled `aria-expanded`. `ListHeader` toggle mode supplies it when `actionIcon` is omitted, but the app must reveal matching content; a custom icon replaces it. Author replacement icon content facing right before its configured direction transform is applied. Direction changes take the shortest rotation path, with counterclockwise chosen for a 180-degree closed-to-open tie. Kerf `Select` separately keeps its intrinsic Web Awesome expand glyph at `--kui-disclosure-icon-scale: .5`; an icon-only toolbar Select may set `caret={false}` for a round trigger while preserving its help tag and keyboard listbox, and a custom `renderSelected` icon stays centered.
|
|
367
|
+
7. Decorative icons are hidden; controls are named; focus is visible; state never relies on color alone; reduced motion and increased contrast remain usable. When the app detects a low-power device, it sets `data-kui-effects="static"` on the root element to turn backdrop materials opaque and stop scroll-driven animations; `@media (update: slow)` does the same automatically. `DisclosureArrow` defaults to an 18px root-scaled visual; size it with its typed `size` prop (`size={remify(24)}`); it never becomes the interaction or accessible-name owner. Put it in an owning native control with a stable accessible name and controlled `aria-expanded`. `ListHeader` toggle mode supplies it when `actionIcon` is omitted, but the app must reveal matching content; a custom icon replaces it. Author replacement icon content facing right before its configured direction transform is applied. Direction changes take the shortest rotation path, with counterclockwise chosen for a 180-degree closed-to-open tie. Kerf `Select` separately keeps its intrinsic Web Awesome expand glyph at `--kui-disclosure-icon-scale: .5`; an icon-only toolbar Select may set `caret={false}` for a round trigger while preserving its help tag and keyboard listbox, and a custom `renderSelected` icon stays centered.
|
|
324
368
|
8. `ResizableRegion` uses `wireResizableRegions()` for Arrow, Shift+Arrow, Home/End, and pointer behavior. The app owns size persistence. `handleIcon` replaces decorative dormant glyph content only. Set `responsiveFillAt="narrow"` or `"compact"` when a responsive composition exposes the pane as its only inline track; the component fills that track and hides its dormant separator. For compact overlays, set `presentation="overlay"` and the overlay maximum variables. A lone child (normally a `Pane`) fills the region and owns scrolling; several children stack at natural height. Do not add descendant width/height overrides.
|
|
325
369
|
9. Use controlled `SegmentedControl` for a small exclusive choice set. Select `appearance="toolbar"` when nesting it inside `ToolbarControlGroup`; use rounded or pill shapes for standalone contexts. The package derives inset hover/selection radii from the owning outer shape through `--kui-layout-highlight-inset`; do not restyle an inner highlight to an independent radius. Handle its action, update `value`, keep meaningful choice labels, and preserve every enabled native button in sequential Tab order.
|
|
326
370
|
10. Compose `AppTab` inside controlled `TabBar`; call `wireTabBars()` once and retain its disposer. It owns same-bar drag mechanics, including proximity-based horizontal edge autoscroll, while the app applies `onReorder` and owns order, selection, panels, close policy, routing, and persistence. For a tab-local action followed by a separately pinned workspace action, set `trailingPlacement="adjacent"`, put the local action in `trailing`, and the workspace action in `end`; each action zone accepts one `ToolbarControlGroup` or a standalone `wa-button` when the action needs its own Web Awesome chrome. TabBar owns the shrinking/scrolling tabs and fixed action geometry, so do not add descendant flex overrides. Arrow/Home/End select on move by default and restore focus by bar/tab identity when controlled activation replaces the strip; pass `activation: 'manual'` (or `TabBar activation="manual"` per strip) so arrow keys move focus only and the user selects with Enter/Space/click — use it when selecting a tab is a heavy action. Use runtime-filtered `rootAttributes` for domain metadata and keep an optional `closeIcon` decorative and noninteractive.
|
|
@@ -378,6 +422,8 @@ For a read-only field preview that replaces a Web Awesome input, use `FieldLabel
|
|
|
378
422
|
|
|
379
423
|
`ToolbarControlGroup.tileTone` selects `neutral`, `brand`, `success`, `warning`, or `danger` quiet fill, matching quiet border, and on-quiet foreground for a non-interactive icon tile. Compose a contained `single` group whose only child is a direct decorative LucideIcon (`aria-hidden="true"`). Omission preserves the normal group palette. The prop does not recolor interactive, mixed, multi-control, or borderless groups; keep real actions in controls with their existing focus/hover/pressed treatments.
|
|
380
424
|
|
|
425
|
+
`ToolbarControlGroup` `material="glass"` paints a group that floats over imagery or a clear (transparent) toolbar on the translucent chrome material (`--kui-chrome-material` with the blur/saturate `--kui-chrome-material-filter`), with a specular edge in place of the gray border and a soft shadow. Its controls take `--kui-color-text`, so they stay at AA over any content; a raised or outline selection paints an opaque surface pill. The fill turns opaque under reduced transparency, increased contrast, static effects (`update: slow` or `:root[data-kui-effects="static"]`), or without backdrop-filter support, and paints Canvas/CanvasText in forced colors. A `tone="dark"` glass group keeps its loud fill and gains the blur and edge; a borderless group has no surface and ignores the material. Keep the solid default on an opaque toolbar, and never add your own `backdrop-filter` or translucent background to a group.
|
|
426
|
+
|
|
381
427
|
`ListItem`, `ListItemLink`, and `ListActionRow` take `iconTile` to present their leading `icon` in a filled 32px rounded tile holding an 18px glyph, for settings or command rows that identify each entry by color. Pass a tone (`neutral`, `brand`, `success`, `warning`, or `danger`) for the same quiet fill, matching quiet border, and on-quiet foreground as `ToolbarControlGroup.tileTone`, or `{ color, foreground? }` for an application color: `color` is a `CssColor` (`uiColor()`, `colorVar()`, or `fillColor('#e5484d')`) and `foreground` a `CssForegroundColor`; without one, the glyph is black or white, whichever contrasts with the fill. The tile sits 6px clear of a standard 44px row (a compact row is at least 42px tall), moves the label to the tile's edge, and keeps its colors when the row is hovered or selected. Never wrap the icon in your own tile or resize the row's icon slot.
|
|
382
428
|
|
|
383
429
|
Common mistakes:
|
|
@@ -445,8 +491,10 @@ completion handlers in consumers. Raw `wa-select` elements remain native.
|
|
|
445
491
|
|
|
446
492
|
Neutral lowered surfaces and decorative neutral fills/borders are translucent theme colors; compose nested public components directly. Default/raised canvases, foregrounds, focus indicators, and loud contrast-bearing fills remain opaque. Do not assign depth-specific component tokens in demo wrappers.
|
|
447
493
|
|
|
448
|
-
Use `ToolbarText tone="dark"` on a loud
|
|
449
|
-
match dark control groups
|
|
494
|
+
Use `ToolbarText tone="dark"` on a loud-filled toolbar surface (the inverse
|
|
495
|
+
`--kui-color-neutral-fill-loud`) to match dark control groups; it inverts with
|
|
496
|
+
the color scheme. Over a dark photo or scrim keep the default tone inside a
|
|
497
|
+
`BackdropImage` overlay, which takes the dark scheme under its `scrim`. It applies to read-only headings and actionable
|
|
450
498
|
titles at every size; default tone retains existing identity and heading colors.
|
|
451
499
|
|
|
452
500
|
Navigation transition continuity: `wireNavStack` slides the incoming view over the preserved previous view on push and the outgoing view off on pop, cross-fades both live chrome surfaces with inert snapshots, and settles/cancels an interrupted transition before starting the next. Reduced motion and duration zero settle immediately.
|
|
@@ -471,7 +519,7 @@ details.
|
|
|
471
519
|
|
|
472
520
|
Select menus use native viewport shifting with 10px gutters: default menus grow to content (up to 20rem), while `fitMenu` matches trigger width and long labels wrap. Keep popup sizing and position repairs out of consumer CSS.
|
|
473
521
|
|
|
474
|
-
Give sibling `DialogSurface`s that render conditionally a stable `rootAttributes={{ "data-key": "…" }}` so a re-render morphs each dialog into itself (structurally identical roots otherwise match by position and swap names and open state); never wrap one in a keyed app `div`. Modal `DialogSurface` accepts a typed `preferredWidth` (`CssLength`) that overrides `size` while retaining the viewport width cap. Typed `viewportGutter` and `maxHeight` (`CssLength` or `"viewport"`) bound the modal; explicit height caps stay within the dynamic viewport minus both gutters. Omitted props preserve Web Awesome defaults. Side-sheet/fullscreen geometry, application responsive choices, and preview layout remain separately owned. `height` (`CssLength` or `"viewport"`) gives the modal a definite bounded size, and `bodyLayout="fill"` hands the whole body to one child (a `SplitView` or `Pane`) that owns its scrolling. For a chat-style dialog, `bodyLayout="fill-last"` keeps leading rows (a notice) at their height and gives the last child (a `scrollable` `List` transcript) the rest, and `footerPresentation="floating"` lays the composer footer over the body, a typed `footerOffset` (default 16px) from the panel edges on a transparent background; the body reserves the measured footer height, so never add `::part(footer)` or `::part(body)` rules for it. To let the transcript scroll visibly beneath the floating composer, give the transcript `scrollClearance="block-end"` (on a `scrollable` `List` or a `Pane`): the body then publishes the footer's clearance as the inherited `--kui-scroll-clearance-block-end`, and the transcript adds it inside its own scroll area, so its last message still rests above the composer. Chrome that overlays a region's edge publishes `--kui-scroll-clearance-block-start` / `-end` the same way, and only the one scroller reaching that edge opts in (a composed Pane opts in through `PaneConfig.scrollClearance`: a Workbench `mainPane` or panel `pane`, a `CollapsiblePanel` `pane`, or a `NavStack` view's `pane`); never pad a transcript yourself to clear a footer. `headerPresentation="floating"` lays the dialog's title bar over the body's block start on the translucent `--kui-chrome-material-raised` (opaque under reduced transparency, increased contrast, forced colors, or without `backdrop-filter`); the register measures it and the body reserves it. To let a transcript scroll beneath both the title bar and a floating composer, make it the body's only child (`bodyLayout="fill"`) with `scrollClearance="both"`: the body publishes the header's height as `--kui-scroll-clearance-block-start`. A `ToolbarText` slotted as the label keeps AA on the title bar by itself (normal-color title, lifted description); keep other quiet copy in the body. For a non-modal, light-dismiss dialog use `PopoverDialogSurface` from the same subpath (native `popover="auto"`, `role="dialog"`, Kerf chrome, the same size/gutter/height/fill props, and `presentation="embedded"` for an in-flow catalog or inline preview) instead of a hand-built popover with app CSS. Name it with `label` or `labelledBy`, and describe it with `describedBy` (its `aria-describedby`), usually a title `ToolbarText`'s `descriptionId`.
|
|
522
|
+
Give sibling `DialogSurface`s that render conditionally a stable `rootAttributes={{ "data-key": "…" }}` so a re-render morphs each dialog into itself (structurally identical roots otherwise match by position and swap names and open state); never wrap one in a keyed app `div`. Modal `DialogSurface` accepts a typed `preferredWidth` (`CssLength`) that overrides `size` while retaining the viewport width cap. Typed `viewportGutter` and `maxHeight` (`CssLength` or `"viewport"`) bound the modal; explicit height caps stay within the dynamic viewport minus both gutters. Omitted props preserve Web Awesome defaults. Side-sheet/fullscreen geometry, application responsive choices, and preview layout remain separately owned. `height` (`CssLength` or `"viewport"`) gives the modal a definite bounded size, and `bodyLayout="fill"` hands the whole body to one child (a `SplitView` or `Pane`) that owns its scrolling. For a chat-style dialog, `bodyLayout="fill-last"` keeps leading rows (a notice) at their height and gives the last child (a `scrollable` `List` transcript) the rest, and `footerPresentation="floating"` lays the composer footer over the body, a typed `footerOffset` (default 16px) from the panel edges on a transparent background; the body reserves the measured footer height, so never add `::part(footer)` or `::part(body)` rules for it. To let the transcript scroll visibly beneath the floating composer, give the transcript `scrollClearance="block-end"` (on a `scrollable` `List` or a `Pane`): the body then publishes the footer's clearance as the inherited `--kui-scroll-clearance-block-end`, and the transcript adds it inside its own scroll area, so its last message still rests above the composer. Chrome that overlays a region's edge publishes `--kui-scroll-clearance-block-start` / `-end` the same way, and only the one scroller reaching that edge opts in (a composed Pane opts in through `PaneConfig.scrollClearance`: a Workbench `mainPane` or panel `pane`, a `CollapsiblePanel` `pane`, or a `NavStack` view's `pane`); never pad a transcript yourself to clear a footer. `headerPresentation="floating"` lays the dialog's title bar over the body's block start on the translucent `--kui-chrome-material-raised` (opaque under reduced transparency, increased contrast, forced colors, or without `backdrop-filter`); the register measures it and the body reserves it. To let a transcript scroll beneath both the title bar and a floating composer, make it the body's only child (`bodyLayout="fill"`) with `scrollClearance="both"`: the body publishes the header's height as `--kui-scroll-clearance-block-start`. A `ToolbarText` slotted as the label keeps AA on the title bar by itself (normal-color title, lifted description); keep other quiet copy in the body. `presentation="bottom-sheet"` attaches the dialog to the bottom edge (iOS-style sheet): the top corners keep the dialog radius, the bottom corners are square, and the panel runs behind the home indicator and virtual keyboard while a block-end padding (the larger of `--kui-safe-area-block-end`, the `visualViewport` keyboard overlap the register measures, and `env(keyboard-inset-height)`) keeps content above them; `height` is its opening visible height and `maxHeight` its cap (the dynamic viewport minus the top safe area and one gutter). `resizable` adds a top grabber (a focusable "Resize sheet" separator; drag, arrows, Page Up/Down, Home/End) bounded by `minHeight` (default 160px) and the cap, restarting at `height` on each opening. It slides up on open and down on dismiss by default (`enterMotion` / `exitMotion` = `"standard"` keeps the Web Awesome scale-and-fade), and falls back to Web Awesome motion under reduced motion. Never position a `wa-dialog` at the bottom with `::part(dialog)` rules or add your own keyboard padding. For a non-modal, light-dismiss dialog use `PopoverDialogSurface` from the same subpath (native `popover="auto"`, `role="dialog"`, Kerf chrome, the same size/gutter/height/fill props, and `presentation="embedded"` for an in-flow catalog or inline preview) instead of a hand-built popover with app CSS. Name it with `label` or `labelledBy`, and describe it with `describedBy` (its `aria-describedby`), usually a title `ToolbarText`'s `descriptionId`.
|
|
475
523
|
|
|
476
524
|
Import `@kerfjs/ui/surface-scaffold/register` once when using `DialogSurface`: it registers `wa-dialog` and repairs Web Awesome 3.12 native dialog names before the first modal opening. Headed dialogs reference the rendered title, including live slotted labels; headerless dialogs use the public `label`. Explicit host `aria-label` and pre-existing native names are preserved. A host that is itself an explicit dialog (`role="dialog"` or `"alertdialog"` with its own name) keeps that name alone: the native panel is left unnamed, so one dialog carries the name. Geometry-only markup stays CSS-free and does not register Web Awesome implicitly.
|
|
477
525
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Web Awesome JSX signatures for the UI authoring corpus
|
|
2
2
|
|
|
3
|
-
Generated from the emitted `@kerfjs/ui@5.0.0-beta.
|
|
3
|
+
Generated from the emitted `@kerfjs/ui@5.0.0-beta.101` declaration boundary. Import `@kerfjs/ui/webawesome` for type effects when authoring direct `wa-*` JSX. The module emits no runtime behavior and does not register custom elements.
|
|
4
4
|
|
|
5
5
|
```ts
|
|
6
6
|
import { KerfCustomElement } from 'kerfjs/jsx-runtime';
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import * as kerfjs from 'kerfjs';
|
|
2
|
+
import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
|
|
3
|
+
import { S as StructuralRootAttributes } from './extension-attributes-mu8MFUl0.js';
|
|
4
|
+
import { CssLength, CssColor } from './css-values.js';
|
|
5
|
+
|
|
6
|
+
/** How a single image fills the backdrop (`object-fit`). */
|
|
7
|
+
type BackdropImageFit = 'cover' | 'contain' | 'fill';
|
|
8
|
+
/** Which part of the image stays in view when it is cropped. */
|
|
9
|
+
type BackdropImagePosition = 'center' | 'top' | 'bottom' | 'left' | 'right' | 'top left' | 'top right' | 'bottom left' | 'bottom right';
|
|
10
|
+
/** Tile the image as a background instead of fitting one copy. */
|
|
11
|
+
type BackdropImageRepeat = 'repeat' | 'repeat-x' | 'repeat-y';
|
|
12
|
+
/**
|
|
13
|
+
* How far the image lags the scroll: `none` scrolls with the content,
|
|
14
|
+
* `subtle` lags by 35%, and a number from 0 to 1 is the lag factor (0.5
|
|
15
|
+
* moves the image at half the scroll speed).
|
|
16
|
+
*/
|
|
17
|
+
type BackdropImageParallax = 'none' | 'subtle' | number;
|
|
18
|
+
/**
|
|
19
|
+
* A dimming layer under `overlay` content: `bottom` darkens toward the
|
|
20
|
+
* block end where a title sits, `full` dims the whole image evenly.
|
|
21
|
+
*/
|
|
22
|
+
type BackdropImageScrim = 'none' | 'bottom' | 'full';
|
|
23
|
+
/**
|
|
24
|
+
* A scroll-linked progressive blur: a statically blurred copy of the image
|
|
25
|
+
* fades in as the image block scrolls away. Only the copy's opacity (and the
|
|
26
|
+
* optional dim layer's) animates; the blur itself is set once.
|
|
27
|
+
*/
|
|
28
|
+
interface BackdropImageBlur {
|
|
29
|
+
/**
|
|
30
|
+
* CSS blur radius applied once to the copy. Default 24px; with
|
|
31
|
+
* `blurredSrc` the default is no filter, since that asset is already soft.
|
|
32
|
+
*/
|
|
33
|
+
radius?: CssLength;
|
|
34
|
+
/**
|
|
35
|
+
* An app-supplied pre-blurred or low-resolution copy of the image, used
|
|
36
|
+
* instead of filtering `src`.
|
|
37
|
+
*/
|
|
38
|
+
blurredSrc?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Peak opacity, from 0 to 1, of a black dim layer that ramps in with the
|
|
41
|
+
* blur. Default 0 (no dim layer).
|
|
42
|
+
*/
|
|
43
|
+
dim?: number;
|
|
44
|
+
}
|
|
45
|
+
type BackdropImageRootAttributes = StructuralRootAttributes & Readonly<{
|
|
46
|
+
'data-component'?: never;
|
|
47
|
+
'data-blur'?: never;
|
|
48
|
+
'data-parallax'?: never;
|
|
49
|
+
'data-scrim'?: never;
|
|
50
|
+
'data-fade'?: never;
|
|
51
|
+
'data-repeat'?: never;
|
|
52
|
+
'data-under-chrome'?: never;
|
|
53
|
+
}>;
|
|
54
|
+
interface BackdropImageCommonProps {
|
|
55
|
+
/** Image URL. */
|
|
56
|
+
src: string;
|
|
57
|
+
/**
|
|
58
|
+
* Accessible description of the image. Pass `''` for a decorative image
|
|
59
|
+
* that only sets a mood; assistive technology then skips it.
|
|
60
|
+
*/
|
|
61
|
+
alt: string;
|
|
62
|
+
/** Which part of a cropped image stays in view. Default `center`. */
|
|
63
|
+
position?: BackdropImagePosition;
|
|
64
|
+
/** Height of the image block. Default 320px (`remify(320)`). */
|
|
65
|
+
height?: CssLength;
|
|
66
|
+
/** How far the image lags the scroll. Default `none`. */
|
|
67
|
+
parallax?: BackdropImageParallax;
|
|
68
|
+
/**
|
|
69
|
+
* The color the image fades into at its block end. It also paints the
|
|
70
|
+
* whole surface, so `children` below the image sit on the same color and
|
|
71
|
+
* the page reads as one surface. Omit for a hard edge with no surface.
|
|
72
|
+
*/
|
|
73
|
+
fadeTo?: CssColor;
|
|
74
|
+
/**
|
|
75
|
+
* Blur the image progressively as it scrolls away, by cross-fading a
|
|
76
|
+
* statically blurred copy. Static (unblurred) wherever parallax is.
|
|
77
|
+
*/
|
|
78
|
+
blur?: BackdropImageBlur;
|
|
79
|
+
/**
|
|
80
|
+
* Run the image up beneath the scroller's block-start inset: an overlay or
|
|
81
|
+
* clear Pane header, NavStack chrome handed to a view's Pane, and the top
|
|
82
|
+
* safe area, the way a media page's artwork fills the screen behind
|
|
83
|
+
* transparent chrome. The visible image keeps `height` below that inset,
|
|
84
|
+
* and `overlay` content stays clear of the chrome. Place the image first in
|
|
85
|
+
* the Pane's content; it reads the Pane's
|
|
86
|
+
* `--kui-pane-content-inset-block-start`. Default `false`.
|
|
87
|
+
*/
|
|
88
|
+
underChrome?: boolean;
|
|
89
|
+
/** Dim the image under `overlay` content. Default `none`. */
|
|
90
|
+
scrim?: BackdropImageScrim;
|
|
91
|
+
/** Content laid over the image's block end, such as a title and actions. */
|
|
92
|
+
overlay?: KerfUiContent;
|
|
93
|
+
/** Content that continues below the image on the `fadeTo` surface. */
|
|
94
|
+
children?: KerfUiContent;
|
|
95
|
+
id?: string;
|
|
96
|
+
className?: string;
|
|
97
|
+
/** Safe `data-*`, `aria-*`, and structural `role` metadata on the root. */
|
|
98
|
+
rootAttributes?: BackdropImageRootAttributes;
|
|
99
|
+
/** Native named-slot assignment when composed inside a web component. */
|
|
100
|
+
slot?: string;
|
|
101
|
+
}
|
|
102
|
+
/** One fitted image, with optional responsive candidates. */
|
|
103
|
+
interface BackdropImageSingleProps extends BackdropImageCommonProps {
|
|
104
|
+
repeat?: undefined;
|
|
105
|
+
/** Responsive image candidates (`srcset`). */
|
|
106
|
+
srcset?: string;
|
|
107
|
+
/** Rendered-size hints for `srcset` (`sizes`). */
|
|
108
|
+
sizes?: string;
|
|
109
|
+
/** How the image fills the block. Default `cover`. */
|
|
110
|
+
fit?: BackdropImageFit;
|
|
111
|
+
}
|
|
112
|
+
/** A tiled background image at its natural size. */
|
|
113
|
+
interface BackdropImageTiledProps extends BackdropImageCommonProps {
|
|
114
|
+
repeat: BackdropImageRepeat;
|
|
115
|
+
srcset?: never;
|
|
116
|
+
sizes?: never;
|
|
117
|
+
fit?: never;
|
|
118
|
+
}
|
|
119
|
+
type BackdropImageProps = BackdropImageSingleProps | BackdropImageTiledProps;
|
|
120
|
+
/**
|
|
121
|
+
* An image backdrop at the top of a scrolling Pane or NavStack view: the
|
|
122
|
+
* image can lag the scroll (parallax on a scroll-driven, compositor-only
|
|
123
|
+
* transform), fade through a mask into `fadeTo`, and that color keeps
|
|
124
|
+
* painting under `children` so the page reads as one surface. Kerf owns the
|
|
125
|
+
* static fallbacks: no parallax without scroll-driven animation support,
|
|
126
|
+
* under reduced motion, under `data-kui-effects="static"`, or on a
|
|
127
|
+
* slow-update display, and a hard edge onto solid `fadeTo` under reduced
|
|
128
|
+
* transparency.
|
|
129
|
+
*/
|
|
130
|
+
declare function BackdropImage(props: BackdropImageProps): kerfjs.SafeHtml;
|
|
131
|
+
|
|
132
|
+
export { BackdropImage, type BackdropImageBlur, type BackdropImageFit, type BackdropImageParallax, type BackdropImagePosition, type BackdropImageProps, type BackdropImageRepeat, type BackdropImageScrim, type BackdropImageSingleProps, type BackdropImageTiledProps };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"backdrop-image.js"}
|
|
@@ -5,12 +5,12 @@ import './semantic-content-BbzjvSu9.js';
|
|
|
5
5
|
import './sides-BPSWde0A.js';
|
|
6
6
|
import './pane.js';
|
|
7
7
|
import './scroll-clearance-BikHljTc.js';
|
|
8
|
+
import './css-values.js';
|
|
8
9
|
import './workbench.js';
|
|
9
|
-
import './nav-stack-
|
|
10
|
+
import './nav-stack-CU_0dKtI.js';
|
|
10
11
|
import './list.js';
|
|
11
12
|
import './extension-attributes-mu8MFUl0.js';
|
|
12
13
|
import './flex-alignment-4ms8ZbV8.js';
|
|
13
|
-
import './css-values.js';
|
|
14
14
|
import './panel-toolbar-vg6Ir5Dy.js';
|
|
15
15
|
import './lucide-icon.js';
|
|
16
16
|
import 'lucide';
|
package/dist/catalog.d.ts
CHANGED
|
@@ -7,12 +7,12 @@ import './toolbar.js';
|
|
|
7
7
|
import './sides-BPSWde0A.js';
|
|
8
8
|
import './pane.js';
|
|
9
9
|
import './scroll-clearance-BikHljTc.js';
|
|
10
|
+
import './css-values.js';
|
|
10
11
|
import './workbench.js';
|
|
11
|
-
import './nav-stack-
|
|
12
|
+
import './nav-stack-CU_0dKtI.js';
|
|
12
13
|
import './list.js';
|
|
13
14
|
import './extension-attributes-mu8MFUl0.js';
|
|
14
15
|
import './flex-alignment-4ms8ZbV8.js';
|
|
15
|
-
import './css-values.js';
|
|
16
16
|
import './panel-toolbar-vg6Ir5Dy.js';
|
|
17
17
|
import './lucide-icon.js';
|
|
18
18
|
import 'lucide';
|
package/dist/catalog.js
CHANGED
|
@@ -1,34 +1,35 @@
|
|
|
1
|
-
import { Workbench } from './chunk-
|
|
1
|
+
import { Workbench } from './chunk-YBWQR2OK.js';
|
|
2
2
|
import { uxReviewCaptureUrl } from './chunk-6C6DLP3W.js';
|
|
3
3
|
export { UX_REVIEW_PROJECT_PATH, loadUxReviewProject, uxReviewCaptureUrl } from './chunk-6C6DLP3W.js';
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
import { TokenSearchField } from './chunk-MF6ZUUJZ.js';
|
|
7
|
+
|
|
7
8
|
import { Row } from './chunk-YQ2AC4E2.js';
|
|
8
|
-
import {
|
|
9
|
+
import { ListItem } from './chunk-ZYU5WRC3.js';
|
|
10
|
+
import { ToolbarText } from './chunk-EKHDLBRP.js';
|
|
9
11
|
|
|
10
12
|
import { PopupMenu } from './chunk-HQZYKJ56.js';
|
|
11
|
-
import { ListHeader } from './chunk-
|
|
13
|
+
import { ListHeader } from './chunk-3SKAEPPZ.js';
|
|
12
14
|
import { ListInsetControl } from './chunk-AN5IWMTM.js';
|
|
13
15
|
import { ListInsetText } from './chunk-S4Y3YTAI.js';
|
|
14
|
-
import { ListItem } from './chunk-3GLYIIFR.js';
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
import { Text } from './chunk-LL45C7BB.js';
|
|
19
16
|
|
|
20
17
|
|
|
21
18
|
|
|
22
19
|
|
|
23
|
-
import { ToolbarControlGroup, ToolbarActionLink } from './chunk-
|
|
20
|
+
import { ToolbarControlGroup, ToolbarActionLink } from './chunk-2PXZBFEC.js';
|
|
24
21
|
import { Toolbar } from './chunk-CMLPFIC5.js';
|
|
25
22
|
import { List } from './chunk-HZPHCSCS.js';
|
|
26
23
|
|
|
27
24
|
|
|
25
|
+
|
|
28
26
|
import { ensureSunkenTexture } from './chunk-IKS72C6P.js';
|
|
29
27
|
import { LucideIcon } from './chunk-LOSRXZAH.js';
|
|
30
28
|
|
|
31
29
|
|
|
30
|
+
import { Text } from './chunk-LL45C7BB.js';
|
|
31
|
+
|
|
32
|
+
|
|
32
33
|
|
|
33
34
|
import { filterDataAttributes } from './chunk-KH4KEMSP.js';
|
|
34
35
|
import { Contrast, ZapOff, Moon, Sun, X, Waypoints, ExternalLink, Scan } from 'lucide';
|