@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
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { RenderProp, StateValue } from "../internal/types.mjs";
|
|
2
|
+
import { DialogPopupState } from "./dialog-popup.mjs";
|
|
3
|
+
import { CSSProperties, ComponentPropsWithRef, ReactNode } from "react";
|
|
4
|
+
//#region src/dialog/dialog-title.d.ts
|
|
5
|
+
export type DialogTitleState = DialogPopupState;
|
|
6
|
+
export interface DialogTitleProps extends Omit<ComponentPropsWithRef<"h2">, "id" | "className" | "style" | "children"> {
|
|
7
|
+
className?: StateValue<string | undefined, DialogTitleState>;
|
|
8
|
+
style?: StateValue<CSSProperties | undefined, DialogTitleState>;
|
|
9
|
+
children?: StateValue<ReactNode, DialogTitleState>;
|
|
10
|
+
/** `render={<h3 />}` changes the heading level. */
|
|
11
|
+
render?: RenderProp<ComponentPropsWithRef<"h2">, DialogTitleState>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The dialog's name: an `<h2>` whose id the Popup references with `aria-labelledby`.
|
|
15
|
+
*
|
|
16
|
+
* Owned key (conventions 1.2): `id`.
|
|
17
|
+
*/
|
|
18
|
+
export declare function DialogTitle({ className, style, children, render, ...rest }: DialogTitleProps): ReactNode;
|
|
19
|
+
export declare namespace DialogTitle {
|
|
20
|
+
var displayName: string;
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
//# sourceMappingURL=dialog-title.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dialog-title.d.mts","names":[],"sources":["../../src/dialog/dialog-title.tsx"],"mappings":";;;;YAOY,mBAAmB;iBAEd,yBAAyB,KACxC;EAGA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;;EAEjC,SAAS,WAAW,6BAA6B;;;;;;;wBAQnC,cAAc,WAAW,OAAO,UAAU,WAAW,QAAQ,mBAAgB;yBAA7E"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useRender } from "../internal/use-render.mjs";
|
|
3
|
+
import { useDialogContext } from "./dialog-context.mjs";
|
|
4
|
+
//#region src/dialog/dialog-title.tsx
|
|
5
|
+
/**
|
|
6
|
+
* The dialog's name: an `<h2>` whose id the Popup references with `aria-labelledby`.
|
|
7
|
+
*
|
|
8
|
+
* Owned key (conventions 1.2): `id`.
|
|
9
|
+
*/
|
|
10
|
+
function DialogTitle({ className, style, children, render, ...rest }) {
|
|
11
|
+
const ctx = useDialogContext("Dialog.Title");
|
|
12
|
+
const state = {
|
|
13
|
+
open: ctx.committed,
|
|
14
|
+
modal: ctx.modal
|
|
15
|
+
};
|
|
16
|
+
return useRender({
|
|
17
|
+
defaultElement: "h2",
|
|
18
|
+
render,
|
|
19
|
+
state,
|
|
20
|
+
className,
|
|
21
|
+
style,
|
|
22
|
+
children,
|
|
23
|
+
props: rest,
|
|
24
|
+
libraryProps: { id: ctx.ids.title }
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
DialogTitle.displayName = "DialogTitle";
|
|
28
|
+
//#endregion
|
|
29
|
+
export { DialogTitle };
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=dialog-title.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dialog-title.mjs","names":[],"sources":["../../src/dialog/dialog-title.tsx"],"sourcesContent":["\"use client\";\nimport type { ComponentPropsWithRef, CSSProperties, ReactNode } from \"react\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { useDialogContext } from \"./dialog-context.js\";\nimport type { DialogPopupState } from \"./dialog-popup.js\";\n\nexport type DialogTitleState = DialogPopupState;\n\nexport interface DialogTitleProps extends Omit<\n ComponentPropsWithRef<\"h2\">,\n \"id\" | \"className\" | \"style\" | \"children\"\n> {\n className?: StateValue<string | undefined, DialogTitleState>;\n style?: StateValue<CSSProperties | undefined, DialogTitleState>;\n children?: StateValue<ReactNode, DialogTitleState>;\n /** `render={<h3 />}` changes the heading level. */\n render?: RenderProp<ComponentPropsWithRef<\"h2\">, DialogTitleState>;\n}\n\n/**\n * The dialog's name: an `<h2>` whose id the Popup references with `aria-labelledby`.\n *\n * Owned key (conventions 1.2): `id`.\n */\nexport function DialogTitle({ className, style, children, render, ...rest }: DialogTitleProps) {\n const ctx = useDialogContext(\"Dialog.Title\");\n const state: DialogTitleState = { open: ctx.committed, modal: ctx.modal };\n return useRender<ComponentPropsWithRef<\"h2\">, DialogTitleState>({\n defaultElement: \"h2\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps: { id: ctx.ids.title },\n });\n}\n\nDialogTitle.displayName = \"DialogTitle\";\n"],"mappings":";;;;;;;;;AAyBA,SAAgB,YAAY,EAAE,WAAW,OAAO,UAAU,QAAQ,GAAG,QAA0B;CAC7F,MAAM,MAAM,iBAAiB,cAAc;CAC3C,MAAM,QAA0B;EAAE,MAAM,IAAI;EAAW,OAAO,IAAI;CAAM;CACxE,OAAO,UAAyD;EAC9D,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EACA,OAAO;EACP,cAAc,EAAE,IAAI,IAAI,IAAI,MAAM;CACpC,CAAC;AACH;AAEA,YAAY,cAAc"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { RenderProp, StateValue } from "../internal/types.mjs";
|
|
2
|
+
import { CSSProperties, ComponentPropsWithRef, ReactNode } from "react";
|
|
3
|
+
//#region src/dialog/dialog-trigger.d.ts
|
|
4
|
+
export interface DialogTriggerState {
|
|
5
|
+
/** Optimistic open state (library mode); `false` in JS-free mode. */
|
|
6
|
+
readonly open: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* The Root's transition is pending: an open in flight, a close notification in flight, or a
|
|
9
|
+
* re-open requested while a close notification is still settling.
|
|
10
|
+
*/
|
|
11
|
+
readonly pending: boolean;
|
|
12
|
+
readonly disabled: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface DialogTriggerProps extends Omit<ComponentPropsWithRef<"button">, "onClick" | "className" | "style" | "children"> {
|
|
15
|
+
/** Native `disabled`: a disabled button is not a valid invoker and never dispatches. */
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
className?: StateValue<string | undefined, DialogTriggerState>;
|
|
18
|
+
style?: StateValue<CSSProperties | undefined, DialogTriggerState>;
|
|
19
|
+
/** Rendered from optimistic state; must not suspend. */
|
|
20
|
+
children?: StateValue<ReactNode, DialogTriggerState>;
|
|
21
|
+
/** Should render a `<button>`; another element works only in library mode (click handler). */
|
|
22
|
+
render?: RenderProp<ComponentPropsWithRef<"button">, DialogTriggerState>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The opener: `<button type="button" commandfor command="show-modal">`. In JS-free mode the
|
|
26
|
+
* browser runs the command. In library mode the click is cancelled (so the command does not run)
|
|
27
|
+
* and dispatched through the Root's transition; the button shows optimistic `data-open` and
|
|
28
|
+
* `data-pending` until the dialog has opened. Non-modal dialogs have no command and always use a
|
|
29
|
+
* click handler (`show()`).
|
|
30
|
+
*
|
|
31
|
+
* Owned keys (conventions 1.2): `type` (on a `<button>` only), `disabled`, `commandfor`,
|
|
32
|
+
* `command`, `onClick`, `data-open`, `data-pending`, `data-disabled`.
|
|
33
|
+
*/
|
|
34
|
+
export declare function DialogTrigger({ disabled, className, style, children, render, ...rest }: DialogTriggerProps): ReactNode;
|
|
35
|
+
export declare namespace DialogTrigger {
|
|
36
|
+
var displayName: string;
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
//# sourceMappingURL=dialog-trigger.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dialog-trigger.d.mts","names":[],"sources":["../../src/dialog/dialog-trigger.tsx"],"mappings":";;;iBASiB;;WAEN;;;;;WAKA;WACA;;iBAGM,2BAA2B,KAC1C;;EAIA;EACA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;;EAE9C,WAAW,WAAW,WAAW;;EAEjC,SAAS,WAAW,iCAAiC;;;;;;;;;;;;wBAevC,gBACd,UACA,WACA,OACA,UACA,WACG,QACF,qBAAkB;yBAPL"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { dataAttr } from "../internal/data-attr.mjs";
|
|
3
|
+
import { rendersButton, useRender } from "../internal/use-render.mjs";
|
|
4
|
+
import { useDialogContext } from "./dialog-context.mjs";
|
|
5
|
+
import { useCallback, useEffect } from "react";
|
|
6
|
+
//#region src/dialog/dialog-trigger.tsx
|
|
7
|
+
const isDev = process.env.NODE_ENV !== "production";
|
|
8
|
+
/**
|
|
9
|
+
* The opener: `<button type="button" commandfor command="show-modal">`. In JS-free mode the
|
|
10
|
+
* browser runs the command. In library mode the click is cancelled (so the command does not run)
|
|
11
|
+
* and dispatched through the Root's transition; the button shows optimistic `data-open` and
|
|
12
|
+
* `data-pending` until the dialog has opened. Non-modal dialogs have no command and always use a
|
|
13
|
+
* click handler (`show()`).
|
|
14
|
+
*
|
|
15
|
+
* Owned keys (conventions 1.2): `type` (on a `<button>` only), `disabled`, `commandfor`,
|
|
16
|
+
* `command`, `onClick`, `data-open`, `data-pending`, `data-disabled`.
|
|
17
|
+
*/
|
|
18
|
+
function DialogTrigger({ disabled = false, className, style, children, render, ...rest }) {
|
|
19
|
+
const ctx = useDialogContext("Dialog.Trigger");
|
|
20
|
+
const isLibrary = ctx.mode === "library";
|
|
21
|
+
const { modal, ids, triggerRef, dialogRef } = ctx;
|
|
22
|
+
const state = {
|
|
23
|
+
open: ctx.optimistic,
|
|
24
|
+
pending: ctx.pending,
|
|
25
|
+
disabled
|
|
26
|
+
};
|
|
27
|
+
const libraryRef = useCallback((element) => {
|
|
28
|
+
if (isDev && !isLibrary && modal && element.tagName !== "BUTTON") console.error(`Dialog.Trigger: rendered a <${element.tagName.toLowerCase()}> in JS-free mode. Only a <button> runs \`command="show-modal"\`; this trigger will not open the dialog. Render a <button>, or put the Dialog in library mode (\`defaultOpen={false}\`).`);
|
|
29
|
+
triggerRef.current = element;
|
|
30
|
+
return () => {
|
|
31
|
+
if (triggerRef.current === element) triggerRef.current = null;
|
|
32
|
+
};
|
|
33
|
+
}, [
|
|
34
|
+
isLibrary,
|
|
35
|
+
modal,
|
|
36
|
+
triggerRef
|
|
37
|
+
]);
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (!isDev) return;
|
|
40
|
+
if (document.getElementById(ids.dialog) === null) console.error("Dialog.Trigger: no Dialog.Popup is rendered for this Dialog.Root; the trigger opens nothing.");
|
|
41
|
+
}, [ids.dialog]);
|
|
42
|
+
const installClick = isLibrary || !modal;
|
|
43
|
+
const onClick = (event) => {
|
|
44
|
+
if (isLibrary) {
|
|
45
|
+
event.preventDefault();
|
|
46
|
+
if (disabled) return;
|
|
47
|
+
ctx.requestOpen(event.nativeEvent, "activate");
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (disabled) return;
|
|
51
|
+
const dialog = dialogRef.current;
|
|
52
|
+
if (dialog !== null && !dialog.open && dialog.isConnected) dialog.show();
|
|
53
|
+
};
|
|
54
|
+
const libraryProps = {
|
|
55
|
+
...rendersButton(render) && { type: "button" },
|
|
56
|
+
disabled,
|
|
57
|
+
commandfor: modal ? ids.dialog : void 0,
|
|
58
|
+
command: modal ? "show-modal" : void 0,
|
|
59
|
+
...installClick && { onClick },
|
|
60
|
+
"data-open": dataAttr(state.open),
|
|
61
|
+
"data-pending": dataAttr(state.pending),
|
|
62
|
+
"data-disabled": dataAttr(isLibrary && disabled)
|
|
63
|
+
};
|
|
64
|
+
return useRender({
|
|
65
|
+
defaultElement: "button",
|
|
66
|
+
render,
|
|
67
|
+
state,
|
|
68
|
+
className,
|
|
69
|
+
style,
|
|
70
|
+
children,
|
|
71
|
+
props: rest,
|
|
72
|
+
libraryProps,
|
|
73
|
+
ref: libraryRef
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
DialogTrigger.displayName = "DialogTrigger";
|
|
77
|
+
//#endregion
|
|
78
|
+
export { DialogTrigger };
|
|
79
|
+
|
|
80
|
+
//# sourceMappingURL=dialog-trigger.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dialog-trigger.mjs","names":[],"sources":["../../src/dialog/dialog-trigger.tsx"],"sourcesContent":["\"use client\";\nimport { useCallback, useEffect } from \"react\";\nimport type { ComponentPropsWithRef, CSSProperties, MouseEvent, ReactNode } from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { rendersButton, useRender } from \"../internal/use-render.js\";\nimport type { DataAttributes } from \"../internal/use-render.js\";\nimport { useDialogContext } from \"./dialog-context.js\";\n\nexport interface DialogTriggerState {\n /** Optimistic open state (library mode); `false` in JS-free mode. */\n readonly open: boolean;\n /**\n * The Root's transition is pending: an open in flight, a close notification in flight, or a\n * re-open requested while a close notification is still settling.\n */\n readonly pending: boolean;\n readonly disabled: boolean;\n}\n\nexport interface DialogTriggerProps extends Omit<\n ComponentPropsWithRef<\"button\">,\n \"onClick\" | \"className\" | \"style\" | \"children\"\n> {\n /** Native `disabled`: a disabled button is not a valid invoker and never dispatches. */\n disabled?: boolean;\n className?: StateValue<string | undefined, DialogTriggerState>;\n style?: StateValue<CSSProperties | undefined, DialogTriggerState>;\n /** Rendered from optimistic state; must not suspend. */\n children?: StateValue<ReactNode, DialogTriggerState>;\n /** Should render a `<button>`; another element works only in library mode (click handler). */\n render?: RenderProp<ComponentPropsWithRef<\"button\">, DialogTriggerState>;\n}\n\nconst isDev = process.env.NODE_ENV !== \"production\";\n\n/**\n * The opener: `<button type=\"button\" commandfor command=\"show-modal\">`. In JS-free mode the\n * browser runs the command. In library mode the click is cancelled (so the command does not run)\n * and dispatched through the Root's transition; the button shows optimistic `data-open` and\n * `data-pending` until the dialog has opened. Non-modal dialogs have no command and always use a\n * click handler (`show()`).\n *\n * Owned keys (conventions 1.2): `type` (on a `<button>` only), `disabled`, `commandfor`,\n * `command`, `onClick`, `data-open`, `data-pending`, `data-disabled`.\n */\nexport function DialogTrigger({\n disabled = false,\n className,\n style,\n children,\n render,\n ...rest\n}: DialogTriggerProps) {\n const ctx = useDialogContext(\"Dialog.Trigger\");\n const isLibrary = ctx.mode === \"library\";\n const { modal, ids, triggerRef, dialogRef } = ctx;\n\n const state: DialogTriggerState = {\n open: ctx.optimistic,\n // Every Root dispatch is an open or a close notification and both belong to the Trigger\n // (design 4.2). Not `optimistic !== committed`: a re-open while a close notification is\n // still settling has both `true` (the close never committed) and is pending all the same.\n pending: ctx.pending,\n disabled,\n };\n\n const libraryRef = useCallback(\n (element: HTMLElement) => {\n if (isDev && !isLibrary && modal && element.tagName !== \"BUTTON\") {\n console.error(\n `Dialog.Trigger: rendered a <${element.tagName.toLowerCase()}> in JS-free mode. Only a ` +\n '<button> runs `command=\"show-modal\"`; this trigger will not open the dialog. Render ' +\n \"a <button>, or put the Dialog in library mode (`defaultOpen={false}`).\",\n );\n }\n triggerRef.current = element;\n return () => {\n if (triggerRef.current === element) triggerRef.current = null;\n };\n },\n [isLibrary, modal, triggerRef],\n );\n\n // A Trigger without a Popup opens nothing (design 14, dev warnings).\n useEffect(() => {\n if (!isDev) return;\n if (document.getElementById(ids.dialog) === null) {\n console.error(\n \"Dialog.Trigger: no Dialog.Popup is rendered for this Dialog.Root; the trigger opens nothing.\",\n );\n }\n }, [ids.dialog]);\n\n // Library mode (both modal and non-modal) and non-modal JS-free mode need a click handler;\n // modal JS-free mode is the browser's command.\n const installClick = isLibrary || !modal;\n const onClick = (event: MouseEvent<HTMLElement>) => {\n if (isLibrary) {\n // Cancelling the click cancels the command (it runs as the button's activation\n // behaviour, only if the click was not cancelled).\n event.preventDefault();\n if (disabled) return;\n ctx.requestOpen(event.nativeEvent, \"activate\");\n return;\n }\n if (disabled) return;\n const dialog = dialogRef.current;\n if (dialog !== null && !dialog.open && dialog.isConnected) dialog.show();\n };\n\n const libraryProps: ComponentPropsWithRef<\"button\"> & DataAttributes = {\n // `type` only applies to a <button>; on any other element the key is not owned.\n ...(rendersButton(render) && { type: \"button\" as const }),\n // Owned: a render element must not re-enable a disabled Trigger (in JS-free mode the\n // browser would run its command).\n disabled,\n commandfor: modal ? ids.dialog : undefined,\n command: modal ? \"show-modal\" : undefined,\n // Only owned when installed, so a render element keeps its own `onClick` in modal JS-free\n // mode (Accordion's rule).\n ...(installClick && { onClick }),\n \"data-open\": dataAttr(state.open),\n \"data-pending\": dataAttr(state.pending),\n \"data-disabled\": dataAttr(isLibrary && disabled),\n };\n\n return useRender<ComponentPropsWithRef<\"button\">, DialogTriggerState>({\n defaultElement: \"button\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps,\n ref: libraryRef,\n });\n}\n\nDialogTrigger.displayName = \"DialogTrigger\";\n"],"mappings":";;;;;;AAkCA,MAAM,QAAQ,QAAQ,IAAI,aAAa;;;;;;;;;;;AAYvC,SAAgB,cAAc,EAC5B,WAAW,OACX,WACA,OACA,UACA,QACA,GAAG,QACkB;CACrB,MAAM,MAAM,iBAAiB,gBAAgB;CAC7C,MAAM,YAAY,IAAI,SAAS;CAC/B,MAAM,EAAE,OAAO,KAAK,YAAY,cAAc;CAE9C,MAAM,QAA4B;EAChC,MAAM,IAAI;EAIV,SAAS,IAAI;EACb;CACF;CAEA,MAAM,aAAa,aAChB,YAAyB;EACxB,IAAI,SAAS,CAAC,aAAa,SAAS,QAAQ,YAAY,UACtD,QAAQ,MACN,+BAA+B,QAAQ,QAAQ,YAAY,EAAE,yLAG/D;EAEF,WAAW,UAAU;EACrB,aAAa;GACX,IAAI,WAAW,YAAY,SAAS,WAAW,UAAU;EAC3D;CACF,GACA;EAAC;EAAW;EAAO;CAAU,CAC/B;CAGA,gBAAgB;EACd,IAAI,CAAC,OAAO;EACZ,IAAI,SAAS,eAAe,IAAI,MAAM,MAAM,MAC1C,QAAQ,MACN,8FACF;CAEJ,GAAG,CAAC,IAAI,MAAM,CAAC;CAIf,MAAM,eAAe,aAAa,CAAC;CACnC,MAAM,WAAW,UAAmC;EAClD,IAAI,WAAW;GAGb,MAAM,eAAe;GACrB,IAAI,UAAU;GACd,IAAI,YAAY,MAAM,aAAa,UAAU;GAC7C;EACF;EACA,IAAI,UAAU;EACd,MAAM,SAAS,UAAU;EACzB,IAAI,WAAW,QAAQ,CAAC,OAAO,QAAQ,OAAO,aAAa,OAAO,KAAK;CACzE;CAEA,MAAM,eAAiE;EAErE,GAAI,cAAc,MAAM,KAAK,EAAE,MAAM,SAAkB;EAGvD;EACA,YAAY,QAAQ,IAAI,SAAS,KAAA;EACjC,SAAS,QAAQ,eAAe,KAAA;EAGhC,GAAI,gBAAgB,EAAE,QAAQ;EAC9B,aAAa,SAAS,MAAM,IAAI;EAChC,gBAAgB,SAAS,MAAM,OAAO;EACtC,iBAAiB,SAAS,aAAa,QAAQ;CACjD;CAEA,OAAO,UAA+D;EACpE,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EACA,OAAO;EACP;EACA,KAAK;CACP,CAAC;AACH;AAEA,cAAc,cAAc"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import "../internal/platform-attributes.mjs";
|
|
2
|
+
import { DialogClose, DialogCloseDetails, DialogCloseProps, DialogCloseState } from "./dialog-close.mjs";
|
|
3
|
+
import { DialogPopup, DialogPopupProps, DialogPopupState } from "./dialog-popup.mjs";
|
|
4
|
+
import { DialogDescription, DialogDescriptionProps, DialogDescriptionState } from "./dialog-description.mjs";
|
|
5
|
+
import { DialogForm, DialogFormProps, DialogFormState } from "./dialog-form.mjs";
|
|
6
|
+
import { DialogOpenChangeDetails, DialogRoot, DialogRootProps, DialogRootState } from "./dialog-root.mjs";
|
|
7
|
+
import { DialogTitle, DialogTitleProps, DialogTitleState } from "./dialog-title.mjs";
|
|
8
|
+
import { DialogTrigger, DialogTriggerProps, DialogTriggerState } from "./dialog-trigger.mjs";
|
|
9
|
+
//#region src/dialog/index.d.ts
|
|
10
|
+
/**
|
|
11
|
+
* Dialog built on `<dialog>` and Invoker Commands: `Root` (no DOM) > `Trigger`
|
|
12
|
+
* (`button[command=show-modal]`) + `Popup` (`dialog`) > `Title`, `Description`, `Form`, `Close`.
|
|
13
|
+
* JS-free when the Root has none of `open` / `defaultOpen` / `openChangeAction`; otherwise
|
|
14
|
+
* opening is a transition (pending Trigger, content from committed state) and closing is the
|
|
15
|
+
* browser's, notified through `openChangeAction(false)`.
|
|
16
|
+
*/
|
|
17
|
+
export declare const Dialog: {
|
|
18
|
+
readonly Root: typeof DialogRoot;
|
|
19
|
+
readonly Trigger: typeof DialogTrigger;
|
|
20
|
+
readonly Popup: typeof DialogPopup;
|
|
21
|
+
readonly Close: typeof DialogClose;
|
|
22
|
+
readonly Form: typeof DialogForm;
|
|
23
|
+
readonly Title: typeof DialogTitle;
|
|
24
|
+
readonly Description: typeof DialogDescription;
|
|
25
|
+
};
|
|
26
|
+
//#endregion
|
|
27
|
+
export type { DialogCloseDetails, DialogCloseProps, DialogCloseState, DialogDescriptionProps, DialogDescriptionState, DialogFormProps, DialogFormState, DialogOpenChangeDetails, DialogPopupProps, DialogPopupState, DialogRootProps, DialogRootState, DialogTitleProps, DialogTitleState, DialogTriggerProps, DialogTriggerState };
|
|
28
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/dialog/index.ts"],"mappings":";;;;;;;;;;;;;;;;qBAkBa;WACX,aAAI;WACJ,gBAAO;WACP,cAAK;WACL,cAAK;WACL,aAAI;WACJ,cAAK;WACL,oBAAW"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { DialogClose } from "./dialog-close.mjs";
|
|
2
|
+
import { DialogDescription } from "./dialog-description.mjs";
|
|
3
|
+
import { DialogForm } from "./dialog-form.mjs";
|
|
4
|
+
import { DialogPopup } from "./dialog-popup.mjs";
|
|
5
|
+
import { DialogRoot } from "./dialog-root.mjs";
|
|
6
|
+
import { DialogTitle } from "./dialog-title.mjs";
|
|
7
|
+
import { DialogTrigger } from "./dialog-trigger.mjs";
|
|
8
|
+
//#region src/dialog/index.ts
|
|
9
|
+
/**
|
|
10
|
+
* Dialog built on `<dialog>` and Invoker Commands: `Root` (no DOM) > `Trigger`
|
|
11
|
+
* (`button[command=show-modal]`) + `Popup` (`dialog`) > `Title`, `Description`, `Form`, `Close`.
|
|
12
|
+
* JS-free when the Root has none of `open` / `defaultOpen` / `openChangeAction`; otherwise
|
|
13
|
+
* opening is a transition (pending Trigger, content from committed state) and closing is the
|
|
14
|
+
* browser's, notified through `openChangeAction(false)`.
|
|
15
|
+
*/
|
|
16
|
+
const Dialog = {
|
|
17
|
+
Root: DialogRoot,
|
|
18
|
+
Trigger: DialogTrigger,
|
|
19
|
+
Popup: DialogPopup,
|
|
20
|
+
Close: DialogClose,
|
|
21
|
+
Form: DialogForm,
|
|
22
|
+
Title: DialogTitle,
|
|
23
|
+
Description: DialogDescription
|
|
24
|
+
};
|
|
25
|
+
//#endregion
|
|
26
|
+
export { Dialog };
|
|
27
|
+
|
|
28
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/dialog/index.ts"],"sourcesContent":["// Ships the platform attribute typings (`command`, `commandfor`) with this subpath\n// (conventions 7.4). Type-only: the built JS has no import of it.\nimport \"../internal/platform-attributes.js\";\nimport { DialogClose } from \"./dialog-close.js\";\nimport { DialogDescription } from \"./dialog-description.js\";\nimport { DialogForm } from \"./dialog-form.js\";\nimport { DialogPopup } from \"./dialog-popup.js\";\nimport { DialogRoot } from \"./dialog-root.js\";\nimport { DialogTitle } from \"./dialog-title.js\";\nimport { DialogTrigger } from \"./dialog-trigger.js\";\n\n/**\n * Dialog built on `<dialog>` and Invoker Commands: `Root` (no DOM) > `Trigger`\n * (`button[command=show-modal]`) + `Popup` (`dialog`) > `Title`, `Description`, `Form`, `Close`.\n * JS-free when the Root has none of `open` / `defaultOpen` / `openChangeAction`; otherwise\n * opening is a transition (pending Trigger, content from committed state) and closing is the\n * browser's, notified through `openChangeAction(false)`.\n */\nexport const Dialog = {\n Root: DialogRoot,\n Trigger: DialogTrigger,\n Popup: DialogPopup,\n Close: DialogClose,\n Form: DialogForm,\n Title: DialogTitle,\n Description: DialogDescription,\n} as const;\n\nexport type { DialogRootProps, DialogRootState, DialogOpenChangeDetails } from \"./dialog-root.js\";\nexport type { DialogTriggerProps, DialogTriggerState } from \"./dialog-trigger.js\";\nexport type { DialogPopupProps, DialogPopupState } from \"./dialog-popup.js\";\nexport type { DialogCloseProps, DialogCloseState, DialogCloseDetails } from \"./dialog-close.js\";\nexport type { DialogFormProps, DialogFormState } from \"./dialog-form.js\";\nexport type { DialogTitleProps, DialogTitleState } from \"./dialog-title.js\";\nexport type { DialogDescriptionProps, DialogDescriptionState } from \"./dialog-description.js\";\n"],"mappings":";;;;;;;;;;;;;;;AAkBA,MAAa,SAAS;CACpB,MAAM;CACN,SAAS;CACT,OAAO;CACP,OAAO;CACP,MAAM;CACN,OAAO;CACP,aAAa;AACf"}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import "./internal/platform-attributes.mjs";
|
|
2
|
+
import { Action, ActionDetails, ChangeAction, ChangeReason, RenderProp, StateValue } from "./internal/types.mjs";
|
|
3
|
+
import { AccordionItemProps, AccordionItemState } from "./accordion/accordion-item.mjs";
|
|
4
|
+
import { AccordionPanelProps, AccordionPanelState } from "./accordion/accordion-panel.mjs";
|
|
5
|
+
import { AccordionRootExclusiveProps, AccordionRootMultipleProps, AccordionRootProps, AccordionRootState, AccordionValueChangeDetails } from "./accordion/accordion-root.mjs";
|
|
6
|
+
import { AccordionTriggerProps, AccordionTriggerState } from "./accordion/accordion-trigger.mjs";
|
|
7
|
+
import { Accordion } from "./accordion/index.mjs";
|
|
8
|
+
import { CheckboxGroupItemProps, CheckboxGroupItemState } from "./checkbox-group/checkbox-group-item.mjs";
|
|
9
|
+
import { CheckboxGroupRootProps, CheckboxGroupRootState, CheckboxGroupValueChangeDetails } from "./checkbox-group/checkbox-group-root.mjs";
|
|
10
|
+
import { CheckboxGroupLabelProps } from "./checkbox-group/checkbox-group-label.mjs";
|
|
11
|
+
import { CheckboxGroupParentProps, CheckboxGroupParentState } from "./checkbox-group/checkbox-group-parent.mjs";
|
|
12
|
+
import { CheckboxGroup } from "./checkbox-group/index.mjs";
|
|
13
|
+
import { Checkbox, CheckboxCheckedChangeDetails, CheckboxProps, CheckboxState } from "./checkbox/checkbox.mjs";
|
|
14
|
+
import "./checkbox/index.mjs";
|
|
15
|
+
import { DialogCloseDetails, DialogCloseProps, DialogCloseState } from "./dialog/dialog-close.mjs";
|
|
16
|
+
import { DialogPopupProps, DialogPopupState } from "./dialog/dialog-popup.mjs";
|
|
17
|
+
import { DialogDescriptionProps, DialogDescriptionState } from "./dialog/dialog-description.mjs";
|
|
18
|
+
import { DialogFormProps, DialogFormState } from "./dialog/dialog-form.mjs";
|
|
19
|
+
import { DialogOpenChangeDetails, DialogRootProps, DialogRootState } from "./dialog/dialog-root.mjs";
|
|
20
|
+
import { DialogTitleProps, DialogTitleState } from "./dialog/dialog-title.mjs";
|
|
21
|
+
import { DialogTriggerProps, DialogTriggerState } from "./dialog/dialog-trigger.mjs";
|
|
22
|
+
import { Dialog } from "./dialog/index.mjs";
|
|
23
|
+
import { Toggle, TogglePressedChangeDetails, ToggleProps, ToggleState } from "./toggle/toggle.mjs";
|
|
24
|
+
import "./toggle/index.mjs";
|
|
25
|
+
import { TabsActivationMode, TabsOrientation } from "./tabs/tabs-context.mjs";
|
|
26
|
+
import { TabsIndicatorProps, TabsIndicatorState } from "./tabs/tabs-indicator.mjs";
|
|
27
|
+
import { TabsListProps, TabsListState } from "./tabs/tabs-list.mjs";
|
|
28
|
+
import { TabsPanelProps, TabsPanelState } from "./tabs/tabs-panel.mjs";
|
|
29
|
+
import { TabsRootProps, TabsRootState, TabsValueChangeDetails } from "./tabs/tabs-root.mjs";
|
|
30
|
+
import { TabsTabProps, TabsTabState } from "./tabs/tabs-tab.mjs";
|
|
31
|
+
import { Tabs } from "./tabs/index.mjs";
|
|
32
|
+
import { TooltipAlign, TooltipPopupProps, TooltipPopupState, TooltipSide } from "./tooltip/tooltip-popup.mjs";
|
|
33
|
+
import { TooltipProvides } from "./tooltip/tooltip-context.mjs";
|
|
34
|
+
import { TooltipRootProps, TooltipRootState } from "./tooltip/tooltip-root.mjs";
|
|
35
|
+
import { TooltipTriggerProps, TooltipTriggerState } from "./tooltip/tooltip-trigger.mjs";
|
|
36
|
+
import { Tooltip } from "./tooltip/index.mjs";
|
|
37
|
+
import { Switch, SwitchCheckedChangeDetails, SwitchProps, SwitchState } from "./switch/switch.mjs";
|
|
38
|
+
import "./switch/index.mjs";
|
|
39
|
+
import { PopoverCloseProps, PopoverCloseState } from "./popover/popover-close.mjs";
|
|
40
|
+
import { PopoverAlign, PopoverPopupProps, PopoverPopupState, PopoverSide } from "./popover/popover-popup.mjs";
|
|
41
|
+
import { PopoverDescriptionProps, PopoverDescriptionState } from "./popover/popover-description.mjs";
|
|
42
|
+
import { PopoverOpenChangeDetails, PopoverRootProps, PopoverRootState } from "./popover/popover-root.mjs";
|
|
43
|
+
import { PopoverTitleProps, PopoverTitleState } from "./popover/popover-title.mjs";
|
|
44
|
+
import { PopoverTriggerProps, PopoverTriggerState } from "./popover/popover-trigger.mjs";
|
|
45
|
+
import { Popover } from "./popover/index.mjs";
|
|
46
|
+
import { MenuItemDetails, MenuItemProps, MenuItemState } from "./menu/menu-item.mjs";
|
|
47
|
+
import { MenuCheckboxItemProps, MenuCheckboxItemState } from "./menu/menu-checkbox-item.mjs";
|
|
48
|
+
import { MenuGroupLabelProps, MenuGroupLabelState, MenuGroupProps, MenuGroupState, MenuSeparatorProps, MenuSeparatorState } from "./menu/menu-group.mjs";
|
|
49
|
+
import { MenuAlign, MenuPopupProps, MenuPopupState, MenuSide } from "./menu/menu-popup.mjs";
|
|
50
|
+
import { MenuRadioGroupProps, MenuRadioGroupState } from "./menu/menu-radio-group.mjs";
|
|
51
|
+
import { MenuRadioItemProps, MenuRadioItemState } from "./menu/menu-radio-item.mjs";
|
|
52
|
+
import { MenuOpenChangeDetails, MenuRootProps, MenuRootState } from "./menu/menu-root.mjs";
|
|
53
|
+
import { MenuTriggerProps, MenuTriggerState } from "./menu/menu-trigger.mjs";
|
|
54
|
+
import { MenuSubmenuTriggerProps, MenuSubmenuTriggerState } from "./menu/menu-submenu-trigger.mjs";
|
|
55
|
+
import { Menu } from "./menu/index.mjs";
|
|
56
|
+
import { RadioGroupItemProps, RadioGroupItemState } from "./radio-group/radio-group-item.mjs";
|
|
57
|
+
import { RadioGroupRootProps, RadioGroupRootState, RadioGroupValueChangeDetails } from "./radio-group/radio-group-root.mjs";
|
|
58
|
+
import { RadioGroupLabelProps } from "./radio-group/radio-group-label.mjs";
|
|
59
|
+
import { RadioGroup } from "./radio-group/index.mjs";
|
|
60
|
+
export { Accordion, type AccordionItemProps, type AccordionItemState, type AccordionPanelProps, type AccordionPanelState, type AccordionRootExclusiveProps, type AccordionRootMultipleProps, type AccordionRootProps, type AccordionRootState, type AccordionTriggerProps, type AccordionTriggerState, type AccordionValueChangeDetails, type Action, type ActionDetails, type ChangeAction, type ChangeReason, Checkbox, type CheckboxCheckedChangeDetails, CheckboxGroup, type CheckboxGroupItemProps, type CheckboxGroupItemState, type CheckboxGroupLabelProps, type CheckboxGroupParentProps, type CheckboxGroupParentState, type CheckboxGroupRootProps, type CheckboxGroupRootState, type CheckboxGroupValueChangeDetails, type CheckboxProps, type CheckboxState, Dialog, type DialogCloseDetails, type DialogCloseProps, type DialogCloseState, type DialogDescriptionProps, type DialogDescriptionState, type DialogFormProps, type DialogFormState, type DialogOpenChangeDetails, type DialogPopupProps, type DialogPopupState, type DialogRootProps, type DialogRootState, type DialogTitleProps, type DialogTitleState, type DialogTriggerProps, type DialogTriggerState, Menu, type MenuAlign, type MenuCheckboxItemProps, type MenuCheckboxItemState, type MenuGroupLabelProps, type MenuGroupLabelState, type MenuGroupProps, type MenuGroupState, type MenuItemDetails, type MenuItemProps, type MenuItemState, type MenuOpenChangeDetails, type MenuPopupProps, type MenuPopupState, type MenuRadioGroupProps, type MenuRadioGroupState, type MenuRadioItemProps, type MenuRadioItemState, type MenuRootProps, type MenuRootState, type MenuSeparatorProps, type MenuSeparatorState, type MenuSide, type MenuSubmenuTriggerProps, type MenuSubmenuTriggerState, type MenuTriggerProps, type MenuTriggerState, Popover, type PopoverAlign, type PopoverCloseProps, type PopoverCloseState, type PopoverDescriptionProps, type PopoverDescriptionState, type PopoverOpenChangeDetails, type PopoverPopupProps, type PopoverPopupState, type PopoverRootProps, type PopoverRootState, type PopoverSide, type PopoverTitleProps, type PopoverTitleState, type PopoverTriggerProps, type PopoverTriggerState, RadioGroup, type RadioGroupItemProps, type RadioGroupItemState, type RadioGroupLabelProps, type RadioGroupRootProps, type RadioGroupRootState, type RadioGroupValueChangeDetails, type RenderProp, type StateValue, Switch, type SwitchCheckedChangeDetails, type SwitchProps, type SwitchState, Tabs, type TabsActivationMode, type TabsIndicatorProps, type TabsIndicatorState, type TabsListProps, type TabsListState, type TabsOrientation, type TabsPanelProps, type TabsPanelState, type TabsRootProps, type TabsRootState, type TabsTabProps, type TabsTabState, type TabsValueChangeDetails, Toggle, type TogglePressedChangeDetails, type ToggleProps, type ToggleState, Tooltip, type TooltipAlign, type TooltipPopupProps, type TooltipPopupState, type TooltipProvides, type TooltipRootProps, type TooltipRootState, type TooltipSide, type TooltipTriggerProps, type TooltipTriggerState };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Toggle } from "./toggle/toggle.mjs";
|
|
2
|
+
import { Accordion } from "./accordion/index.mjs";
|
|
3
|
+
import { Tabs } from "./tabs/index.mjs";
|
|
4
|
+
import { Tooltip } from "./tooltip/index.mjs";
|
|
5
|
+
import { Switch } from "./switch/switch.mjs";
|
|
6
|
+
import { Checkbox } from "./checkbox/checkbox.mjs";
|
|
7
|
+
import { Dialog } from "./dialog/index.mjs";
|
|
8
|
+
import { Popover } from "./popover/index.mjs";
|
|
9
|
+
import { Menu } from "./menu/index.mjs";
|
|
10
|
+
import { RadioGroup } from "./radio-group/index.mjs";
|
|
11
|
+
import { CheckboxGroup } from "./checkbox-group/index.mjs";
|
|
12
|
+
export { Accordion, Checkbox, CheckboxGroup, Dialog, Menu, Popover, RadioGroup, Switch, Tabs, Toggle, Tooltip };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
//#region src/internal/action-details.ts
|
|
2
|
+
function isDev() {
|
|
3
|
+
return process.env.NODE_ENV !== "production";
|
|
4
|
+
}
|
|
5
|
+
function rejectEventWrite() {
|
|
6
|
+
throw new TypeError("`details.event` is a read-only virtual property; it cannot be assigned or defined. Keep the DOM event out of `details` so that it stays serialisable.");
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Builds the `details` argument of an action (conventions 2.2).
|
|
10
|
+
*
|
|
11
|
+
* `fields` is a plain, extensible object of serialisable component-specific fields. `event` is a
|
|
12
|
+
* virtual, non-own property served by a Proxy: `details.event` and `"event" in details` work,
|
|
13
|
+
* while `Object.keys`, spread, `JSON.stringify` and React's Server Function serialiser see only
|
|
14
|
+
* the real fields. That is what lets a Server Function be passed directly as an action.
|
|
15
|
+
*
|
|
16
|
+
* Writing `event` (`details.event = x`, `Object.defineProperty(details, "event", ...)`) is
|
|
17
|
+
* rejected so that an own, enumerable `event` can never appear: in development it throws a
|
|
18
|
+
* `TypeError`; in production an assignment is ignored and a `defineProperty` is declined (which
|
|
19
|
+
* makes `Object.defineProperty` throw and `Reflect.defineProperty` return `false`).
|
|
20
|
+
*
|
|
21
|
+
* No `"use client"` directive: this file uses no client-only API, so it is importable from
|
|
22
|
+
* anywhere (conventions 7.1).
|
|
23
|
+
*/
|
|
24
|
+
function createActionDetails(event, fields) {
|
|
25
|
+
return new Proxy(fields, {
|
|
26
|
+
get: (target, key, receiver) => key === "event" ? event : Reflect.get(target, key, receiver),
|
|
27
|
+
has: (target, key) => key === "event" || Reflect.has(target, key),
|
|
28
|
+
set: (target, key, value, receiver) => {
|
|
29
|
+
if (key === "event") {
|
|
30
|
+
if (isDev()) rejectEventWrite();
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
return Reflect.set(target, key, value, receiver);
|
|
34
|
+
},
|
|
35
|
+
defineProperty: (target, key, descriptor) => {
|
|
36
|
+
if (key === "event") {
|
|
37
|
+
if (isDev()) rejectEventWrite();
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
return Reflect.defineProperty(target, key, descriptor);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
export { createActionDetails };
|
|
46
|
+
|
|
47
|
+
//# sourceMappingURL=action-details.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-details.mjs","names":[],"sources":["../../src/internal/action-details.ts"],"sourcesContent":["import type { ActionDetails } from \"./types.js\";\n\nfunction isDev(): boolean {\n return process.env.NODE_ENV !== \"production\";\n}\n\nfunction rejectEventWrite(): never {\n throw new TypeError(\n \"`details.event` is a read-only virtual property; it cannot be assigned or defined. \" +\n \"Keep the DOM event out of `details` so that it stays serialisable.\",\n );\n}\n\n/**\n * Builds the `details` argument of an action (conventions 2.2).\n *\n * `fields` is a plain, extensible object of serialisable component-specific fields. `event` is a\n * virtual, non-own property served by a Proxy: `details.event` and `\"event\" in details` work,\n * while `Object.keys`, spread, `JSON.stringify` and React's Server Function serialiser see only\n * the real fields. That is what lets a Server Function be passed directly as an action.\n *\n * Writing `event` (`details.event = x`, `Object.defineProperty(details, \"event\", ...)`) is\n * rejected so that an own, enumerable `event` can never appear: in development it throws a\n * `TypeError`; in production an assignment is ignored and a `defineProperty` is declined (which\n * makes `Object.defineProperty` throw and `Reflect.defineProperty` return `false`).\n *\n * No `\"use client\"` directive: this file uses no client-only API, so it is importable from\n * anywhere (conventions 7.1).\n */\nexport function createActionDetails<T extends object>(\n event: Event | undefined,\n fields: T,\n): T & ActionDetails {\n return new Proxy(fields, {\n get: (target, key, receiver) => (key === \"event\" ? event : Reflect.get(target, key, receiver)),\n has: (target, key) => key === \"event\" || Reflect.has(target, key),\n set: (target, key, value, receiver) => {\n if (key === \"event\") {\n if (isDev()) rejectEventWrite();\n return true;\n }\n return Reflect.set(target, key, value, receiver);\n },\n defineProperty: (target, key, descriptor) => {\n if (key === \"event\") {\n if (isDev()) rejectEventWrite();\n return false;\n }\n return Reflect.defineProperty(target, key, descriptor);\n },\n }) as T & ActionDetails;\n}\n"],"mappings":";AAEA,SAAS,QAAiB;CACxB,OAAO,QAAQ,IAAI,aAAa;AAClC;AAEA,SAAS,mBAA0B;CACjC,MAAM,IAAI,UACR,uJAEF;AACF;;;;;;;;;;;;;;;;;AAkBA,SAAgB,oBACd,OACA,QACmB;CACnB,OAAO,IAAI,MAAM,QAAQ;EACvB,MAAM,QAAQ,KAAK,aAAc,QAAQ,UAAU,QAAQ,QAAQ,IAAI,QAAQ,KAAK,QAAQ;EAC5F,MAAM,QAAQ,QAAQ,QAAQ,WAAW,QAAQ,IAAI,QAAQ,GAAG;EAChE,MAAM,QAAQ,KAAK,OAAO,aAAa;GACrC,IAAI,QAAQ,SAAS;IACnB,IAAI,MAAM,GAAG,iBAAiB;IAC9B,OAAO;GACT;GACA,OAAO,QAAQ,IAAI,QAAQ,KAAK,OAAO,QAAQ;EACjD;EACA,iBAAiB,QAAQ,KAAK,eAAe;GAC3C,IAAI,QAAQ,SAAS;IACnB,IAAI,MAAM,GAAG,iBAAiB;IAC9B,OAAO;GACT;GACA,OAAO,QAAQ,eAAe,QAAQ,KAAK,UAAU;EACvD;CACF,CAAC;AACH"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
//#region src/internal/anchor-position.d.ts
|
|
2
|
+
/** Physical side of the anchor the popup is placed on. */
|
|
3
|
+
export type AnchorSide = "top" | "bottom" | "left" | "right";
|
|
4
|
+
/** Alignment along that side. */
|
|
5
|
+
export type AnchorAlign = "start" | "center" | "end";
|
|
6
|
+
//#endregion
|
|
7
|
+
//# sourceMappingURL=anchor-position.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anchor-position.d.mts","names":[],"sources":["../../src/internal/anchor-position.ts"],"mappings":";;YAQY;;YAEA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/internal/anchor-position.ts
|
|
2
|
+
/** Flip to the opposite side, then the other axis, then both, when the popup does not fit. */
|
|
3
|
+
const POSITION_TRY_FALLBACKS = "flip-block, flip-inline, flip-block flip-inline";
|
|
4
|
+
/**
|
|
5
|
+
* The `position-area` for a side and an alignment (physical keywords): `bottom` + `center` is
|
|
6
|
+
* `bottom`, `bottom` + `start` is `bottom span-right`, `right` + `start` is `right span-bottom`,
|
|
7
|
+
* and so on.
|
|
8
|
+
*/
|
|
9
|
+
function positionArea(side, align) {
|
|
10
|
+
if (align === "center") return side;
|
|
11
|
+
return `${side} ${side === "top" || side === "bottom" ? align === "start" ? "span-right" : "span-left" : align === "start" ? "span-bottom" : "span-top"}`;
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { POSITION_TRY_FALLBACKS, positionArea };
|
|
15
|
+
|
|
16
|
+
//# sourceMappingURL=anchor-position.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anchor-position.mjs","names":[],"sources":["../../src/internal/anchor-position.ts"],"sourcesContent":["// Placement of a popover against its implicit anchor (the invoker set by `commandfor`,\n// `interestfor` or `showPopover({ source })`): inline `position-area` from a side and an\n// alignment, plus `position-try-fallbacks` that flip it when it does not fit. Shared by Tooltip,\n// Popover and Menu (design/components/tooltip.md 7.1, popover.md 8).\n//\n// No \"use client\" directive: pure functions, importable from anywhere (conventions 7.1).\n\n/** Physical side of the anchor the popup is placed on. */\nexport type AnchorSide = \"top\" | \"bottom\" | \"left\" | \"right\";\n/** Alignment along that side. */\nexport type AnchorAlign = \"start\" | \"center\" | \"end\";\n\n/** Flip to the opposite side, then the other axis, then both, when the popup does not fit. */\nexport const POSITION_TRY_FALLBACKS = \"flip-block, flip-inline, flip-block flip-inline\";\n\n/**\n * The `position-area` for a side and an alignment (physical keywords): `bottom` + `center` is\n * `bottom`, `bottom` + `start` is `bottom span-right`, `right` + `start` is `right span-bottom`,\n * and so on.\n */\nexport function positionArea(side: AnchorSide, align: AnchorAlign): string {\n if (align === \"center\") return side;\n const vertical = side === \"top\" || side === \"bottom\";\n const span = vertical\n ? align === \"start\"\n ? \"span-right\"\n : \"span-left\"\n : align === \"start\"\n ? \"span-bottom\"\n : \"span-top\";\n return `${side} ${span}`;\n}\n"],"mappings":";;AAaA,MAAa,yBAAyB;;;;;;AAOtC,SAAgB,aAAa,MAAkB,OAA4B;CACzE,IAAI,UAAU,UAAU,OAAO;CAS/B,OAAO,GAAG,KAAK,GARE,SAAS,SAAS,SAAS,WAExC,UAAU,UACR,eACA,cACF,UAAU,UACR,gBACA;AAER"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/internal/data-attr.ts
|
|
2
|
+
/**
|
|
3
|
+
* Boolean data attributes are emitted by presence: `data-x=""` when true, absent when false.
|
|
4
|
+
* react-dom would stringify `true` as `"true"`, so this helper is the only place the presence
|
|
5
|
+
* form is spelled out (conventions 4.1).
|
|
6
|
+
*/
|
|
7
|
+
function dataAttr(flag) {
|
|
8
|
+
return flag ? "" : void 0;
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { dataAttr };
|
|
12
|
+
|
|
13
|
+
//# sourceMappingURL=data-attr.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-attr.mjs","names":[],"sources":["../../src/internal/data-attr.ts"],"sourcesContent":["/**\n * Boolean data attributes are emitted by presence: `data-x=\"\"` when true, absent when false.\n * react-dom would stringify `true` as `\"true\"`, so this helper is the only place the presence\n * form is spelled out (conventions 4.1).\n */\nexport function dataAttr(flag: boolean): \"\" | undefined {\n return flag ? \"\" : undefined;\n}\n"],"mappings":";;;;;;AAKA,SAAgB,SAAS,MAA+B;CACtD,OAAO,OAAO,KAAK,KAAA;AACrB"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
//#region src/internal/merge-props.ts
|
|
2
|
+
/**
|
|
3
|
+
* ARIA id-reference lists are merged as token lists rather than overridden (conventions 1.2), so
|
|
4
|
+
* a trigger can be described by more than the element the library wires it to.
|
|
5
|
+
*/
|
|
6
|
+
const ID_REFERENCE_LISTS = /* @__PURE__ */ new Set([
|
|
7
|
+
"aria-labelledby",
|
|
8
|
+
"aria-describedby",
|
|
9
|
+
"aria-controls",
|
|
10
|
+
"aria-owns"
|
|
11
|
+
]);
|
|
12
|
+
function isIdReferenceList(key) {
|
|
13
|
+
return ID_REFERENCE_LISTS.has(key);
|
|
14
|
+
}
|
|
15
|
+
function isEventHandler(key, value) {
|
|
16
|
+
return typeof value === "function" && /^on[A-Z]/.test(key);
|
|
17
|
+
}
|
|
18
|
+
function isObjectRef(ref) {
|
|
19
|
+
return typeof ref === "object" && ref !== null && "current" in ref;
|
|
20
|
+
}
|
|
21
|
+
function attachRef(ref, node) {
|
|
22
|
+
if (ref === null || ref === void 0) return void 0;
|
|
23
|
+
if (typeof ref === "function") {
|
|
24
|
+
const cleanup = ref(node);
|
|
25
|
+
return typeof cleanup === "function" ? cleanup : () => ref(null);
|
|
26
|
+
}
|
|
27
|
+
if (isObjectRef(ref)) {
|
|
28
|
+
ref.current = node;
|
|
29
|
+
return () => {
|
|
30
|
+
ref.current = null;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Merges several refs into one callback ref. The callback returns a cleanup function (React 19),
|
|
36
|
+
* so each inner ref is detached through its own cleanup (callback refs that returned one) or by
|
|
37
|
+
* being set to `null`.
|
|
38
|
+
*/
|
|
39
|
+
function mergeRefs(...refs) {
|
|
40
|
+
return (node) => {
|
|
41
|
+
const cleanups = refs.map((ref) => attachRef(ref, node));
|
|
42
|
+
return () => {
|
|
43
|
+
for (const cleanup of cleanups) cleanup?.();
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** Joins two space-separated id lists, `first` tokens first, without duplicates. */
|
|
48
|
+
function mergeTokenLists(first, second) {
|
|
49
|
+
const tokens = [];
|
|
50
|
+
for (const list of [first, second]) {
|
|
51
|
+
if (typeof list !== "string") continue;
|
|
52
|
+
for (const token of list.split(/\s+/)) if (token !== "" && !tokens.includes(token)) tokens.push(token);
|
|
53
|
+
}
|
|
54
|
+
return tokens.join(" ");
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Layers `over` onto `under`, with the rules shared by every layer of the merge:
|
|
58
|
+
*
|
|
59
|
+
* - `className`: concatenated (`under` first).
|
|
60
|
+
* - `style`: merged, `over` wins per property.
|
|
61
|
+
* - `ref`: both attached.
|
|
62
|
+
* - Event handlers: both run; `overFirst` says whether `over`'s runs before `under`'s.
|
|
63
|
+
* - ARIA id-reference lists: token-merged; `overFirst` says whose tokens come first.
|
|
64
|
+
* - Everything else: `over` wins when it defines the prop. `undefined` is "not given" (JSX
|
|
65
|
+
* optional props are routinely `undefined`), except in an `owned` layer, where a key present
|
|
66
|
+
* with an `undefined` value removes the prop: the library-controlled layer owns its keys.
|
|
67
|
+
*/
|
|
68
|
+
function layer(under, over, overFirst, owned) {
|
|
69
|
+
const result = { ...under };
|
|
70
|
+
for (const key of Object.keys(over)) {
|
|
71
|
+
const overValue = over[key];
|
|
72
|
+
const underValue = under[key];
|
|
73
|
+
if (overValue === void 0) {
|
|
74
|
+
if (owned) result[key] = void 0;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (key === "className") result[key] = typeof underValue === "string" && underValue !== "" ? `${underValue} ${String(overValue)}` : overValue;
|
|
78
|
+
else if (key === "style") result[key] = {
|
|
79
|
+
...underValue,
|
|
80
|
+
...overValue
|
|
81
|
+
};
|
|
82
|
+
else if (key === "ref") result[key] = underValue === void 0 || underValue === null ? overValue : mergeRefs(underValue, overValue);
|
|
83
|
+
else if (isEventHandler(key, overValue) && isEventHandler(key, underValue)) {
|
|
84
|
+
const [first, second] = overFirst ? [overValue, underValue] : [underValue, overValue];
|
|
85
|
+
result[key] = (...args) => {
|
|
86
|
+
first(...args);
|
|
87
|
+
second(...args);
|
|
88
|
+
};
|
|
89
|
+
} else if (isIdReferenceList(key) && typeof underValue === "string") result[key] = overFirst ? mergeTokenLists(overValue, underValue) : mergeTokenLists(underValue, overValue);
|
|
90
|
+
else result[key] = overValue;
|
|
91
|
+
}
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Merges the props for a part's element in the order of conventions 1.2: the part's pass-through
|
|
96
|
+
* props, then the `render` element's props, then the library-controlled attributes on top.
|
|
97
|
+
*
|
|
98
|
+
* - The `render` element wins over pass-through props (`aria-label`, `data-*` from the part's own
|
|
99
|
+
* props, `type`, ...); the library-controlled attributes (`role`, computed `aria-*` state, id
|
|
100
|
+
* wiring, `data-*` state, the library's handlers) win over the element.
|
|
101
|
+
* - Library-controlled keys are **owned**: a key present in `libraryProps` with an `undefined`
|
|
102
|
+
* value removes the attribute, whatever the element or the pass-through props say, so a
|
|
103
|
+
* `render` element can never re-introduce `data-open`, `aria-disabled`, `name`, ... when the
|
|
104
|
+
* part computes none. A part that does not own a key in some mode omits the key instead. The
|
|
105
|
+
* function form of `render` is the way to override library attributes deliberately.
|
|
106
|
+
* - `className` is concatenated (part, element), `style` merged with the element winning.
|
|
107
|
+
* - Event handlers all run: the element's first, then the part's pass-through one, then the
|
|
108
|
+
* library's.
|
|
109
|
+
* - `aria-labelledby` / `aria-describedby` / `aria-controls` / `aria-owns` are merged as token
|
|
110
|
+
* lists, the element's tokens first.
|
|
111
|
+
* - `ref`s are all attached.
|
|
112
|
+
*/
|
|
113
|
+
function mergeProps(partProps, elementProps, libraryProps = {}) {
|
|
114
|
+
return layer(layer(partProps, elementProps, true, false), libraryProps, false, true);
|
|
115
|
+
}
|
|
116
|
+
//#endregion
|
|
117
|
+
export { mergeProps, mergeRefs, mergeTokenLists };
|
|
118
|
+
|
|
119
|
+
//# sourceMappingURL=merge-props.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-props.mjs","names":[],"sources":["../../src/internal/merge-props.ts"],"sourcesContent":["import type { CSSProperties, Ref, RefCallback } from \"react\";\n\ntype AnyProps = Record<string, unknown>;\n\n/**\n * ARIA id-reference lists are merged as token lists rather than overridden (conventions 1.2), so\n * a trigger can be described by more than the element the library wires it to.\n */\nconst ID_REFERENCE_LISTS = new Set([\n \"aria-labelledby\",\n \"aria-describedby\",\n \"aria-controls\",\n \"aria-owns\",\n]);\n\nfunction isIdReferenceList(key: string): boolean {\n return ID_REFERENCE_LISTS.has(key);\n}\n\nfunction isEventHandler(key: string, value: unknown): value is (...args: unknown[]) => void {\n return typeof value === \"function\" && /^on[A-Z]/.test(key);\n}\n\nfunction isObjectRef<T>(ref: unknown): ref is { current: T | null } {\n return typeof ref === \"object\" && ref !== null && \"current\" in ref;\n}\n\nfunction attachRef<T>(ref: Ref<T> | undefined, node: T): (() => void) | undefined {\n if (ref === null || ref === undefined) return undefined;\n if (typeof ref === \"function\") {\n const cleanup = ref(node);\n return typeof cleanup === \"function\" ? cleanup : () => ref(null);\n }\n if (isObjectRef<T>(ref)) {\n ref.current = node;\n return () => {\n ref.current = null;\n };\n }\n return undefined;\n}\n\n/**\n * Merges several refs into one callback ref. The callback returns a cleanup function (React 19),\n * so each inner ref is detached through its own cleanup (callback refs that returned one) or by\n * being set to `null`.\n */\nexport function mergeRefs<T>(...refs: readonly (Ref<T> | undefined)[]): RefCallback<T> {\n return (node: T) => {\n const cleanups = refs.map((ref) => attachRef(ref, node));\n return () => {\n for (const cleanup of cleanups) cleanup?.();\n };\n };\n}\n\n/** Joins two space-separated id lists, `first` tokens first, without duplicates. */\nexport function mergeTokenLists(first: unknown, second: unknown): string {\n const tokens: string[] = [];\n for (const list of [first, second]) {\n if (typeof list !== \"string\") continue;\n for (const token of list.split(/\\s+/)) {\n if (token !== \"\" && !tokens.includes(token)) tokens.push(token);\n }\n }\n return tokens.join(\" \");\n}\n\n/**\n * Layers `over` onto `under`, with the rules shared by every layer of the merge:\n *\n * - `className`: concatenated (`under` first).\n * - `style`: merged, `over` wins per property.\n * - `ref`: both attached.\n * - Event handlers: both run; `overFirst` says whether `over`'s runs before `under`'s.\n * - ARIA id-reference lists: token-merged; `overFirst` says whose tokens come first.\n * - Everything else: `over` wins when it defines the prop. `undefined` is \"not given\" (JSX\n * optional props are routinely `undefined`), except in an `owned` layer, where a key present\n * with an `undefined` value removes the prop: the library-controlled layer owns its keys.\n */\nfunction layer(under: AnyProps, over: AnyProps, overFirst: boolean, owned: boolean): AnyProps {\n const result: AnyProps = { ...under };\n\n for (const key of Object.keys(over)) {\n const overValue = over[key];\n const underValue = under[key];\n\n if (overValue === undefined) {\n // An explicit `undefined` (not a deletion): `cloneElement` layers the merged props over the\n // render element's original props, so only an own `undefined` removes the attribute there.\n if (owned) result[key] = undefined;\n continue;\n }\n\n if (key === \"className\") {\n result[key] =\n typeof underValue === \"string\" && underValue !== \"\"\n ? `${underValue} ${String(overValue)}`\n : overValue;\n } else if (key === \"style\") {\n result[key] = {\n ...(underValue as CSSProperties | undefined),\n ...(overValue as CSSProperties),\n };\n } else if (key === \"ref\") {\n result[key] =\n underValue === undefined || underValue === null\n ? overValue\n : mergeRefs(underValue as Ref<unknown>, overValue as Ref<unknown>);\n } else if (isEventHandler(key, overValue) && isEventHandler(key, underValue)) {\n const [first, second] = overFirst ? [overValue, underValue] : [underValue, overValue];\n result[key] = (...args: unknown[]) => {\n first(...args);\n second(...args);\n };\n } else if (isIdReferenceList(key) && typeof underValue === \"string\") {\n result[key] = overFirst\n ? mergeTokenLists(overValue, underValue)\n : mergeTokenLists(underValue, overValue);\n } else {\n result[key] = overValue;\n }\n }\n\n return result;\n}\n\n/**\n * Merges the props for a part's element in the order of conventions 1.2: the part's pass-through\n * props, then the `render` element's props, then the library-controlled attributes on top.\n *\n * - The `render` element wins over pass-through props (`aria-label`, `data-*` from the part's own\n * props, `type`, ...); the library-controlled attributes (`role`, computed `aria-*` state, id\n * wiring, `data-*` state, the library's handlers) win over the element.\n * - Library-controlled keys are **owned**: a key present in `libraryProps` with an `undefined`\n * value removes the attribute, whatever the element or the pass-through props say, so a\n * `render` element can never re-introduce `data-open`, `aria-disabled`, `name`, ... when the\n * part computes none. A part that does not own a key in some mode omits the key instead. The\n * function form of `render` is the way to override library attributes deliberately.\n * - `className` is concatenated (part, element), `style` merged with the element winning.\n * - Event handlers all run: the element's first, then the part's pass-through one, then the\n * library's.\n * - `aria-labelledby` / `aria-describedby` / `aria-controls` / `aria-owns` are merged as token\n * lists, the element's tokens first.\n * - `ref`s are all attached.\n */\nexport function mergeProps<P extends AnyProps>(\n partProps: P,\n elementProps: AnyProps,\n libraryProps: AnyProps = {},\n): P {\n // The render element's handlers and tokens come first in both layers.\n return layer(layer(partProps, elementProps, true, false), libraryProps, false, true) as P;\n}\n"],"mappings":";;;;;AAQA,MAAM,qCAAqB,IAAI,IAAI;CACjC;CACA;CACA;CACA;AACF,CAAC;AAED,SAAS,kBAAkB,KAAsB;CAC/C,OAAO,mBAAmB,IAAI,GAAG;AACnC;AAEA,SAAS,eAAe,KAAa,OAAuD;CAC1F,OAAO,OAAO,UAAU,cAAc,WAAW,KAAK,GAAG;AAC3D;AAEA,SAAS,YAAe,KAA4C;CAClE,OAAO,OAAO,QAAQ,YAAY,QAAQ,QAAQ,aAAa;AACjE;AAEA,SAAS,UAAa,KAAyB,MAAmC;CAChF,IAAI,QAAQ,QAAQ,QAAQ,KAAA,GAAW,OAAO,KAAA;CAC9C,IAAI,OAAO,QAAQ,YAAY;EAC7B,MAAM,UAAU,IAAI,IAAI;EACxB,OAAO,OAAO,YAAY,aAAa,gBAAgB,IAAI,IAAI;CACjE;CACA,IAAI,YAAe,GAAG,GAAG;EACvB,IAAI,UAAU;EACd,aAAa;GACX,IAAI,UAAU;EAChB;CACF;AAEF;;;;;;AAOA,SAAgB,UAAa,GAAG,MAAuD;CACrF,QAAQ,SAAY;EAClB,MAAM,WAAW,KAAK,KAAK,QAAQ,UAAU,KAAK,IAAI,CAAC;EACvD,aAAa;GACX,KAAK,MAAM,WAAW,UAAU,UAAU;EAC5C;CACF;AACF;;AAGA,SAAgB,gBAAgB,OAAgB,QAAyB;CACvE,MAAM,SAAmB,CAAC;CAC1B,KAAK,MAAM,QAAQ,CAAC,OAAO,MAAM,GAAG;EAClC,IAAI,OAAO,SAAS,UAAU;EAC9B,KAAK,MAAM,SAAS,KAAK,MAAM,KAAK,GAClC,IAAI,UAAU,MAAM,CAAC,OAAO,SAAS,KAAK,GAAG,OAAO,KAAK,KAAK;CAElE;CACA,OAAO,OAAO,KAAK,GAAG;AACxB;;;;;;;;;;;;;AAcA,SAAS,MAAM,OAAiB,MAAgB,WAAoB,OAA0B;CAC5F,MAAM,SAAmB,EAAE,GAAG,MAAM;CAEpC,KAAK,MAAM,OAAO,OAAO,KAAK,IAAI,GAAG;EACnC,MAAM,YAAY,KAAK;EACvB,MAAM,aAAa,MAAM;EAEzB,IAAI,cAAc,KAAA,GAAW;GAG3B,IAAI,OAAO,OAAO,OAAO,KAAA;GACzB;EACF;EAEA,IAAI,QAAQ,aACV,OAAO,OACL,OAAO,eAAe,YAAY,eAAe,KAC7C,GAAG,WAAW,GAAG,OAAO,SAAS,MACjC;OACD,IAAI,QAAQ,SACjB,OAAO,OAAO;GACZ,GAAI;GACJ,GAAI;EACN;OACK,IAAI,QAAQ,OACjB,OAAO,OACL,eAAe,KAAA,KAAa,eAAe,OACvC,YACA,UAAU,YAA4B,SAAyB;OAChE,IAAI,eAAe,KAAK,SAAS,KAAK,eAAe,KAAK,UAAU,GAAG;GAC5E,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,WAAW,UAAU,IAAI,CAAC,YAAY,SAAS;GACpF,OAAO,QAAQ,GAAG,SAAoB;IACpC,MAAM,GAAG,IAAI;IACb,OAAO,GAAG,IAAI;GAChB;EACF,OAAO,IAAI,kBAAkB,GAAG,KAAK,OAAO,eAAe,UACzD,OAAO,OAAO,YACV,gBAAgB,WAAW,UAAU,IACrC,gBAAgB,YAAY,SAAS;OAEzC,OAAO,OAAO;CAElB;CAEA,OAAO;AACT;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,WACd,WACA,cACA,eAAyB,CAAC,GACvB;CAEH,OAAO,MAAM,MAAM,WAAW,cAAc,MAAM,KAAK,GAAG,cAAc,OAAO,IAAI;AACrF"}
|