@kerfjs/ui 4.4.1
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/LICENSE +21 -0
- package/README.md +176 -0
- package/ai/skill.md +38 -0
- package/dist/app-tab.d.ts +18 -0
- package/dist/app-tab.js +3 -0
- package/dist/app-tab.js.map +1 -0
- package/dist/browser/app-tab.js +3 -0
- package/dist/browser/dialog-header.js +3 -0
- package/dist/browser/empty-state.js +4 -0
- package/dist/browser/loading-spinner.js +3 -0
- package/dist/browser/lucide-icon.js +3 -0
- package/dist/browser/menu-header.js +3 -0
- package/dist/browser/menu-item.js +3 -0
- package/dist/browser/page-header.js +3 -0
- package/dist/browser/resizable-region.js +3 -0
- package/dist/browser/segmented-control.js +3 -0
- package/dist/browser/select.js +4 -0
- package/dist/browser/state-banner.js +3 -0
- package/dist/browser/tab-bar.js +3 -0
- package/dist/browser/toolbar-control-group.js +3 -0
- package/dist/browser/toolbar-text.js +3 -0
- package/dist/browser/toolbar.js +3 -0
- package/dist/browser/value-table.js +3 -0
- package/dist/chunk-2PES33HS.js +13 -0
- package/dist/chunk-2PES33HS.js.map +1 -0
- package/dist/chunk-3O7ZEUW2.js +27 -0
- package/dist/chunk-3O7ZEUW2.js.map +1 -0
- package/dist/chunk-4HHCYSGT.js +79 -0
- package/dist/chunk-4HHCYSGT.js.map +1 -0
- package/dist/chunk-55DATV3A.js +10 -0
- package/dist/chunk-55DATV3A.js.map +1 -0
- package/dist/chunk-723YNJBH.js +17 -0
- package/dist/chunk-723YNJBH.js.map +1 -0
- package/dist/chunk-DAFFDO33.js +14 -0
- package/dist/chunk-DAFFDO33.js.map +1 -0
- package/dist/chunk-GY5WH7TO.js +10 -0
- package/dist/chunk-GY5WH7TO.js.map +1 -0
- package/dist/chunk-MBR3TYNL.js +14 -0
- package/dist/chunk-MBR3TYNL.js.map +1 -0
- package/dist/chunk-MFKMHK5W.js +10 -0
- package/dist/chunk-MFKMHK5W.js.map +1 -0
- package/dist/chunk-MQIZAD4A.js +227 -0
- package/dist/chunk-MQIZAD4A.js.map +1 -0
- package/dist/chunk-NHXX4JI5.js +28 -0
- package/dist/chunk-NHXX4JI5.js.map +1 -0
- package/dist/chunk-OPCJRCYO.js +19 -0
- package/dist/chunk-OPCJRCYO.js.map +1 -0
- package/dist/chunk-T5XNMVOI.js +24 -0
- package/dist/chunk-T5XNMVOI.js.map +1 -0
- package/dist/chunk-TRNBHPNW.js +54 -0
- package/dist/chunk-TRNBHPNW.js.map +1 -0
- package/dist/chunk-VHW5YNIB.js +17 -0
- package/dist/chunk-VHW5YNIB.js.map +1 -0
- package/dist/chunk-VKH2JLDZ.js +10 -0
- package/dist/chunk-VKH2JLDZ.js.map +1 -0
- package/dist/chunk-W2FK7ZNY.js +26 -0
- package/dist/chunk-W2FK7ZNY.js.map +1 -0
- package/dist/chunk-WVPYVDXY.js +15 -0
- package/dist/chunk-WVPYVDXY.js.map +1 -0
- package/dist/chunk-WY4CAEPG.js +14 -0
- package/dist/chunk-WY4CAEPG.js.map +1 -0
- package/dist/dialog-header.d.ts +14 -0
- package/dist/dialog-header.js +3 -0
- package/dist/dialog-header.js.map +1 -0
- package/dist/empty-state.d.ts +13 -0
- package/dist/empty-state.js +4 -0
- package/dist/empty-state.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/loading-spinner.d.ts +10 -0
- package/dist/loading-spinner.js +3 -0
- package/dist/loading-spinner.js.map +1 -0
- package/dist/lucide-icon.d.ts +14 -0
- package/dist/lucide-icon.js +3 -0
- package/dist/lucide-icon.js.map +1 -0
- package/dist/menu-header.d.ts +15 -0
- package/dist/menu-header.js +3 -0
- package/dist/menu-header.js.map +1 -0
- package/dist/menu-item.d.ts +22 -0
- package/dist/menu-item.js +3 -0
- package/dist/menu-item.js.map +1 -0
- package/dist/page-header.d.ts +9 -0
- package/dist/page-header.js +3 -0
- package/dist/page-header.js.map +1 -0
- package/dist/resizable-region.d.ts +21 -0
- package/dist/resizable-region.js +3 -0
- package/dist/resizable-region.js.map +1 -0
- package/dist/segmented-control.d.ts +28 -0
- package/dist/segmented-control.js +3 -0
- package/dist/segmented-control.js.map +1 -0
- package/dist/select-register.d.ts +4 -0
- package/dist/select-register.js +10 -0
- package/dist/select-register.js.map +1 -0
- package/dist/select.d.ts +28 -0
- package/dist/select.js +4 -0
- package/dist/select.js.map +1 -0
- package/dist/state-banner.d.ts +15 -0
- package/dist/state-banner.js +3 -0
- package/dist/state-banner.js.map +1 -0
- package/dist/tab-bar.d.ts +14 -0
- package/dist/tab-bar.js +3 -0
- package/dist/tab-bar.js.map +1 -0
- package/dist/toolbar-control-group.d.ts +15 -0
- package/dist/toolbar-control-group.js +3 -0
- package/dist/toolbar-control-group.js.map +1 -0
- package/dist/toolbar-text.d.ts +11 -0
- package/dist/toolbar-text.js +3 -0
- package/dist/toolbar-text.js.map +1 -0
- package/dist/toolbar.d.ts +13 -0
- package/dist/toolbar.js +3 -0
- package/dist/toolbar.js.map +1 -0
- package/dist/value-table.d.ts +10 -0
- package/dist/value-table.js +3 -0
- package/dist/value-table.js.map +1 -0
- package/dist/wire-resizable-regions.d.ts +15 -0
- package/dist/wire-resizable-regions.js +4 -0
- package/dist/wire-resizable-regions.js.map +1 -0
- package/dist/wire-tab-bars.d.ts +17 -0
- package/dist/wire-tab-bars.js +3 -0
- package/dist/wire-tab-bars.js.map +1 -0
- package/docs/accessibility.md +56 -0
- package/docs/apple-hig.md +40 -0
- package/docs/component-contract.md +66 -0
- package/docs/design-philosophy.md +63 -0
- package/docs/ux-demo.md +18 -0
- package/docs/webawesome-theme.md +181 -0
- package/llms.txt +22 -0
- package/package.json +218 -0
- package/src/app-tab.css +20 -0
- package/src/dialog-header.css +9 -0
- package/src/empty-state.css +6 -0
- package/src/foundation.css +106 -0
- package/src/loading-spinner.css +4 -0
- package/src/lucide-icon.css +1 -0
- package/src/menu-header.css +13 -0
- package/src/menu-item.css +12 -0
- package/src/page-header.css +3 -0
- package/src/resizable-region.css +19 -0
- package/src/segmented-control.css +138 -0
- package/src/select.css +18 -0
- package/src/state-banner.css +31 -0
- package/src/styles.css +18 -0
- package/src/tab-bar.css +4 -0
- package/src/toolbar-control-group.css +25 -0
- package/src/toolbar-text.css +4 -0
- package/src/toolbar.css +9 -0
- package/src/value-table.css +5 -0
- package/src/webawesome.css +178 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Brian Westphal
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# @kerfjs/ui
|
|
2
|
+
|
|
3
|
+
Accessible, composable UI primitives for [kerf](https://github.com/brianwestphal/kerf). The package ships production components, component-reachable CSS, accessibility and keyboard contracts, an AI-readable guide, and a production-backed UX catalog.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install kerfjs @kerfjs/ui
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { MenuItem } from '@kerfjs/ui/menu-item';
|
|
11
|
+
import { Toolbar } from '@kerfjs/ui/toolbar';
|
|
12
|
+
import { ToolbarText } from '@kerfjs/ui/toolbar-text';
|
|
13
|
+
|
|
14
|
+
mount(root, () => <>
|
|
15
|
+
<Toolbar label="Document" leading={<ToolbarText text="Notes" />} />
|
|
16
|
+
<MenuItem action="open-notes" label="Notes" selected />
|
|
17
|
+
</>);
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Components return Kerf `SafeHtml`. They do not own application state or attach transient listeners. Actions are stable `data-action` hooks; the application wires them once with `delegate()` or `delegateActions()` and retains the disposer.
|
|
21
|
+
|
|
22
|
+
## Component subpaths
|
|
23
|
+
|
|
24
|
+
| Component | Browser import (includes reachable CSS) | Manual CSS export |
|
|
25
|
+
| --- | --- | --- |
|
|
26
|
+
| `LucideIcon` | `@kerfjs/ui/lucide-icon` | `@kerfjs/ui/lucide-icon.css` |
|
|
27
|
+
| `Toolbar` | `@kerfjs/ui/toolbar` | `@kerfjs/ui/toolbar.css` |
|
|
28
|
+
| `ToolbarControlGroup` | `@kerfjs/ui/toolbar-control-group` | `@kerfjs/ui/toolbar-control-group.css` |
|
|
29
|
+
| `ToolbarText` | `@kerfjs/ui/toolbar-text` | `@kerfjs/ui/toolbar-text.css` |
|
|
30
|
+
| `MenuItem` | `@kerfjs/ui/menu-item` | `@kerfjs/ui/menu-item.css` |
|
|
31
|
+
| `MenuHeader` | `@kerfjs/ui/menu-header` | `@kerfjs/ui/menu-header.css` |
|
|
32
|
+
| `ResizableRegion` | `@kerfjs/ui/resizable-region` | `@kerfjs/ui/resizable-region.css` |
|
|
33
|
+
| `wireResizableRegions` | `@kerfjs/ui/wire-resizable-regions` | — |
|
|
34
|
+
| `AppTab` | `@kerfjs/ui/app-tab` | `@kerfjs/ui/app-tab.css` |
|
|
35
|
+
| `TabBar` | `@kerfjs/ui/tab-bar` | `@kerfjs/ui/tab-bar.css` |
|
|
36
|
+
| `wireTabBars`, `reorderTabs` | `@kerfjs/ui/wire-tab-bars` | — |
|
|
37
|
+
| `PageHeader` | `@kerfjs/ui/page-header` | `@kerfjs/ui/page-header.css` |
|
|
38
|
+
| `LoadingSpinner` | `@kerfjs/ui/loading-spinner` | `@kerfjs/ui/loading-spinner.css` |
|
|
39
|
+
| `Select` | `@kerfjs/ui/select` | `@kerfjs/ui/select.css` |
|
|
40
|
+
| `SegmentedControl` | `@kerfjs/ui/segmented-control` | `@kerfjs/ui/segmented-control.css` |
|
|
41
|
+
| `StateBanner` | `@kerfjs/ui/state-banner` | `@kerfjs/ui/state-banner.css` |
|
|
42
|
+
| `EmptyState` | `@kerfjs/ui/empty-state` | `@kerfjs/ui/empty-state.css` |
|
|
43
|
+
| `DialogHeader` | `@kerfjs/ui/dialog-header` | `@kerfjs/ui/dialog-header.css` |
|
|
44
|
+
| `ValueTable` | `@kerfjs/ui/value-table` | `@kerfjs/ui/value-table.css` |
|
|
45
|
+
|
|
46
|
+
Import components from their explicit JavaScript subpaths. CSS-aware browser
|
|
47
|
+
bundlers such as Vite, webpack, and esbuild follow each subpath's `browser`
|
|
48
|
+
condition, collect its foundation and component CSS, and retain styles for any
|
|
49
|
+
UI subcomponents it uses. Unrelated component CSS is never reached. Application
|
|
50
|
+
roots therefore do not need a transitive stylesheet list, and removing the last
|
|
51
|
+
component import also removes its reachable CSS. This is component-level CSS
|
|
52
|
+
tree shaking; variants within an imported component remain together.
|
|
53
|
+
|
|
54
|
+
The root `@kerfjs/ui` barrel stays JavaScript-only because making a side-effectful
|
|
55
|
+
CSS barrel tree-shakable is not portable across bundlers. If an application uses
|
|
56
|
+
that convenience import, also import `@kerfjs/ui/styles.css`, which deliberately
|
|
57
|
+
contains the complete layer. Non-browser/SSR tools resolve the pure `import`
|
|
58
|
+
condition automatically; `@kerfjs/ui/unstyled` is the explicit CSS-free root
|
|
59
|
+
entry for a browser build with a custom styling pipeline. The exported
|
|
60
|
+
`foundation.css` and component CSS paths remain available for fully manual
|
|
61
|
+
delivery. Load application overrides after package styles, or scope `--kui-*`
|
|
62
|
+
variables directly on a component instance.
|
|
63
|
+
|
|
64
|
+
## Web Awesome theme
|
|
65
|
+
|
|
66
|
+
Apps using Web Awesome's free components can opt into the same visual universe
|
|
67
|
+
with one CSS import:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import '@kerfjs/ui/webawesome.css';
|
|
71
|
+
import '@awesome.me/webawesome/dist/components/button/button.js';
|
|
72
|
+
import '@awesome.me/webawesome/dist/components/input/input.js';
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`webawesome.css` includes Web Awesome's native/base theme and then applies the
|
|
76
|
+
Hot Sheet 2 palette, surfaces, status colors, focus treatment, form geometry,
|
|
77
|
+
radii, tooltips, and shadows through Web Awesome's public `--wa-*` contract.
|
|
78
|
+
Those tokens flow into all free component families. Every free Web Awesome 3.12
|
|
79
|
+
component has an individual UX-catalog route under the collapsible ecosystem
|
|
80
|
+
section, but the theme entry does not import or register component JavaScript,
|
|
81
|
+
so each component module remains independently tree-shakeable in consuming apps.
|
|
82
|
+
Tooltip and Popover surfaces omit pointer arrows by default. Override
|
|
83
|
+
`--wa-tooltip-arrow-size` and `--kui-wa-popover-arrow-size`, or a single
|
|
84
|
+
popover's public `--arrow-size`, when an arrow communicates useful context.
|
|
85
|
+
|
|
86
|
+
Load application CSS afterward to override semantic values globally, or scope
|
|
87
|
+
them to a subtree. Use Web Awesome's `.wa-light`, `.wa-dark`, and `.wa-invert`
|
|
88
|
+
classes for explicit appearance boundaries:
|
|
89
|
+
|
|
90
|
+
```css
|
|
91
|
+
:root {
|
|
92
|
+
--wa-color-brand-fill-loud: #7540a8;
|
|
93
|
+
--wa-form-control-border-radius: .5rem;
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`foundation.css` follows Hot Sheet 2's Web Awesome-compatible semantic palette.
|
|
98
|
+
Brand, neutral, success, warning, and danger each expose fill, border, and
|
|
99
|
+
foreground roles through `--kui-color-*`; stateful components also expose
|
|
100
|
+
component variables such as `--kui-state-banner-background`. Override the
|
|
101
|
+
foundation for an application theme, a tone variable for one semantic state, or
|
|
102
|
+
a component variable on one instance without replacing component selectors.
|
|
103
|
+
|
|
104
|
+
`StateBanner` has opinionated `neutral`, `info`, `success`, `warning`, and
|
|
105
|
+
`danger` palettes. Override an individual banner with
|
|
106
|
+
`--kui-state-banner-background`, `--kui-state-banner-border`,
|
|
107
|
+
`--kui-state-banner-foreground`, `--kui-state-banner-detail`,
|
|
108
|
+
`--kui-state-banner-action-background`, and
|
|
109
|
+
`--kui-state-banner-action-hover-background`. To retheme one tone everywhere,
|
|
110
|
+
override `--kui-state-banner-{tone}-{background|border|foreground}`. Other
|
|
111
|
+
stateful components follow the same public-variable pattern, including
|
|
112
|
+
`--kui-toolbar-control-*`, `--kui-segmented-*`, `--kui-app-tab-*`, and
|
|
113
|
+
`--kui-tab-bar-*`.
|
|
114
|
+
|
|
115
|
+
`SegmentedControl` is a controlled exclusive-choice component. Use
|
|
116
|
+
`appearance="toolbar"` when it sits inside a `ToolbarControlGroup`, or choose a
|
|
117
|
+
standalone `filled`/`outlined` appearance with `shape="rounded"` or
|
|
118
|
+
`shape="pill"`. The app owns `value` and handles the supplied action:
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
<SegmentedControl
|
|
122
|
+
id="view-mode"
|
|
123
|
+
label="View mode"
|
|
124
|
+
value={viewMode.value}
|
|
125
|
+
action="select-view-mode"
|
|
126
|
+
appearance="toolbar"
|
|
127
|
+
shape="pill"
|
|
128
|
+
choices={[
|
|
129
|
+
{ value: 'list', label: 'List' },
|
|
130
|
+
{ value: 'columns', label: 'Columns' },
|
|
131
|
+
]}
|
|
132
|
+
/>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Each choice remains a native button in sequential Tab order and exposes its
|
|
136
|
+
value through `data-segment-value`. Override an instance through
|
|
137
|
+
`--kui-segmented-{background|border|foreground|hover-background}` and
|
|
138
|
+
`--kui-segmented-selected-{background|foreground|border|shadow}`.
|
|
139
|
+
|
|
140
|
+
`TabBar` is controlled: pass ordered `AppTab` children, then wire its keyboard
|
|
141
|
+
and same-bar drag behavior with `wireTabBars(root, { onReorder })`. During a
|
|
142
|
+
drag, the scroll strip automatically moves toward either edge with speed based
|
|
143
|
+
on pointer proximity, exposing earlier or later drop targets. Apply the reported
|
|
144
|
+
change with `reorderTabs()` or application-specific state logic. The application
|
|
145
|
+
still owns selection, closing, routing, and persistence.
|
|
146
|
+
|
|
147
|
+
`Select` uses Web Awesome but does not register anything by itself. Install the optional peer, import the shared theme if desired, and explicitly import the registration entry in the application:
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
import '@kerfjs/ui/webawesome.css';
|
|
151
|
+
import '@kerfjs/ui/select/register';
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
That boundary keeps Web Awesome and its custom-element side effects out of bundles that use unrelated components. Automated consumer-bundle tests enforce it.
|
|
155
|
+
|
|
156
|
+
For application choices and panes, prefer Kerf's purpose-built primitives:
|
|
157
|
+
`Select` over direct Web Awesome selection/dropdown composition,
|
|
158
|
+
`SegmentedControl` over Button Group, `TabBar` or `SegmentedControl` over Web
|
|
159
|
+
Awesome Tabs, `LucideIcon` over Web Awesome Icon, and `ResizableRegion` over
|
|
160
|
+
Split Panel. `ResizableRegion` includes Hot Sheet 2's 1px separator and
|
|
161
|
+
hover/focus grip. Consider Web Awesome Popup when its anchored-positioning
|
|
162
|
+
engine removes custom placement code; treat Tree, Animated Image, Comparison,
|
|
163
|
+
Zoomable Frame, and the displaced alternatives above as exceptional rather
|
|
164
|
+
than default patterns. The detailed rationale lives in the theme contract.
|
|
165
|
+
|
|
166
|
+
## Design and tool guidance
|
|
167
|
+
|
|
168
|
+
- [Design philosophy](./docs/design-philosophy.md)
|
|
169
|
+
- [Apple HIG translation](./docs/apple-hig.md)
|
|
170
|
+
- [Accessibility and keyboard contracts](./docs/accessibility.md)
|
|
171
|
+
- [Component and integration contract](./docs/component-contract.md)
|
|
172
|
+
- [Web Awesome theme contract](./docs/webawesome-theme.md)
|
|
173
|
+
- [UX catalog contract](./docs/ux-demo.md)
|
|
174
|
+
- [AI guide](./ai/skill.md)
|
|
175
|
+
|
|
176
|
+
Run `npm run dev` from this directory for the category-grouped master/detail catalog. Every public visual component has a focused route; all 70 free Web Awesome 3.12 components have focused routes under the collapsible ecosystem section. One grouped `Related components` selector contains derived `Uses` / `Used by` navigation across both sets. Run `npm run check` for static/unit/bundle gates and `npm run test:e2e` for the real-browser suite.
|
package/ai/skill.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kerf-ui
|
|
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.5.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Building with @kerfjs/ui
|
|
8
|
+
|
|
9
|
+
Read `../README.md`, `../docs/component-contract.md`, and `../docs/accessibility.md` before changing a consuming interface. Read `../docs/webawesome-theme.md` when using Web Awesome components or changing shared theme tokens.
|
|
10
|
+
|
|
11
|
+
Hard rules:
|
|
12
|
+
|
|
13
|
+
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
|
+
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.
|
|
16
|
+
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; do not hard-code appearance-specific colors or replace private descendant rules.
|
|
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 uses Web Awesome components, import the CSS-only `@kerfjs/ui/webawesome.css` theme once and keep importing individual Web Awesome component modules so their JavaScript remains tree-shakeable.
|
|
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.
|
|
21
|
+
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. 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. 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.
|
|
24
|
+
12. 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.
|
|
25
|
+
13. 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.
|
|
26
|
+
|
|
27
|
+
Common mistakes:
|
|
28
|
+
|
|
29
|
+
| Mistake | Fix |
|
|
30
|
+
| --- | --- |
|
|
31
|
+
| Hard-coded project/transport action in a component | Pass a semantic `data-action` string from an application adapter |
|
|
32
|
+
| Per-instance signal at module scope | Create state in the application or a factory and pass it in |
|
|
33
|
+
| `role="menuitem"` on one button | Use the native button, or implement the complete ARIA menu widget |
|
|
34
|
+
| Test only a custom-element attribute | Assert live property, emitted event, focus, and rendered output |
|
|
35
|
+
| 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 |
|
|
36
|
+
| Maintain a root list of component styles | Import each visual component from its JS subpath; its reachable CSS follows automatically |
|
|
37
|
+
| Add demo-only markup for a production state | Add the state to the production component, then render that export in the catalog |
|
|
38
|
+
| Choose a listed ecosystem component by default | Apply the component-selection guidance above; catalog coverage means supported and themed, not preferred |
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SafeHtml } from 'kerfjs';
|
|
2
|
+
|
|
3
|
+
interface AppTabProps {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
selected?: boolean;
|
|
7
|
+
closable?: boolean;
|
|
8
|
+
draggable?: boolean;
|
|
9
|
+
leading?: SafeHtml;
|
|
10
|
+
trailing?: SafeHtml;
|
|
11
|
+
selectAction?: string;
|
|
12
|
+
closeAction?: string;
|
|
13
|
+
className?: string;
|
|
14
|
+
rootAttributes?: Readonly<Record<`data-${string}`, string>>;
|
|
15
|
+
}
|
|
16
|
+
declare function AppTab({ id, name, selected, closable, draggable, leading, trailing, selectAction, closeAction, className, rootAttributes }: AppTabProps): SafeHtml;
|
|
17
|
+
|
|
18
|
+
export { AppTab, type AppTabProps };
|
package/dist/app-tab.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"app-tab.js"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'kerfjs/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
// src/page-header.tsx
|
|
4
|
+
function PageHeader({ title, action }) {
|
|
5
|
+
return /* @__PURE__ */ jsxs("header", { class: "kui-page-header", "data-component": "page-header", children: [
|
|
6
|
+
/* @__PURE__ */ jsx("h1", { children: title }),
|
|
7
|
+
action && /* @__PURE__ */ jsx("div", { class: "kui-page-header__action", children: action })
|
|
8
|
+
] });
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { PageHeader };
|
|
12
|
+
|
|
13
|
+
//# sourceMappingURL=chunk-2PES33HS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/page-header.tsx"],"names":[],"mappings":";;;AAOO,SAAS,UAAA,CAAW,EAAE,KAAA,EAAO,MAAA,EAAO,EAAoB;AAC7D,EAAA,uBAAO,IAAA,CAAC,QAAA,EAAA,EAAO,KAAA,EAAM,iBAAA,EAAkB,kBAAe,aAAA,EAAc,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,QAAI,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,IAAM,MAAA,oBAAU,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,2BAA2B,QAAA,EAAA,MAAA,EAAO;AAAA,GAAA,EAAO,CAAA;AACrJ","file":"chunk-2PES33HS.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nexport interface PageHeaderProps {\n title: string | SafeHtml;\n action?: SafeHtml;\n}\n\nexport function PageHeader({ title, action }: PageHeaderProps) {\n return <header class=\"kui-page-header\" data-component=\"page-header\"><h1>{title}</h1>{action && <div class=\"kui-page-header__action\">{action}</div>}</header>;\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsxs, jsx, Fragment } from 'kerfjs/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
// src/resizable-region.tsx
|
|
4
|
+
var clampRegionSize = (size, min, max) => Math.min(max, Math.max(min, Math.round(size)));
|
|
5
|
+
var resizeRegionFromPointer = (startSize, delta, edge) => startSize + delta * (edge === "start" ? -1 : 1);
|
|
6
|
+
function ResizeGrip({ axis }) {
|
|
7
|
+
return /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", children: axis === "horizontal" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8
|
+
/* @__PURE__ */ jsx("path", { d: "M9 6v12" }),
|
|
9
|
+
/* @__PURE__ */ jsx("path", { d: "M15 6v12" })
|
|
10
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
11
|
+
/* @__PURE__ */ jsx("path", { d: "M6 9h12" }),
|
|
12
|
+
/* @__PURE__ */ jsx("path", { d: "M6 15h12" })
|
|
13
|
+
] }) });
|
|
14
|
+
}
|
|
15
|
+
function ResizableRegion({ id, label, size, min, max, axis = "horizontal", edge = "end", collapsed = false, transitioning = false, children }) {
|
|
16
|
+
const expandedSize = clampRegionSize(size, min, max);
|
|
17
|
+
const resolved = collapsed ? 0 : expandedSize;
|
|
18
|
+
const orientation = axis === "horizontal" ? "vertical" : "horizontal";
|
|
19
|
+
return /* @__PURE__ */ jsxs("section", { class: "kui-resizable-region", "data-component": "resizable-region", "data-region-id": id, "data-axis": axis, "data-edge": edge, "data-collapsed": String(collapsed), "data-transitioning": String(transitioning), style: `--kui-resizable-region-size:${resolved}px;--kui-resizable-region-expanded-size:${expandedSize}px`, "aria-label": label, children: [
|
|
20
|
+
/* @__PURE__ */ jsx("div", { class: "kui-resizable-region__content", children }),
|
|
21
|
+
/* @__PURE__ */ jsx("div", { class: "kui-resizable-region__handle", role: "separator", tabindex: "0", "aria-label": `Resize ${label}`, "aria-orientation": orientation, "aria-valuemin": collapsed ? 0 : min, "aria-valuemax": max, "aria-valuenow": resolved, "data-kui-resize-handle": true, "data-region-id": id, children: /* @__PURE__ */ jsx(ResizeGrip, { axis }) })
|
|
22
|
+
] });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { ResizableRegion, clampRegionSize, resizeRegionFromPointer };
|
|
26
|
+
|
|
27
|
+
//# sourceMappingURL=chunk-3O7ZEUW2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resizable-region.tsx"],"names":[],"mappings":";;;AAkBO,IAAM,eAAA,GAAkB,CAAC,IAAA,EAAc,GAAA,EAAa,QAAgB,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,IAAA,CAAK,IAAI,GAAA,EAAK,IAAA,CAAK,KAAA,CAAM,IAAI,CAAC,CAAC;AACjH,IAAM,uBAAA,GAA0B,CAAC,SAAA,EAAmB,KAAA,EAAe,SAA8B,SAAA,GAAY,KAAA,IAAS,IAAA,KAAS,OAAA,GAAU,EAAA,GAAK,CAAA;AAErJ,SAAS,UAAA,CAAW,EAAE,IAAA,EAAK,EAAkC;AAC3D,EAAA,2BAAQ,KAAA,EAAA,EAAI,aAAA,EAAY,MAAA,EAAO,OAAA,EAAQ,aAAY,IAAA,EAAK,MAAA,EAAO,MAAA,EAAO,cAAA,EAAe,gBAAa,GAAA,EAAI,gBAAA,EAAe,OAAA,EAClH,QAAA,EAAA,IAAA,KAAS,+BACN,IAAA,CAAA,QAAA,EAAA,EAAE,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,GAAE,SAAA,EAAU,CAAA;AAAA,oBAAO,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,UAAA,EAAW;AAAA,GAAA,EAAO,oBACrD,IAAA,CAAA,QAAA,EAAA,EAAE,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,GAAE,SAAA,EAAU,CAAA;AAAA,oBAAO,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,UAAA,EAAW;AAAA,GAAA,EAAO,CAAA,EAC3D,CAAA;AACF;AAEO,SAAS,gBAAgB,EAAE,EAAA,EAAI,KAAA,EAAO,IAAA,EAAM,KAAK,GAAA,EAAK,IAAA,GAAO,YAAA,EAAc,IAAA,GAAO,OAAO,SAAA,GAAY,KAAA,EAAO,aAAA,GAAgB,KAAA,EAAO,UAAS,EAAyB;AAC1K,EAAA,MAAM,YAAA,GAAe,eAAA,CAAgB,IAAA,EAAM,GAAA,EAAK,GAAG,CAAA;AACnD,EAAA,MAAM,QAAA,GAAW,YAAY,CAAA,GAAI,YAAA;AACjC,EAAA,MAAM,WAAA,GAAc,IAAA,KAAS,YAAA,GAAe,UAAA,GAAa,YAAA;AACzD,EAAA,uBAAO,IAAA,CAAC,SAAA,EAAA,EAAQ,KAAA,EAAM,sBAAA,EAAuB,gBAAA,EAAe,kBAAA,EAAmB,gBAAA,EAAgB,EAAA,EAAI,WAAA,EAAW,IAAA,EAAM,WAAA,EAAW,IAAA,EAAM,gBAAA,EAAgB,MAAA,CAAO,SAAS,CAAA,EAAG,oBAAA,EAAoB,MAAA,CAAO,aAAa,CAAA,EAAG,KAAA,EAAO,CAAA,4BAAA,EAA+B,QAAQ,CAAA,wCAAA,EAA2C,YAAY,CAAA,EAAA,CAAA,EAAM,YAAA,EAAY,KAAA,EACxU,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,+BAAA,EAAiC,QAAA,EAAS,CAAA;AAAA,oBACrD,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,8BAAA,EAA+B,IAAA,EAAK,WAAA,EAAY,QAAA,EAAS,GAAA,EAAI,YAAA,EAAY,CAAA,OAAA,EAAU,KAAK,CAAA,CAAA,EAAI,kBAAA,EAAkB,WAAA,EAAa,eAAA,EAAe,SAAA,GAAY,CAAA,GAAI,GAAA,EAAK,eAAA,EAAe,GAAA,EAAK,eAAA,EAAe,QAAA,EAAU,wBAAA,EAAsB,IAAA,EAAC,gBAAA,EAAgB,EAAA,EAC5P,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,MAAY,CAAA,EAC1B;AAAA,GAAA,EACF,CAAA;AACF","file":"chunk-3O7ZEUW2.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nexport type ResizableRegionAxis = 'horizontal' | 'vertical';\nexport type ResizableRegionEdge = 'start' | 'end';\n\nexport interface ResizableRegionProps {\n id: string;\n label: string;\n size: number;\n min: number;\n max: number;\n axis?: ResizableRegionAxis;\n edge?: ResizableRegionEdge;\n collapsed?: boolean;\n transitioning?: boolean;\n children: SafeHtml | SafeHtml[];\n}\n\nexport const clampRegionSize = (size: number, min: number, max: number) => Math.min(max, Math.max(min, Math.round(size)));\nexport const resizeRegionFromPointer = (startSize: number, delta: number, edge: ResizableRegionEdge) => startSize + delta * (edge === 'start' ? -1 : 1);\n\nfunction ResizeGrip({ axis }: { axis: ResizableRegionAxis }) {\n return <svg aria-hidden=\"true\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\">\n {axis === 'horizontal'\n ? <><path d=\"M9 6v12\"></path><path d=\"M15 6v12\"></path></>\n : <><path d=\"M6 9h12\"></path><path d=\"M6 15h12\"></path></>}\n </svg>;\n}\n\nexport function ResizableRegion({ id, label, size, min, max, axis = 'horizontal', edge = 'end', collapsed = false, transitioning = false, children }: ResizableRegionProps) {\n const expandedSize = clampRegionSize(size, min, max);\n const resolved = collapsed ? 0 : expandedSize;\n const orientation = axis === 'horizontal' ? 'vertical' : 'horizontal';\n return <section class=\"kui-resizable-region\" data-component=\"resizable-region\" data-region-id={id} data-axis={axis} data-edge={edge} data-collapsed={String(collapsed)} data-transitioning={String(transitioning)} style={`--kui-resizable-region-size:${resolved}px;--kui-resizable-region-expanded-size:${expandedSize}px`} aria-label={label}>\n <div class=\"kui-resizable-region__content\">{children}</div>\n <div class=\"kui-resizable-region__handle\" role=\"separator\" tabindex=\"0\" aria-label={`Resize ${label}`} aria-orientation={orientation} aria-valuemin={collapsed ? 0 : min} aria-valuemax={max} aria-valuenow={resolved} data-kui-resize-handle data-region-id={id}>\n <ResizeGrip axis={axis} />\n </div>\n </section>;\n}\n"]}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { resizeRegionFromPointer, clampRegionSize } from './chunk-3O7ZEUW2.js';
|
|
2
|
+
import { delegate } from 'kerfjs';
|
|
3
|
+
|
|
4
|
+
function regionState(handle) {
|
|
5
|
+
const region = handle.closest('[data-component="resizable-region"]');
|
|
6
|
+
if (!(region instanceof HTMLElement) || !(handle instanceof HTMLElement)) return void 0;
|
|
7
|
+
const id = region.dataset.regionId;
|
|
8
|
+
const axis = region.dataset.axis;
|
|
9
|
+
const edge = region.dataset.edge;
|
|
10
|
+
const min = Number(handle.getAttribute("aria-valuemin"));
|
|
11
|
+
const max = Number(handle.getAttribute("aria-valuemax"));
|
|
12
|
+
const size = Number(handle.getAttribute("aria-valuenow"));
|
|
13
|
+
if (!id || axis !== "horizontal" && axis !== "vertical" || edge !== "start" && edge !== "end" || !Number.isFinite(min) || !Number.isFinite(max) || !Number.isFinite(size)) return void 0;
|
|
14
|
+
return { region, handle, id, axis, edge, min, max, size };
|
|
15
|
+
}
|
|
16
|
+
function preview(state, size, onPreview) {
|
|
17
|
+
const next = clampRegionSize(size, state.min, state.max);
|
|
18
|
+
state.region.style.setProperty("--kui-resizable-region-size", `${next}px`);
|
|
19
|
+
state.handle.setAttribute("aria-valuenow", String(next));
|
|
20
|
+
onPreview?.({ id: state.id, size: next, source: "pointer" });
|
|
21
|
+
return next;
|
|
22
|
+
}
|
|
23
|
+
function wireResizableRegions(root, { step = 16, largeStep = 64, onPreview, onCommit }) {
|
|
24
|
+
let stopPointer;
|
|
25
|
+
const stopKeydown = delegate(root, "keydown", "[data-kui-resize-handle]", (event, handle) => {
|
|
26
|
+
const keyboardEvent = event;
|
|
27
|
+
const state = regionState(handle);
|
|
28
|
+
if (!state) return;
|
|
29
|
+
let next;
|
|
30
|
+
if (keyboardEvent.key === "Home") next = state.min;
|
|
31
|
+
if (keyboardEvent.key === "End") next = state.max;
|
|
32
|
+
const increment = keyboardEvent.shiftKey ? largeStep : step;
|
|
33
|
+
if (state.axis === "horizontal" && keyboardEvent.key === "ArrowLeft") next = resizeRegionFromPointer(state.size, -increment, state.edge);
|
|
34
|
+
if (state.axis === "horizontal" && keyboardEvent.key === "ArrowRight") next = resizeRegionFromPointer(state.size, increment, state.edge);
|
|
35
|
+
if (state.axis === "vertical" && keyboardEvent.key === "ArrowUp") next = resizeRegionFromPointer(state.size, -increment, state.edge);
|
|
36
|
+
if (state.axis === "vertical" && keyboardEvent.key === "ArrowDown") next = resizeRegionFromPointer(state.size, increment, state.edge);
|
|
37
|
+
if (next === void 0) return;
|
|
38
|
+
keyboardEvent.preventDefault();
|
|
39
|
+
const size = clampRegionSize(next, state.min, state.max);
|
|
40
|
+
state.region.style.setProperty("--kui-resizable-region-size", `${size}px`);
|
|
41
|
+
state.handle.setAttribute("aria-valuenow", String(size));
|
|
42
|
+
onCommit({ id: state.id, size, source: "keyboard" });
|
|
43
|
+
});
|
|
44
|
+
const stopPointerDown = delegate(root, "pointerdown", "[data-kui-resize-handle]", (event, handle) => {
|
|
45
|
+
const pointerEvent = event;
|
|
46
|
+
if (pointerEvent.button !== 0) return;
|
|
47
|
+
const state = regionState(handle);
|
|
48
|
+
if (!state) return;
|
|
49
|
+
pointerEvent.preventDefault();
|
|
50
|
+
state.handle.setPointerCapture?.(pointerEvent.pointerId);
|
|
51
|
+
const startCoordinate = state.axis === "horizontal" ? pointerEvent.clientX : pointerEvent.clientY;
|
|
52
|
+
let next = state.size;
|
|
53
|
+
const move = (moveEvent) => {
|
|
54
|
+
const coordinate = state.axis === "horizontal" ? moveEvent.clientX : moveEvent.clientY;
|
|
55
|
+
next = preview(state, resizeRegionFromPointer(state.size, coordinate - startCoordinate, state.edge), onPreview);
|
|
56
|
+
};
|
|
57
|
+
const finish = () => {
|
|
58
|
+
root.removeEventListener("pointermove", move);
|
|
59
|
+
root.removeEventListener("pointerup", finish);
|
|
60
|
+
root.removeEventListener("pointercancel", finish);
|
|
61
|
+
stopPointer = void 0;
|
|
62
|
+
onCommit({ id: state.id, size: next, source: "pointer" });
|
|
63
|
+
};
|
|
64
|
+
stopPointer?.();
|
|
65
|
+
stopPointer = finish;
|
|
66
|
+
root.addEventListener("pointermove", move);
|
|
67
|
+
root.addEventListener("pointerup", finish, { once: true });
|
|
68
|
+
root.addEventListener("pointercancel", finish, { once: true });
|
|
69
|
+
});
|
|
70
|
+
return () => {
|
|
71
|
+
stopPointer?.();
|
|
72
|
+
stopKeydown();
|
|
73
|
+
stopPointerDown();
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export { wireResizableRegions };
|
|
78
|
+
|
|
79
|
+
//# sourceMappingURL=chunk-4HHCYSGT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/wire-resizable-regions.ts"],"names":[],"mappings":"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","file":"chunk-4HHCYSGT.js","sourcesContent":["import { delegate } from 'kerfjs';\n\nimport { clampRegionSize, type ResizableRegionAxis, type ResizableRegionEdge, resizeRegionFromPointer } from './resizable-region.js';\n\nexport interface ResizeCommit {\n id: string;\n size: number;\n source: 'keyboard' | 'pointer';\n}\n\nexport interface WireResizableRegionsOptions {\n step?: number;\n largeStep?: number;\n onPreview?: (change: ResizeCommit) => void;\n onCommit: (change: ResizeCommit) => void;\n}\n\ninterface RegionState {\n region: HTMLElement;\n handle: HTMLElement;\n id: string;\n axis: ResizableRegionAxis;\n edge: ResizableRegionEdge;\n min: number;\n max: number;\n size: number;\n}\n\nfunction regionState(handle: Element): RegionState | undefined {\n const region = handle.closest<HTMLElement>('[data-component=\"resizable-region\"]');\n if (!(region instanceof HTMLElement) || !(handle instanceof HTMLElement)) return undefined;\n const id = region.dataset.regionId;\n const axis = region.dataset.axis;\n const edge = region.dataset.edge;\n const min = Number(handle.getAttribute('aria-valuemin'));\n const max = Number(handle.getAttribute('aria-valuemax'));\n const size = Number(handle.getAttribute('aria-valuenow'));\n if (!id || (axis !== 'horizontal' && axis !== 'vertical') || (edge !== 'start' && edge !== 'end') || !Number.isFinite(min) || !Number.isFinite(max) || !Number.isFinite(size)) return undefined;\n return { region, handle, id, axis, edge, min, max, size };\n}\n\nfunction preview(state: RegionState, size: number, onPreview?: (change: ResizeCommit) => void) {\n const next = clampRegionSize(size, state.min, state.max);\n state.region.style.setProperty('--kui-resizable-region-size', `${next}px`);\n state.handle.setAttribute('aria-valuenow', String(next));\n onPreview?.({ id: state.id, size: next, source: 'pointer' });\n return next;\n}\n\n/** Wire pointer and separator-keyboard behavior for every ResizableRegion below root. */\nexport function wireResizableRegions(root: HTMLElement, { step = 16, largeStep = 64, onPreview, onCommit }: WireResizableRegionsOptions) {\n let stopPointer: (() => void) | undefined;\n\n const stopKeydown = delegate(root, 'keydown', '[data-kui-resize-handle]', (event, handle) => {\n const keyboardEvent = event as KeyboardEvent;\n const state = regionState(handle);\n if (!state) return;\n let next: number | undefined;\n if (keyboardEvent.key === 'Home') next = state.min;\n if (keyboardEvent.key === 'End') next = state.max;\n const increment = keyboardEvent.shiftKey ? largeStep : step;\n if (state.axis === 'horizontal' && keyboardEvent.key === 'ArrowLeft') next = resizeRegionFromPointer(state.size, -increment, state.edge);\n if (state.axis === 'horizontal' && keyboardEvent.key === 'ArrowRight') next = resizeRegionFromPointer(state.size, increment, state.edge);\n if (state.axis === 'vertical' && keyboardEvent.key === 'ArrowUp') next = resizeRegionFromPointer(state.size, -increment, state.edge);\n if (state.axis === 'vertical' && keyboardEvent.key === 'ArrowDown') next = resizeRegionFromPointer(state.size, increment, state.edge);\n if (next === undefined) return;\n keyboardEvent.preventDefault();\n const size = clampRegionSize(next, state.min, state.max);\n state.region.style.setProperty('--kui-resizable-region-size', `${size}px`);\n state.handle.setAttribute('aria-valuenow', String(size));\n onCommit({ id: state.id, size, source: 'keyboard' });\n });\n\n const stopPointerDown = delegate(root, 'pointerdown', '[data-kui-resize-handle]', (event, handle) => {\n const pointerEvent = event as PointerEvent;\n if (pointerEvent.button !== 0) return;\n const state = regionState(handle);\n if (!state) return;\n pointerEvent.preventDefault();\n state.handle.setPointerCapture?.(pointerEvent.pointerId);\n const startCoordinate = state.axis === 'horizontal' ? pointerEvent.clientX : pointerEvent.clientY;\n let next = state.size;\n const move = (moveEvent: PointerEvent) => {\n const coordinate = state.axis === 'horizontal' ? moveEvent.clientX : moveEvent.clientY;\n next = preview(state, resizeRegionFromPointer(state.size, coordinate - startCoordinate, state.edge), onPreview);\n };\n const finish = () => {\n root.removeEventListener('pointermove', move);\n root.removeEventListener('pointerup', finish);\n root.removeEventListener('pointercancel', finish);\n stopPointer = undefined;\n onCommit({ id: state.id, size: next, source: 'pointer' });\n };\n stopPointer?.();\n stopPointer = finish;\n root.addEventListener('pointermove', move);\n root.addEventListener('pointerup', finish, { once: true });\n root.addEventListener('pointercancel', finish, { once: true });\n });\n\n return () => {\n stopPointer?.();\n stopKeydown();\n stopPointerDown();\n };\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx } from 'kerfjs/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
// src/loading-spinner.tsx
|
|
4
|
+
function LoadingSpinner({ className = "", label }) {
|
|
5
|
+
return /* @__PURE__ */ jsx("svg", { class: `kui-loading-spinner ${className}`.trim(), "data-component": "loading-spinner", viewBox: "0 0 24 24", role: label ? "img" : void 0, "aria-label": label, "aria-hidden": label ? void 0 : "true", children: /* @__PURE__ */ jsx("path", { d: "M12,4a8,8,0,0,1,7.89,6.7A1.53,1.53,0,0,0,21.38,12h0a1.5,1.5,0,0,0,1.48-1.75,11,11,0,0,0-21.72,0A1.5,1.5,0,0,0,2.62,12h0a1.53,1.53,0,0,0,1.49-1.3A8,8,0,0,1,12,4Z" }) });
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export { LoadingSpinner };
|
|
9
|
+
|
|
10
|
+
//# sourceMappingURL=chunk-55DATV3A.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/loading-spinner.tsx"],"names":[],"mappings":";;;AAMO,SAAS,cAAA,CAAe,EAAE,SAAA,GAAY,EAAA,EAAI,OAAM,EAAwB;AAC7E,EAAA,uBAAO,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAO,CAAA,oBAAA,EAAuB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK,EAAG,gBAAA,EAAe,iBAAA,EAAkB,OAAA,EAAQ,WAAA,EAAY,IAAA,EAAM,QAAQ,KAAA,GAAQ,MAAA,EAAW,YAAA,EAAY,KAAA,EAAO,aAAA,EAAa,KAAA,GAAQ,MAAA,GAAY,MAAA,EAAQ,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,kKAAA,EAAmK,CAAA,EAAO,CAAA;AACpY","file":"chunk-55DATV3A.js","sourcesContent":["export interface LoadingSpinnerProps {\n className?: string;\n label?: string;\n}\n\n/** Stable viewBox-centered progress ring based on svg-spinners' MIT-licensed 180-ring. */\nexport function LoadingSpinner({ className = '', label }: LoadingSpinnerProps) {\n return <svg class={`kui-loading-spinner ${className}`.trim()} data-component=\"loading-spinner\" viewBox=\"0 0 24 24\" role={label ? 'img' : undefined} aria-label={label} aria-hidden={label ? undefined : 'true'}><path d=\"M12,4a8,8,0,0,1,7.89,6.7A1.53,1.53,0,0,0,21.38,12h0a1.5,1.5,0,0,0,1.48-1.75,11,11,0,0,0-21.72,0A1.5,1.5,0,0,0,2.62,12h0a1.53,1.53,0,0,0,1.49-1.3A8,8,0,0,1,12,4Z\"></path></svg>;\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'kerfjs/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
// src/dialog-header.tsx
|
|
4
|
+
function DialogHeader({ title, titleId, summary, summaryId, icon, iconClassName = "", actions }) {
|
|
5
|
+
return /* @__PURE__ */ jsxs("header", { class: "kui-dialog-header", "data-component": "dialog-header", "data-has-icon": String(Boolean(icon)), children: [
|
|
6
|
+
icon && /* @__PURE__ */ jsx("span", { class: `kui-dialog-header__icon ${iconClassName}`.trim(), children: icon }),
|
|
7
|
+
/* @__PURE__ */ jsxs("div", { class: "kui-dialog-header__copy", children: [
|
|
8
|
+
/* @__PURE__ */ jsx("h2", { id: titleId, children: title }),
|
|
9
|
+
/* @__PURE__ */ jsx("p", { id: summaryId, children: summary })
|
|
10
|
+
] }),
|
|
11
|
+
actions && /* @__PURE__ */ jsx("div", { class: "kui-dialog-header__actions", children: actions })
|
|
12
|
+
] });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export { DialogHeader };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=chunk-723YNJBH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/dialog-header.tsx"],"names":[],"mappings":";;;AAYO,SAAS,YAAA,CAAa,EAAE,KAAA,EAAO,OAAA,EAAS,OAAA,EAAS,WAAW,IAAA,EAAM,aAAA,GAAgB,EAAA,EAAI,OAAA,EAAQ,EAAsB;AACzH,EAAA,uBAAO,IAAA,CAAC,QAAA,EAAA,EAAO,KAAA,EAAM,mBAAA,EAAoB,gBAAA,EAAe,eAAA,EAAgB,eAAA,EAAe,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAC,CAAA,EACxG,QAAA,EAAA;AAAA,IAAA,IAAA,oBAAQ,GAAA,CAAC,UAAK,KAAA,EAAO,CAAA,wBAAA,EAA2B,aAAa,CAAA,CAAA,CAAG,IAAA,IAAS,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,oBAC/E,IAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,yBAAA,EAA0B,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,IAAA,EAAA,EAAG,EAAA,EAAI,OAAA,EAAU,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,sBAAK,GAAA,CAAC,GAAA,EAAA,EAAE,EAAA,EAAI,SAAA,EAAY,QAAA,EAAA,OAAA,EAAQ;AAAA,KAAA,EAAI,CAAA;AAAA,IAChG,OAAA,oBAAW,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,8BAA8B,QAAA,EAAA,OAAA,EAAQ;AAAA,GAAA,EAC/D,CAAA;AACF","file":"chunk-723YNJBH.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nexport interface DialogHeaderProps {\n title: string;\n titleId: string;\n summary: string;\n summaryId?: string;\n icon?: SafeHtml;\n iconClassName?: string;\n actions?: SafeHtml;\n}\n\nexport function DialogHeader({ title, titleId, summary, summaryId, icon, iconClassName = '', actions }: DialogHeaderProps) {\n return <header class=\"kui-dialog-header\" data-component=\"dialog-header\" data-has-icon={String(Boolean(icon))}>\n {icon && <span class={`kui-dialog-header__icon ${iconClassName}`.trim()}>{icon}</span>}\n <div class=\"kui-dialog-header__copy\"><h2 id={titleId}>{title}</h2><p id={summaryId}>{summary}</p></div>\n {actions && <div class=\"kui-dialog-header__actions\">{actions}</div>}\n </header>;\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'kerfjs/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
// src/toolbar.tsx
|
|
4
|
+
function Toolbar({ leading, center, trailing, label, divider = true, className = "" }) {
|
|
5
|
+
return /* @__PURE__ */ jsxs("header", { class: `kui-toolbar ${className}`.trim(), "data-component": "toolbar", "data-divider": String(divider), "data-has-center": String(Boolean(center)), "aria-label": label, children: [
|
|
6
|
+
/* @__PURE__ */ jsx("div", { class: "kui-toolbar__leading", children: leading }),
|
|
7
|
+
/* @__PURE__ */ jsx("div", { class: "kui-toolbar__center", children: center }),
|
|
8
|
+
/* @__PURE__ */ jsx("div", { class: "kui-toolbar__trailing", children: trailing })
|
|
9
|
+
] });
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export { Toolbar };
|
|
13
|
+
|
|
14
|
+
//# sourceMappingURL=chunk-DAFFDO33.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/toolbar.tsx"],"names":[],"mappings":";;;AAWO,SAAS,OAAA,CAAQ,EAAE,OAAA,EAAS,MAAA,EAAQ,QAAA,EAAU,OAAO,OAAA,GAAU,IAAA,EAAM,SAAA,GAAY,EAAA,EAAG,EAAiB;AAC1G,EAAA,uBAAO,IAAA,CAAC,YAAO,KAAA,EAAO,CAAA,YAAA,EAAe,SAAS,CAAA,CAAA,CAAG,IAAA,IAAQ,gBAAA,EAAe,SAAA,EAAU,gBAAc,MAAA,CAAO,OAAO,GAAG,iBAAA,EAAiB,MAAA,CAAO,QAAQ,MAAM,CAAC,CAAA,EAAG,YAAA,EAAY,KAAA,EACrK,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,sBAAA,EAAwB,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,oBAC3C,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,qBAAA,EAAuB,QAAA,EAAA,MAAA,EAAO,CAAA;AAAA,oBACzC,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,uBAAA,EAAyB,QAAA,EAAA,QAAA,EAAS;AAAA,GAAA,EAC/C,CAAA;AACF","file":"chunk-DAFFDO33.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nexport interface ToolbarProps {\n leading?: SafeHtml;\n center?: SafeHtml;\n trailing?: SafeHtml;\n label?: string;\n divider?: boolean;\n className?: string;\n}\n\nexport function Toolbar({ leading, center, trailing, label, divider = true, className = '' }: ToolbarProps) {\n return <header class={`kui-toolbar ${className}`.trim()} data-component=\"toolbar\" data-divider={String(divider)} data-has-center={String(Boolean(center))} aria-label={label}>\n <div class=\"kui-toolbar__leading\">{leading}</div>\n <div class=\"kui-toolbar__center\">{center}</div>\n <div class=\"kui-toolbar__trailing\">{trailing}</div>\n </header>;\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx } from 'kerfjs/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
// src/toolbar-text.tsx
|
|
4
|
+
function ToolbarText({ text, size = "default", className = "" }) {
|
|
5
|
+
return /* @__PURE__ */ jsx("span", { class: `kui-toolbar-text ${className}`.trim(), "data-component": "toolbar-text", "data-size": size, children: text });
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export { ToolbarText };
|
|
9
|
+
|
|
10
|
+
//# sourceMappingURL=chunk-GY5WH7TO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/toolbar-text.tsx"],"names":[],"mappings":";;;AAQO,SAAS,YAAY,EAAE,IAAA,EAAM,OAAO,SAAA,EAAW,SAAA,GAAY,IAAG,EAAqB;AACxF,EAAA,uBAAO,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAO,CAAA,iBAAA,EAAoB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK,EAAG,gBAAA,EAAe,cAAA,EAAe,WAAA,EAAW,IAAA,EAAO,QAAA,EAAA,IAAA,EAAK,CAAA;AACnH","file":"chunk-GY5WH7TO.js","sourcesContent":["export type ToolbarTextSize = 'large' | 'default' | 'small';\n\nexport interface ToolbarTextProps {\n text: string;\n size?: ToolbarTextSize;\n className?: string;\n}\n\nexport function ToolbarText({ text, size = 'default', className = '' }: ToolbarTextProps) {\n return <span class={`kui-toolbar-text ${className}`.trim()} data-component=\"toolbar-text\" data-size={size}>{text}</span>;\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'kerfjs/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
// src/tab-bar.tsx
|
|
4
|
+
function TabBar({ id, label, children, leading, trailing, className = "" }) {
|
|
5
|
+
return /* @__PURE__ */ jsxs("nav", { class: `kui-tab-bar ${className}`.trim(), "data-component": "tab-bar", "data-tab-bar-id": id, "aria-label": label, children: [
|
|
6
|
+
leading && /* @__PURE__ */ jsx("div", { class: "kui-tab-bar__leading", children: leading }),
|
|
7
|
+
/* @__PURE__ */ jsx("div", { class: "kui-tab-bar__tabs", role: "tablist", "aria-label": label, "data-kui-tab-list": true, children }),
|
|
8
|
+
trailing && /* @__PURE__ */ jsx("div", { class: "kui-tab-bar__trailing", children: trailing })
|
|
9
|
+
] });
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export { TabBar };
|
|
13
|
+
|
|
14
|
+
//# sourceMappingURL=chunk-MBR3TYNL.js.map
|