@ariakit/components 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/checkbox/checkbox-store.d.ts +47 -0
  3. package/dist/checkbox/checkbox-store.d.ts.map +1 -0
  4. package/dist/checkbox/checkbox-store.js +16 -0
  5. package/dist/checkbox/checkbox-store.js.map +1 -0
  6. package/dist/collection/collection-store.d.ts +2 -0
  7. package/dist/collection/collection-store.js +132 -0
  8. package/dist/collection/collection-store.js.map +1 -0
  9. package/dist/collection-store-yNe83BiS.d.ts +81 -0
  10. package/dist/collection-store-yNe83BiS.d.ts.map +1 -0
  11. package/dist/combobox/combobox-store.d.ts +150 -0
  12. package/dist/combobox/combobox-store.d.ts.map +1 -0
  13. package/dist/combobox/combobox-store.js +83 -0
  14. package/dist/combobox/combobox-store.js.map +1 -0
  15. package/dist/composite/composite-overflow-store.d.ts +16 -0
  16. package/dist/composite/composite-overflow-store.d.ts.map +1 -0
  17. package/dist/composite/composite-overflow-store.js +12 -0
  18. package/dist/composite/composite-overflow-store.js.map +1 -0
  19. package/dist/composite/composite-store.d.ts +2 -0
  20. package/dist/composite/composite-store.js +167 -0
  21. package/dist/composite/composite-store.js.map +1 -0
  22. package/dist/composite-store-B-iDEtZZ.d.ts +331 -0
  23. package/dist/composite-store-B-iDEtZZ.d.ts.map +1 -0
  24. package/dist/dialog/dialog-store.d.ts +2 -0
  25. package/dist/dialog/dialog-store.js +12 -0
  26. package/dist/dialog/dialog-store.js.map +1 -0
  27. package/dist/dialog-store-BOLvw2IX.d.ts +16 -0
  28. package/dist/dialog-store-BOLvw2IX.d.ts.map +1 -0
  29. package/dist/disclosure/disclosure-store.d.ts +2 -0
  30. package/dist/disclosure/disclosure-store.js +47 -0
  31. package/dist/disclosure/disclosure-store.js.map +1 -0
  32. package/dist/disclosure-store-xKlQffR0.d.ts +142 -0
  33. package/dist/disclosure-store-xKlQffR0.d.ts.map +1 -0
  34. package/dist/form/form-store.d.ts +247 -0
  35. package/dist/form/form-store.d.ts.map +1 -0
  36. package/dist/form/form-store.js +211 -0
  37. package/dist/form/form-store.js.map +1 -0
  38. package/dist/form/types.d.ts +37 -0
  39. package/dist/form/types.d.ts.map +1 -0
  40. package/dist/form/types.js +0 -0
  41. package/dist/hovercard/hovercard-store.d.ts +65 -0
  42. package/dist/hovercard/hovercard-store.d.ts.map +1 -0
  43. package/dist/hovercard/hovercard-store.js +31 -0
  44. package/dist/hovercard/hovercard-store.js.map +1 -0
  45. package/dist/index.d.ts +5 -0
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +6 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/menu/menu-bar-store.d.ts +16 -0
  50. package/dist/menu/menu-bar-store.d.ts.map +1 -0
  51. package/dist/menu/menu-bar-store.js +12 -0
  52. package/dist/menu/menu-bar-store.js.map +1 -0
  53. package/dist/menu/menu-store.d.ts +100 -0
  54. package/dist/menu/menu-store.d.ts.map +1 -0
  55. package/dist/menu/menu-store.js +74 -0
  56. package/dist/menu/menu-store.js.map +1 -0
  57. package/dist/menubar/menubar-store.d.ts +2 -0
  58. package/dist/menubar/menubar-store.js +24 -0
  59. package/dist/menubar/menubar-store.js.map +1 -0
  60. package/dist/menubar-store-CD3YDYfW.d.ts +16 -0
  61. package/dist/menubar-store-CD3YDYfW.d.ts.map +1 -0
  62. package/dist/popover/popover-store.d.ts +2 -0
  63. package/dist/popover/popover-store.js +44 -0
  64. package/dist/popover/popover-store.js.map +1 -0
  65. package/dist/popover-store-DoCiTmUQ.d.ts +106 -0
  66. package/dist/popover-store-DoCiTmUQ.d.ts.map +1 -0
  67. package/dist/radio/radio-store.d.ts +42 -0
  68. package/dist/radio/radio-store.d.ts.map +1 -0
  69. package/dist/radio/radio-store.js +27 -0
  70. package/dist/radio/radio-store.js.map +1 -0
  71. package/dist/select/select-store.d.ts +116 -0
  72. package/dist/select/select-store.d.ts.map +1 -0
  73. package/dist/select/select-store.js +93 -0
  74. package/dist/select/select-store.js.map +1 -0
  75. package/dist/tab/tab-store.d.ts +127 -0
  76. package/dist/tab/tab-store.d.ts.map +1 -0
  77. package/dist/tab/tab-store.js +107 -0
  78. package/dist/tab/tab-store.js.map +1 -0
  79. package/dist/tag/tag-store.d.ts +2 -0
  80. package/dist/tag/tag-store.js +60 -0
  81. package/dist/tag/tag-store.js.map +1 -0
  82. package/dist/tag-store-D47X5_zA.d.ts +83 -0
  83. package/dist/tag-store-D47X5_zA.d.ts.map +1 -0
  84. package/dist/toolbar/toolbar-store.d.ts +21 -0
  85. package/dist/toolbar/toolbar-store.d.ts.map +1 -0
  86. package/dist/toolbar/toolbar-store.js +18 -0
  87. package/dist/toolbar/toolbar-store.js.map +1 -0
  88. package/dist/tooltip/tooltip-store.d.ts +35 -0
  89. package/dist/tooltip/tooltip-store.d.ts.map +1 -0
  90. package/dist/tooltip/tooltip-store.js +29 -0
  91. package/dist/tooltip/tooltip-store.js.map +1 -0
  92. package/license +21 -0
  93. package/package.json +121 -0
  94. package/readme.md +19 -0
  95. package/src/checkbox/checkbox-store.ts +93 -0
  96. package/src/collection/collection-store.ts +301 -0
  97. package/src/combobox/combobox-store.ts +382 -0
  98. package/src/composite/composite-overflow-store.ts +30 -0
  99. package/src/composite/composite-store.ts +711 -0
  100. package/src/dialog/dialog-store.ts +26 -0
  101. package/src/disclosure/disclosure-store.ts +226 -0
  102. package/src/form/form-store.ts +608 -0
  103. package/src/form/types.ts +44 -0
  104. package/src/hovercard/hovercard-store.ts +112 -0
  105. package/src/index.ts +1 -0
  106. package/src/menu/menu-bar-store.ts +28 -0
  107. package/src/menu/menu-store.ts +263 -0
  108. package/src/menubar/menubar-store.ts +51 -0
  109. package/src/popover/popover-store.ts +170 -0
  110. package/src/radio/radio-store.ts +80 -0
  111. package/src/select/select-store.ts +323 -0
  112. package/src/tab/tab-store.ts +330 -0
  113. package/src/tag/tag-store.ts +170 -0
  114. package/src/toolbar/toolbar-store.ts +47 -0
  115. package/src/tooltip/tooltip-store.ts +93 -0
@@ -0,0 +1,112 @@
1
+ import { createStore } from "@ariakit/store";
2
+ import type { Store, StoreOptions, StoreProps } from "@ariakit/store";
3
+ import { defaultValue } from "@ariakit/utils";
4
+ import type { SetState } from "@ariakit/utils";
5
+ import type {
6
+ PopoverStoreFunctions,
7
+ PopoverStoreOptions,
8
+ PopoverStoreState,
9
+ } from "../popover/popover-store.ts";
10
+ import { createPopoverStore } from "../popover/popover-store.ts";
11
+
12
+ /**
13
+ * Creates a hovercard store.
14
+ */
15
+ export function createHovercardStore(
16
+ props: HovercardStoreProps = {},
17
+ ): HovercardStore {
18
+ const syncState = props.store?.getState();
19
+
20
+ const popover = createPopoverStore({
21
+ ...props,
22
+ placement: defaultValue(
23
+ props.placement,
24
+ syncState?.placement,
25
+ "bottom" as const,
26
+ ),
27
+ });
28
+
29
+ const timeout = defaultValue(props.timeout, syncState?.timeout, 500);
30
+
31
+ const initialState: HovercardStoreState = {
32
+ ...popover.getState(),
33
+ timeout,
34
+ showTimeout: defaultValue(props.showTimeout, syncState?.showTimeout),
35
+ hideTimeout: defaultValue(props.hideTimeout, syncState?.hideTimeout),
36
+ autoFocusOnShow: defaultValue(syncState?.autoFocusOnShow, false),
37
+ };
38
+
39
+ const hovercard = createStore(initialState, popover, props.store);
40
+
41
+ return {
42
+ ...popover,
43
+ ...hovercard,
44
+ setAutoFocusOnShow: (value) => hovercard.setState("autoFocusOnShow", value),
45
+ };
46
+ }
47
+
48
+ export interface HovercardStoreState extends PopoverStoreState {
49
+ /** @default "bottom" */
50
+ placement: PopoverStoreState["placement"];
51
+ /**
52
+ * The amount of time in milliseconds to wait before showing and hiding the
53
+ * popup. To control the delay for showing and hiding separately, use
54
+ * [`showTimeout`](https://ariakit.com/reference/hovercard-provider#showtimeout)
55
+ * and
56
+ * [`hideTimeout`](https://ariakit.com/reference/hovercard-provider#hidetimeout).
57
+ * @default 500
58
+ */
59
+ timeout: number;
60
+ /**
61
+ * The amount of time in milliseconds to wait before _showing_ the popup. It
62
+ * defaults to the value passed to
63
+ * [`timeout`](https://ariakit.com/reference/hovercard-provider#timeout).
64
+ *
65
+ * Live examples:
66
+ * - [Navigation Menubar](https://ariakit.com/examples/menubar-navigation)
67
+ * - [Submenu with
68
+ * Combobox](https://ariakit.com/examples/menu-nested-combobox)
69
+ */
70
+ showTimeout?: number;
71
+ /**
72
+ * The amount of time in milliseconds to wait before _hiding_ the popup. It
73
+ * defaults to the value passed to
74
+ * [`timeout`](https://ariakit.com/reference/hovercard-provider#timeout).
75
+ *
76
+ * Live examples:
77
+ * - [Navigation Menubar](https://ariakit.com/examples/menubar-navigation)
78
+ * - [Tooltip with
79
+ * Motion](https://ariakit.com/examples/tooltip-framer-motion)
80
+ */
81
+ hideTimeout?: number;
82
+ /**
83
+ * Whether the popup or an element inside it should be focused when it is
84
+ * shown.
85
+ * @default false
86
+ */
87
+ autoFocusOnShow: boolean;
88
+ }
89
+
90
+ export interface HovercardStoreFunctions extends PopoverStoreFunctions {
91
+ /**
92
+ * Sets the `autoFocusOnShow` state.
93
+ *
94
+ * Live examples:
95
+ * - [Sliding Menu](https://ariakit.com/examples/menu-slide)
96
+ */
97
+ setAutoFocusOnShow: SetState<HovercardStoreState["autoFocusOnShow"]>;
98
+ }
99
+
100
+ export interface HovercardStoreOptions
101
+ extends
102
+ StoreOptions<
103
+ HovercardStoreState,
104
+ "placement" | "timeout" | "showTimeout" | "hideTimeout"
105
+ >,
106
+ PopoverStoreOptions {}
107
+
108
+ export interface HovercardStoreProps
109
+ extends HovercardStoreOptions, StoreProps<HovercardStoreState> {}
110
+
111
+ export interface HovercardStore
112
+ extends HovercardStoreFunctions, Store<HovercardStoreState> {}
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export default {};
@@ -0,0 +1,28 @@
1
+ import type { Store, StoreProps } from "@ariakit/store";
2
+ import type {
3
+ MenubarStoreFunctions,
4
+ MenubarStoreOptions,
5
+ MenubarStoreState,
6
+ } from "../menubar/menubar-store.ts";
7
+ import { createMenubarStore } from "../menubar/menubar-store.ts";
8
+
9
+ /**
10
+ * Creates a menu bar store.
11
+ */
12
+ export function createMenuBarStore(
13
+ props: MenuBarStoreProps = {},
14
+ ): MenuBarStore {
15
+ return createMenubarStore(props);
16
+ }
17
+
18
+ export interface MenuBarStoreState extends MenubarStoreState {}
19
+
20
+ export interface MenuBarStoreFunctions extends MenubarStoreFunctions {}
21
+
22
+ export interface MenuBarStoreOptions extends MenubarStoreOptions {}
23
+
24
+ export interface MenuBarStoreProps
25
+ extends MenuBarStoreOptions, StoreProps<MenuBarStoreState> {}
26
+
27
+ export interface MenuBarStore
28
+ extends MenuBarStoreFunctions, Store<MenuBarStoreState> {}
@@ -0,0 +1,263 @@
1
+ import {
2
+ createStore,
3
+ mergeStore,
4
+ omit,
5
+ pick,
6
+ setup,
7
+ sync,
8
+ throwOnConflictingProps,
9
+ } from "@ariakit/store";
10
+ import type { Store, StoreOptions, StoreProps } from "@ariakit/store";
11
+ import { applyState, defaultValue } from "@ariakit/utils";
12
+ import type {
13
+ BivariantCallback,
14
+ PickRequired,
15
+ SetState,
16
+ SetStateAction,
17
+ } from "@ariakit/utils";
18
+ import type { ComboboxStore } from "../combobox/combobox-store.ts";
19
+ import type {
20
+ CompositeStoreFunctions,
21
+ CompositeStoreOptions,
22
+ CompositeStoreState,
23
+ } from "../composite/composite-store.ts";
24
+ import { createCompositeStore } from "../composite/composite-store.ts";
25
+ import type {
26
+ HovercardStoreFunctions,
27
+ HovercardStoreOptions,
28
+ HovercardStoreState,
29
+ } from "../hovercard/hovercard-store.ts";
30
+ import { createHovercardStore } from "../hovercard/hovercard-store.ts";
31
+ import type { MenuBarStore } from "./menu-bar-store.ts";
32
+
33
+ export function createMenuStore<T extends MenuStoreValues = MenuStoreValues>(
34
+ props: PickRequired<MenuStoreProps<T>, "values" | "defaultValues">,
35
+ ): MenuStore<T>;
36
+
37
+ export function createMenuStore(props?: MenuStoreProps): MenuStore;
38
+
39
+ export function createMenuStore({
40
+ combobox,
41
+ parent,
42
+ menubar,
43
+ ...props
44
+ }: MenuStoreProps = {}): MenuStore {
45
+ const parentIsMenubar = !!menubar && !parent;
46
+
47
+ const store = mergeStore(
48
+ props.store,
49
+ pick(parent, ["values"]),
50
+ omit(combobox, [
51
+ "arrowElement",
52
+ "anchorElement",
53
+ "contentElement",
54
+ "popoverElement",
55
+ "disclosureElement",
56
+ ]),
57
+ );
58
+
59
+ throwOnConflictingProps(props, store);
60
+
61
+ const syncState = store.getState();
62
+
63
+ const composite = createCompositeStore({
64
+ ...props,
65
+ store,
66
+ orientation: defaultValue(
67
+ props.orientation,
68
+ syncState.orientation,
69
+ "vertical" as const,
70
+ ),
71
+ });
72
+
73
+ const hovercard = createHovercardStore({
74
+ ...props,
75
+ store,
76
+ placement: defaultValue(
77
+ props.placement,
78
+ syncState.placement,
79
+ "bottom-start" as const,
80
+ ),
81
+ timeout: defaultValue(
82
+ props.timeout,
83
+ syncState.timeout,
84
+ parentIsMenubar ? 0 : 150,
85
+ ),
86
+ hideTimeout: defaultValue(props.hideTimeout, syncState.hideTimeout, 0),
87
+ });
88
+
89
+ const initialState: MenuStoreState = {
90
+ ...composite.getState(),
91
+ ...hovercard.getState(),
92
+ initialFocus: defaultValue(syncState.initialFocus, "container" as const),
93
+ values: defaultValue(
94
+ props.values,
95
+ syncState.values,
96
+ props.defaultValues,
97
+ {},
98
+ ),
99
+ };
100
+
101
+ const menu = createStore(initialState, composite, hovercard, store);
102
+
103
+ setup(menu, () =>
104
+ sync(menu, ["mounted"], (state) => {
105
+ if (state.mounted) return;
106
+ menu.setState("activeId", null);
107
+ }),
108
+ );
109
+
110
+ setup(menu, () =>
111
+ sync(parent, ["orientation"], (state) => {
112
+ menu.setState(
113
+ "placement",
114
+ state.orientation === "vertical" ? "right-start" : "bottom-start",
115
+ );
116
+ }),
117
+ );
118
+
119
+ return {
120
+ ...composite,
121
+ ...hovercard,
122
+ ...menu,
123
+ combobox,
124
+ parent,
125
+ menubar,
126
+ hideAll: () => {
127
+ hovercard.hide();
128
+ parent?.hideAll();
129
+ },
130
+ setInitialFocus: (value) => menu.setState("initialFocus", value),
131
+ setValues: (values) => menu.setState("values", values),
132
+ setValue: (name, value) => {
133
+ // Avoid prototype pollution
134
+ if (name === "__proto__") return;
135
+ if (name === "constructor") return;
136
+ if (Array.isArray(name)) return;
137
+ menu.setState("values", (values) => {
138
+ const prevValue = values[name];
139
+ const nextValue = applyState(value, prevValue);
140
+ if (nextValue === prevValue) return values;
141
+ return {
142
+ ...values,
143
+ [name]: nextValue !== undefined && nextValue,
144
+ };
145
+ });
146
+ },
147
+ };
148
+ }
149
+
150
+ export type MenuStoreValues = Record<
151
+ string,
152
+ string | boolean | number | ReadonlyArray<string | number>
153
+ >;
154
+
155
+ export interface MenuStoreState<T extends MenuStoreValues = MenuStoreValues>
156
+ extends CompositeStoreState, HovercardStoreState {
157
+ /** @default "vertical" */
158
+ orientation: CompositeStoreState["orientation"];
159
+ /** @default "bottom-start" */
160
+ placement: HovercardStoreState["placement"];
161
+ /** @default 0 */
162
+ hideTimeout?: HovercardStoreState["hideTimeout"];
163
+ /**
164
+ * Determines the element that should be focused when the menu is opened.
165
+ */
166
+ initialFocus: "container" | "first" | "last";
167
+ /**
168
+ * A map of names and values that will be used by the
169
+ * [`MenuItemCheckbox`](https://ariakit.com/reference/menu-item-checkbox) and
170
+ * [`MenuItemRadio`](https://ariakit.com/reference/menu-item-radio)
171
+ * components.
172
+ *
173
+ * Live examples:
174
+ * - [MenuItemCheckbox](https://ariakit.com/examples/menu-item-checkbox)
175
+ * - [Submenu with
176
+ * Combobox](https://ariakit.com/examples/menu-nested-combobox)
177
+ */
178
+ values: T;
179
+ }
180
+
181
+ export interface MenuStoreFunctions<T extends MenuStoreValues = MenuStoreValues>
182
+ extends
183
+ CompositeStoreFunctions,
184
+ HovercardStoreFunctions,
185
+ Pick<MenuStoreOptions, "combobox" | "parent" | "menubar"> {
186
+ /**
187
+ * Hides the menu and all its parent menus.
188
+ *
189
+ * Live examples:
190
+ * - [Submenu with
191
+ * Combobox](https://ariakit.com/examples/menu-nested-combobox)
192
+ */
193
+ hideAll: () => void;
194
+ /**
195
+ * Sets the `initialFocus` state.
196
+ */
197
+ setInitialFocus: SetState<MenuStoreState<T>["initialFocus"]>;
198
+ /**
199
+ * Sets the [`values`](https://ariakit.com/reference/menu-provider#values)
200
+ * state.
201
+ * @example
202
+ * store.setValues({ watching: ["issues"] });
203
+ * store.setValues((values) => ({ ...values, watching: ["issues"] }));
204
+ */
205
+ setValues: SetState<MenuStoreState<T>["values"]>;
206
+ /**
207
+ * Sets a specific menu value.
208
+ *
209
+ * Live examples:
210
+ * - [Submenu with
211
+ * Combobox](https://ariakit.com/examples/menu-nested-combobox)
212
+ * @example
213
+ * store.setValue("watching", ["issues"]);
214
+ * store.setValue("watching", (value) => [...value, "issues"]);
215
+ */
216
+ setValue: BivariantCallback<
217
+ (
218
+ name: string,
219
+ value: SetStateAction<MenuStoreState<T>["values"][string]>,
220
+ ) => void
221
+ >;
222
+ }
223
+
224
+ export interface MenuStoreOptions<T extends MenuStoreValues = MenuStoreValues>
225
+ extends
226
+ StoreOptions<
227
+ MenuStoreState<T>,
228
+ "orientation" | "placement" | "hideTimeout" | "values"
229
+ >,
230
+ CompositeStoreOptions,
231
+ HovercardStoreOptions {
232
+ /**
233
+ * A reference to a combobox store. This is used when combining the combobox
234
+ * with a menu (e.g., dropdown menu with a search input). The stores will
235
+ * share the same state.
236
+ */
237
+ combobox?: ComboboxStore | null;
238
+ /**
239
+ * A reference to a parent menu store. This is used on nested menus.
240
+ */
241
+ parent?: MenuStore | null;
242
+ /**
243
+ * A reference to a menubar store. This is used when rendering menus inside a
244
+ * menubar.
245
+ */
246
+ menubar?: MenuBarStore | null;
247
+ /**
248
+ * The default values for the
249
+ * [`values`](https://ariakit.com/reference/menu-provider#values) state.
250
+ *
251
+ * Live examples:
252
+ * - [MenuItemCheckbox](https://ariakit.com/examples/menu-item-checkbox)
253
+ * - [MenuItemRadio](https://ariakit.com/examples/menu-item-radio)
254
+ * @default {}
255
+ */
256
+ defaultValues?: MenuStoreState<T>["values"];
257
+ }
258
+
259
+ export interface MenuStoreProps<T extends MenuStoreValues = MenuStoreValues>
260
+ extends MenuStoreOptions<T>, StoreProps<MenuStoreState<T>> {}
261
+
262
+ export interface MenuStore<T extends MenuStoreValues = MenuStoreValues>
263
+ extends MenuStoreFunctions<T>, Store<MenuStoreState<T>> {}
@@ -0,0 +1,51 @@
1
+ import { createStore } from "@ariakit/store";
2
+ import type { Store, StoreProps } from "@ariakit/store";
3
+ import { defaultValue } from "@ariakit/utils";
4
+ import type {
5
+ CompositeStoreFunctions,
6
+ CompositeStoreOptions,
7
+ CompositeStoreState,
8
+ } from "../composite/composite-store.ts";
9
+ import { createCompositeStore } from "../composite/composite-store.ts";
10
+
11
+ /**
12
+ * Creates a menubar store.
13
+ */
14
+ export function createMenubarStore(
15
+ props: MenubarStoreProps = {},
16
+ ): MenubarStore {
17
+ const syncState = props.store?.getState();
18
+
19
+ const composite = createCompositeStore({
20
+ ...props,
21
+ orientation: defaultValue(
22
+ props.orientation,
23
+ syncState?.orientation,
24
+ "horizontal" as const,
25
+ ),
26
+ focusLoop: defaultValue(props.focusLoop, syncState?.focusLoop, true),
27
+ });
28
+
29
+ const initialState: MenubarStoreState = {
30
+ ...composite.getState(),
31
+ };
32
+
33
+ const menubar = createStore(initialState, composite, props.store);
34
+
35
+ return {
36
+ ...composite,
37
+ ...menubar,
38
+ };
39
+ }
40
+
41
+ export interface MenubarStoreState extends CompositeStoreState {}
42
+
43
+ export interface MenubarStoreFunctions extends CompositeStoreFunctions {}
44
+
45
+ export interface MenubarStoreOptions extends CompositeStoreOptions {}
46
+
47
+ export interface MenubarStoreProps
48
+ extends MenubarStoreOptions, StoreProps<MenubarStoreState> {}
49
+
50
+ export interface MenubarStore
51
+ extends MenubarStoreFunctions, Store<MenubarStoreState> {}
@@ -0,0 +1,170 @@
1
+ import {
2
+ createStore,
3
+ mergeStore,
4
+ omit,
5
+ throwOnConflictingProps,
6
+ } from "@ariakit/store";
7
+ import type { Store, StoreOptions, StoreProps } from "@ariakit/store";
8
+ import { defaultValue } from "@ariakit/utils";
9
+ import type { SetState } from "@ariakit/utils";
10
+ import type {
11
+ DialogStoreFunctions,
12
+ DialogStoreOptions,
13
+ DialogStoreState,
14
+ } from "../dialog/dialog-store.ts";
15
+ import { createDialogStore } from "../dialog/dialog-store.ts";
16
+
17
+ type BasePlacement = "top" | "bottom" | "left" | "right";
18
+
19
+ type Placement =
20
+ | BasePlacement
21
+ | `${BasePlacement}-start`
22
+ | `${BasePlacement}-end`;
23
+
24
+ /**
25
+ * Creates a popover store.
26
+ */
27
+ export function createPopoverStore({
28
+ popover: otherPopover,
29
+ ...props
30
+ }: PopoverStoreProps = {}): PopoverStore {
31
+ const store = mergeStore(
32
+ props.store,
33
+ omit(otherPopover, [
34
+ "arrowElement",
35
+ "anchorElement",
36
+ "contentElement",
37
+ "popoverElement",
38
+ "disclosureElement",
39
+ ]),
40
+ );
41
+
42
+ throwOnConflictingProps(props, store);
43
+
44
+ const syncState = store?.getState();
45
+
46
+ const dialog = createDialogStore({ ...props, store });
47
+
48
+ const placement = defaultValue(
49
+ props.placement,
50
+ syncState?.placement,
51
+ "bottom" as const,
52
+ );
53
+
54
+ const initialState: PopoverStoreState = {
55
+ ...dialog.getState(),
56
+ placement,
57
+ currentPlacement: placement,
58
+ anchorElement: defaultValue(syncState?.anchorElement, null),
59
+ popoverElement: defaultValue(syncState?.popoverElement, null),
60
+ arrowElement: defaultValue(syncState?.arrowElement, null),
61
+ rendered: Symbol("rendered"),
62
+ };
63
+ const popover = createStore(initialState, dialog, store);
64
+
65
+ return {
66
+ ...dialog,
67
+ ...popover,
68
+ setAnchorElement: (element) => popover.setState("anchorElement", element),
69
+ setPopoverElement: (element) => popover.setState("popoverElement", element),
70
+ setArrowElement: (element) => popover.setState("arrowElement", element),
71
+ render: () => popover.setState("rendered", Symbol("rendered")),
72
+ };
73
+ }
74
+
75
+ export interface PopoverStoreState extends DialogStoreState {
76
+ /**
77
+ * The anchor element.
78
+ *
79
+ * Live examples:
80
+ * - [Navigation Menubar](https://ariakit.com/examples/menubar-navigation)
81
+ */
82
+ anchorElement: HTMLElement | null;
83
+ /**
84
+ * The popover element that will render the placement attributes.
85
+ *
86
+ * Live examples:
87
+ * - [Form with Select](https://ariakit.com/examples/form-select)
88
+ * - [Sliding Menu](https://ariakit.com/examples/menu-slide)
89
+ * - [Responsive Popover](https://ariakit.com/examples/popover-responsive)
90
+ */
91
+ popoverElement: HTMLElement | null;
92
+ /**
93
+ * The arrow element.
94
+ */
95
+ arrowElement: HTMLElement | null;
96
+ /**
97
+ * The current temporary position of the popover. This might differ from the
98
+ * [`placement`](https://ariakit.com/reference/popover-provider#placement)
99
+ * state if the popover has had to adjust its position dynamically.
100
+ *
101
+ * Live examples:
102
+ * - [Tooltip with
103
+ * Motion](https://ariakit.com/examples/tooltip-framer-motion)
104
+ */
105
+ currentPlacement: Placement;
106
+ /**
107
+ * The placement of the popover.
108
+ *
109
+ * Live examples:
110
+ * - [Submenu with
111
+ * Combobox](https://ariakit.com/examples/menu-nested-combobox)
112
+ * - [Sliding Menu](https://ariakit.com/examples/menu-slide)
113
+ * - [Navigation Menubar](https://ariakit.com/examples/menubar-navigation)
114
+ * - [Selection Popover](https://ariakit.com/examples/popover-selection)
115
+ * - [Standalone Popover](https://ariakit.com/examples/popover-standalone)
116
+ * - [Select Grid](https://ariakit.com/examples/select-grid)
117
+ * @default "bottom"
118
+ */
119
+ placement: Placement;
120
+ /**
121
+ * A symbol that's used to recompute the popover position when the
122
+ * [`render`](https://ariakit.com/reference/use-popover-store#render) method
123
+ * is called.
124
+ */
125
+ rendered: symbol;
126
+ }
127
+
128
+ export interface PopoverStoreFunctions extends DialogStoreFunctions {
129
+ /**
130
+ * Sets the anchor element.
131
+ *
132
+ * Live examples:
133
+ * - [Navigation Menubar](https://ariakit.com/examples/menubar-navigation)
134
+ */
135
+ setAnchorElement: SetState<PopoverStoreState["anchorElement"]>;
136
+ /**
137
+ * Sets the popover element.
138
+ */
139
+ setPopoverElement: SetState<PopoverStoreState["popoverElement"]>;
140
+ /**
141
+ * Sets the arrow element.
142
+ */
143
+ setArrowElement: SetState<PopoverStoreState["arrowElement"]>;
144
+ /**
145
+ * A function that can be used to recompute the popover position. This is
146
+ * useful when the popover anchor changes in a way that affects the popover
147
+ * position.
148
+ *
149
+ * Live examples:
150
+ * - [Textarea with inline
151
+ * Combobox](https://ariakit.com/examples/combobox-textarea)
152
+ * - [Selection Popover](https://ariakit.com/examples/popover-selection)
153
+ */
154
+ render: () => void;
155
+ }
156
+
157
+ export interface PopoverStoreOptions
158
+ extends DialogStoreOptions, StoreOptions<PopoverStoreState, "placement"> {
159
+ /**
160
+ * A reference to another popover store that's controlling another popover to
161
+ * keep them in sync.
162
+ */
163
+ popover?: PopoverStore | null;
164
+ }
165
+
166
+ export interface PopoverStoreProps
167
+ extends PopoverStoreOptions, StoreProps<PopoverStoreState> {}
168
+
169
+ export interface PopoverStore
170
+ extends PopoverStoreFunctions, Store<PopoverStoreState> {}
@@ -0,0 +1,80 @@
1
+ import { createStore } from "@ariakit/store";
2
+ import type { Store, StoreOptions, StoreProps } from "@ariakit/store";
3
+ import { defaultValue } from "@ariakit/utils";
4
+ import type { SetState } from "@ariakit/utils";
5
+ import type {
6
+ CompositeStoreFunctions,
7
+ CompositeStoreOptions,
8
+ CompositeStoreState,
9
+ } from "../composite/composite-store.ts";
10
+ import { createCompositeStore } from "../composite/composite-store.ts";
11
+
12
+ /**
13
+ * Creates a radio store.
14
+ */
15
+ export function createRadioStore({
16
+ ...props
17
+ }: RadioStoreProps = {}): RadioStore {
18
+ const syncState = props.store?.getState();
19
+
20
+ const composite = createCompositeStore({
21
+ ...props,
22
+ focusLoop: defaultValue(props.focusLoop, syncState?.focusLoop, true),
23
+ });
24
+
25
+ const initialState: RadioStoreState = {
26
+ ...composite.getState(),
27
+ value: defaultValue(
28
+ props.value,
29
+ syncState?.value,
30
+ props.defaultValue,
31
+ null,
32
+ ),
33
+ };
34
+
35
+ const radio = createStore(initialState, composite, props.store);
36
+
37
+ return {
38
+ ...composite,
39
+ ...radio,
40
+ setValue: (value) => radio.setState("value", value),
41
+ };
42
+ }
43
+
44
+ export interface RadioStoreState extends CompositeStoreState {
45
+ /** @default true */
46
+ focusLoop: CompositeStoreState["focusLoop"];
47
+ /**
48
+ * The value of the radio group.
49
+ * @default null
50
+ */
51
+ value: string | number | null;
52
+ }
53
+
54
+ export interface RadioStoreFunctions extends CompositeStoreFunctions {
55
+ /**
56
+ * Sets the [`value`](https://ariakit.com/reference/radio-provider#value)
57
+ * state.
58
+ * @example
59
+ * store.setValue("apple");
60
+ * store.setValue((value) => value === "apple" ? "orange" : "apple");
61
+ */
62
+ setValue: SetState<RadioStoreState["value"]>;
63
+ }
64
+
65
+ export interface RadioStoreOptions
66
+ extends
67
+ StoreOptions<RadioStoreState, "focusLoop" | "value">,
68
+ CompositeStoreOptions {
69
+ /**
70
+ * The default value of the radio group.
71
+ * @default null
72
+ */
73
+ defaultValue?: RadioStoreState["value"];
74
+ }
75
+
76
+ export interface RadioStoreProps
77
+ extends RadioStoreOptions, StoreProps<RadioStoreState> {}
78
+
79
+ export interface RadioStore
80
+ extends RadioStoreFunctions, Store<RadioStoreState> {}