@stratakit/structures 0.4.0 → 0.4.2

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.
@@ -0,0 +1,153 @@
1
+ import * as React from "react";
2
+ import * as AkDialog from "@ariakit/react/dialog";
3
+ import type { BaseProps, FocusableProps } from "@stratakit/foundations/secret-internals";
4
+ interface DialogRootProps extends BaseProps, Pick<AkDialog.DialogProps, "open" | "onClose" | "backdrop" | "unmountOnHide" | "hideOnInteractOutside"> {
5
+ /**
6
+ * When set to `true`, the content element will be unmounted and removed from
7
+ * the DOM when it's hidden.
8
+ *
9
+ * @default true
10
+ */
11
+ unmountOnHide?: boolean;
12
+ /**
13
+ * Determines whether the dialog is modal.
14
+ * Currently, only modal dialogs are supported.
15
+ */
16
+ modal: true;
17
+ }
18
+ /**
19
+ * A modal dialog component used to display content in a window overlay. Must include `Dialog.Header` and `Dialog.Content` as direct
20
+ * descendants. Additionally, `Dialog.Footer` can be optionally used as a direct descendant.
21
+ *
22
+ * Example:
23
+ * ```tsx
24
+ * const [open, setOpen] = useState(false);
25
+ *
26
+ * <Dialog.Root modal={true} open={open} onClose={() => setOpen(false)}>
27
+ * <Dialog.Heading>Heading</Dialog.Heading>
28
+ * <Dialog.Content>Content</Dialog.Content>
29
+ * <Dialog.Footer>
30
+ * <Dialog.ActionList
31
+ * actions={[
32
+ * <Button key="ok" onClick={() => setOpen(false)}>Ok</Button>,
33
+ * ]}
34
+ * />
35
+ *
36
+ * </Dialog.Footer>
37
+ * </Dialog.Root>
38
+ * ```
39
+ */
40
+ declare const DialogRoot: React.ForwardRefExoticComponent<DialogRootProps & React.RefAttributes<HTMLDivElement | HTMLElement>>;
41
+ interface DialogHeaderProps extends BaseProps {
42
+ }
43
+ /**
44
+ * The header of a dialog. Should be used as a child of `Dialog.Root`. Must include `Dialog.Heading` as a direct
45
+ * descendant. Additionally, `Dialog.CloseButton` can be optionally used as a direct descendant.
46
+ *
47
+ * Example:
48
+ * ```tsx
49
+ * <Dialog.Header>
50
+ * <Dialog.Heading>Heading</Dialog.Heading>
51
+ * <Dialog.CloseButton />
52
+ * </Dialog.Header>
53
+ * ```
54
+ *
55
+ * Use `render` prop when only a heading is displayed in a header.
56
+ *
57
+ * ```tsx
58
+ * <Dialog.Header render={<Dialog.Heading />}>Heading</Dialog.Header>
59
+ * ```
60
+ *
61
+ */
62
+ declare const DialogHeader: React.ForwardRefExoticComponent<DialogHeaderProps & React.RefAttributes<HTMLDivElement | HTMLElement>>;
63
+ interface DialogHeadingProps extends BaseProps<"h1"> {
64
+ }
65
+ /**
66
+ * The heading of a dialog. Should be used as a child of `Dialog.DialogHeader`.
67
+ *
68
+ * Example:
69
+ * ```tsx
70
+ * <Dialog.Heading>Heading</Dialog.Heading>
71
+ * ```
72
+ */
73
+ declare const DialogHeading: React.ForwardRefExoticComponent<DialogHeadingProps & React.RefAttributes<HTMLElement | HTMLHeadingElement>>;
74
+ interface DialogCloseButtonProps extends Omit<FocusableProps<"button">, "children"> {
75
+ /**
76
+ * Label for the close button.
77
+ *
78
+ * @default "Dismiss"
79
+ */
80
+ label?: string;
81
+ }
82
+ /**
83
+ * A button that closes the dialog. Displayed as an icon button in the top-right corner of the dialog.
84
+ * Should be used as a child of `Dialog.DialogHeader`.
85
+ *
86
+ * Example:
87
+ * ```tsx
88
+ * <Dialog.CloseButton />
89
+ * ```
90
+ */
91
+ declare const DialogCloseButton: React.ForwardRefExoticComponent<DialogCloseButtonProps & React.RefAttributes<HTMLElement | HTMLButtonElement>>;
92
+ interface DialogContentProps extends BaseProps {
93
+ }
94
+ /**
95
+ * The content of a dialog. Should be used as a child of `Dialog.Root`.
96
+ *
97
+ * Example:
98
+ * ```tsx
99
+ * <Dialog.Content>Content</Dialog.Content>
100
+ * ```
101
+ */
102
+ declare const DialogContent: React.ForwardRefExoticComponent<DialogContentProps & React.RefAttributes<HTMLDivElement | HTMLElement>>;
103
+ interface DialogFooterProps extends BaseProps {
104
+ }
105
+ /**
106
+ * The footer section of a dialog, typically used to display action buttons at the bottom of the dialog.
107
+ * Should be used as a child of `Dialog.Root`. Use `Dialog.ActionList` as a direct descendant to display a list of actions.
108
+ *
109
+ * Example:
110
+ * ```tsx
111
+ * <Dialog.Footer>
112
+ * <Dialog.ActionList
113
+ * actions={[
114
+ * <Button key="cancel" onClick={() => setOpen(false)}>Cancel</Button>,
115
+ * <Button key="ok" tone="accent" onClick={() => setOpen(false)}>Ok</Button>,
116
+ * ]}
117
+ * />
118
+ * </Dialog.Footer>
119
+ * ```
120
+ */
121
+ declare const DialogFooter: React.ForwardRefExoticComponent<DialogFooterProps & React.RefAttributes<HTMLDivElement | HTMLElement>>;
122
+ interface DialogActionListProps extends Omit<BaseProps, "children"> {
123
+ /**
124
+ * The actions available for the dialog. Must be a list of `Button` components.
125
+ */
126
+ actions?: React.ReactNode[];
127
+ }
128
+ /**
129
+ * A container for action buttons in a dialog. Should be used as a child of `Dialog.Footer`.
130
+ *
131
+ * Example:
132
+ * ```tsx
133
+ * <Dialog.ActionList
134
+ * actions={[
135
+ * <Button key="cancel" onClick={() => setOpen(false)}>Cancel</Button>,
136
+ * <Button key="ok" tone="accent" onClick={() => setOpen(false)}>Ok</Button>,
137
+ * ]}
138
+ * />
139
+ * ```
140
+ */
141
+ declare const DialogActionList: React.ForwardRefExoticComponent<DialogActionListProps & React.RefAttributes<HTMLDivElement | HTMLElement>>;
142
+ interface DialogBackdropProps extends BaseProps {
143
+ }
144
+ /**
145
+ * The backdrop of a dialog. Should be passed into the `backdrop` prop of `Dialog.Root`.
146
+ *
147
+ * Example:
148
+ * ```tsx
149
+ * <Dialog.Root modal={true} backdrop={<Dialog.Backdrop />} />
150
+ * ```
151
+ */
152
+ declare const DialogBackdrop: React.ForwardRefExoticComponent<DialogBackdropProps & React.RefAttributes<HTMLDivElement | HTMLElement>>;
153
+ export { DialogRoot as Root, DialogHeader as Header, DialogHeading as Heading, DialogCloseButton as CloseButton, DialogContent as Content, DialogFooter as Footer, DialogActionList as ActionList, DialogBackdrop as Backdrop, };
package/dist/Dialog.js ADDED
@@ -0,0 +1,170 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import * as AkDialog from "@ariakit/react/dialog";
4
+ import { Portal, PortalContext } from "@ariakit/react/portal";
5
+ import { Role } from "@ariakit/react/role";
6
+ import { useStoreState } from "@ariakit/react/store";
7
+ import { IconButton, Text } from "@stratakit/bricks";
8
+ import { GhostAligner } from "@stratakit/bricks/secret-internals";
9
+ import {
10
+ forwardRef,
11
+ usePopoverApi
12
+ } from "@stratakit/foundations/secret-internals";
13
+ import cx from "classnames";
14
+ import { Dismiss } from "./~utils.icons.js";
15
+ const DialogRoot = forwardRef((props, forwardedRef) => {
16
+ const { backdrop = true, unmountOnHide = true, ...rest } = props;
17
+ const store = AkDialog.useDialogStore();
18
+ const contentElement = useStoreState(store, "contentElement");
19
+ const mounted = useStoreState(store, (state) => {
20
+ if (!unmountOnHide) return true;
21
+ return props.open ?? state?.mounted;
22
+ });
23
+ if (!mounted) return null;
24
+ return /* @__PURE__ */ jsx(AkDialog.DialogProvider, { store, children: /* @__PURE__ */ jsx(DialogWrapper, { open: props.open, children: /* @__PURE__ */ jsxs(
25
+ AkDialog.Dialog,
26
+ {
27
+ unmountOnHide,
28
+ portal: false,
29
+ ...rest,
30
+ backdrop: backdrop === true ? /* @__PURE__ */ jsx(DialogBackdrop, {}) : backdrop,
31
+ className: cx("\u{1F95D}Dialog", props.className),
32
+ ref: forwardedRef,
33
+ children: [
34
+ /* @__PURE__ */ jsx(AkDialog.DialogDismiss, { hidden: true }),
35
+ /* @__PURE__ */ jsx(PortalContext.Provider, { value: contentElement, children: props.children })
36
+ ]
37
+ }
38
+ ) }) });
39
+ });
40
+ function DialogWrapper(props) {
41
+ const [wrapper, setWrapper] = React.useState(null);
42
+ const store = AkDialog.useDialogContext();
43
+ const open = useStoreState(store, (state) => {
44
+ return props.open ?? state?.open;
45
+ });
46
+ const popoverProps = usePopoverApi({
47
+ element: wrapper,
48
+ open
49
+ });
50
+ const mounted = useStoreState(store, "mounted");
51
+ return /* @__PURE__ */ jsx(
52
+ Portal,
53
+ {
54
+ className: "\u{1F95D}DialogWrapper",
55
+ ref: setWrapper,
56
+ ...popoverProps,
57
+ hidden: mounted ? void 0 : true,
58
+ children: props.children
59
+ }
60
+ );
61
+ }
62
+ const DialogHeader = forwardRef(
63
+ (props, forwardedRef) => {
64
+ return /* @__PURE__ */ jsx(
65
+ Role,
66
+ {
67
+ ...props,
68
+ className: cx("\u{1F95D}DialogHeader", props.className),
69
+ ref: forwardedRef
70
+ }
71
+ );
72
+ }
73
+ );
74
+ const DialogHeading = forwardRef(
75
+ (props, forwardedRef) => {
76
+ return /* @__PURE__ */ jsx(
77
+ AkDialog.DialogHeading,
78
+ {
79
+ ...props,
80
+ className: cx("\u{1F95D}DialogHeading", props.className),
81
+ render: /* @__PURE__ */ jsx(Text, { variant: "body-lg", render: props.render ?? /* @__PURE__ */ jsx("h1", {}) }),
82
+ ref: forwardedRef
83
+ }
84
+ );
85
+ }
86
+ );
87
+ const DialogCloseButton = forwardRef(
88
+ (props, forwardedRef) => {
89
+ const { label = "Dismiss", ...rest } = props;
90
+ return /* @__PURE__ */ jsx(GhostAligner, { align: "inline-end", children: /* @__PURE__ */ jsx(
91
+ AkDialog.DialogDismiss,
92
+ {
93
+ ...rest,
94
+ render: /* @__PURE__ */ jsx(
95
+ IconButton,
96
+ {
97
+ render: props.render,
98
+ variant: "ghost",
99
+ label,
100
+ icon: /* @__PURE__ */ jsx(Dismiss, {})
101
+ }
102
+ ),
103
+ ref: forwardedRef
104
+ }
105
+ ) });
106
+ }
107
+ );
108
+ const DialogContent = forwardRef(
109
+ (props, forwardedRef) => {
110
+ return /* @__PURE__ */ jsx(
111
+ Role,
112
+ {
113
+ ...props,
114
+ className: cx("\u{1F95D}DialogContent", props.className),
115
+ ref: forwardedRef
116
+ }
117
+ );
118
+ }
119
+ );
120
+ const DialogFooter = forwardRef(
121
+ (props, forwardedRef) => {
122
+ return /* @__PURE__ */ jsx(
123
+ Role,
124
+ {
125
+ ...props,
126
+ className: cx("\u{1F95D}DialogFooter", props.className),
127
+ ref: forwardedRef
128
+ }
129
+ );
130
+ }
131
+ );
132
+ const DialogActionList = forwardRef(
133
+ (props, forwardedRef) => {
134
+ const { actions, ...rest } = props;
135
+ return /* @__PURE__ */ jsx(
136
+ Role,
137
+ {
138
+ role: "list",
139
+ ...rest,
140
+ className: cx("\u{1F95D}DialogActionList", props.className),
141
+ ref: forwardedRef,
142
+ children: React.Children.map(actions, (action) => {
143
+ return /* @__PURE__ */ jsx("div", { role: "listitem", children: action });
144
+ })
145
+ }
146
+ );
147
+ }
148
+ );
149
+ const DialogBackdrop = forwardRef(
150
+ (props, forwardedRef) => {
151
+ return /* @__PURE__ */ jsx(
152
+ Role,
153
+ {
154
+ ...props,
155
+ className: cx("\u{1F95D}DialogBackdrop", props.className),
156
+ ref: forwardedRef
157
+ }
158
+ );
159
+ }
160
+ );
161
+ export {
162
+ DialogActionList as ActionList,
163
+ DialogBackdrop as Backdrop,
164
+ DialogCloseButton as CloseButton,
165
+ DialogContent as Content,
166
+ DialogFooter as Footer,
167
+ DialogHeader as Header,
168
+ DialogHeading as Heading,
169
+ DialogRoot as Root
170
+ };
@@ -0,0 +1,203 @@
1
+ import * as React from "react";
2
+ import type { BaseProps, FocusableProps } from "@stratakit/foundations/secret-internals";
3
+ interface NavigationRailProps extends BaseProps<"nav"> {
4
+ }
5
+ /**
6
+ * The `NavigationRail` presents top-level navigation items in a vertical orientation.
7
+ *
8
+ * Example:
9
+ * ```tsx
10
+ * <NavigationRail.Root>
11
+ * <NavigationRail.Header>
12
+ * <IconButton label="Home" icon={applicationIcon} href="/" />
13
+ * <NavigationRail.ToggleButton />
14
+ * </NavigationRail.Header>
15
+ *
16
+ * <NavigationRail.Content>
17
+ * <NavigationRail.List>
18
+ * <NavigationRail.ListItem>
19
+ * <NavigationRail.Anchor label="Dashboard" icon={dashboardIcon} href="/dashboard" />
20
+ * </NavigationRail.ListItem>
21
+ * <NavigationRail.ListItem>
22
+ * <NavigationRail.Anchor label="Projects" icon={projectsIcon} href="/projects" />
23
+ * </NavigationRail.ListItem>
24
+ * <NavigationRail.ListItem>
25
+ * <NavigationRail.Anchor label="Reports" icon={reportsIcon} href="/reports" />
26
+ * </NavigationRail.ListItem>
27
+ * </NavigationRail.List>
28
+ *
29
+ * <NavigationRail.Footer>
30
+ * <NavigationRail.List>
31
+ * <NavigationRail.ListItem>
32
+ * <NavigationRail.Button label="Help" icon={helpIcon} onClick={…} />
33
+ * </NavigationRail.ListItem>
34
+ * <NavigationRail.ListItem>
35
+ * <NavigationRail.Button label="Settings" icon={settingsIcon} onClick={…} />
36
+ * </NavigationRail.ListItem>
37
+ * <NavigationRail.ListItem>
38
+ * <NavigationRail.Button label="Profile" icon={userIcon} onClick={…} />
39
+ * </NavigationRail.ListItem>
40
+ * </NavigationRail.List>
41
+ * </NavigationRail.Footer>
42
+ * </NavigationRail.Content>
43
+ * </NavigationRail.Root>
44
+ * ```
45
+ */
46
+ declare const NavigationRailRoot: React.ForwardRefExoticComponent<NavigationRailProps & React.RefAttributes<HTMLElement>>;
47
+ interface NavigationRailHeaderProps extends BaseProps<"header"> {
48
+ }
49
+ /**
50
+ * `NavigationRail.Header` represents the header (i.e. top) section of the `NavigationRail` and is
51
+ * visually aligned with the page header next to it.
52
+ *
53
+ * Can contain a logo and a `NavigationRail.ToggleButton` to collapse/expand the `NavigationRail`.
54
+ *
55
+ * **Note**: This component is expected to hug the top edge of the page.
56
+ */
57
+ declare const NavigationRailHeader: React.ForwardRefExoticComponent<NavigationRailHeaderProps & React.RefAttributes<HTMLElement>>;
58
+ interface NavigationRailToggleButtonProps extends Omit<FocusableProps<"button">, "children"> {
59
+ /**
60
+ * Customize the accessible label of the toggle button.
61
+ *
62
+ * @default "Expand navigation".
63
+ */
64
+ label?: string;
65
+ }
66
+ /**
67
+ * `NavigationRail.ToggleButton` toggles the collapsed state of the `NavigationRail`.
68
+ * It is typically placed inside `NavigationRail.Header`, next to the logo.
69
+ */
70
+ declare const NavigationRailToggleButton: React.ForwardRefExoticComponent<NavigationRailToggleButtonProps & React.RefAttributes<HTMLElement | HTMLButtonElement>>;
71
+ interface NavigationRailContentProps extends BaseProps {
72
+ }
73
+ /**
74
+ * `NavigationRail.Content` is a wraps the main content of the `NavigationRail`, including
75
+ * the primary navigation list and an optional footer.
76
+ *
77
+ * Example:
78
+ * ```tsx
79
+ * <NavigationRail.Content>
80
+ * <NavigationRail.List>…</NavigationRail.List>
81
+ *
82
+ * <NavigationRail.Footer>
83
+ * <NavigationRail.List>…</NavigationRail.List>
84
+ * </NavigationRail.Footer>
85
+ * </NavigationRail.Content>
86
+ * ```
87
+ */
88
+ declare const NavigationRailContent: React.ForwardRefExoticComponent<NavigationRailContentProps & React.RefAttributes<HTMLDivElement | HTMLElement>>;
89
+ interface NavigationRailListProps extends BaseProps<"div"> {
90
+ }
91
+ /**
92
+ * The `NavigationRail.List` represents a list of top-level navigation items.
93
+ *
94
+ * It should be used within `NavigationRail.Content` and should contain `NavigationRail.ListItem` elements,
95
+ * which in turn can contain `NavigationRail.Anchor` or `NavigationRail.Button`.
96
+ *
97
+ * Example (with `NavigationRail.Anchor`):
98
+ * ```tsx
99
+ * <NavigationRail.List>
100
+ * <NavigationRail.ListItem>
101
+ * <NavigationRail.Anchor label="Home" icon={homeIcon} href="/" />
102
+ * </NavigationRail.ListItem>
103
+ * <NavigationRail.ListItem>
104
+ * <NavigationRail.Anchor label="Projects" icon={projectsIcon} href="/projects" />
105
+ * </NavigationRail.ListItem>
106
+ * </NavigationRail.List>
107
+ * ```
108
+ *
109
+ * Example (with `NavigationRail.Button`):
110
+ * ```tsx
111
+ * <NavigationRail.List>
112
+ * <NavigationRail.ListItem>
113
+ * <NavigationRail.Button label="Help" icon={helpIcon} onClick={…} />
114
+ * </NavigationRail.ListItem>
115
+ * <NavigationRail.ListItem>
116
+ * <NavigationRail.Button label="Settings" icon={settingsIcon} onClick={…} />
117
+ * </NavigationRail.ListItem>
118
+ * </NavigationRail.List>
119
+ * ```
120
+ *
121
+ * Multiple `NavigationRail.List` elements can be used together and be separated by a `Divider`.
122
+ */
123
+ declare const NavigationRailList: React.ForwardRefExoticComponent<NavigationRailListProps & React.RefAttributes<HTMLDivElement | HTMLElement>>;
124
+ interface NavigationRailListItemProps extends BaseProps<"div"> {
125
+ }
126
+ /**
127
+ * The `NavigationRail.Item` represents a single navigation list item, which should contain
128
+ * either a `NavigationRail.Anchor` or a `NavigationRail.Button`.
129
+ *
130
+ * Example:
131
+ * ```tsx
132
+ * <NavigationRail.ListItem>
133
+ * <NavigationRail.Anchor label="Home" icon={homeIcon} href="/" />
134
+ * </NavigationRail.ListItem>
135
+ * // or
136
+ * <NavigationRail.ListItem>
137
+ * <NavigationRail.Button label="Settings" icon={settingsIcon} onClick={…} />
138
+ * </NavigationRail.ListItem>
139
+ * ```
140
+ *
141
+ * **Note:** This is a non-interactive wrapper element and should not directly handle user interactions.
142
+ */
143
+ declare const NavigationRailListItem: React.ForwardRefExoticComponent<NavigationRailListItemProps & React.RefAttributes<HTMLDivElement | HTMLElement>>;
144
+ interface NavigationRailItemActionOwnProps {
145
+ label: string;
146
+ icon: string | React.JSX.Element;
147
+ }
148
+ interface NavigationRailAnchorProps extends Omit<BaseProps<"a">, "children">, NavigationRailItemActionOwnProps {
149
+ /**
150
+ * Whether the anchor is currently active (i.e. represents the current page).
151
+ */
152
+ active?: boolean;
153
+ }
154
+ /**
155
+ * `NavigationRail.Anchor` is used for top-level navigation items that link to major pages.
156
+ *
157
+ * Should be used inside `NavigationRail.ListItem` and must have a short `label` and a recognizable `icon`.
158
+ * The `label` will be shown as a tooltip when the `NavigationRail` is collapsed.
159
+ *
160
+ * Example:
161
+ * ```tsx
162
+ * <NavigationRail.ListItem>
163
+ * <NavigationRail.Anchor label="Home" icon={homeIcon} href="/" />
164
+ * </NavigationRail.ListItem>
165
+ * ```
166
+ */
167
+ declare const NavigationRailAnchor: React.ForwardRefExoticComponent<NavigationRailAnchorProps & React.RefAttributes<HTMLElement | HTMLAnchorElement>>;
168
+ interface NavigationRailButtonProps extends Omit<BaseProps<"button">, "children">, NavigationRailItemActionOwnProps {
169
+ }
170
+ /**
171
+ * `NavigationRail.Button` is used for actions that do not navigate to a new page, but rather perform
172
+ * an in-page action, such as opening a dialog or menu.
173
+ *
174
+ * Should be used inside `NavigationRail.ListItem` and must have a short `label` and a recognizable `icon`.
175
+ * The `label` will be shown as a tooltip when the `NavigationRail` is collapsed.
176
+ *
177
+ * Example:
178
+ * ```tsx
179
+ * <NavigationRail.ListItem>
180
+ * <NavigationRail.Button label="Notifications" icon={notificationsIcon} onClick={showNotificationsDialog} />
181
+ * </NavigationRail.ListItem>
182
+ * ```
183
+ */
184
+ declare const NavigationRailButton: React.ForwardRefExoticComponent<NavigationRailButtonProps & React.RefAttributes<HTMLElement | HTMLButtonElement>>;
185
+ interface NavigationRailFooterProps extends BaseProps<"footer"> {
186
+ }
187
+ /**
188
+ * `NavigationRail.Footer` is typically used for grouping secondary actions list near the bottom
189
+ * of the `NavigationRail`, away from the main navigation items.
190
+ *
191
+ * Example:
192
+ * ```tsx
193
+ * <NavigationRail.Content>
194
+ * <NavigationRail.List>…</NavigationRail.List>
195
+ *
196
+ * <NavigationRail.Footer>
197
+ * <NavigationRail.List>…</NavigationRail.List>
198
+ * </NavigationRail.Footer>
199
+ * </NavigationRail.Content>
200
+ * ```
201
+ */
202
+ declare const NavigationRailFooter: React.ForwardRefExoticComponent<NavigationRailFooterProps & React.RefAttributes<HTMLElement>>;
203
+ export { NavigationRailRoot as Root, NavigationRailHeader as Header, NavigationRailToggleButton as ToggleButton, NavigationRailContent as Content, NavigationRailList as List, NavigationRailListItem as ListItem, NavigationRailButton as Button, NavigationRailAnchor as Anchor, NavigationRailFooter as Footer, };