@refraktor/core 0.0.3 → 0.0.4
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/.turbo/turbo-build.log +1 -1
- package/build/components/button/button.styles.js +5 -5
- package/build/components/chip/chip-group/chip-group.d.ts +4 -0
- package/build/components/chip/chip-group/chip-group.d.ts.map +1 -0
- package/build/components/chip/chip-group/chip-group.js +43 -0
- package/build/components/chip/chip-group/index.d.ts +2 -0
- package/build/components/chip/chip-group/index.d.ts.map +1 -0
- package/build/components/chip/chip-group/index.js +1 -0
- package/build/components/chip/chip.context.d.ts +15 -0
- package/build/components/chip/chip.context.d.ts.map +1 -0
- package/build/components/chip/chip.context.js +2 -0
- package/build/components/chip/chip.d.ts +4 -0
- package/build/components/chip/chip.d.ts.map +1 -0
- package/build/components/chip/chip.js +85 -0
- package/build/components/chip/chip.styles.d.ts +5 -0
- package/build/components/chip/chip.styles.d.ts.map +1 -0
- package/build/components/chip/chip.styles.js +19 -0
- package/build/components/chip/chip.test.d.ts +2 -0
- package/build/components/chip/chip.test.d.ts.map +1 -0
- package/build/components/chip/chip.test.js +107 -0
- package/build/components/chip/chip.types.d.ts +95 -0
- package/build/components/chip/chip.types.d.ts.map +1 -0
- package/build/components/chip/chip.types.js +1 -0
- package/build/components/chip/index.d.ts +4 -0
- package/build/components/chip/index.d.ts.map +1 -0
- package/build/components/chip/index.js +2 -0
- package/build/components/combobox/combobox-dropdown/combobox-dropdown.d.ts +4 -0
- package/build/components/combobox/combobox-dropdown/combobox-dropdown.d.ts.map +1 -0
- package/build/components/combobox/combobox-dropdown/combobox-dropdown.js +21 -0
- package/build/components/combobox/combobox-dropdown/index.d.ts +2 -0
- package/build/components/combobox/combobox-dropdown/index.d.ts.map +1 -0
- package/build/components/combobox/combobox-dropdown/index.js +1 -0
- package/build/components/combobox/combobox-group/combobox-group.d.ts +4 -0
- package/build/components/combobox/combobox-group/combobox-group.d.ts.map +1 -0
- package/build/components/combobox/combobox-group/combobox-group.js +15 -0
- package/build/components/combobox/combobox-group/index.d.ts +2 -0
- package/build/components/combobox/combobox-group/index.d.ts.map +1 -0
- package/build/components/combobox/combobox-group/index.js +1 -0
- package/build/components/combobox/combobox-input/combobox-input.d.ts +4 -0
- package/build/components/combobox/combobox-input/combobox-input.d.ts.map +1 -0
- package/build/components/combobox/combobox-input/combobox-input.js +101 -0
- package/build/components/combobox/combobox-input/index.d.ts +2 -0
- package/build/components/combobox/combobox-input/index.d.ts.map +1 -0
- package/build/components/combobox/combobox-input/index.js +1 -0
- package/build/components/combobox/combobox-option/combobox-option.d.ts +4 -0
- package/build/components/combobox/combobox-option/combobox-option.d.ts.map +1 -0
- package/build/components/combobox/combobox-option/combobox-option.js +86 -0
- package/build/components/combobox/combobox-option/index.d.ts +2 -0
- package/build/components/combobox/combobox-option/index.d.ts.map +1 -0
- package/build/components/combobox/combobox-option/index.js +1 -0
- package/build/components/combobox/combobox-root/combobox-root.d.ts +4 -0
- package/build/components/combobox/combobox-root/combobox-root.d.ts.map +1 -0
- package/build/components/combobox/combobox-root/combobox-root.js +282 -0
- package/build/components/combobox/combobox-root/index.d.ts +2 -0
- package/build/components/combobox/combobox-root/index.d.ts.map +1 -0
- package/build/components/combobox/combobox-root/index.js +1 -0
- package/build/components/combobox/combobox.context.d.ts +73 -0
- package/build/components/combobox/combobox.context.d.ts.map +1 -0
- package/build/components/combobox/combobox.context.js +50 -0
- package/build/components/combobox/combobox.d.ts +4 -0
- package/build/components/combobox/combobox.d.ts.map +1 -0
- package/build/components/combobox/combobox.js +31 -0
- package/build/components/combobox/combobox.test.d.ts +2 -0
- package/build/components/combobox/combobox.test.d.ts.map +1 -0
- package/build/components/combobox/combobox.test.js +104 -0
- package/build/components/combobox/combobox.types.d.ts +205 -0
- package/build/components/combobox/combobox.types.d.ts.map +1 -0
- package/build/components/combobox/combobox.types.js +1 -0
- package/build/components/combobox/index.d.ts +8 -0
- package/build/components/combobox/index.d.ts.map +1 -0
- package/build/components/combobox/index.js +6 -0
- package/build/components/combobox/use-combobox.d.ts +32 -0
- package/build/components/combobox/use-combobox.d.ts.map +1 -0
- package/build/components/combobox/use-combobox.js +80 -0
- package/build/components/drawer/drawer-body/drawer-body.d.ts +4 -0
- package/build/components/drawer/drawer-body/drawer-body.d.ts.map +1 -0
- package/build/components/drawer/drawer-body/drawer-body.js +11 -0
- package/build/components/drawer/drawer-body/index.d.ts +2 -0
- package/build/components/drawer/drawer-body/index.d.ts.map +1 -0
- package/build/components/drawer/drawer-body/index.js +1 -0
- package/build/components/drawer/drawer-content/drawer-content.d.ts.map +1 -1
- package/build/components/drawer/drawer-content/drawer-content.js +9 -6
- package/build/components/drawer/drawer-overlay/drawer-overlay.d.ts.map +1 -1
- package/build/components/drawer/drawer-overlay/drawer-overlay.js +4 -4
- package/build/components/drawer/drawer-root/drawer-root.d.ts.map +1 -1
- package/build/components/drawer/drawer-root/drawer-root.js +8 -9
- package/build/components/drawer/drawer.context.d.ts +2 -1
- package/build/components/drawer/drawer.context.d.ts.map +1 -1
- package/build/components/drawer/drawer.d.ts.map +1 -1
- package/build/components/drawer/drawer.js +5 -3
- package/build/components/drawer/drawer.test.js +55 -16
- package/build/components/drawer/drawer.types.d.ts +29 -3
- package/build/components/drawer/drawer.types.d.ts.map +1 -1
- package/build/components/drawer/index.d.ts +2 -1
- package/build/components/drawer/index.d.ts.map +1 -1
- package/build/components/drawer/index.js +1 -0
- package/build/components/drawer/use-drawer.d.ts +8 -1
- package/build/components/drawer/use-drawer.d.ts.map +1 -1
- package/build/components/drawer/use-drawer.js +25 -38
- package/build/components/file-input/file-input.d.ts +4 -0
- package/build/components/file-input/file-input.d.ts.map +1 -0
- package/build/components/file-input/file-input.js +88 -0
- package/build/components/file-input/file-input.test.d.ts +2 -0
- package/build/components/file-input/file-input.test.d.ts.map +1 -0
- package/build/components/file-input/file-input.test.js +74 -0
- package/build/components/file-input/file-input.types.d.ts +46 -0
- package/build/components/file-input/file-input.types.d.ts.map +1 -0
- package/build/components/file-input/file-input.types.js +1 -0
- package/build/components/file-input/file-input.utils.d.ts +11 -0
- package/build/components/file-input/file-input.utils.d.ts.map +1 -0
- package/build/components/file-input/file-input.utils.js +67 -0
- package/build/components/file-input/file-input.utils.test.d.ts +2 -0
- package/build/components/file-input/file-input.utils.test.d.ts.map +1 -0
- package/build/components/file-input/file-input.utils.test.js +27 -0
- package/build/components/file-input/index.d.ts +3 -0
- package/build/components/file-input/index.d.ts.map +1 -0
- package/build/components/file-input/index.js +2 -0
- package/build/components/for/for.d.ts +8 -0
- package/build/components/for/for.d.ts.map +1 -0
- package/build/components/for/for.js +32 -0
- package/build/components/for/for.test.d.ts +2 -0
- package/build/components/for/for.test.d.ts.map +1 -0
- package/build/components/for/for.test.js +31 -0
- package/build/components/for/for.types.d.ts +33 -0
- package/build/components/for/for.types.d.ts.map +1 -0
- package/build/components/for/for.types.js +1 -0
- package/build/components/for/index.d.ts +3 -0
- package/build/components/for/index.d.ts.map +1 -0
- package/build/components/for/index.js +1 -0
- package/build/components/index.d.ts +6 -0
- package/build/components/index.d.ts.map +1 -1
- package/build/components/index.js +6 -0
- package/build/components/modal/index.d.ts +2 -1
- package/build/components/modal/index.d.ts.map +1 -1
- package/build/components/modal/index.js +1 -0
- package/build/components/modal/modal-body/index.d.ts +2 -0
- package/build/components/modal/modal-body/index.d.ts.map +1 -0
- package/build/components/modal/modal-body/index.js +1 -0
- package/build/components/modal/modal-body/modal-body.d.ts +4 -0
- package/build/components/modal/modal-body/modal-body.d.ts.map +1 -0
- package/build/components/modal/modal-body/modal-body.js +11 -0
- package/build/components/modal/modal-content/modal-content.d.ts.map +1 -1
- package/build/components/modal/modal-content/modal-content.js +13 -5
- package/build/components/modal/modal-header/modal-header.js +2 -2
- package/build/components/modal/modal-overlay/modal-overlay.d.ts.map +1 -1
- package/build/components/modal/modal-overlay/modal-overlay.js +4 -4
- package/build/components/modal/modal-root/modal-root.d.ts.map +1 -1
- package/build/components/modal/modal-root/modal-root.js +12 -9
- package/build/components/modal/modal.context.d.ts +5 -2
- package/build/components/modal/modal.context.d.ts.map +1 -1
- package/build/components/modal/modal.d.ts.map +1 -1
- package/build/components/modal/modal.js +5 -3
- package/build/components/modal/modal.test.js +78 -13
- package/build/components/modal/modal.types.d.ts +34 -5
- package/build/components/modal/modal.types.d.ts.map +1 -1
- package/build/components/modal/use-modal.d.ts +8 -1
- package/build/components/modal/use-modal.d.ts.map +1 -1
- package/build/components/modal/use-modal.js +25 -38
- package/build/components/password-input/index.d.ts +3 -0
- package/build/components/password-input/index.d.ts.map +1 -0
- package/build/components/password-input/index.js +2 -0
- package/build/components/password-input/password-input.d.ts +4 -0
- package/build/components/password-input/password-input.d.ts.map +1 -0
- package/build/components/password-input/password-input.js +32 -0
- package/build/components/password-input/password-input.test.d.ts +2 -0
- package/build/components/password-input/password-input.test.d.ts.map +1 -0
- package/build/components/password-input/password-input.test.js +47 -0
- package/build/components/password-input/password-input.types.d.ts +24 -0
- package/build/components/password-input/password-input.types.d.ts.map +1 -0
- package/build/components/password-input/password-input.types.js +1 -0
- package/build/components/pin-input/index.d.ts +3 -0
- package/build/components/pin-input/index.d.ts.map +1 -0
- package/build/components/pin-input/index.js +2 -0
- package/build/components/pin-input/pin-input.d.ts +4 -0
- package/build/components/pin-input/pin-input.d.ts.map +1 -0
- package/build/components/pin-input/pin-input.js +245 -0
- package/build/components/pin-input/pin-input.test.d.ts +2 -0
- package/build/components/pin-input/pin-input.test.d.ts.map +1 -0
- package/build/components/pin-input/pin-input.test.js +87 -0
- package/build/components/pin-input/pin-input.types.d.ts +44 -0
- package/build/components/pin-input/pin-input.types.d.ts.map +1 -0
- package/build/components/pin-input/pin-input.types.js +1 -0
- package/build/components/scroll-area/index.d.ts +3 -0
- package/build/components/scroll-area/index.d.ts.map +1 -0
- package/build/components/scroll-area/index.js +1 -0
- package/build/components/scroll-area/scroll-area.d.ts +4 -0
- package/build/components/scroll-area/scroll-area.d.ts.map +1 -0
- package/build/components/scroll-area/scroll-area.js +30 -0
- package/build/components/scroll-area/scroll-area.test.d.ts +2 -0
- package/build/components/scroll-area/scroll-area.test.d.ts.map +1 -0
- package/build/components/scroll-area/scroll-area.test.js +39 -0
- package/build/components/scroll-area/scroll-area.types.d.ts +25 -0
- package/build/components/scroll-area/scroll-area.types.d.ts.map +1 -0
- package/build/components/scroll-area/scroll-area.types.js +1 -0
- package/build/components/segmented-control/segmented-control.d.ts.map +1 -1
- package/build/components/segmented-control/segmented-control.js +3 -3
- package/build/components/segmented-control/segmented-control.styles.js +13 -13
- package/build/components/segmented-control/segmented-control.test.js +11 -0
- package/build/components/segmented-control/segmented-control.types.d.ts +2 -0
- package/build/components/segmented-control/segmented-control.types.d.ts.map +1 -1
- package/build/icons/eye-off.d.ts +4 -0
- package/build/icons/eye-off.d.ts.map +1 -0
- package/build/icons/eye-off.js +5 -0
- package/build/icons/eye.d.ts +4 -0
- package/build/icons/eye.d.ts.map +1 -0
- package/build/icons/eye.js +5 -0
- package/build/icons/index.d.ts +2 -0
- package/build/icons/index.d.ts.map +1 -1
- package/build/icons/index.js +2 -0
- package/build/style.css +1 -1
- package/package.json +2 -2
- package/src/components/button/button.styles.ts +5 -5
- package/src/components/chip/chip-group/chip-group.tsx +107 -0
- package/src/components/chip/chip-group/index.ts +1 -0
- package/src/components/chip/chip.context.ts +15 -0
- package/src/components/chip/chip.styles.ts +36 -0
- package/src/components/chip/chip.test.tsx +197 -0
- package/src/components/chip/chip.tsx +208 -0
- package/src/components/chip/chip.types.ts +134 -0
- package/src/components/chip/index.ts +10 -0
- package/src/components/drawer/drawer-body/drawer-body.tsx +29 -0
- package/src/components/drawer/drawer-body/index.ts +1 -0
- package/src/components/drawer/drawer-content/drawer-content.tsx +63 -26
- package/src/components/drawer/drawer-overlay/drawer-overlay.tsx +6 -5
- package/src/components/drawer/drawer-root/drawer-root.tsx +17 -18
- package/src/components/drawer/drawer.context.ts +2 -1
- package/src/components/drawer/drawer.test.tsx +144 -36
- package/src/components/drawer/drawer.tsx +31 -3
- package/src/components/drawer/drawer.types.ts +37 -3
- package/src/components/drawer/index.ts +2 -0
- package/src/components/drawer/use-drawer.ts +44 -51
- package/src/components/file-input/file-input.test.tsx +134 -0
- package/src/components/file-input/file-input.tsx +224 -0
- package/src/components/file-input/file-input.types.ts +78 -0
- package/src/components/file-input/file-input.utils.test.ts +36 -0
- package/src/components/file-input/file-input.utils.ts +130 -0
- package/src/components/file-input/index.ts +2 -0
- package/src/components/for/for.test.tsx +66 -0
- package/src/components/for/for.tsx +53 -0
- package/src/components/for/for.types.ts +40 -0
- package/src/components/for/index.ts +2 -0
- package/src/components/index.ts +6 -0
- package/src/components/menu/menu-dropdown/menu-dropdown.tsx +220 -220
- package/src/components/menu/menu-sub-dropdown/menu-sub-dropdown.tsx +221 -221
- package/src/components/modal/index.ts +4 -1
- package/src/components/modal/modal-body/index.ts +1 -0
- package/src/components/modal/modal-body/modal-body.tsx +29 -0
- package/src/components/modal/modal-content/modal-content.tsx +71 -24
- package/src/components/modal/modal-header/modal-header.tsx +2 -2
- package/src/components/modal/modal-overlay/modal-overlay.tsx +46 -45
- package/src/components/modal/modal-root/modal-root.tsx +22 -17
- package/src/components/modal/modal.context.ts +5 -2
- package/src/components/modal/modal.test.tsx +234 -64
- package/src/components/modal/modal.tsx +36 -4
- package/src/components/modal/modal.types.ts +49 -8
- package/src/components/modal/use-modal.ts +44 -51
- package/src/components/password-input/index.ts +2 -0
- package/src/components/password-input/password-input.test.tsx +72 -0
- package/src/components/password-input/password-input.tsx +85 -0
- package/src/components/password-input/password-input.types.ts +30 -0
- package/src/components/pin-input/index.ts +2 -0
- package/src/components/pin-input/pin-input.test.tsx +149 -0
- package/src/components/pin-input/pin-input.tsx +473 -0
- package/src/components/pin-input/pin-input.types.ts +78 -0
- package/src/components/scroll-area/index.ts +6 -0
- package/src/components/scroll-area/scroll-area.test.tsx +72 -0
- package/src/components/scroll-area/scroll-area.tsx +70 -0
- package/src/components/scroll-area/scroll-area.types.ts +37 -0
- package/src/components/segmented-control/segmented-control.styles.ts +13 -13
- package/src/components/segmented-control/segmented-control.test.tsx +18 -0
- package/src/components/segmented-control/segmented-control.tsx +11 -1
- package/src/components/segmented-control/segmented-control.types.ts +3 -0
- package/src/components/select/select-dropdown/select-dropdown.tsx +299 -299
- package/src/components/select/select-root/select-root.tsx +333 -333
- package/src/components/select/select-trigger/select-trigger.tsx +123 -123
- package/src/components/select/select.context.ts +140 -140
- package/src/components/select/select.test.tsx +190 -190
- package/src/components/select/select.types.ts +272 -272
- package/src/components/select/use-select.ts +170 -170
- package/src/icons/eye-off.tsx +30 -0
- package/src/icons/eye.tsx +24 -0
- package/src/icons/index.ts +2 -0
- package/src/style.css +14 -8
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal-root.d.ts","sourceRoot":"","sources":["../../../../src/components/modal/modal-root/modal-root.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"modal-root.d.ts","sourceRoot":"","sources":["../../../../src/components/modal/modal-root/modal-root.tsx"],"names":[],"mappings":"AAKA,OAAO,EAEH,uBAAuB,EAE1B,MAAM,gBAAgB,CAAC;AAcxB,QAAA,MAAM,SAAS,gEAiEb,CAAC;AAIH,eAAe,SAAS,CAAC"}
|
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useId } from "@refraktor/utils";
|
|
3
|
-
import { useRef } from "react";
|
|
4
3
|
import { useTheme } from "../../../theme";
|
|
5
4
|
import { factory, useClassNames, useProps } from "../../../utils";
|
|
6
5
|
import { ModalProvider } from "../modal.context";
|
|
7
6
|
import { useModal } from "../use-modal";
|
|
8
|
-
import { RemoveScroll } from "react-remove-scroll";
|
|
9
7
|
const defaultProps = {
|
|
10
8
|
closeOnClickOutside: true,
|
|
11
9
|
closeOnEscape: true,
|
|
12
10
|
lockScroll: true,
|
|
13
11
|
withinPortal: true,
|
|
14
|
-
radius: "md"
|
|
12
|
+
radius: "md",
|
|
13
|
+
size: "md",
|
|
14
|
+
centered: true,
|
|
15
|
+
trapFocus: true,
|
|
16
|
+
returnFocus: true
|
|
15
17
|
};
|
|
16
18
|
const ModalRoot = factory((_props, ref) => {
|
|
17
19
|
const { cx } = useTheme();
|
|
18
|
-
const { id, children, opened, defaultOpened, onOpenedChange, closeOnClickOutside, closeOnEscape, lockScroll, withinPortal, radius, transitionProps, className, classNames, ...props } = useProps("Modal", defaultProps, _props);
|
|
20
|
+
const { id, children, opened, defaultOpened, onOpenedChange, closeOnClickOutside, closeOnEscape, lockScroll, withinPortal, radius, size, centered, trapFocus, returnFocus, transitionProps, className, classNames, ...props } = useProps("Modal", defaultProps, _props);
|
|
19
21
|
const classes = useClassNames("Modal", classNames);
|
|
20
22
|
const _id = useId(id);
|
|
21
23
|
const headerId = `${_id}-header`;
|
|
22
|
-
const contentRef = useRef(null);
|
|
23
24
|
const modal = useModal({
|
|
24
25
|
opened,
|
|
25
26
|
defaultOpened,
|
|
26
27
|
onOpenedChange,
|
|
27
28
|
closeOnClickOutside,
|
|
28
|
-
closeOnEscape
|
|
29
|
-
contentRef
|
|
29
|
+
closeOnEscape
|
|
30
30
|
});
|
|
31
31
|
const getStyles = (part) => classes[part];
|
|
32
32
|
return (_jsx(ModalProvider, { value: {
|
|
@@ -35,12 +35,15 @@ const ModalRoot = factory((_props, ref) => {
|
|
|
35
35
|
lockScroll,
|
|
36
36
|
withinPortal,
|
|
37
37
|
radius,
|
|
38
|
+
size,
|
|
39
|
+
centered,
|
|
40
|
+
trapFocus,
|
|
41
|
+
returnFocus,
|
|
38
42
|
transitionProps,
|
|
39
43
|
headerId,
|
|
40
|
-
contentRef,
|
|
41
44
|
classNames,
|
|
42
45
|
getStyles
|
|
43
|
-
}, children: _jsx(
|
|
46
|
+
}, children: _jsx("div", { ref: ref, id: _id, className: cx(classes.root, className), ...props, children: children }) }));
|
|
44
47
|
});
|
|
45
48
|
ModalRoot.displayName = "@refraktor/core/Modal.Root";
|
|
46
49
|
export default ModalRoot;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RefraktorRadius } from "../../theme";
|
|
2
2
|
import { TransitionProps } from "../transition";
|
|
3
|
-
import { ModalClassNames } from "./modal.types";
|
|
3
|
+
import { ModalClassNames, ModalSize } from "./modal.types";
|
|
4
4
|
import { UseModalReturn } from "./use-modal";
|
|
5
5
|
export interface ModalContextValue {
|
|
6
6
|
modal: UseModalReturn;
|
|
@@ -8,9 +8,12 @@ export interface ModalContextValue {
|
|
|
8
8
|
lockScroll: boolean;
|
|
9
9
|
withinPortal: boolean;
|
|
10
10
|
radius: RefraktorRadius;
|
|
11
|
+
size: ModalSize;
|
|
12
|
+
centered: boolean;
|
|
13
|
+
trapFocus: boolean;
|
|
14
|
+
returnFocus: boolean;
|
|
11
15
|
transitionProps?: Omit<TransitionProps, "children" | "mounted">;
|
|
12
16
|
headerId: string;
|
|
13
|
-
contentRef: React.MutableRefObject<HTMLDivElement | null>;
|
|
14
17
|
classNames?: ModalClassNames;
|
|
15
18
|
getStyles: (part: keyof ModalClassNames) => string | undefined;
|
|
16
19
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal.context.d.ts","sourceRoot":"","sources":["../../../src/components/modal/modal.context.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"modal.context.d.ts","sourceRoot":"","sources":["../../../src/components/modal/modal.context.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,iBAAiB;IAC9B,KAAK,EAAE,cAAc,CAAC;IACtB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,eAAe,CAAC;IACxB,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,SAAS,CAAC,CAAC;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,eAAe,KAAK,MAAM,GAAG,SAAS,CAAC;CAClE;AAED,eAAO,MAAO,aAAa;;;+CAAE,eAAe,yBAGvC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../../../src/components/modal/modal.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../../../src/components/modal/modal.tsx"],"names":[],"mappings":"AAWA,OAAO,EAEH,mBAAmB,EAEtB,MAAM,eAAe,CAAC;AAEvB,QAAA,MAAM,KAAK,yDA4BV,CAAC;AAYF,eAAe,KAAK,CAAC"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { createClassNamesConfig, createComponentConfig, factory } from "../../utils";
|
|
3
|
+
import { ModalBody } from "./modal-body";
|
|
3
4
|
import { ModalClose } from "./modal-close";
|
|
4
5
|
import { ModalContent } from "./modal-content";
|
|
5
6
|
import { ModalHeader } from "./modal-header";
|
|
6
7
|
import { ModalOverlay } from "./modal-overlay";
|
|
7
8
|
import { ModalRoot } from "./modal-root";
|
|
8
|
-
const Modal = factory((
|
|
9
|
-
return
|
|
9
|
+
const Modal = factory(({ title, withOverlay = true, withCloseButton = true, overlayProps, children, ...rootProps }, ref) => {
|
|
10
|
+
return (_jsxs(ModalRoot, { ...rootProps, ref: ref, children: [withOverlay && _jsx(ModalOverlay, { ...overlayProps }), _jsxs(ModalContent, { children: [(title || withCloseButton) && (_jsx(ModalHeader, { withClose: withCloseButton, children: title })), _jsx(ModalBody, { children: children })] })] }));
|
|
10
11
|
});
|
|
11
12
|
Modal.displayName = "@refraktor/core/Modal";
|
|
12
13
|
Modal.configure = createComponentConfig();
|
|
@@ -15,5 +16,6 @@ Modal.Root = ModalRoot;
|
|
|
15
16
|
Modal.Overlay = ModalOverlay;
|
|
16
17
|
Modal.Content = ModalContent;
|
|
17
18
|
Modal.Header = ModalHeader;
|
|
19
|
+
Modal.Body = ModalBody;
|
|
18
20
|
Modal.Close = ModalClose;
|
|
19
21
|
export default Modal;
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { describe, expect, it, vi } from "vitest";
|
|
3
3
|
import { render, screen, userEvent, waitFor } from "../../vitest";
|
|
4
4
|
import Modal from "./modal";
|
|
5
|
+
import { ModalBody } from "./modal-body";
|
|
5
6
|
import { ModalContent } from "./modal-content";
|
|
6
7
|
import { ModalOverlay } from "./modal-overlay";
|
|
7
8
|
import { ModalRoot } from "./modal-root";
|
|
@@ -12,7 +13,7 @@ describe("@refraktor/core/Modal", () => {
|
|
|
12
13
|
};
|
|
13
14
|
it("renders with compound subcomponents and closes with header close button", async () => {
|
|
14
15
|
const user = userEvent.setup();
|
|
15
|
-
await render(_jsxs(Modal, { defaultOpened: true, transitionProps: transitionProps, children: [_jsx(Modal.Overlay, {}), _jsxs(Modal.Content, { children: [_jsx(Modal.Header, {
|
|
16
|
+
await render(_jsxs(Modal.Root, { defaultOpened: true, transitionProps: transitionProps, children: [_jsx(Modal.Overlay, {}), _jsxs(Modal.Content, { children: [_jsx(Modal.Header, { children: "Delete item" }), _jsx(Modal.Body, { children: _jsx("p", { children: "Are you sure?" }) })] })] }));
|
|
16
17
|
expect(await screen.findByRole("dialog", { name: "Delete item" })).toBeInTheDocument();
|
|
17
18
|
await user.click(screen.getByRole("button", { name: "Close" }));
|
|
18
19
|
await waitFor(() => {
|
|
@@ -22,13 +23,13 @@ describe("@refraktor/core/Modal", () => {
|
|
|
22
23
|
it("calls onOpenedChange when clicking overlay in controlled mode", async () => {
|
|
23
24
|
const user = userEvent.setup();
|
|
24
25
|
const onOpenedChange = vi.fn();
|
|
25
|
-
await render(_jsxs(Modal, { opened: true, onOpenedChange: onOpenedChange, transitionProps: transitionProps, children: [_jsx(Modal.Overlay, { "data-testid": "overlay" }), _jsx(Modal.Content, { children: "Controlled modal" })] }));
|
|
26
|
+
await render(_jsxs(Modal.Root, { opened: true, onOpenedChange: onOpenedChange, transitionProps: transitionProps, children: [_jsx(Modal.Overlay, { "data-testid": "overlay" }), _jsx(Modal.Content, { children: "Controlled modal" })] }));
|
|
26
27
|
await user.click(await screen.findByTestId("overlay"));
|
|
27
28
|
expect(onOpenedChange).toHaveBeenCalledWith(false);
|
|
28
29
|
});
|
|
29
30
|
it("closes on Escape key", async () => {
|
|
30
31
|
const user = userEvent.setup();
|
|
31
|
-
await render(_jsx(Modal, { defaultOpened: true, transitionProps: transitionProps, children: _jsx(Modal.Content, { children: "Keyboard close" }) }));
|
|
32
|
+
await render(_jsx(Modal.Root, { defaultOpened: true, transitionProps: transitionProps, children: _jsx(Modal.Content, { children: "Keyboard close" }) }));
|
|
32
33
|
await screen.findByRole("dialog");
|
|
33
34
|
await user.keyboard("{Escape}");
|
|
34
35
|
await waitFor(() => {
|
|
@@ -40,7 +41,7 @@ describe("@refraktor/core/Modal", () => {
|
|
|
40
41
|
expect(await screen.findByRole("dialog")).toBeInTheDocument();
|
|
41
42
|
});
|
|
42
43
|
it("applies custom overlay background opacity and blur", async () => {
|
|
43
|
-
await render(_jsxs(Modal, { defaultOpened: true, transitionProps: transitionProps, children: [_jsx(Modal.Overlay, { "data-testid": "overlay", backgroundOpacity: 0.4, blur: 6 }), _jsx(Modal.Content, { children: "Styled overlay" })] }));
|
|
44
|
+
await render(_jsxs(Modal.Root, { defaultOpened: true, transitionProps: transitionProps, children: [_jsx(Modal.Overlay, { "data-testid": "overlay", backgroundOpacity: 0.4, blur: 6 }), _jsx(Modal.Content, { children: "Styled overlay" })] }));
|
|
44
45
|
const overlay = await screen.findByTestId("overlay");
|
|
45
46
|
expect(overlay).toHaveStyle({
|
|
46
47
|
backgroundColor: "rgba(0, 0, 0, 0.4)",
|
|
@@ -48,22 +49,86 @@ describe("@refraktor/core/Modal", () => {
|
|
|
48
49
|
});
|
|
49
50
|
});
|
|
50
51
|
it("does not set backdrop blur for zero blur", async () => {
|
|
51
|
-
await render(_jsxs(Modal, { defaultOpened: true, transitionProps: transitionProps, children: [_jsx(Modal.Overlay, { "data-testid": "overlay", blur: 0 }), _jsx(Modal.Content, { children: "No blur" })] }));
|
|
52
|
+
await render(_jsxs(Modal.Root, { defaultOpened: true, transitionProps: transitionProps, children: [_jsx(Modal.Overlay, { "data-testid": "overlay", blur: 0 }), _jsx(Modal.Content, { children: "No blur" })] }));
|
|
52
53
|
const overlay = await screen.findByTestId("overlay");
|
|
53
54
|
expect(overlay).toHaveStyle({
|
|
54
55
|
backgroundColor: "rgba(0, 0, 0, 0.5)"
|
|
55
56
|
});
|
|
56
57
|
expect(overlay.style.backdropFilter).toBe("");
|
|
57
58
|
});
|
|
58
|
-
it("
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
it("renders Modal.Body subcomponent", async () => {
|
|
60
|
+
await render(_jsx(Modal.Root, { defaultOpened: true, transitionProps: transitionProps, children: _jsx(Modal.Content, { children: _jsx(Modal.Body, { "data-testid": "body", children: "Body content" }) }) }));
|
|
61
|
+
const body = await screen.findByTestId("body");
|
|
62
|
+
expect(body).toBeInTheDocument();
|
|
63
|
+
expect(body).toHaveTextContent("Body content");
|
|
64
|
+
});
|
|
65
|
+
it("renders standalone ModalBody component", async () => {
|
|
66
|
+
await render(_jsx(ModalRoot, { defaultOpened: true, transitionProps: transitionProps, children: _jsx(ModalContent, { children: _jsx(ModalBody, { "data-testid": "body", children: "Standalone body" }) }) }));
|
|
67
|
+
expect(await screen.findByTestId("body")).toHaveTextContent("Standalone body");
|
|
68
|
+
});
|
|
69
|
+
describe("single-component shorthand API", () => {
|
|
70
|
+
it("renders with title, overlay, close button, and body", async () => {
|
|
71
|
+
await render(_jsx(Modal, { defaultOpened: true, title: "Confirm action", transitionProps: transitionProps, children: _jsx("p", { children: "Are you sure?" }) }));
|
|
72
|
+
expect(await screen.findByRole("dialog", { name: "Confirm action" })).toBeInTheDocument();
|
|
73
|
+
expect(screen.getByText("Are you sure?")).toBeInTheDocument();
|
|
74
|
+
expect(screen.getByRole("button", { name: "Close" })).toBeInTheDocument();
|
|
63
75
|
});
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
expect(
|
|
76
|
+
it("hides overlay when withOverlay is false", async () => {
|
|
77
|
+
const { container } = await render(_jsx(Modal, { defaultOpened: true, title: "No overlay", withOverlay: false, transitionProps: transitionProps }));
|
|
78
|
+
expect(await screen.findByRole("dialog")).toBeInTheDocument();
|
|
79
|
+
expect(container.ownerDocument.querySelector("[aria-hidden='true']")).toBeNull();
|
|
80
|
+
});
|
|
81
|
+
it("hides close button when withCloseButton is false", async () => {
|
|
82
|
+
await render(_jsx(Modal, { defaultOpened: true, title: "No close", withCloseButton: false, transitionProps: transitionProps }));
|
|
83
|
+
await screen.findByRole("dialog");
|
|
84
|
+
expect(screen.queryByRole("button", { name: "Close" })).not.toBeInTheDocument();
|
|
85
|
+
});
|
|
86
|
+
it("closes via shorthand close button", async () => {
|
|
87
|
+
const user = userEvent.setup();
|
|
88
|
+
await render(_jsx(Modal, { defaultOpened: true, title: "Closeable", transitionProps: transitionProps, children: "Content" }));
|
|
89
|
+
await screen.findByRole("dialog");
|
|
90
|
+
await user.click(screen.getByRole("button", { name: "Close" }));
|
|
91
|
+
await waitFor(() => {
|
|
92
|
+
expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
it("passes overlayProps to the overlay", async () => {
|
|
96
|
+
await render(_jsx(Modal, { defaultOpened: true, title: "Custom overlay", overlayProps: {
|
|
97
|
+
backgroundOpacity: 0.8,
|
|
98
|
+
blur: 10,
|
|
99
|
+
"data-testid": "shorthand-overlay"
|
|
100
|
+
}, transitionProps: transitionProps, children: "Content" }));
|
|
101
|
+
const overlay = await screen.findByTestId("shorthand-overlay");
|
|
102
|
+
expect(overlay).toHaveStyle({
|
|
103
|
+
backgroundColor: "rgba(0, 0, 0, 0.8)",
|
|
104
|
+
backdropFilter: "blur(10px)"
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
describe("size prop", () => {
|
|
109
|
+
it("applies md size by default", async () => {
|
|
110
|
+
await render(_jsx(Modal.Root, { defaultOpened: true, transitionProps: transitionProps, children: _jsx(Modal.Content, { "data-testid": "content", children: "Default size" }) }));
|
|
111
|
+
const dialog = await screen.findByRole("dialog");
|
|
112
|
+
expect(dialog.className).toContain("max-w-md");
|
|
113
|
+
});
|
|
114
|
+
it("applies custom size", async () => {
|
|
115
|
+
await render(_jsx(Modal.Root, { defaultOpened: true, size: "lg", transitionProps: transitionProps, children: _jsx(Modal.Content, { children: "Large modal" }) }));
|
|
116
|
+
const dialog = await screen.findByRole("dialog");
|
|
117
|
+
expect(dialog.className).toContain("max-w-lg");
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
describe("centered prop", () => {
|
|
121
|
+
it("centers vertically by default", async () => {
|
|
122
|
+
await render(_jsx(Modal.Root, { defaultOpened: true, transitionProps: transitionProps, children: _jsx(Modal.Content, { children: "Centered" }) }));
|
|
123
|
+
await screen.findByRole("dialog");
|
|
124
|
+
const wrapper = screen.getByRole("dialog").parentElement?.parentElement;
|
|
125
|
+
expect(wrapper?.className).toContain("place-items-center");
|
|
126
|
+
});
|
|
127
|
+
it("positions at top when centered is false", async () => {
|
|
128
|
+
await render(_jsx(Modal.Root, { defaultOpened: true, centered: false, transitionProps: transitionProps, children: _jsx(Modal.Content, { children: "Top aligned" }) }));
|
|
129
|
+
await screen.findByRole("dialog");
|
|
130
|
+
const wrapper = screen.getByRole("dialog").parentElement?.parentElement;
|
|
131
|
+
expect(wrapper?.className).toContain("items-start");
|
|
67
132
|
});
|
|
68
133
|
});
|
|
69
134
|
});
|
|
@@ -6,17 +6,20 @@ import { ModalRoot } from "./modal-root";
|
|
|
6
6
|
import { ModalOverlay } from "./modal-overlay";
|
|
7
7
|
import { ModalContent } from "./modal-content";
|
|
8
8
|
import { ModalHeader } from "./modal-header";
|
|
9
|
+
import { ModalBody } from "./modal-body";
|
|
9
10
|
import { ModalClose } from "./modal-close";
|
|
11
|
+
export type ModalSize = "xs" | "sm" | "md" | "lg" | "xl" | "full";
|
|
10
12
|
export type ModalClassNames = {
|
|
11
13
|
root?: string;
|
|
12
14
|
overlay?: string;
|
|
13
15
|
content?: string;
|
|
14
16
|
header?: string;
|
|
17
|
+
body?: string;
|
|
15
18
|
close?: string;
|
|
16
19
|
};
|
|
17
|
-
export interface
|
|
20
|
+
export interface ModalRootProps extends ComponentPropsWithoutRef<"div"> {
|
|
18
21
|
/** Children containing modal subcomponents */
|
|
19
|
-
children
|
|
22
|
+
children?: ReactNode;
|
|
20
23
|
/** State of the modal (controlled) */
|
|
21
24
|
opened?: boolean;
|
|
22
25
|
/** Initial state of the modal (uncontrolled) */
|
|
@@ -33,6 +36,14 @@ export interface ModalProps extends ComponentPropsWithoutRef<"div"> {
|
|
|
33
36
|
withinPortal?: boolean;
|
|
34
37
|
/** Radius for modal content @default `md` */
|
|
35
38
|
radius?: RefraktorRadius;
|
|
39
|
+
/** Modal content width @default `md` */
|
|
40
|
+
size?: ModalSize;
|
|
41
|
+
/** Whether to center modal vertically @default `true` */
|
|
42
|
+
centered?: boolean;
|
|
43
|
+
/** Whether to trap focus within the modal @default `true` */
|
|
44
|
+
trapFocus?: boolean;
|
|
45
|
+
/** Whether to return focus to trigger after close @default `true` */
|
|
46
|
+
returnFocus?: boolean;
|
|
36
47
|
/** Transition props for overlay/content, uses Transition internally */
|
|
37
48
|
transitionProps?: Omit<TransitionProps, "children" | "mounted">;
|
|
38
49
|
/** Used for editing root class name */
|
|
@@ -40,7 +51,16 @@ export interface ModalProps extends ComponentPropsWithoutRef<"div"> {
|
|
|
40
51
|
/** Used for styling different parts of the component */
|
|
41
52
|
classNames?: ModalClassNames;
|
|
42
53
|
}
|
|
43
|
-
export
|
|
54
|
+
export interface ModalProps extends Omit<ModalRootProps, "title"> {
|
|
55
|
+
/** Title text rendered in the header */
|
|
56
|
+
title?: ReactNode;
|
|
57
|
+
/** Whether to render the overlay @default `true` */
|
|
58
|
+
withOverlay?: boolean;
|
|
59
|
+
/** Whether to show the close button in the header @default `true` */
|
|
60
|
+
withCloseButton?: boolean;
|
|
61
|
+
/** Props passed to the Overlay subcomponent */
|
|
62
|
+
overlayProps?: ModalOverlayProps;
|
|
63
|
+
}
|
|
44
64
|
export interface ModalOverlayProps extends ComponentPropsWithoutRef<"div"> {
|
|
45
65
|
/** Whether clicking the overlay closes modal @default `true` */
|
|
46
66
|
closeOnClick?: boolean;
|
|
@@ -60,13 +80,17 @@ export interface ModalContentProps extends ComponentPropsWithoutRef<"div"> {
|
|
|
60
80
|
export interface ModalHeaderProps extends ComponentPropsWithoutRef<"div"> {
|
|
61
81
|
/** Header content */
|
|
62
82
|
children?: ReactNode;
|
|
63
|
-
/** Shorthand header text */
|
|
64
|
-
text?: ReactNode;
|
|
65
83
|
/** Whether to show close button inside header @default `true` */
|
|
66
84
|
withClose?: boolean;
|
|
67
85
|
/** Used for editing root class name */
|
|
68
86
|
className?: string;
|
|
69
87
|
}
|
|
88
|
+
export interface ModalBodyProps extends ComponentPropsWithoutRef<"div"> {
|
|
89
|
+
/** Body content */
|
|
90
|
+
children?: ReactNode;
|
|
91
|
+
/** Used for editing root class name */
|
|
92
|
+
className?: string;
|
|
93
|
+
}
|
|
70
94
|
export interface ModalCloseProps extends Omit<ComponentPropsWithoutRef<"button">, "onClick"> {
|
|
71
95
|
/** Optional close content (defaults to `x`) */
|
|
72
96
|
children?: ReactNode;
|
|
@@ -85,6 +109,7 @@ export interface ModalFactoryPayload extends FactoryPayload {
|
|
|
85
109
|
Overlay: typeof ModalOverlay;
|
|
86
110
|
Content: typeof ModalContent;
|
|
87
111
|
Header: typeof ModalHeader;
|
|
112
|
+
Body: typeof ModalBody;
|
|
88
113
|
Close: typeof ModalClose;
|
|
89
114
|
};
|
|
90
115
|
}
|
|
@@ -104,6 +129,10 @@ export interface ModalHeaderFactoryPayload extends FactoryPayload {
|
|
|
104
129
|
props: ModalHeaderProps;
|
|
105
130
|
ref: HTMLDivElement;
|
|
106
131
|
}
|
|
132
|
+
export interface ModalBodyFactoryPayload extends FactoryPayload {
|
|
133
|
+
props: ModalBodyProps;
|
|
134
|
+
ref: HTMLDivElement;
|
|
135
|
+
}
|
|
107
136
|
export interface ModalCloseFactoryPayload extends FactoryPayload {
|
|
108
137
|
props: ModalCloseProps;
|
|
109
138
|
ref: HTMLButtonElement;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal.types.d.ts","sourceRoot":"","sources":["../../../src/components/modal/modal.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACxE,OAAO,EACH,sBAAsB,EACtB,qBAAqB,EACrB,cAAc,EACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,MAAM,MAAM,eAAe,GAAG;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"modal.types.d.ts","sourceRoot":"","sources":["../../../src/components/modal/modal.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +1,23 @@
|
|
|
1
|
+
import { FloatingContext } from "@floating-ui/react";
|
|
1
2
|
interface UseModalProps {
|
|
2
3
|
opened?: boolean;
|
|
3
4
|
defaultOpened?: boolean;
|
|
4
5
|
onOpenedChange?: (opened: boolean) => void;
|
|
5
6
|
closeOnClickOutside?: boolean;
|
|
6
7
|
closeOnEscape?: boolean;
|
|
7
|
-
contentRef: React.MutableRefObject<HTMLElement | null>;
|
|
8
8
|
}
|
|
9
9
|
export interface UseModalReturn {
|
|
10
10
|
opened: boolean;
|
|
11
11
|
open: () => void;
|
|
12
12
|
close: () => void;
|
|
13
13
|
toggle: () => void;
|
|
14
|
+
context: FloatingContext;
|
|
15
|
+
refs: {
|
|
16
|
+
setReference: (node: HTMLElement | null) => void;
|
|
17
|
+
setFloating: (node: HTMLElement | null) => void;
|
|
18
|
+
floating: React.MutableRefObject<HTMLElement | null>;
|
|
19
|
+
};
|
|
20
|
+
getFloatingProps: (userProps?: React.HTMLAttributes<HTMLElement>) => Record<string, unknown>;
|
|
14
21
|
}
|
|
15
22
|
export declare function useModal(options: UseModalProps): UseModalReturn;
|
|
16
23
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-modal.d.ts","sourceRoot":"","sources":["../../../src/components/modal/use-modal.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-modal.d.ts","sourceRoot":"","sources":["../../../src/components/modal/use-modal.ts"],"names":[],"mappings":"AACA,OAAO,EACH,eAAe,EAKlB,MAAM,oBAAoB,CAAC;AAG5B,UAAU,aAAa;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3C,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,OAAO,EAAE,eAAe,CAAC;IACzB,IAAI,EAAE;QACF,YAAY,EAAE,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;QACjD,WAAW,EAAE,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;QAChD,QAAQ,EAAE,KAAK,CAAC,gBAAgB,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;KACxD,CAAC;IACF,gBAAgB,EAAE,CACd,SAAS,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC,KAC5C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,cAAc,CA2D/D"}
|
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
import { useUncontrolled } from "@refraktor/utils";
|
|
2
|
-
import {
|
|
2
|
+
import { useDismiss, useFloating, useInteractions, useRole } from "@floating-ui/react";
|
|
3
|
+
import { useCallback } from "react";
|
|
3
4
|
export function useModal(options) {
|
|
4
|
-
const { opened, defaultOpened, onOpenedChange, closeOnClickOutside = true, closeOnEscape = true
|
|
5
|
+
const { opened, defaultOpened, onOpenedChange, closeOnClickOutside = true, closeOnEscape = true } = options;
|
|
5
6
|
const [isOpen, setIsOpen] = useUncontrolled({
|
|
6
7
|
value: opened,
|
|
7
8
|
defaultValue: defaultOpened,
|
|
8
9
|
finalValue: false,
|
|
9
10
|
onChange: onOpenedChange
|
|
10
11
|
});
|
|
12
|
+
const floating = useFloating({
|
|
13
|
+
open: isOpen,
|
|
14
|
+
onOpenChange: setIsOpen
|
|
15
|
+
});
|
|
16
|
+
const dismiss = useDismiss(floating.context, {
|
|
17
|
+
outsidePress: closeOnClickOutside,
|
|
18
|
+
outsidePressEvent: "mousedown",
|
|
19
|
+
escapeKey: closeOnEscape
|
|
20
|
+
});
|
|
21
|
+
const role = useRole(floating.context, {
|
|
22
|
+
role: "dialog"
|
|
23
|
+
});
|
|
24
|
+
const { getFloatingProps } = useInteractions([dismiss, role]);
|
|
11
25
|
const open = useCallback(() => {
|
|
12
26
|
setIsOpen(true);
|
|
13
27
|
}, [setIsOpen]);
|
|
@@ -17,45 +31,18 @@ export function useModal(options) {
|
|
|
17
31
|
const toggle = useCallback(() => {
|
|
18
32
|
setIsOpen(!isOpen);
|
|
19
33
|
}, [isOpen, setIsOpen]);
|
|
20
|
-
useEffect(() => {
|
|
21
|
-
if (!isOpen || !closeOnEscape) {
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
const handleKeyDown = (event) => {
|
|
25
|
-
if (event.key === "Escape") {
|
|
26
|
-
setIsOpen(false);
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
30
|
-
return () => {
|
|
31
|
-
document.removeEventListener("keydown", handleKeyDown);
|
|
32
|
-
};
|
|
33
|
-
}, [closeOnEscape, isOpen, setIsOpen]);
|
|
34
|
-
useEffect(() => {
|
|
35
|
-
if (!isOpen || !closeOnClickOutside) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
const handlePointerDown = (event) => {
|
|
39
|
-
const target = event.target;
|
|
40
|
-
if (!(target instanceof Node)) {
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
if (contentRef.current?.contains(target)) {
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
setIsOpen(false);
|
|
47
|
-
};
|
|
48
|
-
document.addEventListener("mousedown", handlePointerDown);
|
|
49
|
-
document.addEventListener("touchstart", handlePointerDown);
|
|
50
|
-
return () => {
|
|
51
|
-
document.removeEventListener("mousedown", handlePointerDown);
|
|
52
|
-
document.removeEventListener("touchstart", handlePointerDown);
|
|
53
|
-
};
|
|
54
|
-
}, [closeOnClickOutside, contentRef, isOpen, setIsOpen]);
|
|
55
34
|
return {
|
|
56
35
|
opened: isOpen,
|
|
57
36
|
open,
|
|
58
37
|
close,
|
|
59
|
-
toggle
|
|
38
|
+
toggle,
|
|
39
|
+
context: floating.context,
|
|
40
|
+
refs: {
|
|
41
|
+
setReference: floating.refs.setReference,
|
|
42
|
+
setFloating: floating.refs.setFloating,
|
|
43
|
+
floating: floating.refs
|
|
44
|
+
.floating
|
|
45
|
+
},
|
|
46
|
+
getFloatingProps
|
|
60
47
|
};
|
|
61
48
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/password-input/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC5D,cAAc,wBAAwB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password-input.d.ts","sourceRoot":"","sources":["../../../src/components/password-input/password-input.tsx"],"names":[],"mappings":"AAKA,OAAO,EACH,2BAA2B,EAE9B,MAAM,wBAAwB,CAAC;AAQhC,QAAA,MAAM,aAAa,iEA+DjB,CAAC;AAKH,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useUncontrolled } from "@refraktor/utils";
|
|
3
|
+
import { EyeIcon, EyeOffIcon } from "../../icons";
|
|
4
|
+
import { useTheme } from "../../theme";
|
|
5
|
+
import { createComponentConfig, factory, useProps } from "../../utils";
|
|
6
|
+
import { Input } from "../input";
|
|
7
|
+
const defaultProps = {
|
|
8
|
+
withVisibilityToggle: true,
|
|
9
|
+
showPasswordLabel: "Show password",
|
|
10
|
+
hidePasswordLabel: "Hide password"
|
|
11
|
+
};
|
|
12
|
+
const PasswordInput = factory((_props, ref) => {
|
|
13
|
+
const { cx } = useTheme();
|
|
14
|
+
const { visible, defaultVisible, onVisibilityChange, withVisibilityToggle, showPasswordLabel, hidePasswordLabel, rightSection, disabled, ...props } = useProps("PasswordInput", defaultProps, _props);
|
|
15
|
+
const [isVisible, setVisible] = useUncontrolled({
|
|
16
|
+
value: visible,
|
|
17
|
+
defaultValue: defaultVisible,
|
|
18
|
+
finalValue: false,
|
|
19
|
+
onChange: onVisibilityChange
|
|
20
|
+
});
|
|
21
|
+
const Icon = isVisible ? EyeOffIcon : EyeIcon;
|
|
22
|
+
const toggleLabel = isVisible ? hidePasswordLabel : showPasswordLabel;
|
|
23
|
+
const visibilityToggle = (_jsx("button", { type: "button", disabled: disabled, "aria-label": toggleLabel, "aria-pressed": isVisible, className: cx("inline-flex cursor-pointer items-center justify-center border-0 bg-transparent p-0 text-[var(--refraktor-text-secondary)] transition-colors hover:text-[var(--refraktor-text)]", disabled && "cursor-not-allowed opacity-50"), onMouseDown: (event) => event.preventDefault(), onClick: () => setVisible(!isVisible), children: _jsx(Icon, { size: 16 }) }));
|
|
24
|
+
let resolvedRightSection = rightSection;
|
|
25
|
+
if (withVisibilityToggle) {
|
|
26
|
+
resolvedRightSection = rightSection ? (_jsxs("span", { className: "inline-flex items-center gap-1", children: [rightSection, visibilityToggle] })) : (visibilityToggle);
|
|
27
|
+
}
|
|
28
|
+
return (_jsx(Input, { ...props, ref: ref, type: isVisible ? "text" : "password", disabled: disabled, rightSection: resolvedRightSection }));
|
|
29
|
+
});
|
|
30
|
+
PasswordInput.displayName = "@refraktor/core/PasswordInput";
|
|
31
|
+
PasswordInput.configure = createComponentConfig();
|
|
32
|
+
export default PasswordInput;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password-input.test.d.ts","sourceRoot":"","sources":["../../../src/components/password-input/password-input.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { render, screen, userEvent } from "../../vitest";
|
|
4
|
+
import PasswordInput from "./password-input";
|
|
5
|
+
describe("@refraktor/core/PasswordInput", () => {
|
|
6
|
+
it("supports input wrapper props", async () => {
|
|
7
|
+
await render(_jsx(PasswordInput, { label: "Password", description: "Use at least 8 characters", error: "Password is required" }));
|
|
8
|
+
const input = screen.getByLabelText("Password");
|
|
9
|
+
expect(input).toHaveAttribute("type", "password");
|
|
10
|
+
expect(input).toHaveAttribute("aria-invalid", "true");
|
|
11
|
+
expect(screen.getByText("Use at least 8 characters")).toBeInTheDocument();
|
|
12
|
+
expect(screen.getByText("Password is required")).toBeInTheDocument();
|
|
13
|
+
});
|
|
14
|
+
it("toggles password visibility", async () => {
|
|
15
|
+
const user = userEvent.setup();
|
|
16
|
+
await render(_jsx(PasswordInput, { label: "Password" }));
|
|
17
|
+
const input = screen.getByLabelText("Password");
|
|
18
|
+
const showButton = screen.getByRole("button", {
|
|
19
|
+
name: "Show password"
|
|
20
|
+
});
|
|
21
|
+
expect(input).toHaveAttribute("type", "password");
|
|
22
|
+
await user.click(showButton);
|
|
23
|
+
expect(input).toHaveAttribute("type", "text");
|
|
24
|
+
const hideButton = screen.getByRole("button", {
|
|
25
|
+
name: "Hide password"
|
|
26
|
+
});
|
|
27
|
+
await user.click(hideButton);
|
|
28
|
+
expect(input).toHaveAttribute("type", "password");
|
|
29
|
+
});
|
|
30
|
+
it("respects disabled state", async () => {
|
|
31
|
+
const user = userEvent.setup();
|
|
32
|
+
await render(_jsx(PasswordInput, { label: "Password", disabled: true }));
|
|
33
|
+
const input = screen.getByLabelText("Password");
|
|
34
|
+
const toggle = screen.getByRole("button", {
|
|
35
|
+
name: "Show password"
|
|
36
|
+
});
|
|
37
|
+
expect(toggle).toBeDisabled();
|
|
38
|
+
await user.click(toggle);
|
|
39
|
+
expect(input).toHaveAttribute("type", "password");
|
|
40
|
+
});
|
|
41
|
+
it("allows disabling visibility toggle", async () => {
|
|
42
|
+
await render(_jsx(PasswordInput, { label: "Password", withVisibilityToggle: false }));
|
|
43
|
+
const input = screen.getByLabelText("Password");
|
|
44
|
+
expect(input).toHaveAttribute("type", "password");
|
|
45
|
+
expect(screen.queryByRole("button", { name: "Show password" })).not.toBeInTheDocument();
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createComponentConfig, FactoryPayload } from "../../utils";
|
|
2
|
+
import { InputProps } from "../input";
|
|
3
|
+
export interface PasswordInputProps extends Omit<InputProps, "type"> {
|
|
4
|
+
/** Whether to render the visibility toggle icon @default `true` */
|
|
5
|
+
withVisibilityToggle?: boolean;
|
|
6
|
+
/** Controls visibility state */
|
|
7
|
+
visible?: boolean;
|
|
8
|
+
/** Initial visibility state */
|
|
9
|
+
defaultVisible?: boolean;
|
|
10
|
+
/** Callback called when visibility changes */
|
|
11
|
+
onVisibilityChange?: (visible: boolean) => void;
|
|
12
|
+
/** Accessible label for showing the password @default `Show password` */
|
|
13
|
+
showPasswordLabel?: string;
|
|
14
|
+
/** Accessible label for hiding the password @default `Hide password` */
|
|
15
|
+
hidePasswordLabel?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface PasswordInputFactoryPayload extends FactoryPayload {
|
|
18
|
+
props: PasswordInputProps;
|
|
19
|
+
ref: HTMLInputElement;
|
|
20
|
+
compound: {
|
|
21
|
+
configure: ReturnType<typeof createComponentConfig<PasswordInputProps>>;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=password-input.types.d.ts.map
|