@funstack/ui 0.0.0-stage → 0.1.0-alpha.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 +42 -2
- package/dist/accordion/accordion-context.d.mts +5 -0
- package/dist/accordion/accordion-context.d.mts.map +1 -0
- package/dist/accordion/accordion-context.mjs +9 -0
- package/dist/accordion/accordion-context.mjs.map +1 -0
- package/dist/accordion/accordion-item.d.mts +53 -0
- package/dist/accordion/accordion-item.d.mts.map +1 -0
- package/dist/accordion/accordion-item.mjs +85 -0
- package/dist/accordion/accordion-item.mjs.map +1 -0
- package/dist/accordion/accordion-panel.d.mts +40 -0
- package/dist/accordion/accordion-panel.d.mts.map +1 -0
- package/dist/accordion/accordion-panel.mjs +40 -0
- package/dist/accordion/accordion-panel.mjs.map +1 -0
- package/dist/accordion/accordion-root.d.mts +90 -0
- package/dist/accordion/accordion-root.d.mts.map +1 -0
- package/dist/accordion/accordion-root.mjs +229 -0
- package/dist/accordion/accordion-root.mjs.map +1 -0
- package/dist/accordion/accordion-trigger.d.mts +37 -0
- package/dist/accordion/accordion-trigger.d.mts.map +1 -0
- package/dist/accordion/accordion-trigger.mjs +81 -0
- package/dist/accordion/accordion-trigger.mjs.map +1 -0
- package/dist/accordion/index.d.mts +20 -0
- package/dist/accordion/index.d.mts.map +1 -0
- package/dist/accordion/index.mjs +20 -0
- package/dist/accordion/index.mjs.map +1 -0
- package/dist/checkbox/checkbox.d.mts +92 -0
- package/dist/checkbox/checkbox.d.mts.map +1 -0
- package/dist/checkbox/checkbox.mjs +82 -0
- package/dist/checkbox/checkbox.mjs.map +1 -0
- package/dist/checkbox/index.d.mts +3 -0
- package/dist/checkbox/index.mjs +1 -0
- package/dist/checkbox-group/checkbox-group-context.mjs +24 -0
- package/dist/checkbox-group/checkbox-group-context.mjs.map +1 -0
- package/dist/checkbox-group/checkbox-group-item.d.mts +55 -0
- package/dist/checkbox-group/checkbox-group-item.d.mts.map +1 -0
- package/dist/checkbox-group/checkbox-group-item.mjs +90 -0
- package/dist/checkbox-group/checkbox-group-item.mjs.map +1 -0
- package/dist/checkbox-group/checkbox-group-label.d.mts +21 -0
- package/dist/checkbox-group/checkbox-group-label.d.mts.map +1 -0
- package/dist/checkbox-group/checkbox-group-label.mjs +30 -0
- package/dist/checkbox-group/checkbox-group-label.mjs.map +1 -0
- package/dist/checkbox-group/checkbox-group-parent.d.mts +68 -0
- package/dist/checkbox-group/checkbox-group-parent.d.mts.map +1 -0
- package/dist/checkbox-group/checkbox-group-parent.mjs +145 -0
- package/dist/checkbox-group/checkbox-group-parent.mjs.map +1 -0
- package/dist/checkbox-group/checkbox-group-root.d.mts +100 -0
- package/dist/checkbox-group/checkbox-group-root.d.mts.map +1 -0
- package/dist/checkbox-group/checkbox-group-root.mjs +291 -0
- package/dist/checkbox-group/checkbox-group-root.mjs.map +1 -0
- package/dist/checkbox-group/index.d.mts +23 -0
- package/dist/checkbox-group/index.d.mts.map +1 -0
- package/dist/checkbox-group/index.mjs +23 -0
- package/dist/checkbox-group/index.mjs.map +1 -0
- package/dist/dialog/dialog-close.d.mts +44 -0
- package/dist/dialog/dialog-close.d.mts.map +1 -0
- package/dist/dialog/dialog-close.mjs +76 -0
- package/dist/dialog/dialog-close.mjs.map +1 -0
- package/dist/dialog/dialog-context.mjs +13 -0
- package/dist/dialog/dialog-context.mjs.map +1 -0
- package/dist/dialog/dialog-description.d.mts +22 -0
- package/dist/dialog/dialog-description.d.mts.map +1 -0
- package/dist/dialog/dialog-description.mjs +31 -0
- package/dist/dialog/dialog-description.mjs.map +1 -0
- package/dist/dialog/dialog-form.d.mts +58 -0
- package/dist/dialog/dialog-form.d.mts.map +1 -0
- package/dist/dialog/dialog-form.mjs +108 -0
- package/dist/dialog/dialog-form.mjs.map +1 -0
- package/dist/dialog/dialog-popup.d.mts +81 -0
- package/dist/dialog/dialog-popup.d.mts.map +1 -0
- package/dist/dialog/dialog-popup.mjs +367 -0
- package/dist/dialog/dialog-popup.mjs.map +1 -0
- package/dist/dialog/dialog-root.d.mts +70 -0
- package/dist/dialog/dialog-root.d.mts.map +1 -0
- package/dist/dialog/dialog-root.mjs +113 -0
- package/dist/dialog/dialog-root.mjs.map +1 -0
- package/dist/dialog/dialog-title.d.mts +23 -0
- package/dist/dialog/dialog-title.d.mts.map +1 -0
- package/dist/dialog/dialog-title.mjs +31 -0
- package/dist/dialog/dialog-title.mjs.map +1 -0
- package/dist/dialog/dialog-trigger.d.mts +39 -0
- package/dist/dialog/dialog-trigger.d.mts.map +1 -0
- package/dist/dialog/dialog-trigger.mjs +80 -0
- package/dist/dialog/dialog-trigger.mjs.map +1 -0
- package/dist/dialog/index.d.mts +28 -0
- package/dist/dialog/index.d.mts.map +1 -0
- package/dist/dialog/index.mjs +28 -0
- package/dist/dialog/index.mjs.map +1 -0
- package/dist/index.d.mts +60 -0
- package/dist/index.mjs +12 -0
- package/dist/internal/action-details.mjs +47 -0
- package/dist/internal/action-details.mjs.map +1 -0
- package/dist/internal/anchor-position.d.mts +7 -0
- package/dist/internal/anchor-position.d.mts.map +1 -0
- package/dist/internal/anchor-position.mjs +16 -0
- package/dist/internal/anchor-position.mjs.map +1 -0
- package/dist/internal/data-attr.mjs +13 -0
- package/dist/internal/data-attr.mjs.map +1 -0
- package/dist/internal/merge-props.mjs +119 -0
- package/dist/internal/merge-props.mjs.map +1 -0
- package/dist/internal/platform-attributes.d.mts +55 -0
- package/dist/internal/platform-attributes.d.mts.map +1 -0
- package/dist/internal/sync-presence.mjs +19 -0
- package/dist/internal/sync-presence.mjs.map +1 -0
- package/dist/internal/transition-boundary.mjs +52 -0
- package/dist/internal/transition-boundary.mjs.map +1 -0
- package/dist/internal/transition-types.mjs +15 -0
- package/dist/internal/transition-types.mjs.map +1 -0
- package/dist/internal/types.d.mts +38 -0
- package/dist/internal/types.d.mts.map +1 -0
- package/dist/internal/use-action-trigger.mjs +58 -0
- package/dist/internal/use-action-trigger.mjs.map +1 -0
- package/dist/internal/use-controllable-action.mjs +115 -0
- package/dist/internal/use-controllable-action.mjs.map +1 -0
- package/dist/internal/use-delayed-pair.mjs +40 -0
- package/dist/internal/use-delayed-pair.mjs.map +1 -0
- package/dist/internal/use-dev-warning.mjs +21 -0
- package/dist/internal/use-dev-warning.mjs.map +1 -0
- package/dist/internal/use-exit-animation.mjs +55 -0
- package/dist/internal/use-exit-animation.mjs.map +1 -0
- package/dist/internal/use-form-reset.mjs +50 -0
- package/dist/internal/use-form-reset.mjs.map +1 -0
- package/dist/internal/use-native-checked.mjs +113 -0
- package/dist/internal/use-native-checked.mjs.map +1 -0
- package/dist/internal/use-native-group-reconciliation.mjs +64 -0
- package/dist/internal/use-native-group-reconciliation.mjs.map +1 -0
- package/dist/internal/use-popover-popup.mjs +274 -0
- package/dist/internal/use-popover-popup.mjs.map +1 -0
- package/dist/internal/use-popover-root.d.mts +2 -0
- package/dist/internal/use-popover-root.mjs +112 -0
- package/dist/internal/use-popover-root.mjs.map +1 -0
- package/dist/internal/use-popover-trigger.mjs +86 -0
- package/dist/internal/use-popover-trigger.mjs.map +1 -0
- package/dist/internal/use-render.mjs +51 -0
- package/dist/internal/use-render.mjs.map +1 -0
- package/dist/internal/use-until-found.mjs +40 -0
- package/dist/internal/use-until-found.mjs.map +1 -0
- package/dist/menu/index.d.mts +34 -0
- package/dist/menu/index.d.mts.map +1 -0
- package/dist/menu/index.mjs +34 -0
- package/dist/menu/index.mjs.map +1 -0
- package/dist/menu/menu-checkbox-item.d.mts +42 -0
- package/dist/menu/menu-checkbox-item.d.mts.map +1 -0
- package/dist/menu/menu-checkbox-item.mjs +71 -0
- package/dist/menu/menu-checkbox-item.mjs.map +1 -0
- package/dist/menu/menu-context.d.mts +1 -0
- package/dist/menu/menu-context.mjs +28 -0
- package/dist/menu/menu-context.mjs.map +1 -0
- package/dist/menu/menu-dom.mjs +37 -0
- package/dist/menu/menu-dom.mjs.map +1 -0
- package/dist/menu/menu-group.d.mts +48 -0
- package/dist/menu/menu-group.d.mts.map +1 -0
- package/dist/menu/menu-group.mjs +69 -0
- package/dist/menu/menu-group.mjs.map +1 -0
- package/dist/menu/menu-hover.mjs +29 -0
- package/dist/menu/menu-hover.mjs.map +1 -0
- package/dist/menu/menu-item.d.mts +45 -0
- package/dist/menu/menu-item.d.mts.map +1 -0
- package/dist/menu/menu-item.mjs +54 -0
- package/dist/menu/menu-item.mjs.map +1 -0
- package/dist/menu/menu-popup.d.mts +69 -0
- package/dist/menu/menu-popup.d.mts.map +1 -0
- package/dist/menu/menu-popup.mjs +207 -0
- package/dist/menu/menu-popup.mjs.map +1 -0
- package/dist/menu/menu-radio-group.d.mts +37 -0
- package/dist/menu/menu-radio-group.d.mts.map +1 -0
- package/dist/menu/menu-radio-group.mjs +72 -0
- package/dist/menu/menu-radio-group.mjs.map +1 -0
- package/dist/menu/menu-radio-item.d.mts +33 -0
- package/dist/menu/menu-radio-item.d.mts.map +1 -0
- package/dist/menu/menu-radio-item.mjs +62 -0
- package/dist/menu/menu-radio-item.mjs.map +1 -0
- package/dist/menu/menu-root.d.mts +54 -0
- package/dist/menu/menu-root.d.mts.map +1 -0
- package/dist/menu/menu-root.mjs +102 -0
- package/dist/menu/menu-root.mjs.map +1 -0
- package/dist/menu/menu-submenu-trigger.d.mts +31 -0
- package/dist/menu/menu-submenu-trigger.d.mts.map +1 -0
- package/dist/menu/menu-submenu-trigger.mjs +92 -0
- package/dist/menu/menu-submenu-trigger.mjs.map +1 -0
- package/dist/menu/menu-trigger.d.mts +36 -0
- package/dist/menu/menu-trigger.d.mts.map +1 -0
- package/dist/menu/menu-trigger.mjs +81 -0
- package/dist/menu/menu-trigger.mjs.map +1 -0
- package/dist/menu/use-menu-item.mjs +54 -0
- package/dist/menu/use-menu-item.mjs.map +1 -0
- package/dist/popover/index.d.mts +28 -0
- package/dist/popover/index.d.mts.map +1 -0
- package/dist/popover/index.mjs +28 -0
- package/dist/popover/index.mjs.map +1 -0
- package/dist/popover/popover-close.d.mts +41 -0
- package/dist/popover/popover-close.d.mts.map +1 -0
- package/dist/popover/popover-close.mjs +90 -0
- package/dist/popover/popover-close.mjs.map +1 -0
- package/dist/popover/popover-context.mjs +26 -0
- package/dist/popover/popover-context.mjs.map +1 -0
- package/dist/popover/popover-description.d.mts +22 -0
- package/dist/popover/popover-description.d.mts.map +1 -0
- package/dist/popover/popover-description.mjs +28 -0
- package/dist/popover/popover-description.mjs.map +1 -0
- package/dist/popover/popover-popup.d.mts +82 -0
- package/dist/popover/popover-popup.d.mts.map +1 -0
- package/dist/popover/popover-popup.mjs +93 -0
- package/dist/popover/popover-popup.mjs.map +1 -0
- package/dist/popover/popover-root.d.mts +64 -0
- package/dist/popover/popover-root.d.mts.map +1 -0
- package/dist/popover/popover-root.mjs +39 -0
- package/dist/popover/popover-root.mjs.map +1 -0
- package/dist/popover/popover-title.d.mts +23 -0
- package/dist/popover/popover-title.d.mts.map +1 -0
- package/dist/popover/popover-title.mjs +28 -0
- package/dist/popover/popover-title.mjs.map +1 -0
- package/dist/popover/popover-trigger.d.mts +37 -0
- package/dist/popover/popover-trigger.d.mts.map +1 -0
- package/dist/popover/popover-trigger.mjs +40 -0
- package/dist/popover/popover-trigger.mjs.map +1 -0
- package/dist/radio-group/index.d.mts +20 -0
- package/dist/radio-group/index.d.mts.map +1 -0
- package/dist/radio-group/index.mjs +20 -0
- package/dist/radio-group/index.mjs.map +1 -0
- package/dist/radio-group/radio-group-context.mjs +13 -0
- package/dist/radio-group/radio-group-context.mjs.map +1 -0
- package/dist/radio-group/radio-group-item.d.mts +54 -0
- package/dist/radio-group/radio-group-item.d.mts.map +1 -0
- package/dist/radio-group/radio-group-item.mjs +83 -0
- package/dist/radio-group/radio-group-item.mjs.map +1 -0
- package/dist/radio-group/radio-group-label.d.mts +21 -0
- package/dist/radio-group/radio-group-label.d.mts.map +1 -0
- package/dist/radio-group/radio-group-label.mjs +30 -0
- package/dist/radio-group/radio-group-label.mjs.map +1 -0
- package/dist/radio-group/radio-group-root.d.mts +92 -0
- package/dist/radio-group/radio-group-root.d.mts.map +1 -0
- package/dist/radio-group/radio-group-root.mjs +137 -0
- package/dist/radio-group/radio-group-root.mjs.map +1 -0
- package/dist/switch/index.d.mts +3 -0
- package/dist/switch/index.mjs +1 -0
- package/dist/switch/switch.d.mts +78 -0
- package/dist/switch/switch.d.mts.map +1 -0
- package/dist/switch/switch.mjs +77 -0
- package/dist/switch/switch.mjs.map +1 -0
- package/dist/tabs/index.d.mts +24 -0
- package/dist/tabs/index.d.mts.map +1 -0
- package/dist/tabs/index.mjs +23 -0
- package/dist/tabs/index.mjs.map +1 -0
- package/dist/tabs/tabs-context.d.mts +7 -0
- package/dist/tabs/tabs-context.d.mts.map +1 -0
- package/dist/tabs/tabs-context.mjs +14 -0
- package/dist/tabs/tabs-context.mjs.map +1 -0
- package/dist/tabs/tabs-ids.mjs +39 -0
- package/dist/tabs/tabs-ids.mjs.map +1 -0
- package/dist/tabs/tabs-indicator.d.mts +32 -0
- package/dist/tabs/tabs-indicator.d.mts.map +1 -0
- package/dist/tabs/tabs-indicator.mjs +49 -0
- package/dist/tabs/tabs-indicator.mjs.map +1 -0
- package/dist/tabs/tabs-list.d.mts +34 -0
- package/dist/tabs/tabs-list.d.mts.map +1 -0
- package/dist/tabs/tabs-list.mjs +130 -0
- package/dist/tabs/tabs-list.mjs.map +1 -0
- package/dist/tabs/tabs-panel.d.mts +50 -0
- package/dist/tabs/tabs-panel.d.mts.map +1 -0
- package/dist/tabs/tabs-panel.mjs +81 -0
- package/dist/tabs/tabs-panel.mjs.map +1 -0
- package/dist/tabs/tabs-root.d.mts +64 -0
- package/dist/tabs/tabs-root.d.mts.map +1 -0
- package/dist/tabs/tabs-root.mjs +90 -0
- package/dist/tabs/tabs-root.mjs.map +1 -0
- package/dist/tabs/tabs-tab.d.mts +49 -0
- package/dist/tabs/tabs-tab.d.mts.map +1 -0
- package/dist/tabs/tabs-tab.mjs +89 -0
- package/dist/tabs/tabs-tab.mjs.map +1 -0
- package/dist/toggle/index.d.mts +3 -0
- package/dist/toggle/index.mjs +1 -0
- package/dist/toggle/toggle.d.mts +57 -0
- package/dist/toggle/toggle.d.mts.map +1 -0
- package/dist/toggle/toggle.mjs +59 -0
- package/dist/toggle/toggle.mjs.map +1 -0
- package/dist/tooltip/index.d.mts +20 -0
- package/dist/tooltip/index.d.mts.map +1 -0
- package/dist/tooltip/index.mjs +19 -0
- package/dist/tooltip/index.mjs.map +1 -0
- package/dist/tooltip/tooltip-context.d.mts +5 -0
- package/dist/tooltip/tooltip-context.d.mts.map +1 -0
- package/dist/tooltip/tooltip-context.mjs +13 -0
- package/dist/tooltip/tooltip-context.mjs.map +1 -0
- package/dist/tooltip/tooltip-popup.d.mts +49 -0
- package/dist/tooltip/tooltip-popup.d.mts.map +1 -0
- package/dist/tooltip/tooltip-popup.mjs +52 -0
- package/dist/tooltip/tooltip-popup.mjs.map +1 -0
- package/dist/tooltip/tooltip-root.d.mts +41 -0
- package/dist/tooltip/tooltip-root.d.mts.map +1 -0
- package/dist/tooltip/tooltip-root.mjs +86 -0
- package/dist/tooltip/tooltip-root.mjs.map +1 -0
- package/dist/tooltip/tooltip-trigger.d.mts +38 -0
- package/dist/tooltip/tooltip-trigger.d.mts.map +1 -0
- package/dist/tooltip/tooltip-trigger.mjs +55 -0
- package/dist/tooltip/tooltip-trigger.mjs.map +1 -0
- package/dist/tooltip/use-tooltip-interaction.mjs +119 -0
- package/dist/tooltip/use-tooltip-interaction.mjs.map +1 -0
- package/package.json +73 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 uhyo
|
|
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
CHANGED
|
@@ -1,3 +1,43 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @funstack/ui
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> **Experimental.** APIs will change without notice.
|
|
4
|
+
|
|
5
|
+
Headless UI library for React — the first **Async React-native** UI library. Part of the
|
|
6
|
+
[FUNSTACK](https://github.com/uhyo/funstack-ui) family.
|
|
7
|
+
|
|
8
|
+
- **Transition by default.** Interactions are _action props_ (`pressedChangeAction`,
|
|
9
|
+
`valueChangeAction`, …), run inside a React transition. Actions can be async; components expose
|
|
10
|
+
`data-pending` and show optimistic state while they run.
|
|
11
|
+
- **Server Functions pass directly.** `<Toggle pressedChangeAction={serverFn} />` works from a
|
|
12
|
+
Server Component.
|
|
13
|
+
- **Suspense-native.** Content that suspends keeps the previous UI visible instead of flashing a
|
|
14
|
+
fallback.
|
|
15
|
+
- **`<ViewTransition>` built in** via a `transition` prop.
|
|
16
|
+
- **Modern HTML/CSS first.** Popover API, CSS Anchor Positioning, `<details>`, `hidden="until-found"`;
|
|
17
|
+
bleeding-edge features behind `experimental_*` props.
|
|
18
|
+
|
|
19
|
+
Documentation: https://ui.funstack.work
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
npm install @funstack/ui@alpha
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
React 19.3 or later is required (`react` and `react-dom` are peer dependencies).
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
import { Toggle } from "@funstack/ui/toggle";
|
|
31
|
+
|
|
32
|
+
<Toggle pressedChangeAction={async (pressed) => await saveFavorite(pressed)}>Favorite</Toggle>;
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Components: `Toggle`, `Tabs`, `Accordion`, `Tooltip`.
|
|
36
|
+
|
|
37
|
+
## Browser support
|
|
38
|
+
|
|
39
|
+
Latest stable version of each major engine. No fallbacks.
|
|
40
|
+
|
|
41
|
+
## License
|
|
42
|
+
|
|
43
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accordion-context.d.mts","names":[],"sources":["../../src/accordion/accordion-context.ts"],"mappings":";;YAIY"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { createContext } from "react";
|
|
3
|
+
//#region src/accordion/accordion-context.ts
|
|
4
|
+
const AccordionRootContext = createContext(null);
|
|
5
|
+
const AccordionItemContext = createContext(null);
|
|
6
|
+
//#endregion
|
|
7
|
+
export { AccordionItemContext, AccordionRootContext };
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=accordion-context.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accordion-context.mjs","names":[],"sources":["../../src/accordion/accordion-context.ts"],"sourcesContent":["\"use client\";\nimport { createContext } from \"react\";\n\n/** Why a change was dispatched (design 2.2 / 2.3). */\nexport type AccordionChangeReason = \"activate\" | \"platform\";\n\n/**\n * \"static\": JS-free mode, the browser owns `open`. \"library\": `open` is driven by React\n * committed state inside the Root's transition (design section 2).\n */\nexport type AccordionMode = \"static\" | \"library\";\n\nexport interface AccordionRootContextValue {\n readonly mode: AccordionMode;\n readonly exclusive: boolean;\n /** `name` for every `<details>`; set only in static exclusive mode. */\n readonly name: string | undefined;\n readonly disabled: boolean;\n readonly pending: boolean;\n /** Committed open set (library mode). Empty in static mode. */\n readonly committed: ReadonlySet<string>;\n /** Optimistic open set (library mode). Empty in static mode. */\n readonly optimistic: ReadonlySet<string>;\n /** A Trigger was activated: compute `next` from the optimistic set and dispatch. */\n readonly dispatch: (item: string, open: boolean, event: Event | undefined) => void;\n /** The browser changed `details.open`: compute `next` from the DOM and dispatch (design 2.3). */\n readonly dispatchFromDom: (item: string, open: boolean, event: Event | undefined) => void;\n /** Items register their `<details>` so `dispatchFromDom` can read every item's DOM state. */\n readonly registerItem: (value: string, element: HTMLDetailsElement) => () => void;\n /** Triggers register their `<summary>` for arrow-key navigation (design section 5). */\n readonly registerTrigger: (element: HTMLElement) => () => void;\n}\n\nexport const AccordionRootContext = createContext<AccordionRootContextValue | null>(null);\n\nexport interface AccordionItemContextValue {\n readonly value: string;\n readonly disabled: boolean;\n /** `undefined` in static mode (browser-owned, unknown to React). */\n readonly committedOpen: boolean | undefined;\n /** `undefined` in static mode. */\n readonly optimisticOpen: boolean | undefined;\n readonly pending: boolean;\n}\n\nexport const AccordionItemContext = createContext<AccordionItemContextValue | null>(null);\n"],"mappings":";;;AAiCA,MAAa,uBAAuB,cAAgD,IAAI;AAYxF,MAAa,uBAAuB,cAAgD,IAAI"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { RenderProp, StateValue } from "../internal/types.mjs";
|
|
2
|
+
import { CSSProperties, ComponentPropsWithRef, ReactNode, ViewTransitionClass } from "react";
|
|
3
|
+
//#region src/accordion/accordion-item.d.ts
|
|
4
|
+
export interface AccordionItemState {
|
|
5
|
+
readonly value: string;
|
|
6
|
+
/** Optimistic open state. `undefined` in JS-free mode (browser-owned, unknown to React). */
|
|
7
|
+
readonly open: boolean | undefined;
|
|
8
|
+
/** This item's open state is changing through an in-flight action. */
|
|
9
|
+
readonly pending: boolean;
|
|
10
|
+
/** Disabled by its own prop or by the Root. */
|
|
11
|
+
readonly disabled: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface AccordionItemProps extends Omit<ComponentPropsWithRef<"details">, "open" | "name" | "onToggle" | "className" | "style" | "children"> {
|
|
14
|
+
/** Identifies the item in the Root's `value`. Required in both modes. */
|
|
15
|
+
value: string;
|
|
16
|
+
/**
|
|
17
|
+
* JS-free mode only: renders the initial `open` attribute; the browser owns it from then on.
|
|
18
|
+
* Ignored (dev warning) in library mode, where the Root's `defaultValue` / `value` decide.
|
|
19
|
+
*/
|
|
20
|
+
defaultOpen?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Disables this item: the Trigger renders `aria-disabled` and never toggles. Enforced by a
|
|
23
|
+
* click handler, so in JS-free mode it does not hold before hydration or with JS off.
|
|
24
|
+
*/
|
|
25
|
+
disabled?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Library mode only. Forwarded as `default` to the `<ViewTransition>` around the `<details>`;
|
|
28
|
+
* animates the commit that ends an action (the `open` attribute flip), not the optimistic
|
|
29
|
+
* `data-open` flip. Ignored (dev warning) in JS-free mode.
|
|
30
|
+
*
|
|
31
|
+
* Static: without `transition` the part renders no `<ViewTransition>`; changing it between
|
|
32
|
+
* `undefined` and a value remounts the element. Any value, `"none"` included, makes a mount or
|
|
33
|
+
* `<Activity>` reveal of this part inside a transition start a document view transition: the
|
|
34
|
+
* page cross-fades for about 250 ms and the next transition commit waits for it (issue #35).
|
|
35
|
+
*/
|
|
36
|
+
transition?: ViewTransitionClass;
|
|
37
|
+
className?: StateValue<string | undefined, AccordionItemState>;
|
|
38
|
+
style?: StateValue<CSSProperties | undefined, AccordionItemState>;
|
|
39
|
+
children?: StateValue<ReactNode, AccordionItemState>;
|
|
40
|
+
/** Must render a `<details>` element. */
|
|
41
|
+
render?: RenderProp<ComponentPropsWithRef<"details">, AccordionItemState>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* One accordion entry: the `<details>` element. In library mode its `open` attribute follows
|
|
45
|
+
* committed state and `data-open` / `data-pending` follow optimistic state; in JS-free mode (or
|
|
46
|
+
* outside any Root, as a standalone disclosure) the browser owns `open`.
|
|
47
|
+
*/
|
|
48
|
+
export declare function AccordionItem({ value, defaultOpen, disabled: disabledProp, transition, className, style, children, render, ...rest }: AccordionItemProps): ReactNode;
|
|
49
|
+
export declare namespace AccordionItem {
|
|
50
|
+
var displayName: string;
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
//# sourceMappingURL=accordion-item.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accordion-item.d.mts","names":[],"sources":["../../src/accordion/accordion-item.tsx"],"mappings":";;;iBAiBiB;WACN;;WAEA;;WAEA;;WAEA;;iBAGM,2BAA2B,KAC1C;;EAIA;;;;;EAKA;;;;;EAKA;;;;;;;;;;;EAWA,aAAa;EACb,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;;EAEjC,SAAS,WAAW,kCAAkC;;;;;;;wBAUxC,gBACd,OACA,aACA,UAAU,cACV,YACA,WACA,OACA,UACA,WACG,QACF,qBAAkB;yBAVL"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
|
|
3
|
+
import { dataAttr } from "../internal/data-attr.mjs";
|
|
4
|
+
import { useRender } from "../internal/use-render.mjs";
|
|
5
|
+
import { useDevWarning } from "../internal/use-dev-warning.mjs";
|
|
6
|
+
import { AccordionItemContext, AccordionRootContext } from "./accordion-context.mjs";
|
|
7
|
+
import { use, useCallback, useState } from "react";
|
|
8
|
+
import { jsx } from "react/jsx-runtime";
|
|
9
|
+
//#region src/accordion/accordion-item.tsx
|
|
10
|
+
const isDev = process.env.NODE_ENV !== "production";
|
|
11
|
+
/**
|
|
12
|
+
* One accordion entry: the `<details>` element. In library mode its `open` attribute follows
|
|
13
|
+
* committed state and `data-open` / `data-pending` follow optimistic state; in JS-free mode (or
|
|
14
|
+
* outside any Root, as a standalone disclosure) the browser owns `open`.
|
|
15
|
+
*/
|
|
16
|
+
function AccordionItem({ value, defaultOpen = false, disabled: disabledProp = false, transition, className, style, children, render, ...rest }) {
|
|
17
|
+
const root = use(AccordionRootContext);
|
|
18
|
+
const isLibrary = root?.mode === "library";
|
|
19
|
+
const disabled = disabledProp || (root?.disabled ?? false);
|
|
20
|
+
const committedOpen = isLibrary ? root.committed.has(value) : void 0;
|
|
21
|
+
const optimisticOpen = isLibrary ? root.optimistic.has(value) : void 0;
|
|
22
|
+
const rootPending = root?.pending ?? false;
|
|
23
|
+
const pending = isLibrary && rootPending && committedOpen !== optimisticOpen;
|
|
24
|
+
const [staticOpen] = useState(defaultOpen);
|
|
25
|
+
useDevWarning(isLibrary && defaultOpen, "Accordion.Item: `defaultOpen` is ignored in library mode. Use `defaultValue` or `value` on Accordion.Root instead.");
|
|
26
|
+
useDevWarning(!isLibrary && transition !== void 0, "Accordion.Item: `transition` has no effect in JS-free mode; the browser toggles the item outside any React transition. Animate `::details-content` with CSS instead.");
|
|
27
|
+
const registerItem = root?.registerItem;
|
|
28
|
+
const libraryRef = useCallback((element) => {
|
|
29
|
+
if (isDev && element.tagName !== "DETAILS") console.error(`Accordion.Item: expected to render a <details> element but got <${element.tagName.toLowerCase()}>. The platform semantics (toggle, find-in-page, exclusive groups) need a real <details>.`);
|
|
30
|
+
const unregister = registerItem?.(value, element);
|
|
31
|
+
return () => {
|
|
32
|
+
unregister?.();
|
|
33
|
+
};
|
|
34
|
+
}, [registerItem, value]);
|
|
35
|
+
const onToggle = isLibrary ? (event) => {
|
|
36
|
+
const element = event.currentTarget;
|
|
37
|
+
if (element.open === committedOpen) return;
|
|
38
|
+
if (disabled) {
|
|
39
|
+
if (!rootPending) element.open = committedOpen === true;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
root.dispatchFromDom(value, element.open, event.nativeEvent);
|
|
43
|
+
} : void 0;
|
|
44
|
+
const state = {
|
|
45
|
+
value,
|
|
46
|
+
open: optimisticOpen,
|
|
47
|
+
pending,
|
|
48
|
+
disabled
|
|
49
|
+
};
|
|
50
|
+
const itemContext = {
|
|
51
|
+
value,
|
|
52
|
+
disabled,
|
|
53
|
+
committedOpen,
|
|
54
|
+
optimisticOpen,
|
|
55
|
+
pending
|
|
56
|
+
};
|
|
57
|
+
const element = useRender({
|
|
58
|
+
defaultElement: "details",
|
|
59
|
+
render,
|
|
60
|
+
state,
|
|
61
|
+
className,
|
|
62
|
+
style,
|
|
63
|
+
children,
|
|
64
|
+
ref: libraryRef,
|
|
65
|
+
props: rest,
|
|
66
|
+
libraryProps: {
|
|
67
|
+
open: isLibrary ? committedOpen : staticOpen,
|
|
68
|
+
suppressHydrationWarning: true,
|
|
69
|
+
name: !isLibrary ? root?.name : void 0,
|
|
70
|
+
...isLibrary && { onToggle },
|
|
71
|
+
"data-open": dataAttr(optimisticOpen === true),
|
|
72
|
+
"data-pending": dataAttr(pending),
|
|
73
|
+
"data-disabled": dataAttr(disabled)
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
return useTransitionBoundary("Accordion.Item", isLibrary ? transition : void 0, /* @__PURE__ */ jsx(AccordionItemContext, {
|
|
77
|
+
value: itemContext,
|
|
78
|
+
children: element
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
AccordionItem.displayName = "AccordionItem";
|
|
82
|
+
//#endregion
|
|
83
|
+
export { AccordionItem };
|
|
84
|
+
|
|
85
|
+
//# sourceMappingURL=accordion-item.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accordion-item.mjs","names":[],"sources":["../../src/accordion/accordion-item.tsx"],"sourcesContent":["\"use client\";\nimport { use, useCallback, useState } from \"react\";\nimport type {\n ComponentPropsWithRef,\n CSSProperties,\n ReactNode,\n SyntheticEvent,\n ViewTransitionClass,\n} from \"react\";\nimport { useTransitionBoundary } from \"../internal/transition-boundary.js\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { useDevWarning } from \"../internal/use-dev-warning.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { AccordionItemContext, AccordionRootContext } from \"./accordion-context.js\";\nimport type { AccordionItemContextValue } from \"./accordion-context.js\";\n\nexport interface AccordionItemState {\n readonly value: string;\n /** Optimistic open state. `undefined` in JS-free mode (browser-owned, unknown to React). */\n readonly open: boolean | undefined;\n /** This item's open state is changing through an in-flight action. */\n readonly pending: boolean;\n /** Disabled by its own prop or by the Root. */\n readonly disabled: boolean;\n}\n\nexport interface AccordionItemProps extends Omit<\n ComponentPropsWithRef<\"details\">,\n \"open\" | \"name\" | \"onToggle\" | \"className\" | \"style\" | \"children\"\n> {\n /** Identifies the item in the Root's `value`. Required in both modes. */\n value: string;\n /**\n * JS-free mode only: renders the initial `open` attribute; the browser owns it from then on.\n * Ignored (dev warning) in library mode, where the Root's `defaultValue` / `value` decide.\n */\n defaultOpen?: boolean;\n /**\n * Disables this item: the Trigger renders `aria-disabled` and never toggles. Enforced by a\n * click handler, so in JS-free mode it does not hold before hydration or with JS off.\n */\n disabled?: boolean;\n /**\n * Library mode only. Forwarded as `default` to the `<ViewTransition>` around the `<details>`;\n * animates the commit that ends an action (the `open` attribute flip), not the optimistic\n * `data-open` flip. Ignored (dev warning) in JS-free mode.\n *\n * Static: without `transition` the part renders no `<ViewTransition>`; changing it between\n * `undefined` and a value remounts the element. Any value, `\"none\"` included, makes a mount or\n * `<Activity>` reveal of this part inside a transition start a document view transition: the\n * page cross-fades for about 250 ms and the next transition commit waits for it (issue #35).\n */\n transition?: ViewTransitionClass;\n className?: StateValue<string | undefined, AccordionItemState>;\n style?: StateValue<CSSProperties | undefined, AccordionItemState>;\n children?: StateValue<ReactNode, AccordionItemState>;\n /** Must render a `<details>` element. */\n render?: RenderProp<ComponentPropsWithRef<\"details\">, AccordionItemState>;\n}\n\nconst isDev = process.env.NODE_ENV !== \"production\";\n\n/**\n * One accordion entry: the `<details>` element. In library mode its `open` attribute follows\n * committed state and `data-open` / `data-pending` follow optimistic state; in JS-free mode (or\n * outside any Root, as a standalone disclosure) the browser owns `open`.\n */\nexport function AccordionItem({\n value,\n defaultOpen = false,\n disabled: disabledProp = false,\n transition,\n className,\n style,\n children,\n render,\n ...rest\n}: AccordionItemProps) {\n const root = use(AccordionRootContext);\n const isLibrary = root?.mode === \"library\";\n const disabled = disabledProp || (root?.disabled ?? false);\n const committedOpen = isLibrary ? root.committed.has(value) : undefined;\n const optimisticOpen = isLibrary ? root.optimistic.has(value) : undefined;\n const rootPending = root?.pending ?? false;\n const pending = isLibrary && rootPending && committedOpen !== optimisticOpen;\n // JS-free mode: the prop React writes never changes after the first render, so React never\n // rewrites the attribute the browser now owns.\n const [staticOpen] = useState(defaultOpen);\n\n useDevWarning(\n isLibrary && defaultOpen,\n \"Accordion.Item: `defaultOpen` is ignored in library mode. Use `defaultValue` or `value` on \" +\n \"Accordion.Root instead.\",\n );\n useDevWarning(\n !isLibrary && transition !== undefined,\n \"Accordion.Item: `transition` has no effect in JS-free mode; the browser toggles the item \" +\n \"outside any React transition. Animate `::details-content` with CSS instead.\",\n );\n\n const registerItem = root?.registerItem;\n const libraryRef = useCallback(\n (element: HTMLDetailsElement) => {\n if (isDev && element.tagName !== \"DETAILS\") {\n console.error(\n `Accordion.Item: expected to render a <details> element but got <${element.tagName.toLowerCase()}>. ` +\n \"The platform semantics (toggle, find-in-page, exclusive groups) need a real <details>.\",\n );\n }\n const unregister = registerItem?.(value, element);\n return () => {\n unregister?.();\n };\n },\n [registerItem, value],\n );\n\n // Platform path (design 2.3): the Root reconciles pre-hydration clicks on mount and re-applies\n // committed state once nothing is in flight; this handler reports the browser's own flips.\n const onToggle = isLibrary\n ? (event: SyntheticEvent<HTMLDetailsElement>) => {\n const element = event.currentTarget;\n // Read `details.open`, never `ToggleEvent.newState`: `toggle` is coalesced.\n if (element.open === committedOpen) return; // our own commit echoing back\n if (disabled) {\n // A disabled item cannot be opened by the browser either; close it again now or, while\n // an action is in flight, when the Root re-applies committed state.\n if (!rootPending) element.open = committedOpen === true;\n return;\n }\n root.dispatchFromDom(value, element.open, event.nativeEvent);\n }\n : undefined;\n\n const state: AccordionItemState = { value, open: optimisticOpen, pending, disabled };\n const itemContext: AccordionItemContextValue = {\n value,\n disabled,\n committedOpen,\n optimisticOpen,\n pending,\n };\n\n const element = useRender<ComponentPropsWithRef<\"details\">, AccordionItemState>({\n defaultElement: \"details\",\n render,\n state,\n className,\n style,\n children,\n ref: libraryRef,\n props: rest,\n // Library-controlled layer: `open`, `name` and `onToggle` are owned by the library in at\n // least one mode, so a `render` element cannot override them either (conventions 1.2).\n libraryProps: {\n open: isLibrary ? committedOpen : staticOpen,\n // A click before hydration changes `open` under React's feet in both modes; the mismatch is\n // expected and reconciled (library mode) or the browser's business (JS-free mode).\n suppressHydrationWarning: true,\n // Owned in both modes: in library mode there is one writer of `open`, so a render element's\n // `name` (a second, platform-level writer) is removed.\n name: !isLibrary ? root?.name : undefined,\n // Only installed in library mode; owning the key in static mode would strip a render\n // element's own `onToggle`.\n ...(isLibrary && { onToggle }),\n \"data-open\": dataAttr(optimisticOpen === true),\n \"data-pending\": dataAttr(pending),\n \"data-disabled\": dataAttr(disabled),\n },\n });\n\n return useTransitionBoundary(\n \"Accordion.Item\",\n isLibrary ? transition : undefined,\n <AccordionItemContext value={itemContext}>{element}</AccordionItemContext>,\n );\n}\n\nAccordionItem.displayName = \"AccordionItem\";\n"],"mappings":";;;;;;;;;AA6DA,MAAM,QAAQ,QAAQ,IAAI,aAAa;;;;;;AAOvC,SAAgB,cAAc,EAC5B,OACA,cAAc,OACd,UAAU,eAAe,OACzB,YACA,WACA,OACA,UACA,QACA,GAAG,QACkB;CACrB,MAAM,OAAO,IAAI,oBAAoB;CACrC,MAAM,YAAY,MAAM,SAAS;CACjC,MAAM,WAAW,iBAAiB,MAAM,YAAY;CACpD,MAAM,gBAAgB,YAAY,KAAK,UAAU,IAAI,KAAK,IAAI,KAAA;CAC9D,MAAM,iBAAiB,YAAY,KAAK,WAAW,IAAI,KAAK,IAAI,KAAA;CAChE,MAAM,cAAc,MAAM,WAAW;CACrC,MAAM,UAAU,aAAa,eAAe,kBAAkB;CAG9D,MAAM,CAAC,cAAc,SAAS,WAAW;CAEzC,cACE,aAAa,aACb,oHAEF;CACA,cACE,CAAC,aAAa,eAAe,KAAA,GAC7B,sKAEF;CAEA,MAAM,eAAe,MAAM;CAC3B,MAAM,aAAa,aAChB,YAAgC;EAC/B,IAAI,SAAS,QAAQ,YAAY,WAC/B,QAAQ,MACN,mEAAmE,QAAQ,QAAQ,YAAY,EAAE,0FAEnG;EAEF,MAAM,aAAa,eAAe,OAAO,OAAO;EAChD,aAAa;GACX,aAAa;EACf;CACF,GACA,CAAC,cAAc,KAAK,CACtB;CAIA,MAAM,WAAW,aACZ,UAA8C;EAC7C,MAAM,UAAU,MAAM;EAEtB,IAAI,QAAQ,SAAS,eAAe;EACpC,IAAI,UAAU;GAGZ,IAAI,CAAC,aAAa,QAAQ,OAAO,kBAAkB;GACnD;EACF;EACA,KAAK,gBAAgB,OAAO,QAAQ,MAAM,MAAM,WAAW;CAC7D,IACA,KAAA;CAEJ,MAAM,QAA4B;EAAE;EAAO,MAAM;EAAgB;EAAS;CAAS;CACnF,MAAM,cAAyC;EAC7C;EACA;EACA;EACA;EACA;CACF;CAEA,MAAM,UAAU,UAAgE;EAC9E,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EACA,KAAK;EACL,OAAO;EAGP,cAAc;GACZ,MAAM,YAAY,gBAAgB;GAGlC,0BAA0B;GAG1B,MAAM,CAAC,YAAY,MAAM,OAAO,KAAA;GAGhC,GAAI,aAAa,EAAE,SAAS;GAC5B,aAAa,SAAS,mBAAmB,IAAI;GAC7C,gBAAgB,SAAS,OAAO;GAChC,iBAAiB,SAAS,QAAQ;EACpC;CACF,CAAC;CAED,OAAO,sBACL,kBACA,YAAY,aAAa,KAAA,GACzB,oBAAC,sBAAD;EAAsB,OAAO;EAAc,UAAA;CAA8B,CAAA,CAC3E;AACF;AAEA,cAAc,cAAc"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { RenderProp, StateValue } from "../internal/types.mjs";
|
|
2
|
+
import { CSSProperties, ComponentPropsWithRef, ReactNode, ViewTransitionClass } from "react";
|
|
3
|
+
//#region src/accordion/accordion-panel.d.ts
|
|
4
|
+
export interface AccordionPanelState {
|
|
5
|
+
readonly value: string;
|
|
6
|
+
/** Committed open state. `undefined` in JS-free mode. */
|
|
7
|
+
readonly open: boolean | undefined;
|
|
8
|
+
readonly disabled: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface AccordionPanelProps extends Omit<ComponentPropsWithRef<"div">, "className" | "style" | "children"> {
|
|
11
|
+
/**
|
|
12
|
+
* Library mode only. Forwarded as `default` to the `<ViewTransition>` around the panel's
|
|
13
|
+
* `div`; animates content that mounts or changes in the commit that ends an action.
|
|
14
|
+
*
|
|
15
|
+
* Static: without `transition` the part renders no `<ViewTransition>`; changing it between
|
|
16
|
+
* `undefined` and a value remounts the element. Any value, `"none"` included, makes a mount or
|
|
17
|
+
* `<Activity>` reveal of this part inside a transition start a document view transition: the
|
|
18
|
+
* page cross-fades for about 250 ms and the next transition commit waits for it (issue #35).
|
|
19
|
+
*/
|
|
20
|
+
transition?: ViewTransitionClass;
|
|
21
|
+
className?: StateValue<string | undefined, AccordionPanelState>;
|
|
22
|
+
style?: StateValue<CSSProperties | undefined, AccordionPanelState>;
|
|
23
|
+
/**
|
|
24
|
+
* Always mounted (closed `<details>` content stays in the DOM, indexable and searchable). The
|
|
25
|
+
* function form receives committed `open`, which is how content is mounted lazily and how
|
|
26
|
+
* suspending content keeps the item closed until it is ready.
|
|
27
|
+
*/
|
|
28
|
+
children?: StateValue<ReactNode, AccordionPanelState>;
|
|
29
|
+
render?: RenderProp<ComponentPropsWithRef<"div">, AccordionPanelState>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The item's content region: a `div` inside the `<details>`, after the Trigger. Its visibility
|
|
33
|
+
* is the parent's `open` attribute (`details:open > .panel`); it renders committed state.
|
|
34
|
+
*/
|
|
35
|
+
export declare function AccordionPanel({ transition, className, style, children, render, ...rest }: AccordionPanelProps): ReactNode;
|
|
36
|
+
export declare namespace AccordionPanel {
|
|
37
|
+
var displayName: string;
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
//# sourceMappingURL=accordion-panel.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accordion-panel.d.mts","names":[],"sources":["../../src/accordion/accordion-panel.tsx"],"mappings":";;;iBAUiB;WACN;;WAEA;WACA;;iBAGM,4BAA4B,KAC3C;;;;;;;;;;EAYA,aAAa;EACb,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;;;;;;EAM9C,WAAW,WAAW,WAAW;EACjC,SAAS,WAAW,8BAA8B;;;;;;wBAOpC,iBACd,YACA,WACA,OACA,UACA,WACG,QACF,sBAAmB;yBAPN"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
|
|
3
|
+
import { dataAttr } from "../internal/data-attr.mjs";
|
|
4
|
+
import { useRender } from "../internal/use-render.mjs";
|
|
5
|
+
import { useDevWarning } from "../internal/use-dev-warning.mjs";
|
|
6
|
+
import { AccordionItemContext, AccordionRootContext } from "./accordion-context.mjs";
|
|
7
|
+
import { use } from "react";
|
|
8
|
+
//#region src/accordion/accordion-panel.tsx
|
|
9
|
+
/**
|
|
10
|
+
* The item's content region: a `div` inside the `<details>`, after the Trigger. Its visibility
|
|
11
|
+
* is the parent's `open` attribute (`details:open > .panel`); it renders committed state.
|
|
12
|
+
*/
|
|
13
|
+
function AccordionPanel({ transition, className, style, children, render, ...rest }) {
|
|
14
|
+
const root = use(AccordionRootContext);
|
|
15
|
+
const item = use(AccordionItemContext);
|
|
16
|
+
if (item === null) throw new Error("Accordion.Panel must be rendered inside an Accordion.Item.");
|
|
17
|
+
const isLibrary = root?.mode === "library";
|
|
18
|
+
useDevWarning(!isLibrary && transition !== void 0, "Accordion.Panel: `transition` has no effect in JS-free mode; the browser toggles the item outside any React transition.");
|
|
19
|
+
const state = {
|
|
20
|
+
value: item.value,
|
|
21
|
+
open: item.committedOpen,
|
|
22
|
+
disabled: item.disabled
|
|
23
|
+
};
|
|
24
|
+
const element = useRender({
|
|
25
|
+
defaultElement: "div",
|
|
26
|
+
render,
|
|
27
|
+
state,
|
|
28
|
+
className,
|
|
29
|
+
style,
|
|
30
|
+
children,
|
|
31
|
+
props: rest,
|
|
32
|
+
libraryProps: { "data-disabled": dataAttr(item.disabled) }
|
|
33
|
+
});
|
|
34
|
+
return useTransitionBoundary("Accordion.Panel", isLibrary ? transition : void 0, element);
|
|
35
|
+
}
|
|
36
|
+
AccordionPanel.displayName = "AccordionPanel";
|
|
37
|
+
//#endregion
|
|
38
|
+
export { AccordionPanel };
|
|
39
|
+
|
|
40
|
+
//# sourceMappingURL=accordion-panel.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accordion-panel.mjs","names":[],"sources":["../../src/accordion/accordion-panel.tsx"],"sourcesContent":["\"use client\";\nimport { use } from \"react\";\nimport type { ComponentPropsWithRef, CSSProperties, ReactNode, ViewTransitionClass } from \"react\";\nimport { useTransitionBoundary } from \"../internal/transition-boundary.js\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { useDevWarning } from \"../internal/use-dev-warning.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { AccordionItemContext, AccordionRootContext } from \"./accordion-context.js\";\n\nexport interface AccordionPanelState {\n readonly value: string;\n /** Committed open state. `undefined` in JS-free mode. */\n readonly open: boolean | undefined;\n readonly disabled: boolean;\n}\n\nexport interface AccordionPanelProps extends Omit<\n ComponentPropsWithRef<\"div\">,\n \"className\" | \"style\" | \"children\"\n> {\n /**\n * Library mode only. Forwarded as `default` to the `<ViewTransition>` around the panel's\n * `div`; animates content that mounts or changes in the commit that ends an action.\n *\n * Static: without `transition` the part renders no `<ViewTransition>`; changing it between\n * `undefined` and a value remounts the element. Any value, `\"none\"` included, makes a mount or\n * `<Activity>` reveal of this part inside a transition start a document view transition: the\n * page cross-fades for about 250 ms and the next transition commit waits for it (issue #35).\n */\n transition?: ViewTransitionClass;\n className?: StateValue<string | undefined, AccordionPanelState>;\n style?: StateValue<CSSProperties | undefined, AccordionPanelState>;\n /**\n * Always mounted (closed `<details>` content stays in the DOM, indexable and searchable). The\n * function form receives committed `open`, which is how content is mounted lazily and how\n * suspending content keeps the item closed until it is ready.\n */\n children?: StateValue<ReactNode, AccordionPanelState>;\n render?: RenderProp<ComponentPropsWithRef<\"div\">, AccordionPanelState>;\n}\n\n/**\n * The item's content region: a `div` inside the `<details>`, after the Trigger. Its visibility\n * is the parent's `open` attribute (`details:open > .panel`); it renders committed state.\n */\nexport function AccordionPanel({\n transition,\n className,\n style,\n children,\n render,\n ...rest\n}: AccordionPanelProps) {\n const root = use(AccordionRootContext);\n const item = use(AccordionItemContext);\n if (item === null) {\n throw new Error(\"Accordion.Panel must be rendered inside an Accordion.Item.\");\n }\n const isLibrary = root?.mode === \"library\";\n\n useDevWarning(\n !isLibrary && transition !== undefined,\n \"Accordion.Panel: `transition` has no effect in JS-free mode; the browser toggles the item \" +\n \"outside any React transition.\",\n );\n\n const state: AccordionPanelState = {\n value: item.value,\n open: item.committedOpen,\n disabled: item.disabled,\n };\n\n const element = useRender<ComponentPropsWithRef<\"div\">, AccordionPanelState>({\n defaultElement: \"div\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps: {\n \"data-disabled\": dataAttr(item.disabled),\n },\n });\n\n return useTransitionBoundary(\"Accordion.Panel\", isLibrary ? transition : undefined, element);\n}\n\nAccordionPanel.displayName = \"AccordionPanel\";\n"],"mappings":";;;;;;;;;;;;AA8CA,SAAgB,eAAe,EAC7B,YACA,WACA,OACA,UACA,QACA,GAAG,QACmB;CACtB,MAAM,OAAO,IAAI,oBAAoB;CACrC,MAAM,OAAO,IAAI,oBAAoB;CACrC,IAAI,SAAS,MACX,MAAM,IAAI,MAAM,4DAA4D;CAE9E,MAAM,YAAY,MAAM,SAAS;CAEjC,cACE,CAAC,aAAa,eAAe,KAAA,GAC7B,yHAEF;CAEA,MAAM,QAA6B;EACjC,OAAO,KAAK;EACZ,MAAM,KAAK;EACX,UAAU,KAAK;CACjB;CAEA,MAAM,UAAU,UAA6D;EAC3E,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EACA,OAAO;EACP,cAAc,EACZ,iBAAiB,SAAS,KAAK,QAAQ,EACzC;CACF,CAAC;CAED,OAAO,sBAAsB,mBAAmB,YAAY,aAAa,KAAA,GAAW,OAAO;AAC7F;AAEA,eAAe,cAAc"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { ActionDetails, ChangeAction, RenderProp, StateValue } from "../internal/types.mjs";
|
|
2
|
+
import { AccordionChangeReason } from "./accordion-context.mjs";
|
|
3
|
+
import { CSSProperties, ComponentPropsWithRef, ReactNode } from "react";
|
|
4
|
+
//#region src/accordion/accordion-root.d.ts
|
|
5
|
+
export interface AccordionRootState {
|
|
6
|
+
/** An action dispatched through this Accordion is in flight (library mode only). */
|
|
7
|
+
readonly pending: boolean;
|
|
8
|
+
/** The Root's `disabled` prop. */
|
|
9
|
+
readonly disabled: boolean;
|
|
10
|
+
}
|
|
11
|
+
/** Details passed as the second argument of `valueChangeAction`. */
|
|
12
|
+
export interface AccordionValueChangeDetails extends ActionDetails {
|
|
13
|
+
/**
|
|
14
|
+
* `"activate"`: the user activated a Trigger. `"platform"`: the browser changed `open` itself
|
|
15
|
+
* (find-in-page, a text fragment, a click before hydration); `event` is then the `toggle`
|
|
16
|
+
* event, or `undefined` when the mismatch was found on mount.
|
|
17
|
+
*/
|
|
18
|
+
readonly reason: AccordionChangeReason;
|
|
19
|
+
/** The item whose open state changed. */
|
|
20
|
+
readonly item: string;
|
|
21
|
+
/** That item's new open state. */
|
|
22
|
+
readonly open: boolean;
|
|
23
|
+
}
|
|
24
|
+
interface AccordionRootBaseProps extends Omit<ComponentPropsWithRef<"div">, "onKeyDown" | "defaultValue" | "className" | "style" | "children"> {
|
|
25
|
+
/** Disables every item: triggers render `aria-disabled` and never dispatch. Default `false`. */
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Renders `interpolate-size: allow-keywords` on the root so `::details-content` can transition
|
|
29
|
+
* `height` to `auto`. Chromium-only polish today; use the `grid-template-rows` form for a
|
|
30
|
+
* cross-engine animation. Merged with `style`; the consumer's declaration wins.
|
|
31
|
+
*/
|
|
32
|
+
experimental_interpolateSize?: boolean;
|
|
33
|
+
className?: StateValue<string | undefined, AccordionRootState>;
|
|
34
|
+
style?: StateValue<CSSProperties | undefined, AccordionRootState>;
|
|
35
|
+
children?: StateValue<ReactNode, AccordionRootState>;
|
|
36
|
+
render?: RenderProp<ComponentPropsWithRef<"div">, AccordionRootState>;
|
|
37
|
+
}
|
|
38
|
+
export interface AccordionRootMultipleProps extends AccordionRootBaseProps {
|
|
39
|
+
/** Any number of items may be open. */
|
|
40
|
+
exclusive?: false;
|
|
41
|
+
/** Controlled open items. `undefined` means uncontrolled; `[]` means none open. */
|
|
42
|
+
value?: string[];
|
|
43
|
+
/** Initial open items in uncontrolled library mode. */
|
|
44
|
+
defaultValue?: string[];
|
|
45
|
+
/**
|
|
46
|
+
* Called with the next open items on every change. Runs inside the Root's transition; may be
|
|
47
|
+
* sync or async (also a Server Function). Rejections reach the nearest Error Boundary.
|
|
48
|
+
*
|
|
49
|
+
* May also be called with `details.reason === "platform"` when the browser opened an item
|
|
50
|
+
* itself (find-in-page, a click before hydration); committed state is re-applied to the DOM
|
|
51
|
+
* once the action settles.
|
|
52
|
+
*
|
|
53
|
+
* A `setState` placed after your own `await` is not a Transition update; wrap it in
|
|
54
|
+
* `startTransition` (React limitation).
|
|
55
|
+
*/
|
|
56
|
+
valueChangeAction?: ChangeAction<string[], AccordionValueChangeDetails>;
|
|
57
|
+
}
|
|
58
|
+
export interface AccordionRootExclusiveProps extends AccordionRootBaseProps {
|
|
59
|
+
/**
|
|
60
|
+
* At most one item open. JS-free mode: renders the same `name` on every `<details>` (the
|
|
61
|
+
* platform's exclusive group). Library mode: the value is a single item or `null`.
|
|
62
|
+
*/
|
|
63
|
+
exclusive: true;
|
|
64
|
+
/** Controlled open item. `undefined` means uncontrolled; `null` means none open. */
|
|
65
|
+
value?: string | null;
|
|
66
|
+
/** Initial open item in uncontrolled library mode. */
|
|
67
|
+
defaultValue?: string | null;
|
|
68
|
+
/** See {@link AccordionRootMultipleProps.valueChangeAction}. */
|
|
69
|
+
valueChangeAction?: ChangeAction<string | null, AccordionValueChangeDetails>;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Props of `Accordion.Root`, discriminated on `exclusive`.
|
|
73
|
+
*
|
|
74
|
+
* Without `value`, `defaultValue` and `valueChangeAction` the Accordion runs in **JS-free mode**:
|
|
75
|
+
* the browser owns each `<details open>`, nothing runs on toggle, and `exclusive` renders `name`.
|
|
76
|
+
* With any of them it runs in **library mode**: the summary click is intercepted, `open` is driven
|
|
77
|
+
* by committed state inside a transition, and triggers show optimistic `data-open`.
|
|
78
|
+
*/
|
|
79
|
+
export type AccordionRootProps = AccordionRootMultipleProps | AccordionRootExclusiveProps;
|
|
80
|
+
/**
|
|
81
|
+
* The accordion container: a `div` that owns the open state, the transition, the context the
|
|
82
|
+
* other parts read, and ArrowUp/ArrowDown/Home/End navigation between triggers.
|
|
83
|
+
*/
|
|
84
|
+
export declare function AccordionRoot(props: AccordionRootProps): import("react").JSX.Element;
|
|
85
|
+
export declare namespace AccordionRoot {
|
|
86
|
+
var displayName: string;
|
|
87
|
+
}
|
|
88
|
+
//#endregion
|
|
89
|
+
export {};
|
|
90
|
+
//# sourceMappingURL=accordion-root.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accordion-root.d.mts","names":[],"sources":["../../src/accordion/accordion-root.tsx"],"mappings":";;;;iBAyBiB;;WAEN;;WAEA;;;iBAIM,oCAAoC;;;;;;WAM1C,QAAQ;;WAER;;WAEA;;UAGD,+BAA+B,KACvC;;EAKA;;;;;;EAMA;EACA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;EACjC,SAAS,WAAW,8BAA8B;;iBAGnC,mCAAmC;;EAElD;;EAEA;;EAEA;;;;;;;;;;;;EAYA,oBAAoB,uBAAuB;;iBAG5B,oCAAoC;;;;;EAKnD;;EAEA;;EAEA;;EAEA,oBAAoB,4BAA4B;;;;;;;;;;YAWtC,qBAAqB,6BAA6B;;;;;wBAqF9C,cAAc,OAAO,qCAAkB,IAAA;yBAAvC"}
|