@blockle/blocks 0.12.0 → 0.12.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/dist/index.cjs +8 -1
- package/dist/index.mjs +10 -3
- package/dist/momotaro.chunk.d.ts +2 -3
- package/dist/styles/components/overlay/Dialog/Dialog.cjs +41 -69
- package/dist/styles/components/overlay/Dialog/Dialog.mjs +44 -72
- package/dist/styles/components/overlay/Dialog/dialog.css.cjs +10 -12
- package/dist/styles/components/overlay/Dialog/dialog.css.mjs +10 -12
- package/dist/styles/themes/momotaro/components/dialog.css.cjs +13 -16
- package/dist/styles/themes/momotaro/components/dialog.css.mjs +13 -16
- package/dist/styles/themes/momotaro/components/progress.css.cjs +6 -6
- package/dist/styles/themes/momotaro/components/progress.css.mjs +6 -6
- package/package.json +38 -37
package/dist/index.cjs
CHANGED
|
@@ -352,6 +352,13 @@ const Tooltip = ({
|
|
|
352
352
|
)
|
|
353
353
|
] });
|
|
354
354
|
};
|
|
355
|
+
const useRootAriaHidden = (hidden) => {
|
|
356
|
+
const context = react.useContext(styles_components_display_Divider_Divider_cjs.BlocksProviderContext);
|
|
357
|
+
if (!context) {
|
|
358
|
+
throw new Error("useRootAriaHidden must be used within a BlocksProvider");
|
|
359
|
+
}
|
|
360
|
+
context.setAriaHidden(hidden);
|
|
361
|
+
};
|
|
355
362
|
exports.breakpointQuery = styles_lib_css_atoms_breakpoints_cjs.breakpointQuery;
|
|
356
363
|
exports.style = styles_lib_css_style_style_cjs.style;
|
|
357
364
|
exports.makeComponentTheme = styles_lib_theme_makeComponentTheme_cjs.makeComponentTheme;
|
|
@@ -380,7 +387,6 @@ exports.Portal = styles_components_overlay_Dialog_Dialog_cjs.Portal;
|
|
|
380
387
|
exports.useIsomorphicLayoutEffect = styles_components_overlay_Dialog_Dialog_cjs.useIsomorphicLayoutEffect;
|
|
381
388
|
exports.useKeyboard = styles_components_overlay_Dialog_Dialog_cjs.useKeyboard;
|
|
382
389
|
exports.usePreventBodyScroll = styles_components_overlay_Dialog_Dialog_cjs.usePreventBodyScroll;
|
|
383
|
-
exports.useRootAriaHidden = styles_components_overlay_Dialog_Dialog_cjs.useRootAriaHidden;
|
|
384
390
|
exports.Heading = styles_components_typography_Heading_Heading_cjs.Heading;
|
|
385
391
|
exports.Text = styles_components_typography_Text_Text_cjs.Text;
|
|
386
392
|
exports.Inline = Inline;
|
|
@@ -388,3 +394,4 @@ exports.Link = Link;
|
|
|
388
394
|
exports.Progress = Progress;
|
|
389
395
|
exports.Stack = Stack;
|
|
390
396
|
exports.Tooltip = Tooltip;
|
|
397
|
+
exports.useRootAriaHidden = useRootAriaHidden;
|
package/dist/index.mjs
CHANGED
|
@@ -5,11 +5,11 @@ import { style } from "./styles/lib/css/style/style.mjs";
|
|
|
5
5
|
import { makeComponentTheme } from "./styles/lib/theme/makeComponentTheme.mjs";
|
|
6
6
|
import { makeTheme } from "./styles/lib/theme/makeTheme.mjs";
|
|
7
7
|
import { vars } from "./styles/lib/theme/vars.css.mjs";
|
|
8
|
-
import { useComponentStyles, Box, classnames, createSlottable, composeRefs } from "./styles/components/display/Divider/Divider.mjs";
|
|
8
|
+
import { useComponentStyles, Box, classnames, createSlottable, composeRefs, BlocksProviderContext } from "./styles/components/display/Divider/Divider.mjs";
|
|
9
9
|
import { Divider, Slot, useComponentStyleDefaultProps } from "./styles/components/display/Divider/Divider.mjs";
|
|
10
10
|
import { atoms } from "./styles/lib/css/atoms/sprinkles.css.mjs";
|
|
11
11
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
12
|
-
import { forwardRef, useEffect, useState, useRef, useLayoutEffect, useCallback, useId, Children, isValidElement, cloneElement } from "react";
|
|
12
|
+
import { forwardRef, useEffect, useState, useRef, useLayoutEffect, useCallback, useId, Children, isValidElement, cloneElement, useContext } from "react";
|
|
13
13
|
import { Button, Spinner } from "./styles/components/form/Button/Button.mjs";
|
|
14
14
|
import { Checkbox, Label } from "./styles/components/form/Checkbox/Checkbox.mjs";
|
|
15
15
|
import { Input } from "./styles/components/form/Input/Input.mjs";
|
|
@@ -19,7 +19,7 @@ import { Slider } from "./styles/components/form/Slider/Slider.mjs";
|
|
|
19
19
|
import { Switch } from "./styles/components/form/Switch/Switch.mjs";
|
|
20
20
|
import { BlocksProvider } from "./styles/components/other/BlocksProvider/BlocksProvider.mjs";
|
|
21
21
|
import { useLayer, useVisibilityState, useIsomorphicLayoutEffect, hasAnimationDuration, useKeyboard, Portal } from "./styles/components/overlay/Dialog/Dialog.mjs";
|
|
22
|
-
import { Dialog, usePreventBodyScroll
|
|
22
|
+
import { Dialog, usePreventBodyScroll } from "./styles/components/overlay/Dialog/Dialog.mjs";
|
|
23
23
|
import { Heading } from "./styles/components/typography/Heading/Heading.mjs";
|
|
24
24
|
import { Text } from "./styles/components/typography/Text/Text.mjs";
|
|
25
25
|
const Progress = forwardRef(function Progress2({ value, max = 100, className, ...restProps }, ref) {
|
|
@@ -354,6 +354,13 @@ const Tooltip = ({
|
|
|
354
354
|
)
|
|
355
355
|
] });
|
|
356
356
|
};
|
|
357
|
+
const useRootAriaHidden = (hidden) => {
|
|
358
|
+
const context = useContext(BlocksProviderContext);
|
|
359
|
+
if (!context) {
|
|
360
|
+
throw new Error("useRootAriaHidden must be used within a BlocksProvider");
|
|
361
|
+
}
|
|
362
|
+
context.setAriaHidden(hidden);
|
|
363
|
+
};
|
|
357
364
|
export {
|
|
358
365
|
BlocksProvider,
|
|
359
366
|
Box,
|
package/dist/momotaro.chunk.d.ts
CHANGED
|
@@ -234,7 +234,7 @@ declare const atoms: ((props: {
|
|
|
234
234
|
wide?: "center" | "flex-start" | "flex-end" | undefined;
|
|
235
235
|
} | undefined) | _vanilla_extract_sprinkles.ResponsiveArray<4 | 1 | 2 | 3, "center" | "flex-start" | "flex-end" | null>;
|
|
236
236
|
}) => string) & {
|
|
237
|
-
properties: Set<"borderRadius" | "color" | "borderWidth" | "fontFamily" | "fontSize" | "fontWeight" | "lineHeight" | "transition" | "boxShadow" | "alignContent" | "alignItems" | "alignSelf" | "backgroundColor" | "blockSize" | "columnGap" | "cursor" | "display" | "flexDirection" | "flexGrow" | "flexShrink" | "flexWrap" | "fontStyle" | "inlineSize" | "insetBlockEnd" | "insetBlockStart" | "insetInlineEnd" | "insetInlineStart" | "justifyContent" | "marginBlockEnd" | "marginBlockStart" | "marginInlineEnd" | "marginInlineStart" | "maxBlockSize" | "maxInlineSize" | "opacity" | "overflowBlock" | "overflowInline" | "paddingBlockEnd" | "paddingBlockStart" | "paddingInlineEnd" | "paddingInlineStart" | "pointerEvents" | "position" | "rowGap" | "textAlign" | "textTransform" | "userSelect" | "whiteSpace" | "wordBreak" | "wordWrap" | "border" | "borderColor" | "flex" | "gap" | "inset" | "insetBlock" | "insetInline" | "margin" | "marginBlock" | "marginInline" | "outline" | "overflow" | "padding" | "paddingBlock" | "paddingInline" | "placeItems" | "textDecoration"
|
|
237
|
+
properties: Set<"borderRadius" | "color" | "borderWidth" | "fontFamily" | "fontSize" | "fontWeight" | "lineHeight" | "transition" | "boxShadow" | "alignContent" | "alignItems" | "alignSelf" | "backgroundColor" | "blockSize" | "columnGap" | "cursor" | "display" | "flexDirection" | "flexGrow" | "flexShrink" | "flexWrap" | "fontStyle" | "inlineSize" | "insetBlockEnd" | "insetBlockStart" | "insetInlineEnd" | "insetInlineStart" | "justifyContent" | "marginBlockEnd" | "marginBlockStart" | "marginInlineEnd" | "marginInlineStart" | "maxBlockSize" | "maxInlineSize" | "opacity" | "overflowBlock" | "overflowInline" | "paddingBlockEnd" | "paddingBlockStart" | "paddingInlineEnd" | "paddingInlineStart" | "pointerEvents" | "position" | "rowGap" | "textAlign" | "textTransform" | "textWrap" | "userSelect" | "whiteSpace" | "wordBreak" | "wordWrap" | "border" | "borderColor" | "flex" | "gap" | "inset" | "insetBlock" | "insetInline" | "margin" | "marginBlock" | "marginInline" | "outline" | "overflow" | "padding" | "paddingBlock" | "paddingInline" | "placeItems" | "textDecoration">;
|
|
238
238
|
};
|
|
239
239
|
|
|
240
240
|
declare const breakpoints: {
|
|
@@ -330,7 +330,6 @@ type DividerTheme = {
|
|
|
330
330
|
};
|
|
331
331
|
};
|
|
332
332
|
type DialogTheme = {
|
|
333
|
-
backdrop: string;
|
|
334
333
|
dialog: string;
|
|
335
334
|
variants: {
|
|
336
335
|
size: 'small' | 'medium' | 'large';
|
|
@@ -1139,7 +1138,7 @@ type UseKeyboardOptions = {
|
|
|
1139
1138
|
enabled?: boolean;
|
|
1140
1139
|
type?: 'keydown' | 'keyup';
|
|
1141
1140
|
};
|
|
1142
|
-
declare const useKeyboard: (key: KeyboardEvent['key'], callback: () => void, { enabled, type }?: UseKeyboardOptions) => void;
|
|
1141
|
+
declare const useKeyboard: (key: KeyboardEvent['key'], callback: (event: KeyboardEvent) => void, { enabled, type }?: UseKeyboardOptions) => void;
|
|
1143
1142
|
|
|
1144
1143
|
declare const usePreventBodyScroll: (enabled?: boolean) => void;
|
|
1145
1144
|
|
|
@@ -12,33 +12,6 @@ const Portal = ({ children, container }) => {
|
|
|
12
12
|
container || document.body
|
|
13
13
|
);
|
|
14
14
|
};
|
|
15
|
-
const focusableSelectors = 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
16
|
-
const getFirstFocusableElement = (container) => {
|
|
17
|
-
const focusable = container.querySelector(focusableSelectors);
|
|
18
|
-
return focusable || null;
|
|
19
|
-
};
|
|
20
|
-
const focusFirstElement = (container) => {
|
|
21
|
-
const focusable = getFirstFocusableElement(container);
|
|
22
|
-
if (focusable) {
|
|
23
|
-
focusable.focus();
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
const useFocusLock = ({ ref, active }) => {
|
|
27
|
-
react.useEffect(() => {
|
|
28
|
-
if (!active) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
const handleFocus = (event) => {
|
|
32
|
-
if (ref.current && event.target instanceof HTMLElement && !ref.current.contains(event.target)) {
|
|
33
|
-
focusFirstElement(ref.current);
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
document.addEventListener("focusin", handleFocus);
|
|
37
|
-
return () => {
|
|
38
|
-
document.removeEventListener("focusin", handleFocus);
|
|
39
|
-
};
|
|
40
|
-
}, [active, ref]);
|
|
41
|
-
};
|
|
42
15
|
const useIsomorphicLayoutEffect = typeof window === "undefined" ? react.useEffect : react.useLayoutEffect;
|
|
43
16
|
const useKeyboard = (key, callback, { enabled = true, type = "keydown" } = {}) => {
|
|
44
17
|
react.useEffect(() => {
|
|
@@ -47,7 +20,7 @@ const useKeyboard = (key, callback, { enabled = true, type = "keydown" } = {}) =
|
|
|
47
20
|
}
|
|
48
21
|
function handleKeyDown(event) {
|
|
49
22
|
if (event.key === key) {
|
|
50
|
-
callback();
|
|
23
|
+
callback(event);
|
|
51
24
|
}
|
|
52
25
|
}
|
|
53
26
|
document.addEventListener(type, handleKeyDown);
|
|
@@ -110,21 +83,13 @@ const useRestoreFocus = (active) => {
|
|
|
110
83
|
target.current = document.activeElement;
|
|
111
84
|
}
|
|
112
85
|
react.useEffect(() => {
|
|
86
|
+
var _a;
|
|
113
87
|
if (target.current && !active && target.current instanceof HTMLElement) {
|
|
114
|
-
target.current.focus();
|
|
115
|
-
}
|
|
116
|
-
if (!active) {
|
|
88
|
+
(_a = target.current) == null ? void 0 : _a.focus();
|
|
117
89
|
target.current = null;
|
|
118
90
|
}
|
|
119
91
|
}, [active]);
|
|
120
92
|
};
|
|
121
|
-
const useRootAriaHidden = (hidden) => {
|
|
122
|
-
const context = react.useContext(styles_components_display_Divider_Divider_cjs.BlocksProviderContext);
|
|
123
|
-
if (!context) {
|
|
124
|
-
throw new Error("useRootAriaHidden must be used within a BlocksProvider");
|
|
125
|
-
}
|
|
126
|
-
context.setAriaHidden(hidden);
|
|
127
|
-
};
|
|
128
93
|
const useVisibilityState = (open) => {
|
|
129
94
|
const [visible, setVisible] = react.useState(open);
|
|
130
95
|
const hide = react.useCallback(() => {
|
|
@@ -166,38 +131,56 @@ const Dialog = ({
|
|
|
166
131
|
size,
|
|
167
132
|
...restProps
|
|
168
133
|
}) => {
|
|
169
|
-
const backdropClassName = styles_components_display_Divider_Divider_cjs.useComponentStyles("dialog", { backdrop: true }, false);
|
|
170
134
|
const dialogClassName = styles_components_display_Divider_Divider_cjs.useComponentStyles("dialog", { dialog: true, variants: { size } });
|
|
171
|
-
const backdropRef = react.useRef(null);
|
|
172
135
|
const dialogRef = react.useRef(null);
|
|
173
136
|
const layer = useLayer();
|
|
174
137
|
const [visible, hide] = useVisibilityState(open);
|
|
175
138
|
const [enabled, setEnabled] = react.useState(true);
|
|
176
|
-
const
|
|
139
|
+
const lastAction = react.useRef(0);
|
|
140
|
+
useRestoreFocus(open);
|
|
141
|
+
const isNested = useNestedDialog(visible);
|
|
142
|
+
usePreventBodyScroll(visible && !isNested);
|
|
143
|
+
const onEscape = react.useCallback(
|
|
177
144
|
(event) => {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
145
|
+
event.preventDefault();
|
|
146
|
+
onRequestClose();
|
|
181
147
|
},
|
|
182
148
|
[onRequestClose]
|
|
183
149
|
);
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
150
|
+
useKeyboard("Escape", onEscape, { enabled: open && enabled });
|
|
151
|
+
react.useEffect(() => {
|
|
152
|
+
if (!open || !enabled) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
lastAction.current = Date.now();
|
|
156
|
+
const listener = (event) => {
|
|
157
|
+
var _a;
|
|
158
|
+
if (lastAction.current + 30 > Date.now()) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
if ((_a = dialogRef.current) == null ? void 0 : _a.contains(event.target)) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
onRequestClose();
|
|
165
|
+
};
|
|
166
|
+
document.addEventListener("click", listener);
|
|
167
|
+
return () => {
|
|
168
|
+
document.removeEventListener("click", listener);
|
|
169
|
+
};
|
|
170
|
+
}, [enabled, onRequestClose, open]);
|
|
190
171
|
useIsomorphicLayoutEffect(() => {
|
|
191
172
|
var _a, _b;
|
|
173
|
+
if (!visible) {
|
|
174
|
+
(_a = dialogRef.current) == null ? void 0 : _a.close();
|
|
175
|
+
}
|
|
192
176
|
if (!open) {
|
|
193
|
-
(_a = backdropRef.current) == null ? void 0 : _a.removeAttribute("data-open");
|
|
194
177
|
(_b = dialogRef.current) == null ? void 0 : _b.removeAttribute("data-open");
|
|
195
178
|
return;
|
|
196
179
|
}
|
|
197
180
|
let timer = requestAnimationFrame(() => {
|
|
198
181
|
timer = requestAnimationFrame(() => {
|
|
199
182
|
var _a2, _b2;
|
|
200
|
-
(_a2 =
|
|
183
|
+
(_a2 = dialogRef.current) == null ? void 0 : _a2.showModal();
|
|
201
184
|
(_b2 = dialogRef.current) == null ? void 0 : _b2.setAttribute("data-open", "");
|
|
202
185
|
});
|
|
203
186
|
});
|
|
@@ -223,26 +206,16 @@ const Dialog = ({
|
|
|
223
206
|
}
|
|
224
207
|
const dataOpen = typeof window === "undefined" && open ? "" : void 0;
|
|
225
208
|
return /* @__PURE__ */ jsxRuntime.jsx(Portal, { container: layer(), children: /* @__PURE__ */ jsxRuntime.jsx(DialogContext.Provider, { value: { setEnabled }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
226
|
-
|
|
209
|
+
"dialog",
|
|
227
210
|
{
|
|
228
|
-
ref:
|
|
229
|
-
|
|
211
|
+
ref: dialogRef,
|
|
212
|
+
"aria-modal": "true",
|
|
230
213
|
"data-open": dataOpen,
|
|
231
|
-
|
|
214
|
+
className: styles_components_display_Divider_Divider_cjs.classnames(styles_components_overlay_Dialog_dialog_css_cjs.dialog, dialogClassName, className),
|
|
232
215
|
onAnimationEnd,
|
|
233
216
|
onTransitionEnd: onAnimationEnd,
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
{
|
|
237
|
-
ref: dialogRef,
|
|
238
|
-
"aria-modal": "true",
|
|
239
|
-
open: true,
|
|
240
|
-
"data-open": dataOpen,
|
|
241
|
-
className: styles_components_display_Divider_Divider_cjs.classnames(dialogClassName, className),
|
|
242
|
-
...restProps,
|
|
243
|
-
children
|
|
244
|
-
}
|
|
245
|
-
)
|
|
217
|
+
...restProps,
|
|
218
|
+
children
|
|
246
219
|
}
|
|
247
220
|
) }) });
|
|
248
221
|
};
|
|
@@ -253,5 +226,4 @@ exports.useIsomorphicLayoutEffect = useIsomorphicLayoutEffect;
|
|
|
253
226
|
exports.useKeyboard = useKeyboard;
|
|
254
227
|
exports.useLayer = useLayer;
|
|
255
228
|
exports.usePreventBodyScroll = usePreventBodyScroll;
|
|
256
|
-
exports.useRootAriaHidden = useRootAriaHidden;
|
|
257
229
|
exports.useVisibilityState = useVisibilityState;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useLayoutEffect, useRef,
|
|
3
|
-
import { useTheme,
|
|
4
|
-
import {
|
|
2
|
+
import { useEffect, useLayoutEffect, useRef, useState, useCallback, createContext, useContext } from "react";
|
|
3
|
+
import { useTheme, useComponentStyles, classnames } from "../../display/Divider/Divider.mjs";
|
|
4
|
+
import { dialog } from "./dialog.css.mjs";
|
|
5
5
|
import { createPortal } from "react-dom";
|
|
6
6
|
import { BlocksProvider } from "../../other/BlocksProvider/BlocksProvider.mjs";
|
|
7
7
|
const Portal = ({ children, container }) => {
|
|
@@ -11,33 +11,6 @@ const Portal = ({ children, container }) => {
|
|
|
11
11
|
container || document.body
|
|
12
12
|
);
|
|
13
13
|
};
|
|
14
|
-
const focusableSelectors = 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
15
|
-
const getFirstFocusableElement = (container) => {
|
|
16
|
-
const focusable = container.querySelector(focusableSelectors);
|
|
17
|
-
return focusable || null;
|
|
18
|
-
};
|
|
19
|
-
const focusFirstElement = (container) => {
|
|
20
|
-
const focusable = getFirstFocusableElement(container);
|
|
21
|
-
if (focusable) {
|
|
22
|
-
focusable.focus();
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
const useFocusLock = ({ ref, active }) => {
|
|
26
|
-
useEffect(() => {
|
|
27
|
-
if (!active) {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
const handleFocus = (event) => {
|
|
31
|
-
if (ref.current && event.target instanceof HTMLElement && !ref.current.contains(event.target)) {
|
|
32
|
-
focusFirstElement(ref.current);
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
document.addEventListener("focusin", handleFocus);
|
|
36
|
-
return () => {
|
|
37
|
-
document.removeEventListener("focusin", handleFocus);
|
|
38
|
-
};
|
|
39
|
-
}, [active, ref]);
|
|
40
|
-
};
|
|
41
14
|
const useIsomorphicLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
|
|
42
15
|
const useKeyboard = (key, callback, { enabled = true, type = "keydown" } = {}) => {
|
|
43
16
|
useEffect(() => {
|
|
@@ -46,7 +19,7 @@ const useKeyboard = (key, callback, { enabled = true, type = "keydown" } = {}) =
|
|
|
46
19
|
}
|
|
47
20
|
function handleKeyDown(event) {
|
|
48
21
|
if (event.key === key) {
|
|
49
|
-
callback();
|
|
22
|
+
callback(event);
|
|
50
23
|
}
|
|
51
24
|
}
|
|
52
25
|
document.addEventListener(type, handleKeyDown);
|
|
@@ -109,21 +82,13 @@ const useRestoreFocus = (active) => {
|
|
|
109
82
|
target.current = document.activeElement;
|
|
110
83
|
}
|
|
111
84
|
useEffect(() => {
|
|
85
|
+
var _a;
|
|
112
86
|
if (target.current && !active && target.current instanceof HTMLElement) {
|
|
113
|
-
target.current.focus();
|
|
114
|
-
}
|
|
115
|
-
if (!active) {
|
|
87
|
+
(_a = target.current) == null ? void 0 : _a.focus();
|
|
116
88
|
target.current = null;
|
|
117
89
|
}
|
|
118
90
|
}, [active]);
|
|
119
91
|
};
|
|
120
|
-
const useRootAriaHidden = (hidden) => {
|
|
121
|
-
const context = useContext(BlocksProviderContext);
|
|
122
|
-
if (!context) {
|
|
123
|
-
throw new Error("useRootAriaHidden must be used within a BlocksProvider");
|
|
124
|
-
}
|
|
125
|
-
context.setAriaHidden(hidden);
|
|
126
|
-
};
|
|
127
92
|
const useVisibilityState = (open) => {
|
|
128
93
|
const [visible, setVisible] = useState(open);
|
|
129
94
|
const hide = useCallback(() => {
|
|
@@ -165,38 +130,56 @@ const Dialog = ({
|
|
|
165
130
|
size,
|
|
166
131
|
...restProps
|
|
167
132
|
}) => {
|
|
168
|
-
const backdropClassName = useComponentStyles("dialog", { backdrop: true }, false);
|
|
169
133
|
const dialogClassName = useComponentStyles("dialog", { dialog: true, variants: { size } });
|
|
170
|
-
const backdropRef = useRef(null);
|
|
171
134
|
const dialogRef = useRef(null);
|
|
172
135
|
const layer = useLayer();
|
|
173
136
|
const [visible, hide] = useVisibilityState(open);
|
|
174
137
|
const [enabled, setEnabled] = useState(true);
|
|
175
|
-
const
|
|
138
|
+
const lastAction = useRef(0);
|
|
139
|
+
useRestoreFocus(open);
|
|
140
|
+
const isNested = useNestedDialog(visible);
|
|
141
|
+
usePreventBodyScroll(visible && !isNested);
|
|
142
|
+
const onEscape = useCallback(
|
|
176
143
|
(event) => {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
}
|
|
144
|
+
event.preventDefault();
|
|
145
|
+
onRequestClose();
|
|
180
146
|
},
|
|
181
147
|
[onRequestClose]
|
|
182
148
|
);
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
149
|
+
useKeyboard("Escape", onEscape, { enabled: open && enabled });
|
|
150
|
+
useEffect(() => {
|
|
151
|
+
if (!open || !enabled) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
lastAction.current = Date.now();
|
|
155
|
+
const listener = (event) => {
|
|
156
|
+
var _a;
|
|
157
|
+
if (lastAction.current + 30 > Date.now()) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if ((_a = dialogRef.current) == null ? void 0 : _a.contains(event.target)) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
onRequestClose();
|
|
164
|
+
};
|
|
165
|
+
document.addEventListener("click", listener);
|
|
166
|
+
return () => {
|
|
167
|
+
document.removeEventListener("click", listener);
|
|
168
|
+
};
|
|
169
|
+
}, [enabled, onRequestClose, open]);
|
|
189
170
|
useIsomorphicLayoutEffect(() => {
|
|
190
171
|
var _a, _b;
|
|
172
|
+
if (!visible) {
|
|
173
|
+
(_a = dialogRef.current) == null ? void 0 : _a.close();
|
|
174
|
+
}
|
|
191
175
|
if (!open) {
|
|
192
|
-
(_a = backdropRef.current) == null ? void 0 : _a.removeAttribute("data-open");
|
|
193
176
|
(_b = dialogRef.current) == null ? void 0 : _b.removeAttribute("data-open");
|
|
194
177
|
return;
|
|
195
178
|
}
|
|
196
179
|
let timer = requestAnimationFrame(() => {
|
|
197
180
|
timer = requestAnimationFrame(() => {
|
|
198
181
|
var _a2, _b2;
|
|
199
|
-
(_a2 =
|
|
182
|
+
(_a2 = dialogRef.current) == null ? void 0 : _a2.showModal();
|
|
200
183
|
(_b2 = dialogRef.current) == null ? void 0 : _b2.setAttribute("data-open", "");
|
|
201
184
|
});
|
|
202
185
|
});
|
|
@@ -222,26 +205,16 @@ const Dialog = ({
|
|
|
222
205
|
}
|
|
223
206
|
const dataOpen = typeof window === "undefined" && open ? "" : void 0;
|
|
224
207
|
return /* @__PURE__ */ jsx(Portal, { container: layer(), children: /* @__PURE__ */ jsx(DialogContext.Provider, { value: { setEnabled }, children: /* @__PURE__ */ jsx(
|
|
225
|
-
|
|
208
|
+
"dialog",
|
|
226
209
|
{
|
|
227
|
-
ref:
|
|
228
|
-
|
|
210
|
+
ref: dialogRef,
|
|
211
|
+
"aria-modal": "true",
|
|
229
212
|
"data-open": dataOpen,
|
|
230
|
-
|
|
213
|
+
className: classnames(dialog, dialogClassName, className),
|
|
231
214
|
onAnimationEnd,
|
|
232
215
|
onTransitionEnd: onAnimationEnd,
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
{
|
|
236
|
-
ref: dialogRef,
|
|
237
|
-
"aria-modal": "true",
|
|
238
|
-
open: true,
|
|
239
|
-
"data-open": dataOpen,
|
|
240
|
-
className: classnames(dialogClassName, className),
|
|
241
|
-
...restProps,
|
|
242
|
-
children
|
|
243
|
-
}
|
|
244
|
-
)
|
|
216
|
+
...restProps,
|
|
217
|
+
children
|
|
245
218
|
}
|
|
246
219
|
) }) });
|
|
247
220
|
};
|
|
@@ -253,6 +226,5 @@ export {
|
|
|
253
226
|
useKeyboard,
|
|
254
227
|
useLayer,
|
|
255
228
|
usePreventBodyScroll,
|
|
256
|
-
useRootAriaHidden,
|
|
257
229
|
useVisibilityState
|
|
258
230
|
};
|
|
@@ -3,21 +3,19 @@ const fileScope = require("@vanilla-extract/css/fileScope");
|
|
|
3
3
|
const css = require("@vanilla-extract/css");
|
|
4
4
|
const styles_lib_css_layers_layers_css_cjs = require("../../../lib/css/layers/layers.css.cjs");
|
|
5
5
|
fileScope.setFileScope("src/components/overlay/Dialog/dialog.css.ts", "@blockle/blocks");
|
|
6
|
-
const
|
|
6
|
+
const dialog = css.style({
|
|
7
7
|
"@layer": {
|
|
8
8
|
[styles_lib_css_layers_layers_css_cjs.blocksLayer]: {
|
|
9
|
-
contain: "layout",
|
|
10
|
-
display: "flex",
|
|
11
|
-
placeItems: "center",
|
|
12
9
|
position: "fixed",
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
inset: 0,
|
|
11
|
+
border: "none",
|
|
12
|
+
"::backdrop": {
|
|
13
|
+
// Remove pointer event to prevent clicks on the backdrop
|
|
14
|
+
// and make it easier to check if the click was outside the dialog
|
|
15
|
+
pointerEvents: "none"
|
|
16
|
+
}
|
|
19
17
|
}
|
|
20
18
|
}
|
|
21
|
-
}, "
|
|
19
|
+
}, "dialog");
|
|
22
20
|
fileScope.endFileScope();
|
|
23
|
-
exports.
|
|
21
|
+
exports.dialog = dialog;
|
|
@@ -2,23 +2,21 @@ import { setFileScope, endFileScope } from "@vanilla-extract/css/fileScope";
|
|
|
2
2
|
import { style } from "@vanilla-extract/css";
|
|
3
3
|
import { blocksLayer } from "../../../lib/css/layers/layers.css.mjs";
|
|
4
4
|
setFileScope("src/components/overlay/Dialog/dialog.css.ts", "@blockle/blocks");
|
|
5
|
-
const
|
|
5
|
+
const dialog = style({
|
|
6
6
|
"@layer": {
|
|
7
7
|
[blocksLayer]: {
|
|
8
|
-
contain: "layout",
|
|
9
|
-
display: "flex",
|
|
10
|
-
placeItems: "center",
|
|
11
8
|
position: "fixed",
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
inset: 0,
|
|
10
|
+
border: "none",
|
|
11
|
+
"::backdrop": {
|
|
12
|
+
// Remove pointer event to prevent clicks on the backdrop
|
|
13
|
+
// and make it easier to check if the click was outside the dialog
|
|
14
|
+
pointerEvents: "none"
|
|
15
|
+
}
|
|
18
16
|
}
|
|
19
17
|
}
|
|
20
|
-
}, "
|
|
18
|
+
}, "dialog");
|
|
21
19
|
endFileScope();
|
|
22
20
|
export {
|
|
23
|
-
|
|
21
|
+
dialog
|
|
24
22
|
};
|
|
@@ -16,34 +16,31 @@ const dialog = styles_lib_theme_makeComponentTheme_cjs.makeComponentTheme("dialo
|
|
|
16
16
|
}), {
|
|
17
17
|
maxHeight: "90%",
|
|
18
18
|
minWidth: "300px",
|
|
19
|
-
|
|
20
|
-
"
|
|
21
|
-
transform: "scale(1)"
|
|
22
|
-
}
|
|
19
|
+
"::backdrop": {
|
|
20
|
+
backgroundColor: "rgba(0, 0, 0, 0.5)"
|
|
23
21
|
},
|
|
24
|
-
// Apply the animation only if the user has not requested reduced motion
|
|
25
|
-
"@media": {
|
|
26
|
-
"(prefers-reduced-motion: no-preference)": {
|
|
27
|
-
transform: "scale(0.9)",
|
|
28
|
-
transition: "transform 160ms"
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}], "dialog_dialog"),
|
|
32
|
-
backdrop: css.style({
|
|
33
|
-
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
34
22
|
selectors: {
|
|
35
23
|
"&[data-open]": {
|
|
24
|
+
transform: "translate(0, 0)",
|
|
25
|
+
opacity: 1
|
|
26
|
+
},
|
|
27
|
+
"&[data-open]::backdrop": {
|
|
36
28
|
opacity: 1
|
|
37
29
|
}
|
|
38
30
|
},
|
|
39
31
|
// Apply the animation only if the user has not requested reduced motion
|
|
40
32
|
"@media": {
|
|
41
33
|
"(prefers-reduced-motion: no-preference)": {
|
|
34
|
+
transform: "translate(0, -120px)",
|
|
42
35
|
opacity: 0,
|
|
43
|
-
transition: "opacity 160ms"
|
|
36
|
+
transition: "transform 240ms, opacity 160ms",
|
|
37
|
+
"::backdrop": {
|
|
38
|
+
opacity: 0,
|
|
39
|
+
transition: "opacity 160ms"
|
|
40
|
+
}
|
|
44
41
|
}
|
|
45
42
|
}
|
|
46
|
-
}, "
|
|
43
|
+
}], "dialog_dialog"),
|
|
47
44
|
variants: {
|
|
48
45
|
size: {
|
|
49
46
|
small: css.style({
|
|
@@ -15,34 +15,31 @@ const dialog = makeComponentTheme("dialog", {
|
|
|
15
15
|
}), {
|
|
16
16
|
maxHeight: "90%",
|
|
17
17
|
minWidth: "300px",
|
|
18
|
-
|
|
19
|
-
"
|
|
20
|
-
transform: "scale(1)"
|
|
21
|
-
}
|
|
18
|
+
"::backdrop": {
|
|
19
|
+
backgroundColor: "rgba(0, 0, 0, 0.5)"
|
|
22
20
|
},
|
|
23
|
-
// Apply the animation only if the user has not requested reduced motion
|
|
24
|
-
"@media": {
|
|
25
|
-
"(prefers-reduced-motion: no-preference)": {
|
|
26
|
-
transform: "scale(0.9)",
|
|
27
|
-
transition: "transform 160ms"
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}], "dialog_dialog"),
|
|
31
|
-
backdrop: style({
|
|
32
|
-
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
33
21
|
selectors: {
|
|
34
22
|
"&[data-open]": {
|
|
23
|
+
transform: "translate(0, 0)",
|
|
24
|
+
opacity: 1
|
|
25
|
+
},
|
|
26
|
+
"&[data-open]::backdrop": {
|
|
35
27
|
opacity: 1
|
|
36
28
|
}
|
|
37
29
|
},
|
|
38
30
|
// Apply the animation only if the user has not requested reduced motion
|
|
39
31
|
"@media": {
|
|
40
32
|
"(prefers-reduced-motion: no-preference)": {
|
|
33
|
+
transform: "translate(0, -120px)",
|
|
41
34
|
opacity: 0,
|
|
42
|
-
transition: "opacity 160ms"
|
|
35
|
+
transition: "transform 240ms, opacity 160ms",
|
|
36
|
+
"::backdrop": {
|
|
37
|
+
opacity: 0,
|
|
38
|
+
transition: "opacity 160ms"
|
|
39
|
+
}
|
|
43
40
|
}
|
|
44
41
|
}
|
|
45
|
-
}, "
|
|
42
|
+
}], "dialog_dialog"),
|
|
46
43
|
variants: {
|
|
47
44
|
size: {
|
|
48
45
|
small: style({
|
|
@@ -37,12 +37,12 @@ const progress = styles_lib_theme_makeComponentTheme_cjs.makeComponentTheme("pro
|
|
|
37
37
|
// For reduce motion we show a striped pattern instead of animating
|
|
38
38
|
"(prefers-reduced-motion: reduce)": {
|
|
39
39
|
backgroundImage: `repeating-linear-gradient(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
45deg,
|
|
41
|
+
transparent,
|
|
42
|
+
transparent 20px,
|
|
43
|
+
${styles_lib_theme_vars_css_cjs.vars.color.primaryDark} 20px,
|
|
44
|
+
${styles_lib_theme_vars_css_cjs.vars.color.primaryDark} 40px
|
|
45
|
+
)`
|
|
46
46
|
},
|
|
47
47
|
"(prefers-reduced-motion: no-preference)": {
|
|
48
48
|
animation: `${indeterminateAnimation} 3s ease-in-out infinite`
|
|
@@ -36,12 +36,12 @@ const progress = makeComponentTheme("progress", {
|
|
|
36
36
|
// For reduce motion we show a striped pattern instead of animating
|
|
37
37
|
"(prefers-reduced-motion: reduce)": {
|
|
38
38
|
backgroundImage: `repeating-linear-gradient(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
45deg,
|
|
40
|
+
transparent,
|
|
41
|
+
transparent 20px,
|
|
42
|
+
${vars.color.primaryDark} 20px,
|
|
43
|
+
${vars.color.primaryDark} 40px
|
|
44
|
+
)`
|
|
45
45
|
},
|
|
46
46
|
"(prefers-reduced-motion: no-preference)": {
|
|
47
47
|
animation: `${indeterminateAnimation} 3s ease-in-out infinite`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blockle/blocks",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"description": "Blocks design system",
|
|
5
5
|
"repository": "git@github.com:Blockle/blocks.git",
|
|
6
6
|
"license": "MIT",
|
|
@@ -60,48 +60,49 @@
|
|
|
60
60
|
"string-width": "^4.2.2"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
|
-
"@changesets/cli": "^2.27.
|
|
64
|
-
"@crackle/cli": "^0.15.
|
|
65
|
-
"@crackle/core": "^0.33.
|
|
66
|
-
"@storybook/addon-a11y": "^8.
|
|
67
|
-
"@storybook/addon-coverage": "^1.0.
|
|
68
|
-
"@storybook/addon-essentials": "^8.
|
|
69
|
-
"@storybook/addon-interactions": "^8.
|
|
70
|
-
"@storybook/addon-links": "^8.
|
|
63
|
+
"@changesets/cli": "^2.27.5",
|
|
64
|
+
"@crackle/cli": "^0.15.4",
|
|
65
|
+
"@crackle/core": "^0.33.3",
|
|
66
|
+
"@storybook/addon-a11y": "^8.1.6",
|
|
67
|
+
"@storybook/addon-coverage": "^1.0.4",
|
|
68
|
+
"@storybook/addon-essentials": "^8.1.6",
|
|
69
|
+
"@storybook/addon-interactions": "^8.1.6",
|
|
70
|
+
"@storybook/addon-links": "^8.1.6",
|
|
71
71
|
"@storybook/addons": "^7.6.17",
|
|
72
|
-
"@storybook/blocks": "^8.
|
|
73
|
-
"@storybook/react": "^8.
|
|
74
|
-
"@storybook/react-vite": "^8.
|
|
75
|
-
"@storybook/test": "^8.
|
|
76
|
-
"@testing-library/jest-dom": "^6.4.
|
|
77
|
-
"@testing-library/react": "^
|
|
78
|
-
"@types/
|
|
79
|
-
"@types/react
|
|
80
|
-
"@
|
|
81
|
-
"@typescript-eslint/
|
|
82
|
-
"@
|
|
83
|
-
"@vanilla-extract/css
|
|
84
|
-
"@vanilla-extract/
|
|
85
|
-
"@vanilla-extract/
|
|
86
|
-
"@
|
|
87
|
-
"
|
|
72
|
+
"@storybook/blocks": "^8.1.6",
|
|
73
|
+
"@storybook/react": "^8.1.6",
|
|
74
|
+
"@storybook/react-vite": "^8.1.6",
|
|
75
|
+
"@storybook/test": "^8.1.6",
|
|
76
|
+
"@testing-library/jest-dom": "^6.4.5",
|
|
77
|
+
"@testing-library/react": "^16.0.0",
|
|
78
|
+
"@types/eslint": "^8.56.10",
|
|
79
|
+
"@types/react": "^18.3.3",
|
|
80
|
+
"@types/react-dom": "^18.3.0",
|
|
81
|
+
"@typescript-eslint/eslint-plugin": "^7.12.0",
|
|
82
|
+
"@typescript-eslint/parser": "^7.12.0",
|
|
83
|
+
"@vanilla-extract/css": "^1.15.2",
|
|
84
|
+
"@vanilla-extract/css-utils": "^0.1.4",
|
|
85
|
+
"@vanilla-extract/sprinkles": "^1.6.2",
|
|
86
|
+
"@vanilla-extract/vite-plugin": "^4.0.10",
|
|
87
|
+
"@vitest/coverage-v8": "^1.6.0",
|
|
88
|
+
"autoprefixer": "^10.4.19",
|
|
88
89
|
"cross-env": "^7.0.3",
|
|
89
|
-
"eslint": "^8
|
|
90
|
+
"eslint": "^8",
|
|
90
91
|
"eslint-config-prettier": "^9.1.0",
|
|
91
|
-
"eslint-plugin-jest": "^
|
|
92
|
+
"eslint-plugin-jest": "^28.6.0",
|
|
92
93
|
"eslint-plugin-prettier": "^5.1.3",
|
|
93
|
-
"eslint-plugin-react": "^7.34.
|
|
94
|
-
"eslint-plugin-react-hooks": "^4.6.
|
|
94
|
+
"eslint-plugin-react": "^7.34.2",
|
|
95
|
+
"eslint-plugin-react-hooks": "^4.6.2",
|
|
95
96
|
"eslint-plugin-storybook": "^0.8.0",
|
|
96
|
-
"eslint-plugin-unicorn": "^
|
|
97
|
-
"jsdom": "^24.
|
|
98
|
-
"prettier": "^3.
|
|
97
|
+
"eslint-plugin-unicorn": "^53.0.0",
|
|
98
|
+
"jsdom": "^24.1.0",
|
|
99
|
+
"prettier": "^3.3.1",
|
|
99
100
|
"prop-types": "^15.8.1",
|
|
100
|
-
"react": "^18.
|
|
101
|
-
"react-dom": "^18.
|
|
102
|
-
"storybook": "^8.
|
|
103
|
-
"typescript": "^5.4.
|
|
104
|
-
"vitest": "^1.
|
|
101
|
+
"react": "^18.3.1",
|
|
102
|
+
"react-dom": "^18.3.1",
|
|
103
|
+
"storybook": "^8.1.6",
|
|
104
|
+
"typescript": "^5.4.5",
|
|
105
|
+
"vitest": "^1.6.0"
|
|
105
106
|
},
|
|
106
107
|
"peerDependencies": {
|
|
107
108
|
"@vanilla-extract/css": "^1.14",
|