aidos-ui 4.0.4 → 4.0.6
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 +1 -1
- package/README.md +23 -3
- package/dist/index.d.ts +801 -68
- package/dist/index.js +3934 -68
- package/dist/index.js.map +1 -1
- package/dist/jsx-dev-runtime.d.ts +6 -2
- package/dist/jsx-dev-runtime.js +87 -42
- package/dist/jsx-dev-runtime.js.map +1 -1
- package/dist/jsx-runtime.d.ts +1 -1
- package/dist/jsx-runtime.js +2 -2
- package/dist/jsx-runtime.js.map +1 -1
- package/dist/vite-plugin-jss-debug.d.ts +3 -1
- package/dist/vite-plugin-jss-debug.js +57 -74
- package/dist/vite-plugin-jss-debug.js.map +1 -1
- package/package.json +61 -27
- package/.prettierrc +0 -4
- package/CLAUDE.md +0 -72
- package/dist/Badge.d.ts +0 -6
- package/dist/Badge.js +0 -22
- package/dist/Badge.js.map +0 -1
- package/dist/BaseButton.d.ts +0 -14
- package/dist/BaseButton.js +0 -23
- package/dist/BaseButton.js.map +0 -1
- package/dist/BaseInput.d.ts +0 -14
- package/dist/BaseInput.js +0 -15
- package/dist/BaseInput.js.map +0 -1
- package/dist/BaseLink.d.ts +0 -18
- package/dist/BaseLink.js +0 -29
- package/dist/BaseLink.js.map +0 -1
- package/dist/BaseList.d.ts +0 -6
- package/dist/BaseList.js +0 -14
- package/dist/BaseList.js.map +0 -1
- package/dist/BaseListAddOn.d.ts +0 -5
- package/dist/BaseListAddOn.js +0 -7
- package/dist/BaseListAddOn.js.map +0 -1
- package/dist/BaseListItem.d.ts +0 -26
- package/dist/BaseListItem.js +0 -29
- package/dist/BaseListItem.js.map +0 -1
- package/dist/BaseView.d.ts +0 -12
- package/dist/BaseView.js +0 -26
- package/dist/BaseView.js.map +0 -1
- package/dist/Box.d.ts +0 -4
- package/dist/Box.js +0 -6
- package/dist/Box.js.map +0 -1
- package/dist/Button.d.ts +0 -20
- package/dist/Button.js +0 -19
- package/dist/Button.js.map +0 -1
- package/dist/Calendar.d.ts +0 -18
- package/dist/Calendar.js +0 -57
- package/dist/Calendar.js.map +0 -1
- package/dist/Card.d.ts +0 -4
- package/dist/Card.js +0 -14
- package/dist/Card.js.map +0 -1
- package/dist/Checkbox.d.ts +0 -11
- package/dist/Checkbox.js +0 -32
- package/dist/Checkbox.js.map +0 -1
- package/dist/Circle.d.ts +0 -5
- package/dist/Circle.js +0 -12
- package/dist/Circle.js.map +0 -1
- package/dist/Column.d.ts +0 -6
- package/dist/Column.js +0 -7
- package/dist/Column.js.map +0 -1
- package/dist/DarkMode.d.ts +0 -13
- package/dist/DarkMode.js +0 -62
- package/dist/DarkMode.js.map +0 -1
- package/dist/DateInput.d.ts +0 -13
- package/dist/DateInput.js +0 -29
- package/dist/DateInput.js.map +0 -1
- package/dist/DatePicker.d.ts +0 -11
- package/dist/DatePicker.js +0 -34
- package/dist/DatePicker.js.map +0 -1
- package/dist/DatetimeInput.d.ts +0 -13
- package/dist/DatetimeInput.js +0 -31
- package/dist/DatetimeInput.js.map +0 -1
- package/dist/DesignBook.d.ts +0 -1
- package/dist/DesignBook.js +0 -55
- package/dist/DesignBook.js.map +0 -1
- package/dist/Dialog.d.ts +0 -17
- package/dist/Dialog.js +0 -92
- package/dist/Dialog.js.map +0 -1
- package/dist/Dropdown.d.ts +0 -14
- package/dist/Dropdown.js +0 -65
- package/dist/Dropdown.js.map +0 -1
- package/dist/Emitter.d.ts +0 -6
- package/dist/Emitter.js +0 -19
- package/dist/Emitter.js.map +0 -1
- package/dist/FlexLayout.d.ts +0 -11
- package/dist/FlexLayout.js +0 -18
- package/dist/FlexLayout.js.map +0 -1
- package/dist/Icon.d.ts +0 -12
- package/dist/Icon.js +0 -60
- package/dist/Icon.js.map +0 -1
- package/dist/IconButton.d.ts +0 -11
- package/dist/IconButton.js +0 -34
- package/dist/IconButton.js.map +0 -1
- package/dist/IconLink.d.ts +0 -9
- package/dist/IconLink.js +0 -32
- package/dist/IconLink.js.map +0 -1
- package/dist/IconType.d.ts +0 -1
- package/dist/IconType.js +0 -2
- package/dist/IconType.js.map +0 -1
- package/dist/Interactable.d.ts +0 -50
- package/dist/Interactable.js +0 -169
- package/dist/Interactable.js.map +0 -1
- package/dist/JSSComment.d.ts +0 -10
- package/dist/JSSComment.js +0 -52
- package/dist/JSSComment.js.map +0 -1
- package/dist/Link.d.ts +0 -22
- package/dist/Link.js +0 -29
- package/dist/Link.js.map +0 -1
- package/dist/List.d.ts +0 -15
- package/dist/List.js +0 -29
- package/dist/List.js.map +0 -1
- package/dist/ListButtonItem.d.ts +0 -14
- package/dist/ListButtonItem.js +0 -11
- package/dist/ListButtonItem.js.map +0 -1
- package/dist/ListDivider.d.ts +0 -1
- package/dist/ListDivider.js +0 -12
- package/dist/ListDivider.js.map +0 -1
- package/dist/ListHeaderItem.d.ts +0 -10
- package/dist/ListHeaderItem.js +0 -15
- package/dist/ListHeaderItem.js.map +0 -1
- package/dist/ListItem.d.ts +0 -9
- package/dist/ListItem.js +0 -9
- package/dist/ListItem.js.map +0 -1
- package/dist/ListLinkItem.d.ts +0 -16
- package/dist/ListLinkItem.js +0 -11
- package/dist/ListLinkItem.js.map +0 -1
- package/dist/ListSpacer.d.ts +0 -1
- package/dist/ListSpacer.js +0 -13
- package/dist/ListSpacer.js.map +0 -1
- package/dist/MenuIcon.d.ts +0 -5
- package/dist/MenuIcon.js +0 -31
- package/dist/MenuIcon.js.map +0 -1
- package/dist/NextJSRouter.d.ts +0 -1
- package/dist/NextJSRouter.js +0 -37
- package/dist/NextJSRouter.js.map +0 -1
- package/dist/NextJSRouterState.d.ts +0 -38
- package/dist/NextJSRouterState.js +0 -111
- package/dist/NextJSRouterState.js.map +0 -1
- package/dist/OnVisible.d.ts +0 -5
- package/dist/OnVisible.js +0 -28
- package/dist/OnVisible.js.map +0 -1
- package/dist/Popover.d.ts +0 -22
- package/dist/Popover.js +0 -90
- package/dist/Popover.js.map +0 -1
- package/dist/ProgressBar.d.ts +0 -7
- package/dist/ProgressBar.js +0 -42
- package/dist/ProgressBar.js.map +0 -1
- package/dist/ProgressCircle.d.ts +0 -5
- package/dist/ProgressCircle.js +0 -12
- package/dist/ProgressCircle.js.map +0 -1
- package/dist/Providers.d.ts +0 -9
- package/dist/Providers.js +0 -16
- package/dist/Providers.js.map +0 -1
- package/dist/RangeInput.d.ts +0 -14
- package/dist/RangeInput.js +0 -32
- package/dist/RangeInput.js.map +0 -1
- package/dist/ResultOrError.d.ts +0 -13
- package/dist/ResultOrError.js +0 -7
- package/dist/ResultOrError.js.map +0 -1
- package/dist/RootView.d.ts +0 -5
- package/dist/RootView.js +0 -35
- package/dist/RootView.js.map +0 -1
- package/dist/Row.d.ts +0 -6
- package/dist/Row.js +0 -7
- package/dist/Row.js.map +0 -1
- package/dist/Select.d.ts +0 -9
- package/dist/Select.js +0 -17
- package/dist/Select.js.map +0 -1
- package/dist/StackContext.d.ts +0 -8
- package/dist/StackContext.js +0 -25
- package/dist/StackContext.js.map +0 -1
- package/dist/StaticCheckbox.d.ts +0 -16
- package/dist/StaticCheckbox.js +0 -48
- package/dist/StaticCheckbox.js.map +0 -1
- package/dist/Storage.d.ts +0 -13
- package/dist/Storage.js +0 -146
- package/dist/Storage.js.map +0 -1
- package/dist/Stream.d.ts +0 -9
- package/dist/Stream.js +0 -36
- package/dist/Stream.js.map +0 -1
- package/dist/Sublist.d.ts +0 -12
- package/dist/Sublist.js +0 -18
- package/dist/Sublist.js.map +0 -1
- package/dist/SubmitIconInput.d.ts +0 -8
- package/dist/SubmitIconInput.js +0 -25
- package/dist/SubmitIconInput.js.map +0 -1
- package/dist/Tabs.d.ts +0 -23
- package/dist/Tabs.js +0 -39
- package/dist/Tabs.js.map +0 -1
- package/dist/Text.d.ts +0 -25
- package/dist/Text.js +0 -52
- package/dist/Text.js.map +0 -1
- package/dist/TextArea.d.ts +0 -11
- package/dist/TextArea.js +0 -27
- package/dist/TextArea.js.map +0 -1
- package/dist/TextInput.d.ts +0 -15
- package/dist/TextInput.js +0 -61
- package/dist/TextInput.js.map +0 -1
- package/dist/TextInputWithState.d.ts +0 -8
- package/dist/TextInputWithState.js +0 -14
- package/dist/TextInputWithState.js.map +0 -1
- package/dist/TextPairing.d.ts +0 -21
- package/dist/TextPairing.js +0 -26
- package/dist/TextPairing.js.map +0 -1
- package/dist/TimeInput.d.ts +0 -15
- package/dist/TimeInput.js +0 -58
- package/dist/TimeInput.js.map +0 -1
- package/dist/Tooltip.d.ts +0 -11
- package/dist/Tooltip.js +0 -73
- package/dist/Tooltip.js.map +0 -1
- package/dist/aria.d.ts +0 -8
- package/dist/aria.js +0 -42
- package/dist/aria.js.map +0 -1
- package/dist/guid.d.ts +0 -1
- package/dist/guid.js +0 -7
- package/dist/guid.js.map +0 -1
- package/dist/hash.d.ts +0 -1
- package/dist/hash.js +0 -20
- package/dist/hash.js.map +0 -1
- package/dist/isServer.d.ts +0 -1
- package/dist/isServer.js +0 -4
- package/dist/isServer.js.map +0 -1
- package/dist/jss.d.ts +0 -122
- package/dist/jss.js +0 -515
- package/dist/jss.js.map +0 -1
- package/dist/numberToBase.d.ts +0 -1
- package/dist/numberToBase.js +0 -44
- package/dist/numberToBase.js.map +0 -1
- package/dist/stateMachineContextFactory.d.ts +0 -36
- package/dist/stateMachineContextFactory.js +0 -48
- package/dist/stateMachineContextFactory.js.map +0 -1
- package/dist/useCookie.d.ts +0 -9
- package/dist/useCookie.js +0 -67
- package/dist/useCookie.js.map +0 -1
- package/dist/useKeyboard.d.ts +0 -8
- package/dist/useKeyboard.js +0 -26
- package/dist/useKeyboard.js.map +0 -1
- package/dist/useNavigation.d.ts +0 -5
- package/dist/useNavigation.js +0 -79
- package/dist/useNavigation.js.map +0 -1
- package/dist/usePromise.d.ts +0 -1
- package/dist/usePromise.js +0 -12
- package/dist/usePromise.js.map +0 -1
- package/dist/useRefEffect.d.ts +0 -1
- package/dist/useRefEffect.js +0 -15
- package/dist/useRefEffect.js.map +0 -1
- package/jss-debug-loader.mjs +0 -44
- package/next-env.d.ts +0 -6
- package/next.config.js +0 -33
- package/scripts/embeddings.js +0 -93
- package/scripts/openai_embeddings.js +0 -100
- package/scripts/publish.js +0 -28
- package/scripts/test_embeddings.js +0 -47
- package/src/Badge.tsx +0 -36
- package/src/BaseButton.tsx +0 -62
- package/src/BaseInput.tsx +0 -63
- package/src/BaseLink.tsx +0 -80
- package/src/BaseList.tsx +0 -26
- package/src/BaseListAddOn.tsx +0 -10
- package/src/BaseListItem.tsx +0 -119
- package/src/BaseView.tsx +0 -57
- package/src/Box.tsx +0 -20
- package/src/Button.tsx +0 -90
- package/src/Calendar.tsx +0 -123
- package/src/Card.tsx +0 -30
- package/src/Checkbox.tsx +0 -63
- package/src/Circle.tsx +0 -24
- package/src/Column.tsx +0 -12
- package/src/DarkMode.tsx +0 -100
- package/src/DateInput.tsx +0 -63
- package/src/DatePicker.tsx +0 -67
- package/src/DatetimeInput.tsx +0 -64
- package/src/DesignBook.tsx +0 -677
- package/src/Dialog.tsx +0 -150
- package/src/Dropdown.tsx +0 -146
- package/src/Emitter.ts +0 -26
- package/src/FlexLayout.tsx +0 -53
- package/src/Icon.tsx +0 -80
- package/src/IconButton.tsx +0 -81
- package/src/IconLink.tsx +0 -59
- package/src/IconType.ts +0 -787
- package/src/Interactable.tsx +0 -210
- package/src/JSSComment.tsx +0 -56
- package/src/Link.tsx +0 -110
- package/src/List.tsx +0 -58
- package/src/ListButtonItem.tsx +0 -69
- package/src/ListDivider.tsx +0 -13
- package/src/ListHeaderItem.tsx +0 -45
- package/src/ListItem.tsx +0 -24
- package/src/ListLinkItem.tsx +0 -76
- package/src/ListSpacer.tsx +0 -14
- package/src/MenuIcon.tsx +0 -50
- package/src/NextJSRouter.tsx +0 -60
- package/src/NextJSRouterState.tsx +0 -154
- package/src/OnVisible.tsx +0 -42
- package/src/Popover.tsx +0 -145
- package/src/ProgressBar.tsx +0 -63
- package/src/ProgressCircle.tsx +0 -38
- package/src/Providers.tsx +0 -33
- package/src/RangeInput.tsx +0 -82
- package/src/ResultOrError.ts +0 -15
- package/src/RootView.tsx +0 -55
- package/src/Row.tsx +0 -12
- package/src/Select.tsx +0 -39
- package/src/StackContext.tsx +0 -52
- package/src/StaticCheckbox.tsx +0 -72
- package/src/Storage.tsx +0 -198
- package/src/Stream.tsx +0 -50
- package/src/Sublist.tsx +0 -61
- package/src/SubmitIconInput.tsx +0 -45
- package/src/Tabs.tsx +0 -110
- package/src/Text.tsx +0 -111
- package/src/TextArea.tsx +0 -58
- package/src/TextInput.tsx +0 -123
- package/src/TextInputWithState.tsx +0 -32
- package/src/TextPairing.tsx +0 -115
- package/src/TimeInput.tsx +0 -109
- package/src/Tooltip.tsx +0 -109
- package/src/aria.ts +0 -72
- package/src/docs/mdx.tsx +0 -137
- package/src/docs/pages.ts +0 -115
- package/src/docs/searchIndex.ts +0 -1
- package/src/examples/ExampleDialog.tsx +0 -28
- package/src/guid.ts +0 -7
- package/src/hash.ts +0 -21
- package/src/index.ts +0 -68
- package/src/isServer.ts +0 -3
- package/src/jss.tsx +0 -712
- package/src/jsx-dev-runtime.ts +0 -74
- package/src/jsx-runtime.ts +0 -2
- package/src/numberToBase.ts +0 -52
- package/src/pages/Badge.mdx +0 -152
- package/src/pages/Button.mdx +0 -163
- package/src/pages/Calendar.mdx +0 -254
- package/src/pages/Card.mdx +0 -147
- package/src/pages/Checkbox.mdx +0 -131
- package/src/pages/Dialog.mdx +0 -197
- package/src/pages/FlexLayout.mdx +0 -211
- package/src/pages/Hashing.mdx +0 -211
- package/src/pages/Icon.mdx +0 -171
- package/src/pages/IconButton.mdx +0 -155
- package/src/pages/Link.mdx +0 -160
- package/src/pages/List.mdx +0 -262
- package/src/pages/ListHeader.mdx +0 -220
- package/src/pages/Popover.mdx +0 -223
- package/src/pages/ProgressBar.mdx +0 -200
- package/src/pages/ProgressCircle.mdx +0 -218
- package/src/pages/RangeInput.mdx +0 -237
- package/src/pages/Tabs.mdx +0 -281
- package/src/pages/Text.mdx +0 -154
- package/src/pages/TextInput.mdx +0 -235
- package/src/pages/TextPairing.mdx +0 -204
- package/src/pages/TimeInput.mdx +0 -178
- package/src/pages/Tooltip.mdx +0 -115
- package/src/pages/_app.tsx +0 -466
- package/src/pages/_document.tsx +0 -30
- package/src/pages/css-in-js.mdx +0 -240
- package/src/pages/index.mdx +0 -58
- package/src/pages/navigation.mdx +0 -158
- package/src/pages/prism.css +0 -3
- package/src/pages/useCookie.mdx +0 -176
- package/src/pages/useKeyboard.mdx +0 -257
- package/src/pages/useNavigation.mdx +0 -258
- package/src/pages/usePromise.mdx +0 -280
- package/src/pages/useRefEffect.mdx +0 -251
- package/src/stateMachineContextFactory.tsx +0 -111
- package/src/useCookie.tsx +0 -95
- package/src/useKeyboard.tsx +0 -43
- package/src/useNavigation.tsx +0 -89
- package/src/usePromise.tsx +0 -18
- package/src/useRefEffect.tsx +0 -18
- package/src/vite-plugin-jss-debug.ts +0 -77
- package/tsconfig.build.json +0 -23
- package/tsconfig.json +0 -38
|
@@ -1,257 +0,0 @@
|
|
|
1
|
-
# useKeyboard
|
|
2
|
-
|
|
3
|
-
A React hook for creating keyboard shortcuts. Useful for improving accessibility and power-user workflows.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Signature
|
|
8
|
-
|
|
9
|
-
```ts
|
|
10
|
-
function useKeyboard<T extends HTMLElement>(
|
|
11
|
-
shortcuts: Array<KeyboardShortcut<T>>
|
|
12
|
-
): (root: T) => void
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## KeyboardShortcut type
|
|
18
|
-
|
|
19
|
-
| Property | Type | Default | Description |
|
|
20
|
-
|----------|------|---------|-------------|
|
|
21
|
-
| `key` | `string` | Required | The key to listen for (case-insensitive) |
|
|
22
|
-
| `metaKey` | `boolean` | - | Require Cmd/Meta key (macOS) |
|
|
23
|
-
| `ctrlKey` | `boolean` | - | Require Ctrl key |
|
|
24
|
-
| `action` | `(root: T) => void` | Required | Function to execute when shortcut triggers |
|
|
25
|
-
| `onlyWhenFocused` | `boolean` | - | Only trigger when the element is focused |
|
|
26
|
-
|
|
27
|
-
---
|
|
28
|
-
|
|
29
|
-
## Basic usage
|
|
30
|
-
|
|
31
|
-
```js
|
|
32
|
-
import { useKeyboard } from "aidos-ui";
|
|
33
|
-
|
|
34
|
-
function SearchInput() {
|
|
35
|
-
const [query, setQuery] = useState("");
|
|
36
|
-
|
|
37
|
-
const ref = useKeyboard([
|
|
38
|
-
{
|
|
39
|
-
key: "Escape",
|
|
40
|
-
onlyWhenFocused: true,
|
|
41
|
-
action: () => setQuery(""),
|
|
42
|
-
},
|
|
43
|
-
]);
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<input
|
|
47
|
-
ref={ref}
|
|
48
|
-
value={query}
|
|
49
|
-
onChange={(e) => setQuery(e.target.value)}
|
|
50
|
-
placeholder="Search..."
|
|
51
|
-
/>
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
---
|
|
57
|
-
|
|
58
|
-
## Global shortcuts
|
|
59
|
-
|
|
60
|
-
Create app-wide keyboard shortcuts by attaching to a root element:
|
|
61
|
-
|
|
62
|
-
```js
|
|
63
|
-
function App() {
|
|
64
|
-
const searchRef = useRef(null);
|
|
65
|
-
|
|
66
|
-
const rootRef = useKeyboard([
|
|
67
|
-
{
|
|
68
|
-
key: "K",
|
|
69
|
-
metaKey: true,
|
|
70
|
-
action: () => searchRef.current?.focus(),
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
key: "/",
|
|
74
|
-
action: () => searchRef.current?.focus(),
|
|
75
|
-
},
|
|
76
|
-
]);
|
|
77
|
-
|
|
78
|
-
return (
|
|
79
|
-
<div ref={rootRef}>
|
|
80
|
-
<SearchInput ref={searchRef} />
|
|
81
|
-
{/* Rest of app */}
|
|
82
|
-
</div>
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
---
|
|
88
|
-
|
|
89
|
-
## Focus management
|
|
90
|
-
|
|
91
|
-
Combine with `onlyWhenFocused` to create context-aware shortcuts:
|
|
92
|
-
|
|
93
|
-
```js
|
|
94
|
-
function CommandPalette() {
|
|
95
|
-
const [open, setOpen] = useState(false);
|
|
96
|
-
const [query, setQuery] = useState("");
|
|
97
|
-
|
|
98
|
-
const ref = useKeyboard([
|
|
99
|
-
{
|
|
100
|
-
key: "K",
|
|
101
|
-
metaKey: true,
|
|
102
|
-
action: () => setOpen(true),
|
|
103
|
-
},
|
|
104
|
-
{
|
|
105
|
-
key: "Escape",
|
|
106
|
-
onlyWhenFocused: true,
|
|
107
|
-
action: () => {
|
|
108
|
-
if (query) {
|
|
109
|
-
setQuery("");
|
|
110
|
-
} else {
|
|
111
|
-
setOpen(false);
|
|
112
|
-
}
|
|
113
|
-
},
|
|
114
|
-
},
|
|
115
|
-
]);
|
|
116
|
-
|
|
117
|
-
return (
|
|
118
|
-
<div ref={ref}>
|
|
119
|
-
{open && (
|
|
120
|
-
<Dialog>
|
|
121
|
-
<TextInput
|
|
122
|
-
value={query}
|
|
123
|
-
onValueChange={setQuery}
|
|
124
|
-
placeholder="Type a command..."
|
|
125
|
-
/>
|
|
126
|
-
</Dialog>
|
|
127
|
-
)}
|
|
128
|
-
</div>
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
---
|
|
134
|
-
|
|
135
|
-
## Modifier keys
|
|
136
|
-
|
|
137
|
-
Use `metaKey` and `ctrlKey` for modifier-based shortcuts:
|
|
138
|
-
|
|
139
|
-
```js
|
|
140
|
-
const ref = useKeyboard([
|
|
141
|
-
// Cmd+S (macOS) / Ctrl+S (Windows/Linux)
|
|
142
|
-
{
|
|
143
|
-
key: "S",
|
|
144
|
-
metaKey: true,
|
|
145
|
-
action: () => saveDocument(),
|
|
146
|
-
},
|
|
147
|
-
// Ctrl+Enter
|
|
148
|
-
{
|
|
149
|
-
key: "Enter",
|
|
150
|
-
ctrlKey: true,
|
|
151
|
-
action: () => submitForm(),
|
|
152
|
-
},
|
|
153
|
-
// Cmd+Shift doesn't have a dedicated prop, but you can handle it:
|
|
154
|
-
{
|
|
155
|
-
key: "Z",
|
|
156
|
-
metaKey: true,
|
|
157
|
-
action: (root) => {
|
|
158
|
-
// Check for Shift in the action if needed
|
|
159
|
-
if (window.event?.shiftKey) {
|
|
160
|
-
redo();
|
|
161
|
-
} else {
|
|
162
|
-
undo();
|
|
163
|
-
}
|
|
164
|
-
},
|
|
165
|
-
},
|
|
166
|
-
]);
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
---
|
|
170
|
-
|
|
171
|
-
## Multiple shortcuts
|
|
172
|
-
|
|
173
|
-
Register multiple shortcuts at once:
|
|
174
|
-
|
|
175
|
-
```js
|
|
176
|
-
const ref = useKeyboard([
|
|
177
|
-
{ key: "ArrowUp", action: () => selectPrevious() },
|
|
178
|
-
{ key: "ArrowDown", action: () => selectNext() },
|
|
179
|
-
{ key: "Enter", action: () => confirm() },
|
|
180
|
-
{ key: "Escape", action: () => cancel() },
|
|
181
|
-
{ key: "Delete", action: () => remove() },
|
|
182
|
-
{ key: "Backspace", action: () => remove() },
|
|
183
|
-
]);
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
---
|
|
187
|
-
|
|
188
|
-
## With TypeScript
|
|
189
|
-
|
|
190
|
-
The hook is generic and preserves the element type:
|
|
191
|
-
|
|
192
|
-
```ts
|
|
193
|
-
// HTMLInputElement
|
|
194
|
-
const inputRef = useKeyboard<HTMLInputElement>([
|
|
195
|
-
{
|
|
196
|
-
key: "Escape",
|
|
197
|
-
onlyWhenFocused: true,
|
|
198
|
-
action: (input) => {
|
|
199
|
-
input.value = ""; // TypeScript knows this is HTMLInputElement
|
|
200
|
-
input.blur();
|
|
201
|
-
},
|
|
202
|
-
},
|
|
203
|
-
]);
|
|
204
|
-
|
|
205
|
-
// HTMLDivElement
|
|
206
|
-
const divRef = useKeyboard<HTMLDivElement>([
|
|
207
|
-
{
|
|
208
|
-
key: "Space",
|
|
209
|
-
action: (div) => div.click(),
|
|
210
|
-
},
|
|
211
|
-
]);
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
---
|
|
215
|
-
|
|
216
|
-
## Common patterns
|
|
217
|
-
|
|
218
|
-
### Text editor shortcuts
|
|
219
|
-
|
|
220
|
-
```js
|
|
221
|
-
const ref = useKeyboard([
|
|
222
|
-
{ key: "B", metaKey: true, action: () => toggleBold() },
|
|
223
|
-
{ key: "I", metaKey: true, action: () => toggleItalic() },
|
|
224
|
-
{ key: "U", metaKey: true, action: () => toggleUnderline() },
|
|
225
|
-
{ key: "Z", metaKey: true, action: () => undo() },
|
|
226
|
-
]);
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
### Navigation shortcuts
|
|
230
|
-
|
|
231
|
-
```js
|
|
232
|
-
const ref = useKeyboard([
|
|
233
|
-
{ key: "H", action: () => navigate("/") },
|
|
234
|
-
{ key: "S", action: () => navigate("/settings") },
|
|
235
|
-
{ key: "?", action: () => showHelp() },
|
|
236
|
-
]);
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
### List navigation
|
|
240
|
-
|
|
241
|
-
```js
|
|
242
|
-
const ref = useKeyboard([
|
|
243
|
-
{ key: "J", action: () => selectNext() },
|
|
244
|
-
{ key: "K", action: () => selectPrevious() },
|
|
245
|
-
{ key: "G", action: () => selectFirst() },
|
|
246
|
-
{ key: "G", ctrlKey: true, action: () => selectLast() },
|
|
247
|
-
]);
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
---
|
|
251
|
-
|
|
252
|
-
## Implementation details
|
|
253
|
-
|
|
254
|
-
- Shortcuts are registered globally via `window.addEventListener`
|
|
255
|
-
- Key matching is case-insensitive
|
|
256
|
-
- The hook cleans up listeners when the component unmounts
|
|
257
|
-
- Built on top of `useRefEffect` for reliable effect management
|
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
# useNavigation
|
|
2
|
-
|
|
3
|
-
A React hook that enables keyboard navigation within a container element. Implements the [WAI-ARIA grid pattern](https://www.w3.org/WAI/ARIA/apg/patterns/grid/examples/layout-grids/) for accessible keyboard navigation.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Signature
|
|
8
|
-
|
|
9
|
-
```ts
|
|
10
|
-
function useNavigation(options?: {
|
|
11
|
-
autofocus?: boolean;
|
|
12
|
-
rowLength?: number;
|
|
13
|
-
enabled?: boolean;
|
|
14
|
-
}): (root: HTMLElement) => void
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## Options
|
|
20
|
-
|
|
21
|
-
| Option | Type | Default | Description |
|
|
22
|
-
|--------|------|---------|-------------|
|
|
23
|
-
| `autofocus` | `boolean` | `false` | Automatically focus the first item on mount |
|
|
24
|
-
| `rowLength` | `number` | `1` | Number of items per row (for grid layouts) |
|
|
25
|
-
| `enabled` | `boolean` | `true` | Enable/disable navigation |
|
|
26
|
-
|
|
27
|
-
---
|
|
28
|
-
|
|
29
|
-
## Basic usage
|
|
30
|
-
|
|
31
|
-
```js
|
|
32
|
-
import { useNavigation } from "aidos-ui";
|
|
33
|
-
|
|
34
|
-
function NavigableList() {
|
|
35
|
-
const rootRef = useNavigation();
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<ul ref={rootRef} aria-label="Options">
|
|
39
|
-
<li><button>Option 1</button></li>
|
|
40
|
-
<li><button>Option 2</button></li>
|
|
41
|
-
<li><button>Option 3</button></li>
|
|
42
|
-
</ul>
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
---
|
|
48
|
-
|
|
49
|
-
## How it works
|
|
50
|
-
|
|
51
|
-
The hook manages `tabIndex` on focusable elements within the container:
|
|
52
|
-
|
|
53
|
-
1. The "active" element gets `tabIndex="0"`
|
|
54
|
-
2. All other elements get `tabIndex="-1"`
|
|
55
|
-
3. This makes the entire area a single Tab stop
|
|
56
|
-
4. Arrow keys move focus between elements
|
|
57
|
-
|
|
58
|
-
**Keyboard controls:**
|
|
59
|
-
- **Arrow Down / Arrow Right**: Move to next item
|
|
60
|
-
- **Arrow Up / Arrow Left**: Move to previous item
|
|
61
|
-
- Navigation wraps around at the ends
|
|
62
|
-
|
|
63
|
-
---
|
|
64
|
-
|
|
65
|
-
## List navigation
|
|
66
|
-
|
|
67
|
-
import { List } from "../List";
|
|
68
|
-
import { ListButtonItem } from "../ListButtonItem";
|
|
69
|
-
|
|
70
|
-
<List ariaLabel="example" navigation={true}>
|
|
71
|
-
<ListButtonItem color="secondary" headline="Headline 1" onClick={() => {}} />
|
|
72
|
-
<ListButtonItem color="secondary" headline="Headline 2" onClick={() => {}} />
|
|
73
|
-
<ListButtonItem
|
|
74
|
-
withDivider={false}
|
|
75
|
-
color="secondary"
|
|
76
|
-
headline="Headline 3"
|
|
77
|
-
onClick={() => {}}
|
|
78
|
-
/>
|
|
79
|
-
</List>
|
|
80
|
-
|
|
81
|
-
```js
|
|
82
|
-
<List ariaLabel="example" navigation={true}>
|
|
83
|
-
<ListButtonItem headline="Headline 1" onClick={() => {}} />
|
|
84
|
-
<ListButtonItem headline="Headline 2" onClick={() => {}} />
|
|
85
|
-
<ListButtonItem headline="Headline 3" onClick={() => {}} />
|
|
86
|
-
</List>
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
---
|
|
90
|
-
|
|
91
|
-
## Disabled navigation
|
|
92
|
-
|
|
93
|
-
<List ariaLabel="example" navigation={false}>
|
|
94
|
-
<ListButtonItem color="secondary" headline="Headline 1" onClick={() => {}} />
|
|
95
|
-
<ListButtonItem color="secondary" headline="Headline 2" onClick={() => {}} />
|
|
96
|
-
<ListButtonItem
|
|
97
|
-
withDivider={false}
|
|
98
|
-
color="secondary"
|
|
99
|
-
headline="Headline 3"
|
|
100
|
-
onClick={() => {}}
|
|
101
|
-
/>
|
|
102
|
-
</List>
|
|
103
|
-
|
|
104
|
-
```js
|
|
105
|
-
<List ariaLabel="example" navigation={false}>
|
|
106
|
-
<ListButtonItem headline="Headline 1" onClick={() => {}} />
|
|
107
|
-
<ListButtonItem headline="Headline 2" onClick={() => {}} />
|
|
108
|
-
<ListButtonItem headline="Headline 3" onClick={() => {}} />
|
|
109
|
-
</List>
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
---
|
|
113
|
-
|
|
114
|
-
## Grid navigation
|
|
115
|
-
|
|
116
|
-
For grid layouts, set `rowLength` to enable proper up/down navigation:
|
|
117
|
-
|
|
118
|
-
```js
|
|
119
|
-
function IconGrid() {
|
|
120
|
-
const rootRef = useNavigation({ rowLength: 4 });
|
|
121
|
-
|
|
122
|
-
return (
|
|
123
|
-
<div
|
|
124
|
-
ref={rootRef}
|
|
125
|
-
style={{
|
|
126
|
-
display: "grid",
|
|
127
|
-
gridTemplateColumns: "repeat(4, 1fr)",
|
|
128
|
-
}}
|
|
129
|
-
>
|
|
130
|
-
{icons.map((icon) => (
|
|
131
|
-
<button key={icon.name} onClick={() => selectIcon(icon)}>
|
|
132
|
-
<Icon icon={icon.name} />
|
|
133
|
-
</button>
|
|
134
|
-
))}
|
|
135
|
-
</div>
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
With `rowLength: 4`:
|
|
141
|
-
- Arrow Left/Right moves horizontally
|
|
142
|
-
- Arrow Up/Down moves vertically (jumps 4 items)
|
|
143
|
-
|
|
144
|
-
---
|
|
145
|
-
|
|
146
|
-
## Autofocus
|
|
147
|
-
|
|
148
|
-
Focus the first item automatically when the component mounts:
|
|
149
|
-
|
|
150
|
-
```js
|
|
151
|
-
function DropdownMenu({ items }) {
|
|
152
|
-
const rootRef = useNavigation({ autofocus: true });
|
|
153
|
-
|
|
154
|
-
return (
|
|
155
|
-
<ul ref={rootRef} role="menu">
|
|
156
|
-
{items.map((item) => (
|
|
157
|
-
<li key={item.id} role="menuitem">
|
|
158
|
-
<button onClick={item.action}>{item.label}</button>
|
|
159
|
-
</li>
|
|
160
|
-
))}
|
|
161
|
-
</ul>
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
---
|
|
167
|
-
|
|
168
|
-
## Conditional navigation
|
|
169
|
-
|
|
170
|
-
Enable or disable navigation dynamically:
|
|
171
|
-
|
|
172
|
-
```js
|
|
173
|
-
function EditableList({ isEditing }) {
|
|
174
|
-
const rootRef = useNavigation({
|
|
175
|
-
enabled: !isEditing, // Disable during edit mode
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
return (
|
|
179
|
-
<ul ref={rootRef}>
|
|
180
|
-
{items.map((item) => (
|
|
181
|
-
<li key={item.id}>
|
|
182
|
-
{isEditing ? (
|
|
183
|
-
<TextInput value={item.name} />
|
|
184
|
-
) : (
|
|
185
|
-
<button>{item.name}</button>
|
|
186
|
-
)}
|
|
187
|
-
</li>
|
|
188
|
-
))}
|
|
189
|
-
</ul>
|
|
190
|
-
);
|
|
191
|
-
}
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
---
|
|
195
|
-
|
|
196
|
-
## Dynamic lists
|
|
197
|
-
|
|
198
|
-
The hook uses a MutationObserver to handle items being added or removed:
|
|
199
|
-
|
|
200
|
-
```js
|
|
201
|
-
function DynamicList() {
|
|
202
|
-
const [items, setItems] = useState(initialItems);
|
|
203
|
-
const rootRef = useNavigation();
|
|
204
|
-
|
|
205
|
-
const addItem = () => {
|
|
206
|
-
setItems([...items, { id: Date.now(), name: "New Item" }]);
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
return (
|
|
210
|
-
<div>
|
|
211
|
-
<button onClick={addItem}>Add Item</button>
|
|
212
|
-
<ul ref={rootRef}>
|
|
213
|
-
{items.map((item) => (
|
|
214
|
-
<li key={item.id}>
|
|
215
|
-
<button>{item.name}</button>
|
|
216
|
-
</li>
|
|
217
|
-
))}
|
|
218
|
-
</ul>
|
|
219
|
-
</div>
|
|
220
|
-
);
|
|
221
|
-
}
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
---
|
|
225
|
-
|
|
226
|
-
## Implementation notes
|
|
227
|
-
|
|
228
|
-
- Uses `queryFocusables()` to find focusable elements (buttons, links, inputs, etc.)
|
|
229
|
-
- Manages focus state via `tabIndex` manipulation
|
|
230
|
-
- Handles wrap-around navigation at list boundaries
|
|
231
|
-
- Observes DOM mutations to handle dynamic content
|
|
232
|
-
- Built on `useRefEffect` for cleanup management
|
|
233
|
-
|
|
234
|
-
---
|
|
235
|
-
|
|
236
|
-
## Accessibility
|
|
237
|
-
|
|
238
|
-
This hook helps implement accessible keyboard navigation:
|
|
239
|
-
|
|
240
|
-
- Makes complex widgets keyboard-accessible
|
|
241
|
-
- Follows WAI-ARIA grid pattern recommendations
|
|
242
|
-
- Reduces Tab stops for better keyboard efficiency
|
|
243
|
-
- Works with screen readers
|
|
244
|
-
|
|
245
|
-
For best results, combine with proper ARIA attributes:
|
|
246
|
-
|
|
247
|
-
```js
|
|
248
|
-
<ul
|
|
249
|
-
ref={rootRef}
|
|
250
|
-
role="listbox"
|
|
251
|
-
aria-label="Select an option"
|
|
252
|
-
>
|
|
253
|
-
<li role="option" aria-selected={selected === 1}>
|
|
254
|
-
<button>Option 1</button>
|
|
255
|
-
</li>
|
|
256
|
-
{/* ... */}
|
|
257
|
-
</ul>
|
|
258
|
-
```
|