@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.
Files changed (284) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/build/components/button/button.styles.js +5 -5
  3. package/build/components/chip/chip-group/chip-group.d.ts +4 -0
  4. package/build/components/chip/chip-group/chip-group.d.ts.map +1 -0
  5. package/build/components/chip/chip-group/chip-group.js +43 -0
  6. package/build/components/chip/chip-group/index.d.ts +2 -0
  7. package/build/components/chip/chip-group/index.d.ts.map +1 -0
  8. package/build/components/chip/chip-group/index.js +1 -0
  9. package/build/components/chip/chip.context.d.ts +15 -0
  10. package/build/components/chip/chip.context.d.ts.map +1 -0
  11. package/build/components/chip/chip.context.js +2 -0
  12. package/build/components/chip/chip.d.ts +4 -0
  13. package/build/components/chip/chip.d.ts.map +1 -0
  14. package/build/components/chip/chip.js +85 -0
  15. package/build/components/chip/chip.styles.d.ts +5 -0
  16. package/build/components/chip/chip.styles.d.ts.map +1 -0
  17. package/build/components/chip/chip.styles.js +19 -0
  18. package/build/components/chip/chip.test.d.ts +2 -0
  19. package/build/components/chip/chip.test.d.ts.map +1 -0
  20. package/build/components/chip/chip.test.js +107 -0
  21. package/build/components/chip/chip.types.d.ts +95 -0
  22. package/build/components/chip/chip.types.d.ts.map +1 -0
  23. package/build/components/chip/chip.types.js +1 -0
  24. package/build/components/chip/index.d.ts +4 -0
  25. package/build/components/chip/index.d.ts.map +1 -0
  26. package/build/components/chip/index.js +2 -0
  27. package/build/components/combobox/combobox-dropdown/combobox-dropdown.d.ts +4 -0
  28. package/build/components/combobox/combobox-dropdown/combobox-dropdown.d.ts.map +1 -0
  29. package/build/components/combobox/combobox-dropdown/combobox-dropdown.js +21 -0
  30. package/build/components/combobox/combobox-dropdown/index.d.ts +2 -0
  31. package/build/components/combobox/combobox-dropdown/index.d.ts.map +1 -0
  32. package/build/components/combobox/combobox-dropdown/index.js +1 -0
  33. package/build/components/combobox/combobox-group/combobox-group.d.ts +4 -0
  34. package/build/components/combobox/combobox-group/combobox-group.d.ts.map +1 -0
  35. package/build/components/combobox/combobox-group/combobox-group.js +15 -0
  36. package/build/components/combobox/combobox-group/index.d.ts +2 -0
  37. package/build/components/combobox/combobox-group/index.d.ts.map +1 -0
  38. package/build/components/combobox/combobox-group/index.js +1 -0
  39. package/build/components/combobox/combobox-input/combobox-input.d.ts +4 -0
  40. package/build/components/combobox/combobox-input/combobox-input.d.ts.map +1 -0
  41. package/build/components/combobox/combobox-input/combobox-input.js +101 -0
  42. package/build/components/combobox/combobox-input/index.d.ts +2 -0
  43. package/build/components/combobox/combobox-input/index.d.ts.map +1 -0
  44. package/build/components/combobox/combobox-input/index.js +1 -0
  45. package/build/components/combobox/combobox-option/combobox-option.d.ts +4 -0
  46. package/build/components/combobox/combobox-option/combobox-option.d.ts.map +1 -0
  47. package/build/components/combobox/combobox-option/combobox-option.js +86 -0
  48. package/build/components/combobox/combobox-option/index.d.ts +2 -0
  49. package/build/components/combobox/combobox-option/index.d.ts.map +1 -0
  50. package/build/components/combobox/combobox-option/index.js +1 -0
  51. package/build/components/combobox/combobox-root/combobox-root.d.ts +4 -0
  52. package/build/components/combobox/combobox-root/combobox-root.d.ts.map +1 -0
  53. package/build/components/combobox/combobox-root/combobox-root.js +282 -0
  54. package/build/components/combobox/combobox-root/index.d.ts +2 -0
  55. package/build/components/combobox/combobox-root/index.d.ts.map +1 -0
  56. package/build/components/combobox/combobox-root/index.js +1 -0
  57. package/build/components/combobox/combobox.context.d.ts +73 -0
  58. package/build/components/combobox/combobox.context.d.ts.map +1 -0
  59. package/build/components/combobox/combobox.context.js +50 -0
  60. package/build/components/combobox/combobox.d.ts +4 -0
  61. package/build/components/combobox/combobox.d.ts.map +1 -0
  62. package/build/components/combobox/combobox.js +31 -0
  63. package/build/components/combobox/combobox.test.d.ts +2 -0
  64. package/build/components/combobox/combobox.test.d.ts.map +1 -0
  65. package/build/components/combobox/combobox.test.js +104 -0
  66. package/build/components/combobox/combobox.types.d.ts +205 -0
  67. package/build/components/combobox/combobox.types.d.ts.map +1 -0
  68. package/build/components/combobox/combobox.types.js +1 -0
  69. package/build/components/combobox/index.d.ts +8 -0
  70. package/build/components/combobox/index.d.ts.map +1 -0
  71. package/build/components/combobox/index.js +6 -0
  72. package/build/components/combobox/use-combobox.d.ts +32 -0
  73. package/build/components/combobox/use-combobox.d.ts.map +1 -0
  74. package/build/components/combobox/use-combobox.js +80 -0
  75. package/build/components/drawer/drawer-body/drawer-body.d.ts +4 -0
  76. package/build/components/drawer/drawer-body/drawer-body.d.ts.map +1 -0
  77. package/build/components/drawer/drawer-body/drawer-body.js +11 -0
  78. package/build/components/drawer/drawer-body/index.d.ts +2 -0
  79. package/build/components/drawer/drawer-body/index.d.ts.map +1 -0
  80. package/build/components/drawer/drawer-body/index.js +1 -0
  81. package/build/components/drawer/drawer-content/drawer-content.d.ts.map +1 -1
  82. package/build/components/drawer/drawer-content/drawer-content.js +9 -6
  83. package/build/components/drawer/drawer-overlay/drawer-overlay.d.ts.map +1 -1
  84. package/build/components/drawer/drawer-overlay/drawer-overlay.js +4 -4
  85. package/build/components/drawer/drawer-root/drawer-root.d.ts.map +1 -1
  86. package/build/components/drawer/drawer-root/drawer-root.js +8 -9
  87. package/build/components/drawer/drawer.context.d.ts +2 -1
  88. package/build/components/drawer/drawer.context.d.ts.map +1 -1
  89. package/build/components/drawer/drawer.d.ts.map +1 -1
  90. package/build/components/drawer/drawer.js +5 -3
  91. package/build/components/drawer/drawer.test.js +55 -16
  92. package/build/components/drawer/drawer.types.d.ts +29 -3
  93. package/build/components/drawer/drawer.types.d.ts.map +1 -1
  94. package/build/components/drawer/index.d.ts +2 -1
  95. package/build/components/drawer/index.d.ts.map +1 -1
  96. package/build/components/drawer/index.js +1 -0
  97. package/build/components/drawer/use-drawer.d.ts +8 -1
  98. package/build/components/drawer/use-drawer.d.ts.map +1 -1
  99. package/build/components/drawer/use-drawer.js +25 -38
  100. package/build/components/file-input/file-input.d.ts +4 -0
  101. package/build/components/file-input/file-input.d.ts.map +1 -0
  102. package/build/components/file-input/file-input.js +88 -0
  103. package/build/components/file-input/file-input.test.d.ts +2 -0
  104. package/build/components/file-input/file-input.test.d.ts.map +1 -0
  105. package/build/components/file-input/file-input.test.js +74 -0
  106. package/build/components/file-input/file-input.types.d.ts +46 -0
  107. package/build/components/file-input/file-input.types.d.ts.map +1 -0
  108. package/build/components/file-input/file-input.types.js +1 -0
  109. package/build/components/file-input/file-input.utils.d.ts +11 -0
  110. package/build/components/file-input/file-input.utils.d.ts.map +1 -0
  111. package/build/components/file-input/file-input.utils.js +67 -0
  112. package/build/components/file-input/file-input.utils.test.d.ts +2 -0
  113. package/build/components/file-input/file-input.utils.test.d.ts.map +1 -0
  114. package/build/components/file-input/file-input.utils.test.js +27 -0
  115. package/build/components/file-input/index.d.ts +3 -0
  116. package/build/components/file-input/index.d.ts.map +1 -0
  117. package/build/components/file-input/index.js +2 -0
  118. package/build/components/for/for.d.ts +8 -0
  119. package/build/components/for/for.d.ts.map +1 -0
  120. package/build/components/for/for.js +32 -0
  121. package/build/components/for/for.test.d.ts +2 -0
  122. package/build/components/for/for.test.d.ts.map +1 -0
  123. package/build/components/for/for.test.js +31 -0
  124. package/build/components/for/for.types.d.ts +33 -0
  125. package/build/components/for/for.types.d.ts.map +1 -0
  126. package/build/components/for/for.types.js +1 -0
  127. package/build/components/for/index.d.ts +3 -0
  128. package/build/components/for/index.d.ts.map +1 -0
  129. package/build/components/for/index.js +1 -0
  130. package/build/components/index.d.ts +6 -0
  131. package/build/components/index.d.ts.map +1 -1
  132. package/build/components/index.js +6 -0
  133. package/build/components/modal/index.d.ts +2 -1
  134. package/build/components/modal/index.d.ts.map +1 -1
  135. package/build/components/modal/index.js +1 -0
  136. package/build/components/modal/modal-body/index.d.ts +2 -0
  137. package/build/components/modal/modal-body/index.d.ts.map +1 -0
  138. package/build/components/modal/modal-body/index.js +1 -0
  139. package/build/components/modal/modal-body/modal-body.d.ts +4 -0
  140. package/build/components/modal/modal-body/modal-body.d.ts.map +1 -0
  141. package/build/components/modal/modal-body/modal-body.js +11 -0
  142. package/build/components/modal/modal-content/modal-content.d.ts.map +1 -1
  143. package/build/components/modal/modal-content/modal-content.js +13 -5
  144. package/build/components/modal/modal-header/modal-header.js +2 -2
  145. package/build/components/modal/modal-overlay/modal-overlay.d.ts.map +1 -1
  146. package/build/components/modal/modal-overlay/modal-overlay.js +4 -4
  147. package/build/components/modal/modal-root/modal-root.d.ts.map +1 -1
  148. package/build/components/modal/modal-root/modal-root.js +12 -9
  149. package/build/components/modal/modal.context.d.ts +5 -2
  150. package/build/components/modal/modal.context.d.ts.map +1 -1
  151. package/build/components/modal/modal.d.ts.map +1 -1
  152. package/build/components/modal/modal.js +5 -3
  153. package/build/components/modal/modal.test.js +78 -13
  154. package/build/components/modal/modal.types.d.ts +34 -5
  155. package/build/components/modal/modal.types.d.ts.map +1 -1
  156. package/build/components/modal/use-modal.d.ts +8 -1
  157. package/build/components/modal/use-modal.d.ts.map +1 -1
  158. package/build/components/modal/use-modal.js +25 -38
  159. package/build/components/password-input/index.d.ts +3 -0
  160. package/build/components/password-input/index.d.ts.map +1 -0
  161. package/build/components/password-input/index.js +2 -0
  162. package/build/components/password-input/password-input.d.ts +4 -0
  163. package/build/components/password-input/password-input.d.ts.map +1 -0
  164. package/build/components/password-input/password-input.js +32 -0
  165. package/build/components/password-input/password-input.test.d.ts +2 -0
  166. package/build/components/password-input/password-input.test.d.ts.map +1 -0
  167. package/build/components/password-input/password-input.test.js +47 -0
  168. package/build/components/password-input/password-input.types.d.ts +24 -0
  169. package/build/components/password-input/password-input.types.d.ts.map +1 -0
  170. package/build/components/password-input/password-input.types.js +1 -0
  171. package/build/components/pin-input/index.d.ts +3 -0
  172. package/build/components/pin-input/index.d.ts.map +1 -0
  173. package/build/components/pin-input/index.js +2 -0
  174. package/build/components/pin-input/pin-input.d.ts +4 -0
  175. package/build/components/pin-input/pin-input.d.ts.map +1 -0
  176. package/build/components/pin-input/pin-input.js +245 -0
  177. package/build/components/pin-input/pin-input.test.d.ts +2 -0
  178. package/build/components/pin-input/pin-input.test.d.ts.map +1 -0
  179. package/build/components/pin-input/pin-input.test.js +87 -0
  180. package/build/components/pin-input/pin-input.types.d.ts +44 -0
  181. package/build/components/pin-input/pin-input.types.d.ts.map +1 -0
  182. package/build/components/pin-input/pin-input.types.js +1 -0
  183. package/build/components/scroll-area/index.d.ts +3 -0
  184. package/build/components/scroll-area/index.d.ts.map +1 -0
  185. package/build/components/scroll-area/index.js +1 -0
  186. package/build/components/scroll-area/scroll-area.d.ts +4 -0
  187. package/build/components/scroll-area/scroll-area.d.ts.map +1 -0
  188. package/build/components/scroll-area/scroll-area.js +30 -0
  189. package/build/components/scroll-area/scroll-area.test.d.ts +2 -0
  190. package/build/components/scroll-area/scroll-area.test.d.ts.map +1 -0
  191. package/build/components/scroll-area/scroll-area.test.js +39 -0
  192. package/build/components/scroll-area/scroll-area.types.d.ts +25 -0
  193. package/build/components/scroll-area/scroll-area.types.d.ts.map +1 -0
  194. package/build/components/scroll-area/scroll-area.types.js +1 -0
  195. package/build/components/segmented-control/segmented-control.d.ts.map +1 -1
  196. package/build/components/segmented-control/segmented-control.js +3 -3
  197. package/build/components/segmented-control/segmented-control.styles.js +13 -13
  198. package/build/components/segmented-control/segmented-control.test.js +11 -0
  199. package/build/components/segmented-control/segmented-control.types.d.ts +2 -0
  200. package/build/components/segmented-control/segmented-control.types.d.ts.map +1 -1
  201. package/build/icons/eye-off.d.ts +4 -0
  202. package/build/icons/eye-off.d.ts.map +1 -0
  203. package/build/icons/eye-off.js +5 -0
  204. package/build/icons/eye.d.ts +4 -0
  205. package/build/icons/eye.d.ts.map +1 -0
  206. package/build/icons/eye.js +5 -0
  207. package/build/icons/index.d.ts +2 -0
  208. package/build/icons/index.d.ts.map +1 -1
  209. package/build/icons/index.js +2 -0
  210. package/build/style.css +1 -1
  211. package/package.json +2 -2
  212. package/src/components/button/button.styles.ts +5 -5
  213. package/src/components/chip/chip-group/chip-group.tsx +107 -0
  214. package/src/components/chip/chip-group/index.ts +1 -0
  215. package/src/components/chip/chip.context.ts +15 -0
  216. package/src/components/chip/chip.styles.ts +36 -0
  217. package/src/components/chip/chip.test.tsx +197 -0
  218. package/src/components/chip/chip.tsx +208 -0
  219. package/src/components/chip/chip.types.ts +134 -0
  220. package/src/components/chip/index.ts +10 -0
  221. package/src/components/drawer/drawer-body/drawer-body.tsx +29 -0
  222. package/src/components/drawer/drawer-body/index.ts +1 -0
  223. package/src/components/drawer/drawer-content/drawer-content.tsx +63 -26
  224. package/src/components/drawer/drawer-overlay/drawer-overlay.tsx +6 -5
  225. package/src/components/drawer/drawer-root/drawer-root.tsx +17 -18
  226. package/src/components/drawer/drawer.context.ts +2 -1
  227. package/src/components/drawer/drawer.test.tsx +144 -36
  228. package/src/components/drawer/drawer.tsx +31 -3
  229. package/src/components/drawer/drawer.types.ts +37 -3
  230. package/src/components/drawer/index.ts +2 -0
  231. package/src/components/drawer/use-drawer.ts +44 -51
  232. package/src/components/file-input/file-input.test.tsx +134 -0
  233. package/src/components/file-input/file-input.tsx +224 -0
  234. package/src/components/file-input/file-input.types.ts +78 -0
  235. package/src/components/file-input/file-input.utils.test.ts +36 -0
  236. package/src/components/file-input/file-input.utils.ts +130 -0
  237. package/src/components/file-input/index.ts +2 -0
  238. package/src/components/for/for.test.tsx +66 -0
  239. package/src/components/for/for.tsx +53 -0
  240. package/src/components/for/for.types.ts +40 -0
  241. package/src/components/for/index.ts +2 -0
  242. package/src/components/index.ts +6 -0
  243. package/src/components/menu/menu-dropdown/menu-dropdown.tsx +220 -220
  244. package/src/components/menu/menu-sub-dropdown/menu-sub-dropdown.tsx +221 -221
  245. package/src/components/modal/index.ts +4 -1
  246. package/src/components/modal/modal-body/index.ts +1 -0
  247. package/src/components/modal/modal-body/modal-body.tsx +29 -0
  248. package/src/components/modal/modal-content/modal-content.tsx +71 -24
  249. package/src/components/modal/modal-header/modal-header.tsx +2 -2
  250. package/src/components/modal/modal-overlay/modal-overlay.tsx +46 -45
  251. package/src/components/modal/modal-root/modal-root.tsx +22 -17
  252. package/src/components/modal/modal.context.ts +5 -2
  253. package/src/components/modal/modal.test.tsx +234 -64
  254. package/src/components/modal/modal.tsx +36 -4
  255. package/src/components/modal/modal.types.ts +49 -8
  256. package/src/components/modal/use-modal.ts +44 -51
  257. package/src/components/password-input/index.ts +2 -0
  258. package/src/components/password-input/password-input.test.tsx +72 -0
  259. package/src/components/password-input/password-input.tsx +85 -0
  260. package/src/components/password-input/password-input.types.ts +30 -0
  261. package/src/components/pin-input/index.ts +2 -0
  262. package/src/components/pin-input/pin-input.test.tsx +149 -0
  263. package/src/components/pin-input/pin-input.tsx +473 -0
  264. package/src/components/pin-input/pin-input.types.ts +78 -0
  265. package/src/components/scroll-area/index.ts +6 -0
  266. package/src/components/scroll-area/scroll-area.test.tsx +72 -0
  267. package/src/components/scroll-area/scroll-area.tsx +70 -0
  268. package/src/components/scroll-area/scroll-area.types.ts +37 -0
  269. package/src/components/segmented-control/segmented-control.styles.ts +13 -13
  270. package/src/components/segmented-control/segmented-control.test.tsx +18 -0
  271. package/src/components/segmented-control/segmented-control.tsx +11 -1
  272. package/src/components/segmented-control/segmented-control.types.ts +3 -0
  273. package/src/components/select/select-dropdown/select-dropdown.tsx +299 -299
  274. package/src/components/select/select-root/select-root.tsx +333 -333
  275. package/src/components/select/select-trigger/select-trigger.tsx +123 -123
  276. package/src/components/select/select.context.ts +140 -140
  277. package/src/components/select/select.test.tsx +190 -190
  278. package/src/components/select/select.types.ts +272 -272
  279. package/src/components/select/use-select.ts +170 -170
  280. package/src/icons/eye-off.tsx +30 -0
  281. package/src/icons/eye.tsx +24 -0
  282. package/src/icons/index.ts +2 -0
  283. package/src/style.css +14 -8
  284. 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":"AAMA,OAAO,EAEH,uBAAuB,EAE1B,MAAM,gBAAgB,CAAC;AAWxB,QAAA,MAAM,SAAS,gEA8Db,CAAC;AAIH,eAAe,SAAS,CAAC"}
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(RemoveScroll, { enabled: modal.opened && lockScroll, children: _jsx("div", { ref: ref, id: _id, className: cx(classes.root, className), ...props, children: children }) }) }));
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;AAChD,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,eAAe,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,SAAS,CAAC,CAAC;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,KAAK,CAAC,gBAAgB,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC1D,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
+ {"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":"AAUA,OAAO,EAAmB,mBAAmB,EAAc,MAAM,eAAe,CAAC;AAEjF,QAAA,MAAM,KAAK,yDAET,CAAC;AAWH,eAAe,KAAK,CAAC"}
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((props, ref) => {
9
- return _jsx(ModalRoot, { ...props, ref: ref });
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, { text: "Delete item" }), _jsx("p", { children: "Are you sure?" })] })] }));
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("locks and unlocks body scroll when enabled", async () => {
59
- const user = userEvent.setup();
60
- await render(_jsx(Modal, { defaultOpened: true, lockScroll: true, transitionProps: transitionProps, children: _jsxs(Modal.Content, { children: ["Scroll locked", _jsx(Modal.Close, {})] }) }));
61
- await waitFor(() => {
62
- expect(document.body).toHaveAttribute("data-scroll-locked");
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
- await user.click(screen.getByRole("button", { name: "Close" }));
65
- await waitFor(() => {
66
- expect(document.body).not.toHaveAttribute("data-scroll-locked");
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 ModalProps extends ComponentPropsWithoutRef<"div"> {
20
+ export interface ModalRootProps extends ComponentPropsWithoutRef<"div"> {
18
21
  /** Children containing modal subcomponents */
19
- children: ReactNode;
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 type ModalRootProps = ModalProps;
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":"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"}
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":"AAGA,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;IACxB,UAAU,EAAE,KAAK,CAAC,gBAAgB,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;CAC1D;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;CACtB;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,cAAc,CAiF/D"}
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 { useCallback, useEffect } from "react";
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, contentRef } = options;
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,3 @@
1
+ export { default as PasswordInput } from "./password-input";
2
+ export * from "./password-input.types";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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,2 @@
1
+ export { default as PasswordInput } from "./password-input";
2
+ export * from "./password-input.types";
@@ -0,0 +1,4 @@
1
+ import { PasswordInputFactoryPayload } from "./password-input.types";
2
+ declare const PasswordInput: import("../..").RefraktorComponent<PasswordInputFactoryPayload>;
3
+ export default PasswordInput;
4
+ //# sourceMappingURL=password-input.d.ts.map
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=password-input.test.d.ts.map
@@ -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