ajo-ui 0.1.0
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 +15 -0
- package/README.md +126 -0
- package/dist/accordion.js +130 -0
- package/dist/avatar.js +54 -0
- package/dist/calendar.js +2 -0
- package/dist/carousel.js +239 -0
- package/dist/chart.js +790 -0
- package/dist/checkbox-group.js +70 -0
- package/dist/checkbox.js +77 -0
- package/dist/chunks/bar-CVafh6C1.js +99 -0
- package/dist/chunks/calendar-q8jZ8Cxr.js +1923 -0
- package/dist/chunks/collection-DtRB63U4.js +111 -0
- package/dist/chunks/data-table-DpkWv4y4.js +1039 -0
- package/dist/chunks/menu-B45IyHHC.js +704 -0
- package/dist/chunks/native-BJdhd9XJ.js +20 -0
- package/dist/chunks/popup-C8Bb3l_g.js +459 -0
- package/dist/chunks/popup-surface-BDCgtVU0.js +18 -0
- package/dist/chunks/position-D6_i_SRn.js +434 -0
- package/dist/chunks/virtual-list-B7hjGkjk.js +413 -0
- package/dist/collapsible.js +106 -0
- package/dist/command.js +263 -0
- package/dist/context-menu.js +112 -0
- package/dist/data-table.js +5 -0
- package/dist/dialog.js +207 -0
- package/dist/direction.js +22 -0
- package/dist/drawer.js +139 -0
- package/dist/field.js +26 -0
- package/dist/index.js +38 -0
- package/dist/input-date.js +994 -0
- package/dist/input-group.js +52 -0
- package/dist/input-otp.js +179 -0
- package/dist/menu.js +2 -0
- package/dist/menubar.js +236 -0
- package/dist/message-scroller.js +446 -0
- package/dist/navigation-menu.js +330 -0
- package/dist/popover.js +307 -0
- package/dist/progress.js +39 -0
- package/dist/radio-group.js +107 -0
- package/dist/resizable.js +172 -0
- package/dist/select.js +961 -0
- package/dist/sidebar.js +343 -0
- package/dist/slider.js +259 -0
- package/dist/switch.js +53 -0
- package/dist/tabs.js +182 -0
- package/dist/toast.js +492 -0
- package/dist/toggle-group.js +111 -0
- package/dist/toggle.js +52 -0
- package/dist/toolbar.js +127 -0
- package/dist/tooltip.js +196 -0
- package/dist/utils.js +104 -0
- package/dist/virtual-list.js +2 -0
- package/package.json +250 -0
- package/src/accordion.tsx +261 -0
- package/src/availability.ts +261 -0
- package/src/avatar.tsx +99 -0
- package/src/bar.ts +156 -0
- package/src/calendar.tsx +1441 -0
- package/src/carousel.tsx +424 -0
- package/src/chart.tsx +1194 -0
- package/src/checkbox-group.tsx +132 -0
- package/src/checkbox.tsx +130 -0
- package/src/collapsible.tsx +188 -0
- package/src/collection.ts +154 -0
- package/src/command.tsx +511 -0
- package/src/context-menu.tsx +233 -0
- package/src/data-table-contract.ts +143 -0
- package/src/data-table-model.ts +760 -0
- package/src/data-table.tsx +475 -0
- package/src/dialog.tsx +393 -0
- package/src/direction.tsx +45 -0
- package/src/drawer.tsx +251 -0
- package/src/field.tsx +61 -0
- package/src/index.ts +37 -0
- package/src/input-date.tsx +1539 -0
- package/src/input-group.tsx +142 -0
- package/src/input-otp.tsx +324 -0
- package/src/menu-cluster.ts +124 -0
- package/src/menu.tsx +1095 -0
- package/src/menubar.tsx +459 -0
- package/src/message-scroller.tsx +732 -0
- package/src/native.ts +26 -0
- package/src/navigation-menu.tsx +578 -0
- package/src/popover.tsx +519 -0
- package/src/popup-surface.tsx +31 -0
- package/src/popup.ts +569 -0
- package/src/position.ts +523 -0
- package/src/progress.tsx +70 -0
- package/src/radio-group.tsx +186 -0
- package/src/resizable.tsx +310 -0
- package/src/segments.ts +922 -0
- package/src/select.tsx +1501 -0
- package/src/sidebar.tsx +683 -0
- package/src/slider.tsx +424 -0
- package/src/switch.tsx +104 -0
- package/src/tabs.tsx +314 -0
- package/src/toast.tsx +923 -0
- package/src/toggle-group.tsx +249 -0
- package/src/toggle.tsx +91 -0
- package/src/toolbar.tsx +212 -0
- package/src/tooltip.tsx +359 -0
- package/src/utils.ts +204 -0
- package/src/virtual-list.tsx +205 -0
- package/src/virtual.ts +385 -0
package/package.json
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ajo-ui",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Unstyled accessible UI components for Ajo",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"src",
|
|
10
|
+
"README.md"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./src/index.ts",
|
|
15
|
+
"default": "./dist/index.js",
|
|
16
|
+
"import": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./utils": {
|
|
19
|
+
"types": "./src/utils.ts",
|
|
20
|
+
"default": "./dist/utils.js",
|
|
21
|
+
"import": "./dist/utils.js"
|
|
22
|
+
},
|
|
23
|
+
"./accordion": {
|
|
24
|
+
"types": "./src/accordion.tsx",
|
|
25
|
+
"default": "./dist/accordion.js",
|
|
26
|
+
"import": "./dist/accordion.js"
|
|
27
|
+
},
|
|
28
|
+
"./avatar": {
|
|
29
|
+
"types": "./src/avatar.tsx",
|
|
30
|
+
"default": "./dist/avatar.js",
|
|
31
|
+
"import": "./dist/avatar.js"
|
|
32
|
+
},
|
|
33
|
+
"./calendar": {
|
|
34
|
+
"types": "./src/calendar.tsx",
|
|
35
|
+
"default": "./dist/calendar.js",
|
|
36
|
+
"import": "./dist/calendar.js"
|
|
37
|
+
},
|
|
38
|
+
"./carousel": {
|
|
39
|
+
"types": "./src/carousel.tsx",
|
|
40
|
+
"default": "./dist/carousel.js",
|
|
41
|
+
"import": "./dist/carousel.js"
|
|
42
|
+
},
|
|
43
|
+
"./chart": {
|
|
44
|
+
"types": "./src/chart.tsx",
|
|
45
|
+
"default": "./dist/chart.js",
|
|
46
|
+
"import": "./dist/chart.js"
|
|
47
|
+
},
|
|
48
|
+
"./checkbox": {
|
|
49
|
+
"types": "./src/checkbox.tsx",
|
|
50
|
+
"default": "./dist/checkbox.js",
|
|
51
|
+
"import": "./dist/checkbox.js"
|
|
52
|
+
},
|
|
53
|
+
"./checkbox-group": {
|
|
54
|
+
"types": "./src/checkbox-group.tsx",
|
|
55
|
+
"default": "./dist/checkbox-group.js",
|
|
56
|
+
"import": "./dist/checkbox-group.js"
|
|
57
|
+
},
|
|
58
|
+
"./collapsible": {
|
|
59
|
+
"types": "./src/collapsible.tsx",
|
|
60
|
+
"default": "./dist/collapsible.js",
|
|
61
|
+
"import": "./dist/collapsible.js"
|
|
62
|
+
},
|
|
63
|
+
"./command": {
|
|
64
|
+
"types": "./src/command.tsx",
|
|
65
|
+
"default": "./dist/command.js",
|
|
66
|
+
"import": "./dist/command.js"
|
|
67
|
+
},
|
|
68
|
+
"./context-menu": {
|
|
69
|
+
"types": "./src/context-menu.tsx",
|
|
70
|
+
"default": "./dist/context-menu.js",
|
|
71
|
+
"import": "./dist/context-menu.js"
|
|
72
|
+
},
|
|
73
|
+
"./data-table": {
|
|
74
|
+
"types": "./src/data-table.tsx",
|
|
75
|
+
"default": "./dist/data-table.js",
|
|
76
|
+
"import": "./dist/data-table.js"
|
|
77
|
+
},
|
|
78
|
+
"./dialog": {
|
|
79
|
+
"types": "./src/dialog.tsx",
|
|
80
|
+
"default": "./dist/dialog.js",
|
|
81
|
+
"import": "./dist/dialog.js"
|
|
82
|
+
},
|
|
83
|
+
"./direction": {
|
|
84
|
+
"types": "./src/direction.tsx",
|
|
85
|
+
"default": "./dist/direction.js",
|
|
86
|
+
"import": "./dist/direction.js"
|
|
87
|
+
},
|
|
88
|
+
"./drawer": {
|
|
89
|
+
"types": "./src/drawer.tsx",
|
|
90
|
+
"default": "./dist/drawer.js",
|
|
91
|
+
"import": "./dist/drawer.js"
|
|
92
|
+
},
|
|
93
|
+
"./field": {
|
|
94
|
+
"types": "./src/field.tsx",
|
|
95
|
+
"default": "./dist/field.js",
|
|
96
|
+
"import": "./dist/field.js"
|
|
97
|
+
},
|
|
98
|
+
"./input-date": {
|
|
99
|
+
"types": "./src/input-date.tsx",
|
|
100
|
+
"default": "./dist/input-date.js",
|
|
101
|
+
"import": "./dist/input-date.js"
|
|
102
|
+
},
|
|
103
|
+
"./input-group": {
|
|
104
|
+
"types": "./src/input-group.tsx",
|
|
105
|
+
"default": "./dist/input-group.js",
|
|
106
|
+
"import": "./dist/input-group.js"
|
|
107
|
+
},
|
|
108
|
+
"./input-otp": {
|
|
109
|
+
"types": "./src/input-otp.tsx",
|
|
110
|
+
"default": "./dist/input-otp.js",
|
|
111
|
+
"import": "./dist/input-otp.js"
|
|
112
|
+
},
|
|
113
|
+
"./menu": {
|
|
114
|
+
"types": "./src/menu.tsx",
|
|
115
|
+
"default": "./dist/menu.js",
|
|
116
|
+
"import": "./dist/menu.js"
|
|
117
|
+
},
|
|
118
|
+
"./menubar": {
|
|
119
|
+
"types": "./src/menubar.tsx",
|
|
120
|
+
"default": "./dist/menubar.js",
|
|
121
|
+
"import": "./dist/menubar.js"
|
|
122
|
+
},
|
|
123
|
+
"./message-scroller": {
|
|
124
|
+
"types": "./src/message-scroller.tsx",
|
|
125
|
+
"default": "./dist/message-scroller.js",
|
|
126
|
+
"import": "./dist/message-scroller.js"
|
|
127
|
+
},
|
|
128
|
+
"./navigation-menu": {
|
|
129
|
+
"types": "./src/navigation-menu.tsx",
|
|
130
|
+
"default": "./dist/navigation-menu.js",
|
|
131
|
+
"import": "./dist/navigation-menu.js"
|
|
132
|
+
},
|
|
133
|
+
"./popover": {
|
|
134
|
+
"types": "./src/popover.tsx",
|
|
135
|
+
"default": "./dist/popover.js",
|
|
136
|
+
"import": "./dist/popover.js"
|
|
137
|
+
},
|
|
138
|
+
"./progress": {
|
|
139
|
+
"types": "./src/progress.tsx",
|
|
140
|
+
"default": "./dist/progress.js",
|
|
141
|
+
"import": "./dist/progress.js"
|
|
142
|
+
},
|
|
143
|
+
"./radio-group": {
|
|
144
|
+
"types": "./src/radio-group.tsx",
|
|
145
|
+
"default": "./dist/radio-group.js",
|
|
146
|
+
"import": "./dist/radio-group.js"
|
|
147
|
+
},
|
|
148
|
+
"./resizable": {
|
|
149
|
+
"types": "./src/resizable.tsx",
|
|
150
|
+
"default": "./dist/resizable.js",
|
|
151
|
+
"import": "./dist/resizable.js"
|
|
152
|
+
},
|
|
153
|
+
"./select": {
|
|
154
|
+
"types": "./src/select.tsx",
|
|
155
|
+
"default": "./dist/select.js",
|
|
156
|
+
"import": "./dist/select.js"
|
|
157
|
+
},
|
|
158
|
+
"./sidebar": {
|
|
159
|
+
"types": "./src/sidebar.tsx",
|
|
160
|
+
"default": "./dist/sidebar.js",
|
|
161
|
+
"import": "./dist/sidebar.js"
|
|
162
|
+
},
|
|
163
|
+
"./slider": {
|
|
164
|
+
"types": "./src/slider.tsx",
|
|
165
|
+
"default": "./dist/slider.js",
|
|
166
|
+
"import": "./dist/slider.js"
|
|
167
|
+
},
|
|
168
|
+
"./switch": {
|
|
169
|
+
"types": "./src/switch.tsx",
|
|
170
|
+
"default": "./dist/switch.js",
|
|
171
|
+
"import": "./dist/switch.js"
|
|
172
|
+
},
|
|
173
|
+
"./tabs": {
|
|
174
|
+
"types": "./src/tabs.tsx",
|
|
175
|
+
"default": "./dist/tabs.js",
|
|
176
|
+
"import": "./dist/tabs.js"
|
|
177
|
+
},
|
|
178
|
+
"./toast": {
|
|
179
|
+
"types": "./src/toast.tsx",
|
|
180
|
+
"default": "./dist/toast.js",
|
|
181
|
+
"import": "./dist/toast.js"
|
|
182
|
+
},
|
|
183
|
+
"./toggle": {
|
|
184
|
+
"types": "./src/toggle.tsx",
|
|
185
|
+
"default": "./dist/toggle.js",
|
|
186
|
+
"import": "./dist/toggle.js"
|
|
187
|
+
},
|
|
188
|
+
"./toggle-group": {
|
|
189
|
+
"types": "./src/toggle-group.tsx",
|
|
190
|
+
"default": "./dist/toggle-group.js",
|
|
191
|
+
"import": "./dist/toggle-group.js"
|
|
192
|
+
},
|
|
193
|
+
"./toolbar": {
|
|
194
|
+
"types": "./src/toolbar.tsx",
|
|
195
|
+
"default": "./dist/toolbar.js",
|
|
196
|
+
"import": "./dist/toolbar.js"
|
|
197
|
+
},
|
|
198
|
+
"./tooltip": {
|
|
199
|
+
"types": "./src/tooltip.tsx",
|
|
200
|
+
"default": "./dist/tooltip.js",
|
|
201
|
+
"import": "./dist/tooltip.js"
|
|
202
|
+
},
|
|
203
|
+
"./virtual-list": {
|
|
204
|
+
"types": "./src/virtual-list.tsx",
|
|
205
|
+
"default": "./dist/virtual-list.js",
|
|
206
|
+
"import": "./dist/virtual-list.js"
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
"dependencies": {
|
|
210
|
+
"@floating-ui/dom": "1.8.0",
|
|
211
|
+
"@tanstack/table-core": "9.0.0-beta.47",
|
|
212
|
+
"@tanstack/virtual-core": "3.17.4",
|
|
213
|
+
"ajo-cloves": "^0.1.0"
|
|
214
|
+
},
|
|
215
|
+
"peerDependencies": {
|
|
216
|
+
"ajo": "^0.1.35"
|
|
217
|
+
},
|
|
218
|
+
"devDependencies": {
|
|
219
|
+
"ajo": "0.1.35"
|
|
220
|
+
},
|
|
221
|
+
"engines": {
|
|
222
|
+
"node": ">=22.18.0"
|
|
223
|
+
},
|
|
224
|
+
"keywords": [
|
|
225
|
+
"ajo",
|
|
226
|
+
"ui",
|
|
227
|
+
"components",
|
|
228
|
+
"accessibility",
|
|
229
|
+
"headless"
|
|
230
|
+
],
|
|
231
|
+
"author": "Cristian Falcone",
|
|
232
|
+
"license": "ISC",
|
|
233
|
+
"repository": {
|
|
234
|
+
"type": "git",
|
|
235
|
+
"url": "git+https://github.com/cristianfalcone/ajo-kit.git",
|
|
236
|
+
"directory": "packages/ajo-ui"
|
|
237
|
+
},
|
|
238
|
+
"bugs": {
|
|
239
|
+
"url": "https://github.com/cristianfalcone/ajo-kit/issues"
|
|
240
|
+
},
|
|
241
|
+
"homepage": "https://github.com/cristianfalcone/ajo-kit/tree/main/packages/ajo-ui#readme",
|
|
242
|
+
"publishConfig": {
|
|
243
|
+
"access": "public"
|
|
244
|
+
},
|
|
245
|
+
"scripts": {
|
|
246
|
+
"build": "pnpm -w exec tsx scripts/package-build.ts ajo-ui",
|
|
247
|
+
"test": "pnpm -w exec vitest run packages/ajo-ui/tests",
|
|
248
|
+
"test:bundle": "pnpm -w exec tsx packages/ajo-ui/tests/bundle.ts"
|
|
249
|
+
}
|
|
250
|
+
}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import type { IntrinsicElements, Stateful, Stateless, WithChildren } from 'ajo'
|
|
2
|
+
import { controlled, listen, roving, statefulRootAttrs as rootAttrs } from 'ajo-cloves'
|
|
3
|
+
import { context } from 'ajo/context'
|
|
4
|
+
import type { FixedArgs, OmitArg } from './utils'
|
|
5
|
+
import { strings } from './utils'
|
|
6
|
+
import { Collapsible, CollapsibleContent, CollapsibleContext, CollapsibleTrigger } from './collapsible'
|
|
7
|
+
|
|
8
|
+
/** Selection model supported by an Accordion root. */
|
|
9
|
+
export type AccordionType = 'multiple' | 'single'
|
|
10
|
+
|
|
11
|
+
type AccordionSharedArgs = WithChildren<OmitArg<IntrinsicElements['div'], 'onchange'> & {
|
|
12
|
+
/** Disable every accordion item. */
|
|
13
|
+
disabled?: boolean
|
|
14
|
+
}> & FixedArgs<'onchange'>
|
|
15
|
+
|
|
16
|
+
/** Arguments for a single-open Accordion. */
|
|
17
|
+
export type AccordionSingleArgs = AccordionSharedArgs & {
|
|
18
|
+
/** Allow the open item to close. */
|
|
19
|
+
collapsible?: boolean
|
|
20
|
+
/** Initial open item for uncontrolled usage. */
|
|
21
|
+
defaultValue?: string
|
|
22
|
+
/** Single-open accordion mode. */
|
|
23
|
+
type?: 'single'
|
|
24
|
+
/** Controlled open item. */
|
|
25
|
+
value?: string
|
|
26
|
+
/** Called whenever the open item changes. */
|
|
27
|
+
onValueChange?: (value: string, event?: Event) => void
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Arguments for an Accordion that may keep several items open. */
|
|
31
|
+
export type AccordionMultipleArgs = AccordionSharedArgs & {
|
|
32
|
+
/** Initial open items for uncontrolled usage. */
|
|
33
|
+
defaultValue?: string[]
|
|
34
|
+
/** Multiple-open accordion mode. */
|
|
35
|
+
type: 'multiple'
|
|
36
|
+
/** Controlled open items. */
|
|
37
|
+
value?: string[]
|
|
38
|
+
/** Called whenever the open items change. */
|
|
39
|
+
onValueChange?: (value: string[], event?: Event) => void
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Public arguments accepted by the Accordion root. */
|
|
43
|
+
export type AccordionArgs = AccordionMultipleArgs | AccordionSingleArgs
|
|
44
|
+
|
|
45
|
+
/** Arguments for one value-bearing Accordion item. */
|
|
46
|
+
export type AccordionItemArgs = WithChildren<OmitArg<IntrinsicElements['details'], 'open'> & {
|
|
47
|
+
/** Stable item value used by the parent accordion. */
|
|
48
|
+
value: string
|
|
49
|
+
/** Disable this item. */
|
|
50
|
+
disabled?: boolean
|
|
51
|
+
}> & FixedArgs<'open'>
|
|
52
|
+
|
|
53
|
+
/** Arguments for an Accordion item's summary trigger. */
|
|
54
|
+
export type AccordionTriggerArgs = WithChildren<IntrinsicElements['summary']>
|
|
55
|
+
|
|
56
|
+
/** Arguments for an Accordion item's collapsible panel. */
|
|
57
|
+
export type AccordionContentArgs = WithChildren<IntrinsicElements['div'] & {
|
|
58
|
+
/** Classes for an inner content wrapper. */
|
|
59
|
+
innerClass?: string
|
|
60
|
+
}>
|
|
61
|
+
|
|
62
|
+
type AccordionRootArgs = WithChildren<{
|
|
63
|
+
collapsible?: boolean
|
|
64
|
+
defaultValue?: string | string[]
|
|
65
|
+
disabled?: boolean
|
|
66
|
+
onValueChange?: ((value: string, event?: Event) => void) | ((value: string[], event?: Event) => void)
|
|
67
|
+
type: AccordionType
|
|
68
|
+
value?: string | string[]
|
|
69
|
+
}>
|
|
70
|
+
|
|
71
|
+
type AccordionContextValue = {
|
|
72
|
+
collapsible: boolean
|
|
73
|
+
disabled: boolean
|
|
74
|
+
isOpen: (value: string) => boolean
|
|
75
|
+
toggle: (value: string, event?: Event) => void
|
|
76
|
+
type: AccordionType
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const AccordionContext = context<AccordionContextValue | null>(null)
|
|
80
|
+
|
|
81
|
+
const sameArray = (first: string[], second: string[]) =>
|
|
82
|
+
first.length === second.length && first.every((value, index) => value === second[index])
|
|
83
|
+
|
|
84
|
+
const AccordionRoot: Stateful<AccordionRootArgs> = function* ({ defaultValue, type, value }) {
|
|
85
|
+
let collapsible = false
|
|
86
|
+
let disabled = false
|
|
87
|
+
let onValueChange: AccordionArgs['onValueChange']
|
|
88
|
+
let mode: AccordionType = type
|
|
89
|
+
const multipleState = controlled<string[]>(this, {
|
|
90
|
+
fallback: type === 'multiple' ? strings(value ?? defaultValue) : [],
|
|
91
|
+
onChange: (next, event) => {
|
|
92
|
+
const notify = onValueChange as ((value: string[], event?: Event) => void) | undefined
|
|
93
|
+
notify?.(next, event)
|
|
94
|
+
},
|
|
95
|
+
})
|
|
96
|
+
const singleState = controlled<string>(this, {
|
|
97
|
+
fallback: type === 'single' ? String(value ?? defaultValue ?? '') : '',
|
|
98
|
+
onChange: (next, event) => {
|
|
99
|
+
const notify = onValueChange as ((value: string, event?: Event) => void) | undefined
|
|
100
|
+
notify?.(next, event)
|
|
101
|
+
},
|
|
102
|
+
})
|
|
103
|
+
let multiple = multipleState.value
|
|
104
|
+
let single = singleState.value
|
|
105
|
+
|
|
106
|
+
const isOpen = (itemValue: string) =>
|
|
107
|
+
mode === 'multiple' ? multiple.includes(itemValue) : single === itemValue
|
|
108
|
+
|
|
109
|
+
const setSingle = (next: string, event?: Event) => {
|
|
110
|
+
if (next === single) return
|
|
111
|
+
singleState.set(next, event)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const setMultiple = (next: string[], event?: Event) => {
|
|
115
|
+
if (sameArray(next, multiple)) return
|
|
116
|
+
multipleState.set(next, event)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const toggle = (itemValue: string, event?: Event) => {
|
|
120
|
+
if (disabled) return
|
|
121
|
+
|
|
122
|
+
if (mode === 'multiple') {
|
|
123
|
+
setMultiple(
|
|
124
|
+
multiple.includes(itemValue)
|
|
125
|
+
? multiple.filter(value => value !== itemValue)
|
|
126
|
+
: [...multiple, itemValue],
|
|
127
|
+
event,
|
|
128
|
+
)
|
|
129
|
+
return
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (single === itemValue) {
|
|
133
|
+
if (collapsible) setSingle('', event)
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
setSingle(itemValue, event)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const nav = roving(this, {
|
|
141
|
+
items: () => Array.from(this.querySelectorAll<HTMLElement>('[data-slot="accordion-trigger"]'))
|
|
142
|
+
.filter(trigger => trigger.getAttribute('aria-disabled') !== 'true' && trigger.offsetParent !== null),
|
|
143
|
+
onMove: target => target.focus(),
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
listen(this, 'keydown', (event: KeyboardEvent) => {
|
|
147
|
+
const target = event.target as HTMLElement | null
|
|
148
|
+
if (!target?.matches('[data-slot="accordion-trigger"]')) return
|
|
149
|
+
|
|
150
|
+
nav.handle(event)
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
for (const args of this) {
|
|
154
|
+
mode = args.type ?? 'single'
|
|
155
|
+
collapsible = mode === 'single' && Boolean((args as AccordionSingleArgs).collapsible)
|
|
156
|
+
disabled = Boolean(args.disabled)
|
|
157
|
+
onValueChange = args.onValueChange
|
|
158
|
+
multipleState.sync(mode === 'multiple' && args.value != null ? strings(args.value) : undefined)
|
|
159
|
+
singleState.sync(mode === 'single' && args.value != null ? String(args.value ?? '') : undefined)
|
|
160
|
+
multiple = mode === 'multiple' ? multipleState.value : []
|
|
161
|
+
single = mode === 'single' ? singleState.value : ''
|
|
162
|
+
|
|
163
|
+
AccordionContext({ collapsible, disabled, isOpen, toggle, type: mode })
|
|
164
|
+
yield <>{args.children}</>
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
/** Unstyled root provider for accordion state. */
|
|
170
|
+
const Accordion: Stateless<AccordionArgs> = ({
|
|
171
|
+
children,
|
|
172
|
+
collapsible,
|
|
173
|
+
defaultValue,
|
|
174
|
+
disabled,
|
|
175
|
+
onValueChange,
|
|
176
|
+
type = 'single',
|
|
177
|
+
value,
|
|
178
|
+
...attrs
|
|
179
|
+
}) => (
|
|
180
|
+
<AccordionRoot
|
|
181
|
+
{...rootAttrs(attrs)}
|
|
182
|
+
collapsible={collapsible === true}
|
|
183
|
+
defaultValue={defaultValue}
|
|
184
|
+
disabled={Boolean(disabled)}
|
|
185
|
+
onValueChange={onValueChange}
|
|
186
|
+
type={type}
|
|
187
|
+
value={value}
|
|
188
|
+
attr:data-slot="accordion"
|
|
189
|
+
>
|
|
190
|
+
{children}
|
|
191
|
+
</AccordionRoot>
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
/** Unstyled accordion section: a group-controlled collapsible details element. */
|
|
195
|
+
const AccordionItem: Stateless<AccordionItemArgs> = ({
|
|
196
|
+
children,
|
|
197
|
+
disabled,
|
|
198
|
+
open: _open,
|
|
199
|
+
value,
|
|
200
|
+
...attrs
|
|
201
|
+
}) => {
|
|
202
|
+
const accordion = AccordionContext()
|
|
203
|
+
const itemValue = String(value)
|
|
204
|
+
const opened = Boolean(accordion?.isOpen(itemValue))
|
|
205
|
+
const disabledFlag = Boolean(disabled ?? accordion?.disabled)
|
|
206
|
+
|
|
207
|
+
return (
|
|
208
|
+
<Collapsible
|
|
209
|
+
data-orientation="vertical"
|
|
210
|
+
data-slot="accordion-item"
|
|
211
|
+
data-value={value}
|
|
212
|
+
{...attrs}
|
|
213
|
+
disabled={disabledFlag}
|
|
214
|
+
onOpenChange={(_next: boolean, event?: Event) => accordion?.toggle(itemValue, event)}
|
|
215
|
+
open={opened}
|
|
216
|
+
>
|
|
217
|
+
{children}
|
|
218
|
+
</Collapsible>
|
|
219
|
+
)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** Unstyled accordion heading trigger: a collapsible summary locked by group rules. */
|
|
223
|
+
const AccordionTrigger: Stateless<AccordionTriggerArgs> = ({
|
|
224
|
+
children,
|
|
225
|
+
...attrs
|
|
226
|
+
}) => {
|
|
227
|
+
const accordion = AccordionContext()
|
|
228
|
+
const item = CollapsibleContext()
|
|
229
|
+
const locked = Boolean(item?.open && accordion?.type === 'single' && !accordion.collapsible)
|
|
230
|
+
|
|
231
|
+
return (
|
|
232
|
+
<CollapsibleTrigger
|
|
233
|
+
data-orientation="vertical"
|
|
234
|
+
data-slot="accordion-trigger"
|
|
235
|
+
{...attrs}
|
|
236
|
+
locked={locked}
|
|
237
|
+
>
|
|
238
|
+
{children}
|
|
239
|
+
</CollapsibleTrigger>
|
|
240
|
+
)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/** Unstyled accordion panel content. */
|
|
244
|
+
const AccordionContent: Stateless<AccordionContentArgs> = ({
|
|
245
|
+
children,
|
|
246
|
+
innerClass,
|
|
247
|
+
...attrs
|
|
248
|
+
}) => (
|
|
249
|
+
<CollapsibleContent
|
|
250
|
+
data-orientation="vertical"
|
|
251
|
+
data-slot="accordion-content"
|
|
252
|
+
role="region"
|
|
253
|
+
{...attrs}
|
|
254
|
+
>
|
|
255
|
+
<div class={innerClass}>
|
|
256
|
+
{children}
|
|
257
|
+
</div>
|
|
258
|
+
</CollapsibleContent>
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger }
|