@remix-run/ui 0.0.0 → 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 +21 -0
- package/README.md +195 -2
- package/dist/animation/animate-layout-mixin.d.ts +12 -0
- package/dist/animation/animate-layout-mixin.js +214 -0
- package/dist/animation/animate-layout-mixin.js.map +1 -0
- package/dist/animation/animate-mixins.d.ts +29 -0
- package/dist/animation/animate-mixins.js +235 -0
- package/dist/animation/animate-mixins.js.map +1 -0
- package/dist/animation/index.d.ts +6 -0
- package/dist/animation/index.js +5 -0
- package/dist/animation/index.js.map +1 -0
- package/dist/animation/spring.d.ts +75 -0
- package/dist/animation/spring.js +183 -0
- package/dist/animation/spring.js.map +1 -0
- package/dist/animation/tween.d.ts +70 -0
- package/dist/animation/tween.js +93 -0
- package/dist/animation/tween.js.map +1 -0
- package/dist/components/accordion/accordion.d.ts +92 -0
- package/dist/components/accordion/accordion.js +337 -0
- package/dist/components/accordion/accordion.js.map +1 -0
- package/dist/components/anchor/anchor.d.ts +13 -0
- package/dist/components/anchor/anchor.js +558 -0
- package/dist/components/anchor/anchor.js.map +1 -0
- package/dist/components/breadcrumbs/breadcrumbs.d.ts +11 -0
- package/dist/components/breadcrumbs/breadcrumbs.js +78 -0
- package/dist/components/breadcrumbs/breadcrumbs.js.map +1 -0
- package/dist/components/button/button.d.ts +23 -0
- package/dist/components/button/button.js +147 -0
- package/dist/components/button/button.js.map +1 -0
- package/dist/components/combobox/combobox.d.ts +101 -0
- package/dist/components/combobox/combobox.js +708 -0
- package/dist/components/combobox/combobox.js.map +1 -0
- package/dist/components/glyph/glyph.d.ts +14 -0
- package/dist/components/glyph/glyph.js +65 -0
- package/dist/components/glyph/glyph.js.map +1 -0
- package/dist/components/listbox/listbox.d.ts +67 -0
- package/dist/components/listbox/listbox.js +340 -0
- package/dist/components/listbox/listbox.js.map +1 -0
- package/dist/components/menu/hover-aim.d.ts +5 -0
- package/dist/components/menu/hover-aim.js +308 -0
- package/dist/components/menu/hover-aim.js.map +1 -0
- package/dist/components/menu/menu.d.ts +164 -0
- package/dist/components/menu/menu.js +1106 -0
- package/dist/components/menu/menu.js.map +1 -0
- package/dist/components/popover/popover.d.ts +35 -0
- package/dist/components/popover/popover.js +138 -0
- package/dist/components/popover/popover.js.map +1 -0
- package/dist/components/select/select.d.ts +67 -0
- package/dist/components/select/select.js +397 -0
- package/dist/components/select/select.js.map +1 -0
- package/dist/components/separator/separator.d.ts +2 -0
- package/dist/components/separator/separator.js +15 -0
- package/dist/components/separator/separator.js.map +1 -0
- package/dist/components/tabs/tabs.d.ts +78 -0
- package/dist/components/tabs/tabs.js +341 -0
- package/dist/components/tabs/tabs.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/interactions/keydown/keydown.d.ts +1 -0
- package/dist/interactions/keydown/keydown.js +8 -0
- package/dist/interactions/keydown/keydown.js.map +1 -0
- package/dist/interactions/outside-click/outside-click-mixin.d.ts +2 -0
- package/dist/interactions/outside-click/outside-click-mixin.js +29 -0
- package/dist/interactions/outside-click/outside-click-mixin.js.map +1 -0
- package/dist/interactions/typeahead/typeahead-mixin.d.ts +8 -0
- package/dist/interactions/typeahead/typeahead-mixin.js +59 -0
- package/dist/interactions/typeahead/typeahead-mixin.js.map +1 -0
- package/dist/jsx-runtime.d.ts +2 -0
- package/dist/jsx-runtime.js +3 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/runtime/client-entries.d.ts +91 -0
- package/dist/runtime/client-entries.js +40 -0
- package/dist/runtime/client-entries.js.map +1 -0
- package/dist/runtime/component.d.ts +223 -0
- package/dist/runtime/component.js +152 -0
- package/dist/runtime/component.js.map +1 -0
- package/dist/runtime/create-element.d.ts +10 -0
- package/dist/runtime/create-element.js +29 -0
- package/dist/runtime/create-element.js.map +1 -0
- package/dist/runtime/diff-dom.d.ts +2 -0
- package/dist/runtime/diff-dom.js +364 -0
- package/dist/runtime/diff-dom.js.map +1 -0
- package/dist/runtime/diff-props.d.ts +9 -0
- package/dist/runtime/diff-props.js +195 -0
- package/dist/runtime/diff-props.js.map +1 -0
- package/dist/runtime/document-state.d.ts +11 -0
- package/dist/runtime/document-state.js +106 -0
- package/dist/runtime/document-state.js.map +1 -0
- package/dist/runtime/dom.d.ts +3189 -0
- package/dist/runtime/dom.js +2 -0
- package/dist/runtime/dom.js.map +1 -0
- package/dist/runtime/error-event.d.ts +20 -0
- package/dist/runtime/error-event.js +19 -0
- package/dist/runtime/error-event.js.map +1 -0
- package/dist/runtime/event-listeners.d.ts +50 -0
- package/dist/runtime/event-listeners.js +31 -0
- package/dist/runtime/event-listeners.js.map +1 -0
- package/dist/runtime/frame.d.ts +119 -0
- package/dist/runtime/frame.js +915 -0
- package/dist/runtime/frame.js.map +1 -0
- package/dist/runtime/invariant.d.ts +23 -0
- package/dist/runtime/invariant.js +33 -0
- package/dist/runtime/invariant.js.map +1 -0
- package/dist/runtime/jsx.d.ts +320 -0
- package/dist/runtime/jsx.js +31 -0
- package/dist/runtime/jsx.js.map +1 -0
- package/dist/runtime/mixins/attrs-mixin.d.ts +9 -0
- package/dist/runtime/mixins/attrs-mixin.js +23 -0
- package/dist/runtime/mixins/attrs-mixin.js.map +1 -0
- package/dist/runtime/mixins/link-mixin.d.ts +17 -0
- package/dist/runtime/mixins/link-mixin.js +101 -0
- package/dist/runtime/mixins/link-mixin.js.map +1 -0
- package/dist/runtime/mixins/mixin.d.ts +145 -0
- package/dist/runtime/mixins/mixin.js +570 -0
- package/dist/runtime/mixins/mixin.js.map +1 -0
- package/dist/runtime/mixins/on-mixin.d.ts +16 -0
- package/dist/runtime/mixins/on-mixin.js +49 -0
- package/dist/runtime/mixins/on-mixin.js.map +1 -0
- package/dist/runtime/mixins/ref-mixin.d.ts +9 -0
- package/dist/runtime/mixins/ref-mixin.js +21 -0
- package/dist/runtime/mixins/ref-mixin.js.map +1 -0
- package/dist/runtime/navigation.d.ts +22 -0
- package/dist/runtime/navigation.js +102 -0
- package/dist/runtime/navigation.js.map +1 -0
- package/dist/runtime/reconcile.d.ts +11 -0
- package/dist/runtime/reconcile.js +1240 -0
- package/dist/runtime/reconcile.js.map +1 -0
- package/dist/runtime/render.d.ts +54 -0
- package/dist/runtime/render.js +50 -0
- package/dist/runtime/render.js.map +1 -0
- package/dist/runtime/run.d.ts +45 -0
- package/dist/runtime/run.js +68 -0
- package/dist/runtime/run.js.map +1 -0
- package/dist/runtime/scheduler.d.ts +30 -0
- package/dist/runtime/scheduler.js +185 -0
- package/dist/runtime/scheduler.js.map +1 -0
- package/dist/runtime/svg-attributes.d.ts +5 -0
- package/dist/runtime/svg-attributes.js +124 -0
- package/dist/runtime/svg-attributes.js.map +1 -0
- package/dist/runtime/to-vnode.d.ts +3 -0
- package/dist/runtime/to-vnode.js +43 -0
- package/dist/runtime/to-vnode.js.map +1 -0
- package/dist/runtime/typed-event-target.d.ts +50 -0
- package/dist/runtime/typed-event-target.js +6 -0
- package/dist/runtime/typed-event-target.js.map +1 -0
- package/dist/runtime/vdom.d.ts +55 -0
- package/dist/runtime/vdom.js +198 -0
- package/dist/runtime/vdom.js.map +1 -0
- package/dist/runtime/vnode.d.ts +79 -0
- package/dist/runtime/vnode.js +38 -0
- package/dist/runtime/vnode.js.map +1 -0
- package/dist/server/stream.d.ts +57 -0
- package/dist/server/stream.js +1007 -0
- package/dist/server/stream.js.map +1 -0
- package/dist/style/css-mixin.d.ts +8 -0
- package/dist/style/css-mixin.js +54 -0
- package/dist/style/css-mixin.js.map +1 -0
- package/dist/style/index.d.ts +5 -0
- package/dist/style/index.js +4 -0
- package/dist/style/index.js.map +1 -0
- package/dist/style/style.d.ts +24 -0
- package/dist/style/style.js +269 -0
- package/dist/style/style.js.map +1 -0
- package/dist/style/stylesheet.d.ts +11 -0
- package/dist/style/stylesheet.js +174 -0
- package/dist/style/stylesheet.js.map +1 -0
- package/dist/test.d.ts +2 -0
- package/dist/test.js +2 -0
- package/dist/test.js.map +1 -0
- package/dist/theme/contract.d.ts +259 -0
- package/dist/theme/contract.js +131 -0
- package/dist/theme/contract.js.map +1 -0
- package/dist/theme/glyph-contract.d.ts +13 -0
- package/dist/theme/glyph-contract.js +34 -0
- package/dist/theme/glyph-contract.js.map +1 -0
- package/dist/theme/presets/rmx-01/glyphs.d.ts +2 -0
- package/dist/theme/presets/rmx-01/glyphs.js +252 -0
- package/dist/theme/presets/rmx-01/glyphs.js.map +1 -0
- package/dist/theme/presets/rmx-01/index.d.ts +2 -0
- package/dist/theme/presets/rmx-01/index.js +119 -0
- package/dist/theme/presets/rmx-01/index.js.map +1 -0
- package/dist/theme/runtime.d.ts +2 -0
- package/dist/theme/runtime.js +81 -0
- package/dist/theme/runtime.js.map +1 -0
- package/dist/theme/theme.d.ts +6 -0
- package/dist/theme/theme.js +5 -0
- package/dist/theme/theme.js.map +1 -0
- package/dist/utils/flash-attribute.d.ts +1 -0
- package/dist/utils/flash-attribute.js +11 -0
- package/dist/utils/flash-attribute.js.map +1 -0
- package/dist/utils/scroll-lock.d.ts +3 -0
- package/dist/utils/scroll-lock.js +69 -0
- package/dist/utils/scroll-lock.js.map +1 -0
- package/dist/utils/wait-for-css-transition.d.ts +1 -0
- package/dist/utils/wait-for-css-transition.js +58 -0
- package/dist/utils/wait-for-css-transition.js.map +1 -0
- package/dist/utils/wait.d.ts +1 -0
- package/dist/utils/wait.js +6 -0
- package/dist/utils/wait.js.map +1 -0
- package/package.json +125 -5
- package/src/animation/animate-layout-mixin.ts +266 -0
- package/src/animation/animate-mixins.ts +292 -0
- package/src/animation/index.ts +6 -0
- package/src/animation/spring.ts +299 -0
- package/src/animation/tween.ts +134 -0
- package/src/components/accordion/accordion.tsx +565 -0
- package/src/components/anchor/anchor.ts +904 -0
- package/src/components/breadcrumbs/breadcrumbs.tsx +124 -0
- package/src/components/button/README.md +44 -0
- package/src/components/button/button.tsx +188 -0
- package/src/components/combobox/README.md +145 -0
- package/src/components/combobox/combobox.tsx +1014 -0
- package/src/components/glyph/glyph.tsx +110 -0
- package/src/components/listbox/listbox.ts +447 -0
- package/src/components/menu/hover-aim.ts +428 -0
- package/src/components/menu/menu.tsx +1547 -0
- package/src/components/popover/README.md +122 -0
- package/src/components/popover/popover.ts +201 -0
- package/src/components/select/select.tsx +585 -0
- package/src/components/separator/separator.ts +19 -0
- package/src/components/tabs/README.md +105 -0
- package/src/components/tabs/tabs.tsx +499 -0
- package/src/index.ts +72 -0
- package/src/interactions/keydown/keydown.ts +14 -0
- package/src/interactions/outside-click/outside-click-mixin.ts +55 -0
- package/src/interactions/typeahead/typeahead-mixin.ts +89 -0
- package/src/jsx-runtime.ts +2 -0
- package/src/runtime/client-entries.ts +137 -0
- package/src/runtime/component.ts +402 -0
- package/src/runtime/create-element.ts +38 -0
- package/src/runtime/diff-dom.ts +404 -0
- package/src/runtime/diff-props.ts +209 -0
- package/src/runtime/document-state.ts +130 -0
- package/src/runtime/dom.ts +3971 -0
- package/src/runtime/error-event.ts +26 -0
- package/src/runtime/event-listeners.ts +171 -0
- package/src/runtime/frame.ts +1211 -0
- package/src/runtime/invariant.ts +31 -0
- package/src/runtime/jsx.ts +398 -0
- package/src/runtime/mixins/attrs-mixin.ts +35 -0
- package/src/runtime/mixins/link-mixin.ts +131 -0
- package/src/runtime/mixins/mixin.ts +908 -0
- package/src/runtime/mixins/on-mixin.ts +89 -0
- package/src/runtime/mixins/ref-mixin.ts +32 -0
- package/src/runtime/navigation.ts +136 -0
- package/src/runtime/reconcile.ts +1722 -0
- package/src/runtime/render.ts +101 -0
- package/src/runtime/run.ts +100 -0
- package/src/runtime/scheduler.ts +262 -0
- package/src/runtime/svg-attributes.ts +133 -0
- package/src/runtime/to-vnode.ts +50 -0
- package/src/runtime/typed-event-target.ts +67 -0
- package/src/runtime/vdom.ts +295 -0
- package/src/runtime/vnode.ts +137 -0
- package/src/server/stream.ts +1342 -0
- package/src/style/css-mixin.ts +82 -0
- package/src/style/index.ts +10 -0
- package/src/style/style.ts +312 -0
- package/src/style/stylesheet.ts +209 -0
- package/src/test/setup.ts +7 -0
- package/src/test/utils.ts +45 -0
- package/src/test.ts +2 -0
- package/src/theme/contract.ts +183 -0
- package/src/theme/glyph-contract.ts +57 -0
- package/src/theme/presets/rmx-01/glyphs.tsx +308 -0
- package/src/theme/presets/rmx-01/index.ts +121 -0
- package/src/theme/runtime.ts +116 -0
- package/src/theme/theme.ts +15 -0
- package/src/utils/flash-attribute.ts +11 -0
- package/src/utils/scroll-lock.ts +97 -0
- package/src/utils/wait-for-css-transition.ts +66 -0
- package/src/utils/wait.ts +5 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attempt to find the t value for a given x on a cubic bezier curve.
|
|
3
|
+
* Uses Newton-Raphson iteration for fast convergence.
|
|
4
|
+
* @param x1 First control point x coordinate
|
|
5
|
+
* @param x2 Second control point x coordinate
|
|
6
|
+
* @param targetX The x value to solve for
|
|
7
|
+
* @returns The t parameter value
|
|
8
|
+
*/
|
|
9
|
+
function solveCubicBezierX(x1: number, x2: number, targetX: number): number {
|
|
10
|
+
// Initial guess
|
|
11
|
+
let t = targetX
|
|
12
|
+
|
|
13
|
+
// Newton-Raphson iteration (usually converges in 4-8 iterations)
|
|
14
|
+
for (let i = 0; i < 8; i++) {
|
|
15
|
+
let currentX = cubicBezier(t, x1, x2)
|
|
16
|
+
let slope = cubicBezierDerivative(t, x1, x2)
|
|
17
|
+
|
|
18
|
+
if (Math.abs(slope) < 1e-6) break
|
|
19
|
+
|
|
20
|
+
let error = currentX - targetX
|
|
21
|
+
if (Math.abs(error) < 1e-6) break
|
|
22
|
+
|
|
23
|
+
t -= error / slope
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return Math.max(0, Math.min(1, t))
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Compute the value of a cubic bezier at parameter t.
|
|
31
|
+
* For CSS-style beziers, start is (0,0) and end is (1,1),
|
|
32
|
+
* so we only need the two middle control point coordinates.
|
|
33
|
+
* @param t The parameter value (0 to 1)
|
|
34
|
+
* @param p1 First control point coordinate
|
|
35
|
+
* @param p2 Second control point coordinate
|
|
36
|
+
* @returns The bezier value at t
|
|
37
|
+
*/
|
|
38
|
+
function cubicBezier(t: number, p1: number, p2: number): number {
|
|
39
|
+
// B(t) = 3(1-t)²t·p1 + 3(1-t)t²·p2 + t³
|
|
40
|
+
let oneMinusT = 1 - t
|
|
41
|
+
return 3 * oneMinusT * oneMinusT * t * p1 + 3 * oneMinusT * t * t * p2 + t * t * t
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Derivative of the cubic bezier function.
|
|
46
|
+
* @param t The parameter value (0 to 1)
|
|
47
|
+
* @param p1 First control point coordinate
|
|
48
|
+
* @param p2 Second control point coordinate
|
|
49
|
+
* @returns The derivative of the bezier at t
|
|
50
|
+
*/
|
|
51
|
+
function cubicBezierDerivative(t: number, p1: number, p2: number): number {
|
|
52
|
+
// B'(t) = 3(1-t)²·p1 + 6(1-t)t·(p2-p1) + 3t²·(1-p2)
|
|
53
|
+
let oneMinusT = 1 - t
|
|
54
|
+
return 3 * oneMinusT * oneMinusT * p1 + 6 * oneMinusT * t * (p2 - p1) + 3 * t * t * (1 - p2)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Cubic-bezier control points used by {@link tween}.
|
|
59
|
+
*/
|
|
60
|
+
export interface BezierCurve {
|
|
61
|
+
/** First control point x coordinate. */
|
|
62
|
+
x1: number
|
|
63
|
+
/** First control point y coordinate. */
|
|
64
|
+
y1: number
|
|
65
|
+
/** Second control point x coordinate. */
|
|
66
|
+
x2: number
|
|
67
|
+
/** Second control point y coordinate. */
|
|
68
|
+
y2: number
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Common easing presets
|
|
72
|
+
/**
|
|
73
|
+
* Common cubic-bezier presets for {@link tween}.
|
|
74
|
+
*/
|
|
75
|
+
export const easings = {
|
|
76
|
+
linear: { x1: 0, y1: 0, x2: 1, y2: 1 },
|
|
77
|
+
ease: { x1: 0.25, y1: 0.1, x2: 0.25, y2: 1 },
|
|
78
|
+
easeIn: { x1: 0.42, y1: 0, x2: 1, y2: 1 },
|
|
79
|
+
easeOut: { x1: 0, y1: 0, x2: 0.58, y2: 1 },
|
|
80
|
+
easeInOut: { x1: 0.42, y1: 0, x2: 0.58, y2: 1 },
|
|
81
|
+
} as const
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Options for generating tweened values over time.
|
|
85
|
+
*/
|
|
86
|
+
export interface TweenOptions {
|
|
87
|
+
/** Starting value for the tween. */
|
|
88
|
+
from: number
|
|
89
|
+
/** Ending value for the tween. */
|
|
90
|
+
to: number
|
|
91
|
+
/** Total tween duration in milliseconds. */
|
|
92
|
+
duration: number
|
|
93
|
+
/** Cubic-bezier curve used to shape the interpolation. */
|
|
94
|
+
curve: BezierCurve
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Generator that tweens a value over time using a cubic bezier curve.
|
|
99
|
+
* Yields the current value on each frame. Use the iterator's `done` property
|
|
100
|
+
* to check if the animation is complete.
|
|
101
|
+
* @param options The tween configuration
|
|
102
|
+
* @yields The current tweened value
|
|
103
|
+
* @returns The final value
|
|
104
|
+
*/
|
|
105
|
+
export function* tween(options: TweenOptions): Generator<number, number, number> {
|
|
106
|
+
let { from, to, duration, curve } = options
|
|
107
|
+
let { x1, y1, x2, y2 } = curve
|
|
108
|
+
|
|
109
|
+
let startTime: number | null = null
|
|
110
|
+
let value = from
|
|
111
|
+
|
|
112
|
+
while (true) {
|
|
113
|
+
// Yield current value and receive the next timestamp
|
|
114
|
+
let timestamp: number = yield value
|
|
115
|
+
|
|
116
|
+
if (startTime === null) {
|
|
117
|
+
startTime = timestamp
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
let elapsed = timestamp - startTime
|
|
121
|
+
let linearProgress = Math.min(elapsed / duration, 1)
|
|
122
|
+
|
|
123
|
+
// Map linear progress through the bezier curve
|
|
124
|
+
// x-axis = time, y-axis = value
|
|
125
|
+
let t = solveCubicBezierX(x1, x2, linearProgress)
|
|
126
|
+
let easedProgress = cubicBezier(t, y1, y2)
|
|
127
|
+
|
|
128
|
+
value = from + (to - from) * easedProgress
|
|
129
|
+
|
|
130
|
+
if (linearProgress >= 1) {
|
|
131
|
+
return to
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -0,0 +1,565 @@
|
|
|
1
|
+
// @jsxRuntime classic
|
|
2
|
+
// @jsx createElement
|
|
3
|
+
import {
|
|
4
|
+
css,
|
|
5
|
+
createElement,
|
|
6
|
+
on,
|
|
7
|
+
ref,
|
|
8
|
+
type CSSMixinDescriptor,
|
|
9
|
+
type Handle,
|
|
10
|
+
type Props,
|
|
11
|
+
type RemixNode,
|
|
12
|
+
} from '@remix-run/ui'
|
|
13
|
+
|
|
14
|
+
import { spring } from '@remix-run/ui/animation'
|
|
15
|
+
import { Glyph } from '../glyph/glyph.tsx'
|
|
16
|
+
import { theme } from '../../theme/theme.ts'
|
|
17
|
+
|
|
18
|
+
const ACCORDION_CHANGE_EVENT = 'rmx:accordion-change' as const
|
|
19
|
+
|
|
20
|
+
type AccordionChangeHandler = (
|
|
21
|
+
event: AccordionChangeEvent,
|
|
22
|
+
signal: AbortSignal,
|
|
23
|
+
) => void | Promise<void>
|
|
24
|
+
|
|
25
|
+
declare global {
|
|
26
|
+
interface HTMLElementEventMap {
|
|
27
|
+
[ACCORDION_CHANGE_EVENT]: AccordionChangeEvent
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export class AccordionChangeEvent extends Event {
|
|
32
|
+
accordionType: AccordionType
|
|
33
|
+
itemValue: string
|
|
34
|
+
value: string | null | string[]
|
|
35
|
+
|
|
36
|
+
constructor(
|
|
37
|
+
value: string | null | string[],
|
|
38
|
+
init: {
|
|
39
|
+
accordionType: AccordionType
|
|
40
|
+
itemValue: string
|
|
41
|
+
},
|
|
42
|
+
) {
|
|
43
|
+
super(ACCORDION_CHANGE_EVENT, {
|
|
44
|
+
bubbles: true,
|
|
45
|
+
})
|
|
46
|
+
this.accordionType = init.accordionType
|
|
47
|
+
this.itemValue = init.itemValue
|
|
48
|
+
this.value = value
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
type AccordionType = 'single' | 'multiple'
|
|
53
|
+
type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6
|
|
54
|
+
|
|
55
|
+
type AccordionBaseProps = Omit<Props<'div'>, 'children'> & {
|
|
56
|
+
children?: RemixNode
|
|
57
|
+
disabled?: boolean
|
|
58
|
+
headingLevel?: HeadingLevel
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export type AccordionSingleProps = AccordionBaseProps & {
|
|
62
|
+
type?: 'single'
|
|
63
|
+
value?: string | null
|
|
64
|
+
defaultValue?: string | null
|
|
65
|
+
onValueChange?: (value: string | null) => void
|
|
66
|
+
collapsible?: boolean
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export type AccordionMultipleProps = AccordionBaseProps & {
|
|
70
|
+
type: 'multiple'
|
|
71
|
+
value?: string[]
|
|
72
|
+
defaultValue?: string[]
|
|
73
|
+
onValueChange?: (value: string[]) => void
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export type AccordionProps = AccordionSingleProps | AccordionMultipleProps
|
|
77
|
+
|
|
78
|
+
export type AccordionItemProps = Omit<Props<'div'>, 'children'> & {
|
|
79
|
+
children?: RemixNode
|
|
80
|
+
disabled?: boolean
|
|
81
|
+
value: string
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export type AccordionTriggerProps = Omit<Props<'button'>, 'children' | 'type'> & {
|
|
85
|
+
children?: RemixNode
|
|
86
|
+
indicator?: RemixNode | null
|
|
87
|
+
type?: 'button' | 'submit' | 'reset'
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export type AccordionContentProps = Omit<Props<'div'>, 'children'> & {
|
|
91
|
+
children?: RemixNode
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
type RegisteredItem = {
|
|
95
|
+
disabled: boolean
|
|
96
|
+
getTriggerNode(): HTMLButtonElement | null
|
|
97
|
+
value: string
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
type AccordionContext = {
|
|
101
|
+
collapsible: boolean
|
|
102
|
+
disabled: boolean
|
|
103
|
+
focusItem(value: string, direction: FocusDirection): void
|
|
104
|
+
getPanelId(value: string): string | undefined
|
|
105
|
+
getTriggerId(value: string): string | undefined
|
|
106
|
+
headingLevel: HeadingLevel
|
|
107
|
+
isOpen(value: string): boolean
|
|
108
|
+
registerItem(item: RegisteredItem): void
|
|
109
|
+
toggleItem(value: string): void
|
|
110
|
+
type: AccordionType
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
type AccordionItemContext = {
|
|
114
|
+
disabled: boolean
|
|
115
|
+
headingLevel: HeadingLevel
|
|
116
|
+
lockedOpen: boolean
|
|
117
|
+
open: boolean
|
|
118
|
+
panelId: string
|
|
119
|
+
setTriggerNode(node: HTMLButtonElement | null): void
|
|
120
|
+
triggerId: string
|
|
121
|
+
value: string
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
type FocusDirection = 'first' | 'last' | 'next' | 'previous'
|
|
125
|
+
|
|
126
|
+
const accordionPanelClipCss = css({
|
|
127
|
+
minHeight: 0,
|
|
128
|
+
overflow: 'hidden',
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
const accordionTransition = spring()
|
|
132
|
+
|
|
133
|
+
const accordionRootCss: CSSMixinDescriptor = css({
|
|
134
|
+
display: 'flex',
|
|
135
|
+
flexDirection: 'column',
|
|
136
|
+
minWidth: 0,
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
const accordionItemCss: CSSMixinDescriptor = css({
|
|
140
|
+
minWidth: 0,
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
const accordionTriggerCss: CSSMixinDescriptor = css({
|
|
144
|
+
all: 'unset',
|
|
145
|
+
boxSizing: 'border-box',
|
|
146
|
+
cursor: 'revert',
|
|
147
|
+
display: 'grid',
|
|
148
|
+
gridTemplateColumns: 'minmax(0, 1fr) auto',
|
|
149
|
+
alignItems: 'center',
|
|
150
|
+
gap: theme.space.md,
|
|
151
|
+
width: '100%',
|
|
152
|
+
minHeight: theme.control.height.lg,
|
|
153
|
+
padding: `${theme.space.md} 0`,
|
|
154
|
+
color: theme.colors.text.primary,
|
|
155
|
+
fontFamily: theme.fontFamily.sans,
|
|
156
|
+
fontSize: theme.fontSize.sm,
|
|
157
|
+
lineHeight: theme.lineHeight.normal,
|
|
158
|
+
fontWeight: theme.fontWeight.medium,
|
|
159
|
+
textAlign: 'left',
|
|
160
|
+
'&:hover:not(:disabled)': {
|
|
161
|
+
backgroundColor: theme.surface.lvl1,
|
|
162
|
+
},
|
|
163
|
+
'&:focus-visible': {
|
|
164
|
+
outline: `2px solid ${theme.colors.focus.ring}`,
|
|
165
|
+
outlineOffset: '2px',
|
|
166
|
+
},
|
|
167
|
+
'&:disabled': {
|
|
168
|
+
opacity: 0.55,
|
|
169
|
+
},
|
|
170
|
+
'& > span:first-child': {
|
|
171
|
+
minWidth: 0,
|
|
172
|
+
},
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
const accordionIndicatorCss: CSSMixinDescriptor = css({
|
|
176
|
+
display: 'inline-flex',
|
|
177
|
+
alignItems: 'center',
|
|
178
|
+
justifyContent: 'center',
|
|
179
|
+
width: theme.fontSize.sm,
|
|
180
|
+
height: theme.fontSize.sm,
|
|
181
|
+
color: theme.colors.text.muted,
|
|
182
|
+
transition: `transform ${accordionTransition}`,
|
|
183
|
+
'& > svg': {
|
|
184
|
+
display: 'block',
|
|
185
|
+
width: '100%',
|
|
186
|
+
height: '100%',
|
|
187
|
+
},
|
|
188
|
+
'&[data-state="open"]': {
|
|
189
|
+
transform: 'rotate(90deg)',
|
|
190
|
+
},
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
const accordionPanelCss: CSSMixinDescriptor = css({
|
|
194
|
+
display: 'grid',
|
|
195
|
+
gridTemplateRows: '0fr',
|
|
196
|
+
transition: `grid-template-rows ${accordionTransition}`,
|
|
197
|
+
'&[data-state="open"]': {
|
|
198
|
+
gridTemplateRows: '1fr',
|
|
199
|
+
},
|
|
200
|
+
'&[data-state="closed"]': {
|
|
201
|
+
pointerEvents: 'none',
|
|
202
|
+
},
|
|
203
|
+
'@media (prefers-reduced-motion: reduce)': {
|
|
204
|
+
transition: 'none',
|
|
205
|
+
},
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
const accordionBodyCss: CSSMixinDescriptor = css({
|
|
209
|
+
display: 'flow-root',
|
|
210
|
+
minHeight: 0,
|
|
211
|
+
paddingBottom: theme.space.md,
|
|
212
|
+
color: theme.colors.text.secondary,
|
|
213
|
+
fontSize: theme.fontSize.sm,
|
|
214
|
+
lineHeight: theme.lineHeight.relaxed,
|
|
215
|
+
'& > :first-child': {
|
|
216
|
+
marginTop: 0,
|
|
217
|
+
},
|
|
218
|
+
'& > :last-child': {
|
|
219
|
+
marginBottom: 0,
|
|
220
|
+
},
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
export const rootStyle = accordionRootCss
|
|
224
|
+
export const itemStyle = accordionItemCss
|
|
225
|
+
export const triggerStyle = accordionTriggerCss
|
|
226
|
+
export const indicatorStyle = accordionIndicatorCss
|
|
227
|
+
export const panelStyle = accordionPanelCss
|
|
228
|
+
export const bodyStyle = accordionBodyCss
|
|
229
|
+
|
|
230
|
+
function isMultipleProps(props: AccordionProps | null): props is AccordionMultipleProps {
|
|
231
|
+
return props?.type === 'multiple'
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function AccordionImpl(handle: Handle<AccordionProps, AccordionContext>) {
|
|
235
|
+
let rootNode: HTMLElement | null = null
|
|
236
|
+
let registeredItems: RegisteredItem[] = []
|
|
237
|
+
let uncontrolledSingleValue: string | null = null
|
|
238
|
+
let uncontrolledMultipleValue: string[] = []
|
|
239
|
+
let hasInitializedSingle = false
|
|
240
|
+
let hasInitializedMultiple = false
|
|
241
|
+
|
|
242
|
+
let getType = () => (isMultipleProps(handle.props) ? 'multiple' : 'single')
|
|
243
|
+
|
|
244
|
+
let getSingleValue = () => {
|
|
245
|
+
if (isMultipleProps(handle.props)) {
|
|
246
|
+
return null
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (handle.props.value !== undefined) {
|
|
250
|
+
return handle.props.value
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (!hasInitializedSingle) {
|
|
254
|
+
uncontrolledSingleValue = handle.props.defaultValue ?? null
|
|
255
|
+
hasInitializedSingle = true
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return uncontrolledSingleValue
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
let getMultipleValue = () => {
|
|
262
|
+
if (!isMultipleProps(handle.props)) {
|
|
263
|
+
return []
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (handle.props.value !== undefined) {
|
|
267
|
+
return handle.props.value
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (!hasInitializedMultiple) {
|
|
271
|
+
uncontrolledMultipleValue = [...(handle.props.defaultValue ?? [])]
|
|
272
|
+
hasInitializedMultiple = true
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return uncontrolledMultipleValue
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
let isOpen = (value: string) => {
|
|
279
|
+
if (getType() === 'multiple') {
|
|
280
|
+
return getMultipleValue().includes(value)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return getSingleValue() === value
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
let dispatchChange = (itemValue: string, value: string | null | string[]) => {
|
|
287
|
+
rootNode?.dispatchEvent(
|
|
288
|
+
new AccordionChangeEvent(value, {
|
|
289
|
+
accordionType: getType(),
|
|
290
|
+
itemValue,
|
|
291
|
+
}),
|
|
292
|
+
)
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
let toggleItem = (itemValue: string) => {
|
|
296
|
+
if (handle.props.disabled) {
|
|
297
|
+
return
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (isMultipleProps(handle.props)) {
|
|
301
|
+
let currentValue = getMultipleValue()
|
|
302
|
+
let nextValue = currentValue.includes(itemValue)
|
|
303
|
+
? currentValue.filter((value) => value !== itemValue)
|
|
304
|
+
: [...currentValue, itemValue]
|
|
305
|
+
|
|
306
|
+
if (handle.props.value === undefined) {
|
|
307
|
+
uncontrolledMultipleValue = nextValue
|
|
308
|
+
void handle.update()
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
handle.props.onValueChange?.(nextValue)
|
|
312
|
+
dispatchChange(itemValue, nextValue)
|
|
313
|
+
return
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
let isCurrentItemOpen = getSingleValue() === itemValue
|
|
317
|
+
if (isCurrentItemOpen && !(handle.props.collapsible ?? true)) {
|
|
318
|
+
return
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
let nextValue = isCurrentItemOpen ? null : itemValue
|
|
322
|
+
|
|
323
|
+
if (handle.props.value === undefined) {
|
|
324
|
+
uncontrolledSingleValue = nextValue
|
|
325
|
+
void handle.update()
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
handle.props.onValueChange?.(nextValue)
|
|
329
|
+
dispatchChange(itemValue, nextValue)
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
let focusItem = (itemValue: string, direction: FocusDirection) => {
|
|
333
|
+
let items = registeredItems.filter((item) => !item.disabled && item.getTriggerNode() !== null)
|
|
334
|
+
if (items.length === 0) {
|
|
335
|
+
return
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
let currentIndex = items.findIndex((item) => item.value === itemValue)
|
|
339
|
+
let targetIndex = 0
|
|
340
|
+
|
|
341
|
+
switch (direction) {
|
|
342
|
+
case 'first':
|
|
343
|
+
targetIndex = 0
|
|
344
|
+
break
|
|
345
|
+
case 'last':
|
|
346
|
+
targetIndex = items.length - 1
|
|
347
|
+
break
|
|
348
|
+
case 'previous':
|
|
349
|
+
targetIndex = currentIndex <= 0 ? items.length - 1 : currentIndex - 1
|
|
350
|
+
break
|
|
351
|
+
case 'next':
|
|
352
|
+
targetIndex =
|
|
353
|
+
currentIndex === -1 || currentIndex === items.length - 1 ? 0 : currentIndex + 1
|
|
354
|
+
break
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
items[targetIndex]?.getTriggerNode()?.focus()
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
let registerItem = (item: RegisteredItem) => {
|
|
361
|
+
registeredItems.push(item)
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
let getTriggerId = (value: string) =>
|
|
365
|
+
registeredItems.find((item) => item.value === value)?.getTriggerNode()?.id
|
|
366
|
+
|
|
367
|
+
let getPanelId = (value: string) => `${handle.id}-${value}-panel`
|
|
368
|
+
|
|
369
|
+
return () => {
|
|
370
|
+
let collapsible = 'collapsible' in handle.props ? handle.props.collapsible : undefined
|
|
371
|
+
let {
|
|
372
|
+
children,
|
|
373
|
+
defaultValue,
|
|
374
|
+
disabled,
|
|
375
|
+
headingLevel,
|
|
376
|
+
mix,
|
|
377
|
+
onValueChange,
|
|
378
|
+
type,
|
|
379
|
+
value,
|
|
380
|
+
...divProps
|
|
381
|
+
} = handle.props
|
|
382
|
+
void defaultValue
|
|
383
|
+
void onValueChange
|
|
384
|
+
void value
|
|
385
|
+
registeredItems = []
|
|
386
|
+
|
|
387
|
+
handle.context.set({
|
|
388
|
+
collapsible: type === 'multiple' ? true : (collapsible ?? true),
|
|
389
|
+
disabled: disabled ?? false,
|
|
390
|
+
focusItem,
|
|
391
|
+
getPanelId,
|
|
392
|
+
getTriggerId,
|
|
393
|
+
headingLevel: headingLevel ?? 3,
|
|
394
|
+
isOpen,
|
|
395
|
+
registerItem,
|
|
396
|
+
toggleItem,
|
|
397
|
+
type: type ?? 'single',
|
|
398
|
+
})
|
|
399
|
+
|
|
400
|
+
return (
|
|
401
|
+
<div
|
|
402
|
+
{...divProps}
|
|
403
|
+
data-disabled={disabled ? '' : undefined}
|
|
404
|
+
data-type={type ?? 'single'}
|
|
405
|
+
mix={[
|
|
406
|
+
rootStyle,
|
|
407
|
+
ref((node) => {
|
|
408
|
+
rootNode = node as HTMLElement
|
|
409
|
+
}),
|
|
410
|
+
...(mix ?? []),
|
|
411
|
+
]}
|
|
412
|
+
>
|
|
413
|
+
{children}
|
|
414
|
+
</div>
|
|
415
|
+
)
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
export function onAccordionChange(handler: AccordionChangeHandler, captureBoolean?: boolean) {
|
|
420
|
+
return on<HTMLElement, typeof ACCORDION_CHANGE_EVENT>(
|
|
421
|
+
ACCORDION_CHANGE_EVENT,
|
|
422
|
+
handler,
|
|
423
|
+
captureBoolean,
|
|
424
|
+
)
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
export const Accordion = AccordionImpl
|
|
428
|
+
|
|
429
|
+
export function AccordionItem(handle: Handle<AccordionItemProps, AccordionItemContext>) {
|
|
430
|
+
let triggerNode: HTMLButtonElement | null = null
|
|
431
|
+
let triggerId = `${handle.id}-trigger`
|
|
432
|
+
let panelId = `${handle.id}-panel`
|
|
433
|
+
|
|
434
|
+
return () => {
|
|
435
|
+
let { children, disabled: itemDisabled, mix, value, ...divProps } = handle.props
|
|
436
|
+
let accordion = handle.context.get(Accordion)
|
|
437
|
+
let disabled = accordion.disabled || itemDisabled === true
|
|
438
|
+
let open = accordion.isOpen(value)
|
|
439
|
+
let lockedOpen = accordion.type === 'single' && !accordion.collapsible && open
|
|
440
|
+
|
|
441
|
+
accordion.registerItem({
|
|
442
|
+
disabled,
|
|
443
|
+
getTriggerNode: () => triggerNode,
|
|
444
|
+
value,
|
|
445
|
+
})
|
|
446
|
+
|
|
447
|
+
handle.context.set({
|
|
448
|
+
disabled,
|
|
449
|
+
headingLevel: accordion.headingLevel,
|
|
450
|
+
lockedOpen,
|
|
451
|
+
open,
|
|
452
|
+
panelId,
|
|
453
|
+
setTriggerNode(node) {
|
|
454
|
+
triggerNode = node
|
|
455
|
+
},
|
|
456
|
+
triggerId,
|
|
457
|
+
value,
|
|
458
|
+
})
|
|
459
|
+
|
|
460
|
+
return (
|
|
461
|
+
<div
|
|
462
|
+
{...divProps}
|
|
463
|
+
data-disabled={disabled ? '' : undefined}
|
|
464
|
+
data-state={open ? 'open' : 'closed'}
|
|
465
|
+
mix={[itemStyle, ...(mix ?? [])]}
|
|
466
|
+
>
|
|
467
|
+
{children}
|
|
468
|
+
</div>
|
|
469
|
+
)
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
export function AccordionTrigger(handle: Handle<AccordionTriggerProps>) {
|
|
474
|
+
return () => {
|
|
475
|
+
let accordion = handle.context.get(Accordion)
|
|
476
|
+
let item = handle.context.get(AccordionItem)
|
|
477
|
+
let headingTag = `h${item.headingLevel}` as keyof JSX.IntrinsicElements
|
|
478
|
+
let { children, indicator, mix, type, ...buttonProps } = handle.props
|
|
479
|
+
let disabled = item.disabled || handle.props.disabled === true
|
|
480
|
+
let toggleItem = () => {
|
|
481
|
+
if (disabled || item.lockedOpen) {
|
|
482
|
+
return
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
accordion.toggleItem(item.value)
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
let button = (
|
|
489
|
+
<button
|
|
490
|
+
{...buttonProps}
|
|
491
|
+
aria-controls={item.panelId}
|
|
492
|
+
aria-disabled={item.lockedOpen ? true : undefined}
|
|
493
|
+
aria-expanded={item.open}
|
|
494
|
+
data-state={item.open ? 'open' : 'closed'}
|
|
495
|
+
disabled={disabled ? true : undefined}
|
|
496
|
+
id={item.triggerId}
|
|
497
|
+
mix={[
|
|
498
|
+
triggerStyle,
|
|
499
|
+
ref((node) => {
|
|
500
|
+
item.setTriggerNode(node as HTMLButtonElement)
|
|
501
|
+
}),
|
|
502
|
+
on('click', toggleItem),
|
|
503
|
+
on('keydown', (event) => {
|
|
504
|
+
switch (event.key) {
|
|
505
|
+
case 'ArrowDown':
|
|
506
|
+
event.preventDefault()
|
|
507
|
+
accordion.focusItem(item.value, 'next')
|
|
508
|
+
break
|
|
509
|
+
case 'ArrowUp':
|
|
510
|
+
event.preventDefault()
|
|
511
|
+
accordion.focusItem(item.value, 'previous')
|
|
512
|
+
break
|
|
513
|
+
case 'Home':
|
|
514
|
+
event.preventDefault()
|
|
515
|
+
accordion.focusItem(item.value, 'first')
|
|
516
|
+
break
|
|
517
|
+
case 'End':
|
|
518
|
+
event.preventDefault()
|
|
519
|
+
accordion.focusItem(item.value, 'last')
|
|
520
|
+
break
|
|
521
|
+
}
|
|
522
|
+
}),
|
|
523
|
+
mix,
|
|
524
|
+
]}
|
|
525
|
+
type={type ?? 'button'}
|
|
526
|
+
>
|
|
527
|
+
<span>{children}</span>
|
|
528
|
+
{indicator === null ? null : (
|
|
529
|
+
<span
|
|
530
|
+
data-rmx-accordion-indicator=""
|
|
531
|
+
data-state={item.open ? 'open' : 'closed'}
|
|
532
|
+
mix={indicatorStyle}
|
|
533
|
+
>
|
|
534
|
+
{indicator ?? <Glyph name="chevronRight" />}
|
|
535
|
+
</span>
|
|
536
|
+
)}
|
|
537
|
+
</button>
|
|
538
|
+
)
|
|
539
|
+
|
|
540
|
+
return createElement(headingTag, {}, button)
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
export function AccordionContent(handle: Handle<AccordionContentProps>) {
|
|
545
|
+
return () => {
|
|
546
|
+
let item = handle.context.get(AccordionItem)
|
|
547
|
+
let { children, mix, ...panelProps } = handle.props
|
|
548
|
+
|
|
549
|
+
return (
|
|
550
|
+
<div
|
|
551
|
+
{...panelProps}
|
|
552
|
+
aria-hidden={item.open ? undefined : true}
|
|
553
|
+
aria-labelledby={item.triggerId}
|
|
554
|
+
data-state={item.open ? 'open' : 'closed'}
|
|
555
|
+
id={item.panelId}
|
|
556
|
+
inert={item.open ? undefined : true}
|
|
557
|
+
mix={[panelStyle, mix ?? []]}
|
|
558
|
+
>
|
|
559
|
+
<div mix={accordionPanelClipCss}>
|
|
560
|
+
<div mix={bodyStyle}>{children}</div>
|
|
561
|
+
</div>
|
|
562
|
+
</div>
|
|
563
|
+
)
|
|
564
|
+
}
|
|
565
|
+
}
|