@kerfjs/ui 4.4.1 → 5.0.0-beta.4
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 +234 -5
- package/ai/component-catalog.json +4473 -0
- package/ai/component-catalog.schema.json +79 -0
- package/ai/public-api-signatures-v1.md +619 -0
- package/ai/skill.md +65 -11
- package/ai/webawesome-jsx-signatures-v1.md +106 -0
- package/dist/app-tab.d.ts +12 -2
- package/dist/app-tab.js +2 -1
- package/dist/browser/app-tab.js +2 -2
- package/dist/browser/dialog-header.js +4 -2
- package/dist/browser/disclosure-arrow.js +4 -0
- package/dist/browser/empty-state.js +3 -3
- package/dist/browser/loading-spinner.js +2 -2
- package/dist/browser/lucide-icon.js +2 -2
- package/dist/browser/menu-action-row.js +3 -0
- package/dist/browser/menu-header.js +4 -2
- package/dist/browser/menu-item.js +2 -2
- package/dist/browser/page-header.js +2 -2
- package/dist/browser/resizable-region.js +2 -2
- package/dist/browser/segmented-control.js +2 -2
- package/dist/browser/select.js +3 -3
- package/dist/browser/state-banner.js +2 -2
- package/dist/browser/tab-bar.js +2 -2
- package/dist/browser/token-search-field.js +4 -0
- package/dist/browser/toolbar-control-group.js +2 -2
- package/dist/browser/toolbar-text.js +2 -2
- package/dist/browser/toolbar.js +2 -2
- package/dist/browser/value-table.js +2 -2
- package/dist/chunk-56RJXPHG.js +43 -0
- package/dist/chunk-56RJXPHG.js.map +1 -0
- package/dist/chunk-7BR3DO2A.js +31 -0
- package/dist/chunk-7BR3DO2A.js.map +1 -0
- package/dist/chunk-7LDCTU7D.js +134 -0
- package/dist/chunk-7LDCTU7D.js.map +1 -0
- package/dist/{chunk-4HHCYSGT.js → chunk-AQNKJRFH.js} +2 -2
- package/dist/{chunk-4HHCYSGT.js.map → chunk-AQNKJRFH.js.map} +1 -1
- package/dist/{chunk-NHXX4JI5.js → chunk-CTQKI2XL.js} +3 -3
- package/dist/chunk-CTQKI2XL.js.map +1 -0
- package/dist/chunk-EGHL5S4P.js +33 -0
- package/dist/chunk-EGHL5S4P.js.map +1 -0
- package/dist/chunk-H5AGGVU5.js +75 -0
- package/dist/chunk-H5AGGVU5.js.map +1 -0
- package/dist/chunk-K3G72I6D.js +24 -0
- package/dist/chunk-K3G72I6D.js.map +1 -0
- package/dist/{chunk-3O7ZEUW2.js → chunk-M5JRI6MN.js} +3 -3
- package/dist/chunk-M5JRI6MN.js.map +1 -0
- package/dist/chunk-NPPD2A6O.js +40 -0
- package/dist/chunk-NPPD2A6O.js.map +1 -0
- package/dist/chunk-R6JHHBKQ.js +19 -0
- package/dist/chunk-R6JHHBKQ.js.map +1 -0
- package/dist/chunk-S3TPM2LP.js +23 -0
- package/dist/chunk-S3TPM2LP.js.map +1 -0
- package/dist/{chunk-T5XNMVOI.js → chunk-XZXRLY5Q.js} +14 -5
- package/dist/chunk-XZXRLY5Q.js.map +1 -0
- package/dist/dialog-header.d.ts +3 -2
- package/dist/dialog-header.js +3 -1
- package/dist/disclosure-arrow.d.ts +14 -0
- package/dist/disclosure-arrow.js +4 -0
- package/dist/disclosure-arrow.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +16 -11
- package/dist/menu-action-row.d.ts +50 -0
- package/dist/menu-action-row.js +4 -0
- package/dist/menu-action-row.js.map +1 -0
- package/dist/menu-header.d.ts +28 -2
- package/dist/menu-header.js +4 -1
- package/dist/menu-item.d.ts +10 -1
- package/dist/menu-item.js +2 -1
- package/dist/resizable-region.d.ts +3 -1
- package/dist/resizable-region.js +1 -1
- package/dist/select.js +1 -1
- package/dist/styles/app-tab.css +152 -0
- package/dist/styles/dialog-header.css +87 -0
- package/dist/styles/disclosure-arrow.css +23 -0
- package/dist/styles/empty-state.css +47 -0
- package/dist/styles/foundation.css +326 -0
- package/dist/styles/layout.css +73 -0
- package/dist/styles/loading-spinner.css +21 -0
- package/dist/styles/lucide-icon.css +6 -0
- package/dist/styles/menu-action-row.css +160 -0
- package/dist/styles/menu-header.css +143 -0
- package/dist/styles/menu-item.css +123 -0
- package/dist/styles/page-header.css +33 -0
- package/dist/styles/resizable-region.css +111 -0
- package/{src → dist/styles}/segmented-control.css +62 -31
- package/dist/styles/select.css +96 -0
- package/dist/styles/state-banner.css +173 -0
- package/dist/styles/styles.css +22 -0
- package/dist/styles/tab-bar.css +45 -0
- package/dist/styles/token-search-field.css +281 -0
- package/dist/styles/toolbar-control-group.css +161 -0
- package/dist/styles/toolbar-text.css +29 -0
- package/dist/styles/toolbar.css +52 -0
- package/dist/styles/value-table.css +75 -0
- package/{src → dist/styles}/webawesome.css +119 -29
- package/dist/token-search-field.d.ts +43 -0
- package/dist/token-search-field.js +4 -0
- package/dist/token-search-field.js.map +1 -0
- package/dist/value-table.d.ts +10 -2
- package/dist/value-table.js +1 -1
- package/dist/webawesome.d.ts +100 -0
- package/dist/webawesome.js +3 -0
- package/dist/webawesome.js.map +1 -0
- package/dist/wire-resizable-regions.js +1 -1
- package/dist/wire-token-search-fields.d.ts +11 -0
- package/dist/wire-token-search-fields.js +5 -0
- package/dist/wire-token-search-fields.js.map +1 -0
- package/docs/accessibility.md +60 -3
- package/docs/component-contract.md +131 -3
- package/docs/component-selection.md +133 -0
- package/docs/design-philosophy.md +38 -0
- package/docs/examples/command-palette-adapter.tsx +70 -0
- package/docs/layout.md +106 -0
- package/docs/recipes.md +124 -0
- package/docs/ux-demo.md +23 -9
- package/docs/webawesome-theme.md +15 -0
- package/llms.txt +25 -2
- package/package.json +70 -27
- package/ux-demo/recipes/app-shell.tsx +32 -0
- package/ux-demo/recipes/compact-toolbar.tsx +43 -0
- package/ux-demo/recipes/composer-form.tsx +63 -0
- package/ux-demo/recipes/list-workspace-states.tsx +26 -0
- package/ux-demo/recipes/loaders.ts +27 -0
- package/ux-demo/recipes/master-detail-dialog.tsx +45 -0
- package/ux-demo/recipes/mount-recipe.ts +38 -0
- package/ux-demo/recipes/navigation-sidebar.tsx +26 -0
- package/ux-demo/recipes/recipes.css +344 -0
- package/ux-demo/recipes/types.ts +11 -0
- package/ux-demo/recipes/workspace-header.tsx +12 -0
- package/dist/chunk-3O7ZEUW2.js.map +0 -1
- package/dist/chunk-723YNJBH.js +0 -17
- package/dist/chunk-723YNJBH.js.map +0 -1
- package/dist/chunk-NHXX4JI5.js.map +0 -1
- package/dist/chunk-OPCJRCYO.js +0 -19
- package/dist/chunk-OPCJRCYO.js.map +0 -1
- package/dist/chunk-T5XNMVOI.js.map +0 -1
- package/dist/chunk-VKH2JLDZ.js +0 -10
- package/dist/chunk-VKH2JLDZ.js.map +0 -1
- package/dist/chunk-WY4CAEPG.js +0 -14
- package/dist/chunk-WY4CAEPG.js.map +0 -1
- package/src/app-tab.css +0 -20
- package/src/dialog-header.css +0 -9
- package/src/empty-state.css +0 -6
- package/src/foundation.css +0 -106
- package/src/loading-spinner.css +0 -4
- package/src/lucide-icon.css +0 -1
- package/src/menu-header.css +0 -13
- package/src/menu-item.css +0 -12
- package/src/page-header.css +0 -3
- package/src/resizable-region.css +0 -19
- package/src/select.css +0 -18
- package/src/state-banner.css +0 -31
- package/src/styles.css +0 -18
- package/src/tab-bar.css +0 -4
- package/src/toolbar-control-group.css +0 -25
- package/src/toolbar-text.css +0 -4
- package/src/toolbar.css +0 -9
- package/src/value-table.css +0 -5
package/ai/skill.md
CHANGED
|
@@ -1,28 +1,71 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: kerf-ui
|
|
3
3
|
description: Build interfaces with kerfjs and the @kerfjs/ui production component package. Use whenever code imports @kerfjs/ui or a task asks for Kerf UI components.
|
|
4
|
-
kerf-ui-skill-version: 1.
|
|
4
|
+
kerf-ui-skill-version: 1.32.0
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Building with @kerfjs/ui
|
|
8
8
|
|
|
9
|
-
Read `../
|
|
9
|
+
Read `../docs/component-selection.md` first, then `./component-catalog.json`,
|
|
10
|
+
`./public-api-signatures-v1.md`, `./webawesome-jsx-signatures-v1.md`,
|
|
11
|
+
`../docs/recipes.md`, `../README.md`,
|
|
12
|
+
`../docs/component-contract.md`, and `../docs/accessibility.md` before changing
|
|
13
|
+
a consuming interface. Use the signature snapshot for exact props, callbacks,
|
|
14
|
+
return values, and supported import paths; do not infer them from examples.
|
|
15
|
+
Read `../docs/webawesome-theme.md` when using Web Awesome components or changing
|
|
16
|
+
shared theme tokens.
|
|
17
|
+
|
|
18
|
+
Choose from the need, not from visual resemblance:
|
|
19
|
+
|
|
20
|
+
1. Search the Kerf catalog and preferred Web Awesome subset.
|
|
21
|
+
2. Reuse a primitive when purpose, anatomy, state, and interaction match.
|
|
22
|
+
3. Compose primitives for recurring layout. Prefer public props and tokens; use only cataloged `publicClasses` when composition-specific CSS needs a selector.
|
|
23
|
+
4. Add a thin application adapter for copy, domain mapping, actions, routing, persistence, permissions, and transport.
|
|
24
|
+
5. Build custom markup only when the semantic contract differs; if it recurs across products, open an upstream component or recipe request.
|
|
25
|
+
|
|
26
|
+
Quick routing:
|
|
27
|
+
|
|
28
|
+
| Need | Choose | Nearest alternatives / boundary |
|
|
29
|
+
| --- | --- | --- |
|
|
30
|
+
| Navigation row | `MenuItem` | Use an ordinary link or button when sidebar/menu anatomy and state do not apply. Multiline leading icons stay aligned with the first text line. |
|
|
31
|
+
| Navigation row with a trailing action | `MenuActionRow` | Use `MenuItem` when the trailing region is dormant; never put controls inside either component's SafeHtml slots. Multiline leading icons stay aligned with the first text line. |
|
|
32
|
+
| Page chrome or heading | `Toolbar`, `PageHeader`, or `DialogHeader` | Toolbar is persistent chrome; page and dialog headers identify different scopes. |
|
|
33
|
+
| Exclusive choice | `TabBar`, `SegmentedControl`, or `Select` | Tabs switch tabpanels; segments expose a few choices; Select handles a longer value list. |
|
|
34
|
+
| Status or absent content | `StateBanner` or `EmptyState` | Web Awesome callouts suit ecosystem content; toasts are transient and never the only record of important state. |
|
|
35
|
+
| Adjustable or static columns | `ResizableRegion` or CSS grid | Use the component only for a user-operable controlled separator. |
|
|
36
|
+
| Structured or ordinary search | `TokenSearchField` or an input | Use token search only when text and ordered filter chips form one editor. |
|
|
37
|
+
| Key/value facts | `ValueTable` with `ValueTableRow` | Use rows with `icon` only when the optional 24px leading visual adds context. |
|
|
38
|
+
| Command search | Application-local semantics using shared layout vocabulary | No runtime component or production recipe is exported; the app owns behavior, policy, and copy. |
|
|
39
|
+
|
|
40
|
+
For a complete shell, sidebar, workspace header, master-detail dialog, composer
|
|
41
|
+
form, list-state lifecycle, or mixed-control toolbar, start from the runnable
|
|
42
|
+
reference in [`docs/recipes.md`](../docs/recipes.md). Preserve its production
|
|
43
|
+
primitives and semantic ownership; replace application state, policy, and copy.
|
|
44
|
+
|
|
45
|
+
The concise human decision matrix is in [`component-selection.md`](../docs/component-selection.md). For exhaustive tool retrieval, load [`component-catalog.json`](./component-catalog.json), the canonical metadata for every public component/helper, composition, and supported Web Awesome entry. Use its linked current recipes instead of inferring behavior from CSS.
|
|
10
46
|
|
|
11
47
|
Hard rules:
|
|
12
48
|
|
|
13
49
|
1. Import visual components from explicit JavaScript subpaths. In CSS-aware browser builds each subpath brings in its own reachable CSS, including UI subcomponents, while unrelated CSS remains out. The root barrel and `@kerfjs/ui/unstyled` are CSS-free; pair the root barrel with `styles.css` only when the complete layer is intentional. Manual CSS subpaths remain available for custom pipelines.
|
|
14
50
|
2. Components return Kerf `SafeHtml`. Never pass DOM nodes as children or use inline JSX event handlers.
|
|
15
|
-
3. Keep state, product copy, persistence, and domain mappings in the application. Do not add product-specific actions or fields to a generic component.
|
|
51
|
+
3. Keep state, product copy, persistence, and domain mappings in the application. Do not add product-specific actions or fields to a generic component. Put MenuItem/MenuActionRow/MenuHeader/AppTab domain `data-*` metadata in `rootAttributes`; use MenuActionRow `trailingActionAttributes` and MenuHeader `triggerAttributes` only for domain `data-*` or native popover target/action and `aria-controls`/`aria-haspopup`. These slots do not replace component-owned action, item/tab identity, selection, disclosure, naming, disabled, icon, or role semantics.
|
|
16
52
|
4. Wire `data-action` hooks from one stable root with `delegate()` or `delegateActions()` and retain disposers.
|
|
17
|
-
5. Use the opinionated `--kui-color-*` semantic ramps and component-level override properties. Override tokens at the narrowest useful scope
|
|
18
|
-
6. `Select` is pure until the app explicitly imports `@kerfjs/ui/select/register`; do not import Web Awesome's full registration bundle. When an app
|
|
19
|
-
7. Decorative icons are hidden; controls are named; focus is visible; state never relies on color alone; reduced motion and increased contrast remain usable.
|
|
20
|
-
8. `ResizableRegion` uses `wireResizableRegions()` for Arrow, Shift+Arrow, Home/End, and pointer behavior. The app owns size persistence.
|
|
53
|
+
5. Use the opinionated `--kui-color-*` semantic ramps and component-level override properties. Override tokens at the narrowest useful scope and prefer equivalent props/tokens. Public-class-to-public-class selectors are supported when every Kerf class appears in the catalog entry's `publicClasses`; never target descendant tags, ids, attribute-only anatomy, or unlisted implementation classes.
|
|
54
|
+
6. `Select` is pure until the app explicitly imports `@kerfjs/ui/select/register`; 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.
|
|
55
|
+
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 and exposes `--kui-disclosure-arrow-size` for consumer sizing; 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`. `MenuHeader` 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`.
|
|
56
|
+
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.
|
|
21
57
|
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. Handle its action, update `value`, keep meaningful choice labels, and preserve every enabled native button in sequential Tab order.
|
|
22
|
-
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.
|
|
23
|
-
11.
|
|
24
|
-
12.
|
|
25
|
-
13.
|
|
58
|
+
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. Use runtime-filtered `rootAttributes` for domain metadata and keep an optional `closeIcon` decorative and noninteractive.
|
|
59
|
+
11. Use token-controlled `TokenSearchField` when free text and removable structured filters share one editor. Editable text stays DOM-owned between token changes. The leading icon, first text line, clear action, and trailing slot share one fixed row when content wraps. The app owns parsing and suggestions; call `readTokenSearchField()` on input, empty `textContent` on clear, use `placeTokenSearchCaret()` after explicit controlled focus changes, and call `wireTokenSearchFields()` once so Enter submits without inserting a line break and keyboard chip deletion restores focus plus the text-relative caret after controlled replacement. Enable `collapsible` for an animated iconic closed state, standalone or inside `ToolbarControlGroup`; the field keeps text or tokens expanded while the app controls transient `expanded` state, focus transfer, and focusout timing.
|
|
60
|
+
12. Demo work uses public production component subpaths and their browser-selected CSS. Give every public visual component its own category-grouped catalog route; list themed third-party components under a clearly labeled collapsible ecosystem section, with a focused route for each. Project its deterministic repository-relative demo source and existing documentation path so the detail can expose `View demo source` and `Read guidance` links without a runtime export; also derive first-party component implementation paths from their canonical browser imports, and label Web Awesome documentation as Kerf integration guidance. Declare direct `uses` relationships so `Used by` stays derivable, and theme shell chrome through the same semantic tokens as the stage instead of drawing a substitute.
|
|
61
|
+
13. The Web Awesome theme makes Tooltip and Popover arrowless by default. Keep that default unless a pointer materially clarifies the anchor; opt back in with `--wa-tooltip-arrow-size`, `--kui-wa-popover-arrow-size`, or a popover's public `--arrow-size`, and use `without-arrow` when local no-arrow intent should survive theme changes.
|
|
62
|
+
14. Treat the complete Web Awesome catalog as support coverage, not a recommendation list. Consider Popup when it replaces custom anchored positioning. Prefer Kerf `Select` over direct Dropdown/Dropdown Item/Select/Option composition, `SegmentedControl` over Button Group, `TabBar` or `SegmentedControl` over Web Awesome Tabs, `LucideIcon` over Web Awesome Icon, and `ResizableRegion` over Split Panel. Use Tree/Tree Item, Animated Image, and Comparison only for a specific required behavior; avoid Zoomable Frame.
|
|
63
|
+
15. Build sidebars, main areas, inspectors, and dialogs from `@kerfjs/ui/layout.css`: an unpadded `.kui-pane`, optional `.kui-pane__toolbar`, one scrolling `.kui-pane__content`, and optional `.kui-pane__footer`. Add `.kui-content` for 24px major vertical separation and `.kui-content-item` for a child-owned 8px inline margin, 1px transparent-or-visible border, 8px padding, and 12px radius. Use the pill modifier for 22px. Do not pad pane shells or duplicate item geometry in wrappers.
|
|
64
|
+
16. Keep a visible collapsible pane's collapse control in its own toolbar. When hidden, move its restore control into the adjacent main toolbar on the corresponding logical edge: leading for an inline-start sidebar and trailing for an inline-end inspector. Collapse the pane completely; do not preserve an empty icon-only rail.
|
|
65
|
+
16. Wrap every toolbar item, including dormant text, in `ToolbarControlGroup`. A group remains 44px outside (`calc(2px + remify(42px))`) when its border/background are transparent; use 8px between groups and inside items. Split dormant and interactive regions: `MenuHeader` fills the available inline width and keeps its label and mutually exclusive semantic count or non-count `badge` together, with an independent logical-end 44px action unless disclosure mode makes the title cluster the button. Its action visual defaults to 18px through `--kui-menu-header-action-icon-size`; never shrink the target to match it. Pass every non-negative safe-integer section quantity through `count` with a localized full spoken `countLabel`; never concatenate it into `label` or put a number in `badge`. `MenuItem.trailing` is dormant; use `MenuActionRow` when primary and trailing actions need sibling 44px native buttons. Its `label`, `icon`, and `trailingActionIcon` slots are also dormant and cannot contain controls. Let panes relocate at narrow widths instead of shrinking targets.
|
|
66
|
+
17. When a recurring concept has no matching export or production recipe, keep its semantics in a thin application adapter while reusing the public layout vocabulary. The composer recipe uses one visible form surface, `DialogHeader` title/summary ids, shared 8px field/action gutters, 24px major rhythm, and a conditional StateBanner as its only nested semantic surface; do not turn every section into a card or double-inset intrinsically bordered controls. The application-local `../docs/examples/command-palette-adapter.tsx` is reference source for one such missing concept, not an `@kerfjs/ui` runtime export or catalog recipe. The application owns its registration, ranking, history, permissions, availability, shortcut policy, focus policy, dispatch, and copy. If a missing concept recurs across products, open an upstream component or recipe request.
|
|
67
|
+
18. Compose `ValueTable` from typed `ValueTableRow` entries instead of handwritten `dt`/`dd` wrappers. Pass `icon` for the optional 24px leading visual; the row owns 8px of root-scaled top and bottom padding, the 8px iconless or 40px icon-bearing separator start, and the common 8px right inset.
|
|
68
|
+
19. Use `DialogHeader` for dialog hierarchy, not a custom heading row. Its real top `Toolbar` puts the optional 24px icon in a 34px circular background and the first title line in a borderless `ToolbarControlGroup`, centered against the automatic action `ToolbarControlGroup`; pass action children directly and add a localized `actionsLabel` when that group needs a name. Its optional `summary`/`summaryId` row stays below the title. The app owns modal behavior, focus, dismissal, command policy, and action handling.
|
|
26
69
|
|
|
27
70
|
Common mistakes:
|
|
28
71
|
|
|
@@ -31,8 +74,19 @@ Common mistakes:
|
|
|
31
74
|
| Hard-coded project/transport action in a component | Pass a semantic `data-action` string from an application adapter |
|
|
32
75
|
| Per-instance signal at module scope | Create state in the application or a factory and pass it in |
|
|
33
76
|
| `role="menuitem"` on one button | Use the native button, or implement the complete ARIA menu widget |
|
|
77
|
+
| Put a button/link/interactive role in `MenuItem.trailing` or a `MenuActionRow` SafeHtml slot | Use `MenuActionRow` for the sibling controls and keep its label/icon slots dormant |
|
|
78
|
+
| Copy MenuItem/MenuHeader markup to add product data or a popover target | Use the typed `rootAttributes`/`triggerAttributes` slots and retain the component's protected semantics |
|
|
79
|
+
| Concatenate a section count into a MenuHeader label or numeric badge | Pass `count={value}` and a localized full phrase such as `countLabel="3 notes"`; reserve `badge` for non-count SafeHtml |
|
|
80
|
+
| Put a chevron on navigation that reveals nothing | Remove it, or model a real controlled `MenuHeader` disclosure; omit `actionIcon` to use the production `DisclosureArrow` |
|
|
34
81
|
| Test only a custom-element attribute | Assert live property, emitted event, focus, and rendered output |
|
|
35
82
|
| Import all Web Awesome components | Import only `@kerfjs/ui/select/register` for `Select`, or individual Web Awesome modules for other controls; `webawesome.css` registers no JavaScript |
|
|
83
|
+
| Write `wa-*` JSX without activating its types | Add `import type {} from '@kerfjs/ui/webawesome'`; registration and theme imports remain separate |
|
|
36
84
|
| Maintain a root list of component styles | Import each visual component from its JS subpath; its reachable CSS follows automatically |
|
|
37
85
|
| Add demo-only markup for a production state | Add the state to the production component, then render that export in the catalog |
|
|
38
86
|
| Choose a listed ecosystem component by default | Apply the component-selection guidance above; catalog coverage means supported and themed, not preferred |
|
|
87
|
+
| Add sidebar-specific wrapper padding | Use the unpadded `.kui-pane`; let `MenuHeader`, `MenuItem`, and `.kui-content-item` own their 8/1/8 geometry |
|
|
88
|
+
| Put bare text or controls directly in a toolbar slot | Wrap every item in `ToolbarControlGroup`, using `appearance="borderless"` for transparent chrome |
|
|
89
|
+
| Let the document, pane, and list all scroll | Keep fixed chrome outside one `.kui-pane__content` scroll owner per pane |
|
|
90
|
+
| Invent an `@kerfjs/ui` command-palette export | Keep the semantics application-local, reuse public layout vocabulary, and propose recurring behavior upstream |
|
|
91
|
+
| Handwrite `ValueTable` row wrappers or compensate their padding or separators | Compose `ValueTableRow`; its root-scaled block padding, optional icon hook, and separator geometry are public contract |
|
|
92
|
+
| Rebuild a dialog heading or pre-wrap new `DialogHeader.actions` in groups | Pass action children directly; `DialogHeader` supplies aligned identity/action groups and keeps the optional subtitle below |
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Web Awesome JSX signatures for the UI authoring corpus
|
|
2
|
+
|
|
3
|
+
Generated from the emitted `@kerfjs/ui@5.0.0-beta.4` 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
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { KerfCustomElement } from 'kerfjs/jsx-runtime';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Opt-in Kerf JSX declarations for the Web Awesome elements supported by the
|
|
10
|
+
* @kerfjs/ui catalog. Import this module for type effects only; component
|
|
11
|
+
* registration remains an explicit application concern.
|
|
12
|
+
*/
|
|
13
|
+
declare module 'kerfjs/jsx-runtime' {
|
|
14
|
+
namespace JSX {
|
|
15
|
+
interface IntrinsicElements {
|
|
16
|
+
'wa-accordion': KerfCustomElement;
|
|
17
|
+
'wa-accordion-item': KerfCustomElement;
|
|
18
|
+
'wa-animated-image': KerfCustomElement;
|
|
19
|
+
'wa-animation': KerfCustomElement;
|
|
20
|
+
'wa-avatar': KerfCustomElement;
|
|
21
|
+
'wa-badge': KerfCustomElement;
|
|
22
|
+
'wa-breadcrumb': KerfCustomElement;
|
|
23
|
+
'wa-breadcrumb-item': KerfCustomElement;
|
|
24
|
+
'wa-select': KerfCustomElement & {
|
|
25
|
+
class?: string;
|
|
26
|
+
name?: string;
|
|
27
|
+
label?: string;
|
|
28
|
+
'aria-label'?: string;
|
|
29
|
+
value?: string;
|
|
30
|
+
placeholder?: string;
|
|
31
|
+
disabled?: boolean;
|
|
32
|
+
};
|
|
33
|
+
'wa-option': KerfCustomElement & {
|
|
34
|
+
value?: string;
|
|
35
|
+
};
|
|
36
|
+
'wa-button-group': KerfCustomElement;
|
|
37
|
+
'wa-callout': KerfCustomElement;
|
|
38
|
+
'wa-card': KerfCustomElement;
|
|
39
|
+
'wa-carousel': KerfCustomElement;
|
|
40
|
+
'wa-carousel-item': KerfCustomElement;
|
|
41
|
+
'wa-checkbox': KerfCustomElement;
|
|
42
|
+
'wa-checkbox-group': KerfCustomElement;
|
|
43
|
+
'wa-color-picker': KerfCustomElement;
|
|
44
|
+
'wa-comparison': KerfCustomElement;
|
|
45
|
+
'wa-copy-button': KerfCustomElement;
|
|
46
|
+
'wa-details': KerfCustomElement;
|
|
47
|
+
'wa-divider': KerfCustomElement;
|
|
48
|
+
'wa-dialog': KerfCustomElement;
|
|
49
|
+
'wa-drawer': KerfCustomElement;
|
|
50
|
+
'wa-button': KerfCustomElement & {
|
|
51
|
+
slot?: string;
|
|
52
|
+
appearance?: string;
|
|
53
|
+
'with-caret'?: boolean;
|
|
54
|
+
'aria-label'?: string;
|
|
55
|
+
};
|
|
56
|
+
'wa-dropdown': KerfCustomElement & {
|
|
57
|
+
placement?: string;
|
|
58
|
+
};
|
|
59
|
+
'wa-dropdown-item': KerfCustomElement;
|
|
60
|
+
'wa-format-bytes': KerfCustomElement;
|
|
61
|
+
'wa-format-date': KerfCustomElement;
|
|
62
|
+
'wa-format-number': KerfCustomElement;
|
|
63
|
+
'wa-icon': KerfCustomElement;
|
|
64
|
+
'wa-include': KerfCustomElement;
|
|
65
|
+
'wa-input': KerfCustomElement;
|
|
66
|
+
'wa-intersection-observer': KerfCustomElement;
|
|
67
|
+
'wa-known-date': KerfCustomElement;
|
|
68
|
+
'wa-markdown': KerfCustomElement;
|
|
69
|
+
'wa-mutation-observer': KerfCustomElement;
|
|
70
|
+
'wa-number-input': KerfCustomElement;
|
|
71
|
+
'wa-otp-input': KerfCustomElement;
|
|
72
|
+
'wa-page': KerfCustomElement;
|
|
73
|
+
'wa-pagination': KerfCustomElement;
|
|
74
|
+
'wa-popover': KerfCustomElement;
|
|
75
|
+
'wa-popup': KerfCustomElement;
|
|
76
|
+
'wa-progress-bar': KerfCustomElement;
|
|
77
|
+
'wa-progress-ring': KerfCustomElement;
|
|
78
|
+
'wa-qr-code': KerfCustomElement;
|
|
79
|
+
'wa-radio': KerfCustomElement;
|
|
80
|
+
'wa-radio-group': KerfCustomElement;
|
|
81
|
+
'wa-random-content': KerfCustomElement;
|
|
82
|
+
'wa-rating': KerfCustomElement;
|
|
83
|
+
'wa-relative-time': KerfCustomElement;
|
|
84
|
+
'wa-resize-observer': KerfCustomElement;
|
|
85
|
+
'wa-scroller': KerfCustomElement;
|
|
86
|
+
'wa-skeleton': KerfCustomElement;
|
|
87
|
+
'wa-slider': KerfCustomElement;
|
|
88
|
+
'wa-spinner': KerfCustomElement;
|
|
89
|
+
'wa-split-panel': KerfCustomElement;
|
|
90
|
+
'wa-switch': KerfCustomElement;
|
|
91
|
+
'wa-tab': KerfCustomElement;
|
|
92
|
+
'wa-tab-group': KerfCustomElement;
|
|
93
|
+
'wa-tab-panel': KerfCustomElement;
|
|
94
|
+
'wa-tag': KerfCustomElement;
|
|
95
|
+
'wa-textarea': KerfCustomElement;
|
|
96
|
+
'wa-time-input': KerfCustomElement;
|
|
97
|
+
'wa-toast': KerfCustomElement;
|
|
98
|
+
'wa-toast-item': KerfCustomElement;
|
|
99
|
+
'wa-tooltip': KerfCustomElement;
|
|
100
|
+
'wa-tree': KerfCustomElement;
|
|
101
|
+
'wa-tree-item': KerfCustomElement;
|
|
102
|
+
'wa-zoomable-frame': KerfCustomElement;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
package/dist/app-tab.d.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { SafeHtml } from 'kerfjs';
|
|
2
2
|
|
|
3
|
+
type AppTabRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
|
|
4
|
+
'data-component'?: never;
|
|
5
|
+
'data-action'?: never;
|
|
6
|
+
'data-tab-id'?: never;
|
|
7
|
+
'data-selected'?: never;
|
|
8
|
+
'data-tab-dragging'?: never;
|
|
9
|
+
'data-tab-drop-position'?: never;
|
|
10
|
+
}>;
|
|
3
11
|
interface AppTabProps {
|
|
4
12
|
id: string;
|
|
5
13
|
name: string;
|
|
@@ -8,11 +16,13 @@ interface AppTabProps {
|
|
|
8
16
|
draggable?: boolean;
|
|
9
17
|
leading?: SafeHtml;
|
|
10
18
|
trailing?: SafeHtml;
|
|
19
|
+
/** Decorative dormant content for the close button. Must not contain interactive descendants. */
|
|
20
|
+
closeIcon?: SafeHtml;
|
|
11
21
|
selectAction?: string;
|
|
12
22
|
closeAction?: string;
|
|
13
23
|
className?: string;
|
|
14
|
-
rootAttributes?:
|
|
24
|
+
rootAttributes?: AppTabRootAttributes;
|
|
15
25
|
}
|
|
16
|
-
declare function AppTab({ id, name, selected, closable, draggable, leading, trailing, selectAction, closeAction, className, rootAttributes }: AppTabProps): SafeHtml;
|
|
26
|
+
declare function AppTab({ id, name, selected, closable, draggable, leading, trailing, closeIcon, selectAction, closeAction, className, rootAttributes }: AppTabProps): SafeHtml;
|
|
17
27
|
|
|
18
28
|
export { AppTab, type AppTabProps };
|
package/dist/app-tab.js
CHANGED
package/dist/browser/app-tab.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import '
|
|
2
|
-
import '
|
|
1
|
+
import '../styles/foundation.css';
|
|
2
|
+
import '../styles/app-tab.css';
|
|
3
3
|
export * from '../app-tab.js';
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
import '
|
|
2
|
-
import '
|
|
1
|
+
import '../styles/foundation.css';
|
|
2
|
+
import '../styles/toolbar.css';
|
|
3
|
+
import '../styles/toolbar-control-group.css';
|
|
4
|
+
import '../styles/dialog-header.css';
|
|
3
5
|
export * from '../dialog-header.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import '
|
|
2
|
-
import '
|
|
3
|
-
import '
|
|
1
|
+
import '../styles/foundation.css';
|
|
2
|
+
import '../styles/loading-spinner.css';
|
|
3
|
+
import '../styles/empty-state.css';
|
|
4
4
|
export * from '../empty-state.js';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import '
|
|
2
|
-
import '
|
|
1
|
+
import '../styles/foundation.css';
|
|
2
|
+
import '../styles/loading-spinner.css';
|
|
3
3
|
export * from '../loading-spinner.js';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import '
|
|
2
|
-
import '
|
|
1
|
+
import '../styles/foundation.css';
|
|
2
|
+
import '../styles/lucide-icon.css';
|
|
3
3
|
export * from '../lucide-icon.js';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import '
|
|
2
|
-
import '
|
|
1
|
+
import '../styles/foundation.css';
|
|
2
|
+
import '../styles/menu-item.css';
|
|
3
3
|
export * from '../menu-item.js';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import '
|
|
2
|
-
import '
|
|
1
|
+
import '../styles/foundation.css';
|
|
2
|
+
import '../styles/page-header.css';
|
|
3
3
|
export * from '../page-header.js';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import '
|
|
2
|
-
import '
|
|
1
|
+
import '../styles/foundation.css';
|
|
2
|
+
import '../styles/resizable-region.css';
|
|
3
3
|
export * from '../resizable-region.js';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import '
|
|
2
|
-
import '
|
|
1
|
+
import '../styles/foundation.css';
|
|
2
|
+
import '../styles/segmented-control.css';
|
|
3
3
|
export * from '../segmented-control.js';
|
package/dist/browser/select.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import '
|
|
2
|
-
import '
|
|
3
|
-
import '
|
|
1
|
+
import '../styles/foundation.css';
|
|
2
|
+
import '../styles/lucide-icon.css';
|
|
3
|
+
import '../styles/select.css';
|
|
4
4
|
export * from '../select.js';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import '
|
|
2
|
-
import '
|
|
1
|
+
import '../styles/foundation.css';
|
|
2
|
+
import '../styles/state-banner.css';
|
|
3
3
|
export * from '../state-banner.js';
|
package/dist/browser/tab-bar.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import '
|
|
2
|
-
import '
|
|
1
|
+
import '../styles/foundation.css';
|
|
2
|
+
import '../styles/tab-bar.css';
|
|
3
3
|
export * from '../tab-bar.js';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import '
|
|
2
|
-
import '
|
|
1
|
+
import '../styles/foundation.css';
|
|
2
|
+
import '../styles/toolbar-control-group.css';
|
|
3
3
|
export * from '../toolbar-control-group.js';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import '
|
|
2
|
-
import '
|
|
1
|
+
import '../styles/foundation.css';
|
|
2
|
+
import '../styles/toolbar-text.css';
|
|
3
3
|
export * from '../toolbar-text.js';
|
package/dist/browser/toolbar.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import '
|
|
2
|
-
import '
|
|
1
|
+
import '../styles/foundation.css';
|
|
2
|
+
import '../styles/toolbar.css';
|
|
3
3
|
export * from '../toolbar.js';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import '
|
|
2
|
-
import '
|
|
1
|
+
import '../styles/foundation.css';
|
|
2
|
+
import '../styles/value-table.css';
|
|
3
3
|
export * from '../value-table.js';
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { LucideIcon } from './chunk-W2FK7ZNY.js';
|
|
2
|
+
import { ChevronRight } from 'lucide';
|
|
3
|
+
import { jsx } from 'kerfjs/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
var directionRotations = {
|
|
6
|
+
right: 0,
|
|
7
|
+
down: 90,
|
|
8
|
+
left: 180,
|
|
9
|
+
up: 270
|
|
10
|
+
};
|
|
11
|
+
function rotationForState(open, openDirection, closedDirection) {
|
|
12
|
+
const closedRotation = directionRotations[closedDirection];
|
|
13
|
+
if (!open) return closedRotation;
|
|
14
|
+
const openRotation = directionRotations[openDirection];
|
|
15
|
+
const shortestDelta = (openRotation - closedRotation + 540) % 360 - 180;
|
|
16
|
+
return closedRotation + shortestDelta;
|
|
17
|
+
}
|
|
18
|
+
function DisclosureArrow({
|
|
19
|
+
open,
|
|
20
|
+
openDirection = "down",
|
|
21
|
+
closedDirection = "right",
|
|
22
|
+
icon,
|
|
23
|
+
className = ""
|
|
24
|
+
}) {
|
|
25
|
+
const direction = open ? openDirection : closedDirection;
|
|
26
|
+
const rotation = rotationForState(open, openDirection, closedDirection);
|
|
27
|
+
return /* @__PURE__ */ jsx(
|
|
28
|
+
"span",
|
|
29
|
+
{
|
|
30
|
+
class: `kui-disclosure-arrow ${className}`.trim(),
|
|
31
|
+
style: `--_kui-disclosure-arrow-rotation:${rotation}deg`,
|
|
32
|
+
"data-component": "disclosure-arrow",
|
|
33
|
+
"data-open": String(open),
|
|
34
|
+
"data-direction": direction,
|
|
35
|
+
"aria-hidden": "true",
|
|
36
|
+
children: icon ?? /* @__PURE__ */ jsx(LucideIcon, { icon: ChevronRight, name: "chevron-right" })
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export { DisclosureArrow };
|
|
42
|
+
|
|
43
|
+
//# sourceMappingURL=chunk-56RJXPHG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/disclosure-arrow.tsx"],"names":[],"mappings":";;;;AAgBA,IAAM,kBAAA,GAA0D;AAAA,EAC9D,KAAA,EAAO,CAAA;AAAA,EACP,IAAA,EAAM,EAAA;AAAA,EACN,IAAA,EAAM,GAAA;AAAA,EACN,EAAA,EAAI;AACN,CAAA;AAEA,SAAS,gBAAA,CACP,IAAA,EACA,aAAA,EACA,eAAA,EACA;AACA,EAAA,MAAM,cAAA,GAAiB,mBAAmB,eAAe,CAAA;AACzD,EAAA,IAAI,CAAC,MAAM,OAAO,cAAA;AAElB,EAAA,MAAM,YAAA,GAAe,mBAAmB,aAAa,CAAA;AACrD,EAAA,MAAM,aAAA,GAAA,CAAiB,YAAA,GAAe,cAAA,GAAiB,GAAA,IAAO,GAAA,GAAM,GAAA;AACpE,EAAA,OAAO,cAAA,GAAiB,aAAA;AAC1B;AAEO,SAAS,eAAA,CAAgB;AAAA,EAC9B,IAAA;AAAA,EACA,aAAA,GAAgB,MAAA;AAAA,EAChB,eAAA,GAAkB,OAAA;AAAA,EAClB,IAAA;AAAA,EACA,SAAA,GAAY;AACd,CAAA,EAAyB;AACvB,EAAA,MAAM,SAAA,GAAY,OAAO,aAAA,GAAgB,eAAA;AACzC,EAAA,MAAM,QAAA,GAAW,gBAAA,CAAiB,IAAA,EAAM,aAAA,EAAe,eAAe,CAAA;AACtE,EAAA,uBAAO,GAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACN,KAAA,EAAO,CAAA,qBAAA,EAAwB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK;AAAA,MAChD,KAAA,EAAO,oCAAoC,QAAQ,CAAA,GAAA,CAAA;AAAA,MACnD,gBAAA,EAAe,kBAAA;AAAA,MACf,WAAA,EAAW,OAAO,IAAI,CAAA;AAAA,MACtB,gBAAA,EAAgB,SAAA;AAAA,MAChB,aAAA,EAAY,MAAA;AAAA,MACZ,kCAAQ,GAAA,CAAC,UAAA,EAAA,EAAW,IAAA,EAAM,YAAA,EAAc,MAAK,eAAA,EAAgB;AAAA;AAAA,GAAG;AACpE","file":"chunk-56RJXPHG.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\nimport { ChevronRight } from 'lucide';\n\nimport { LucideIcon } from './lucide-icon.js';\n\nexport type DisclosureDirection = 'up' | 'down' | 'left' | 'right';\n\nexport interface DisclosureArrowProps {\n open: boolean;\n openDirection?: DisclosureDirection;\n closedDirection?: DisclosureDirection;\n /** Replacement icons should use right as their unrotated orientation. */\n icon?: SafeHtml;\n className?: string;\n}\n\nconst directionRotations: Record<DisclosureDirection, number> = {\n right: 0,\n down: 90,\n left: 180,\n up: 270,\n};\n\nfunction rotationForState(\n open: boolean,\n openDirection: DisclosureDirection,\n closedDirection: DisclosureDirection,\n) {\n const closedRotation = directionRotations[closedDirection];\n if (!open) return closedRotation;\n\n const openRotation = directionRotations[openDirection];\n const shortestDelta = (openRotation - closedRotation + 540) % 360 - 180;\n return closedRotation + shortestDelta;\n}\n\nexport function DisclosureArrow({\n open,\n openDirection = 'down',\n closedDirection = 'right',\n icon,\n className = '',\n}: DisclosureArrowProps) {\n const direction = open ? openDirection : closedDirection;\n const rotation = rotationForState(open, openDirection, closedDirection);\n return <span\n class={`kui-disclosure-arrow ${className}`.trim()}\n style={`--_kui-disclosure-arrow-rotation:${rotation}deg`}\n data-component=\"disclosure-arrow\"\n data-open={String(open)}\n data-direction={direction}\n aria-hidden=\"true\"\n >{icon ?? <LucideIcon icon={ChevronRight} name=\"chevron-right\" />}</span>;\n}\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// src/extension-attributes.ts
|
|
2
|
+
var DATA_ATTRIBUTE_NAME = /^data-[a-z0-9_.:-]+$/;
|
|
3
|
+
var POPOVER_TARGET_ACTIONS = /* @__PURE__ */ new Set(["toggle", "show", "hide"]);
|
|
4
|
+
var ARIA_HASPOPUP_VALUES = /* @__PURE__ */ new Set(["dialog", "menu", "listbox", "tree", "grid", "true"]);
|
|
5
|
+
function filterDataAttributes(attributes, protectedNames) {
|
|
6
|
+
const filtered = {};
|
|
7
|
+
for (const [name, value] of Object.entries(attributes)) {
|
|
8
|
+
const normalizedName = name.toLowerCase();
|
|
9
|
+
if (typeof value === "string" && DATA_ATTRIBUTE_NAME.test(normalizedName) && !protectedNames.has(normalizedName)) {
|
|
10
|
+
filtered[normalizedName] = value;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return filtered;
|
|
14
|
+
}
|
|
15
|
+
function filterControlAttributes(attributes, protectedDataNames) {
|
|
16
|
+
const source = attributes;
|
|
17
|
+
const filtered = filterDataAttributes(attributes, protectedDataNames);
|
|
18
|
+
if (typeof source.popoverTarget === "string") filtered.popoverTarget = source.popoverTarget;
|
|
19
|
+
if (POPOVER_TARGET_ACTIONS.has(source.popoverTargetAction)) {
|
|
20
|
+
filtered.popoverTargetAction = source.popoverTargetAction;
|
|
21
|
+
}
|
|
22
|
+
if (typeof source["aria-controls"] === "string") filtered["aria-controls"] = source["aria-controls"];
|
|
23
|
+
if (ARIA_HASPOPUP_VALUES.has(source["aria-haspopup"])) {
|
|
24
|
+
filtered["aria-haspopup"] = source["aria-haspopup"];
|
|
25
|
+
}
|
|
26
|
+
return filtered;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { filterControlAttributes, filterDataAttributes };
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=chunk-7BR3DO2A.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/extension-attributes.ts"],"names":[],"mappings":";AAEA,IAAM,mBAAA,GAAsB,sBAAA;AAC5B,IAAM,yCAAyB,IAAI,GAAA,CAAI,CAAC,QAAA,EAAU,MAAA,EAAQ,MAAM,CAAC,CAAA;AACjE,IAAM,oBAAA,mBAAuB,IAAI,GAAA,CAAI,CAAC,QAAA,EAAU,QAAQ,SAAA,EAAW,MAAA,EAAQ,MAAA,EAAQ,MAAM,CAAC,CAAA;AAEnF,SAAS,oBAAA,CACd,YACA,cAAA,EACwB;AACxB,EAAA,MAAM,WAAmC,EAAC;AAE1C,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,UAA0B,CAAA,EAAG;AACtE,IAAA,MAAM,cAAA,GAAiB,KAAK,WAAA,EAAY;AACxC,IAAA,IACE,OAAO,KAAA,KAAU,QAAA,IACd,mBAAA,CAAoB,IAAA,CAAK,cAAc,CAAA,IACvC,CAAC,cAAA,CAAe,GAAA,CAAI,cAAc,CAAA,EACrC;AACA,MAAA,QAAA,CAAS,cAAc,CAAA,GAAI,KAAA;AAAA,IAC7B;AAAA,EACF;AAEA,EAAA,OAAO,QAAA;AACT;AAEO,SAAS,uBAAA,CACd,YACA,kBAAA,EACwB;AACxB,EAAA,MAAM,MAAA,GAAS,UAAA;AACf,EAAA,MAAM,QAAA,GAAW,oBAAA,CAAqB,UAAA,EAAY,kBAAkB,CAAA;AAEpE,EAAA,IAAI,OAAO,MAAA,CAAO,aAAA,KAAkB,QAAA,EAAU,QAAA,CAAS,gBAAgB,MAAA,CAAO,aAAA;AAC9E,EAAA,IAAI,sBAAA,CAAuB,GAAA,CAAI,MAAA,CAAO,mBAA6B,CAAA,EAAG;AACpE,IAAA,QAAA,CAAS,sBAAsB,MAAA,CAAO,mBAAA;AAAA,EACxC;AACA,EAAA,IAAI,OAAO,OAAO,eAAe,CAAA,KAAM,UAAU,QAAA,CAAS,eAAe,CAAA,GAAI,MAAA,CAAO,eAAe,CAAA;AACnG,EAAA,IAAI,oBAAA,CAAqB,GAAA,CAAI,MAAA,CAAO,eAAe,CAAW,CAAA,EAAG;AAC/D,IAAA,QAAA,CAAS,eAAe,CAAA,GAAI,MAAA,CAAO,eAAe,CAAA;AAAA,EACpD;AAEA,EAAA,OAAO,QAAA;AACT","file":"chunk-7BR3DO2A.js","sourcesContent":["type AttributeBag = Readonly<Record<string, unknown>>;\n\nconst DATA_ATTRIBUTE_NAME = /^data-[a-z0-9_.:-]+$/;\nconst POPOVER_TARGET_ACTIONS = new Set(['toggle', 'show', 'hide']);\nconst ARIA_HASPOPUP_VALUES = new Set(['dialog', 'menu', 'listbox', 'tree', 'grid', 'true']);\n\nexport function filterDataAttributes(\n attributes: object,\n protectedNames: ReadonlySet<string>,\n): Record<string, string> {\n const filtered: Record<string, string> = {};\n\n for (const [name, value] of Object.entries(attributes as AttributeBag)) {\n const normalizedName = name.toLowerCase();\n if (\n typeof value === 'string'\n && DATA_ATTRIBUTE_NAME.test(normalizedName)\n && !protectedNames.has(normalizedName)\n ) {\n filtered[normalizedName] = value;\n }\n }\n\n return filtered;\n}\n\nexport function filterControlAttributes(\n attributes: object,\n protectedDataNames: ReadonlySet<string>,\n): Record<string, string> {\n const source = attributes as AttributeBag;\n const filtered = filterDataAttributes(attributes, protectedDataNames);\n\n if (typeof source.popoverTarget === 'string') filtered.popoverTarget = source.popoverTarget;\n if (POPOVER_TARGET_ACTIONS.has(source.popoverTargetAction as string)) {\n filtered.popoverTargetAction = source.popoverTargetAction as string;\n }\n if (typeof source['aria-controls'] === 'string') filtered['aria-controls'] = source['aria-controls'];\n if (ARIA_HASPOPUP_VALUES.has(source['aria-haspopup'] as string)) {\n filtered['aria-haspopup'] = source['aria-haspopup'] as string;\n }\n\n return filtered;\n}\n"]}
|