@refraktor/core 0.0.1 → 0.0.3

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 (290) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/build/components/breadcrumbs/breadcrumbs.d.ts +4 -0
  3. package/build/components/breadcrumbs/breadcrumbs.d.ts.map +1 -0
  4. package/build/components/breadcrumbs/breadcrumbs.js +64 -0
  5. package/build/components/breadcrumbs/breadcrumbs.styles.d.ts +12 -0
  6. package/build/components/breadcrumbs/breadcrumbs.styles.d.ts.map +1 -0
  7. package/build/components/breadcrumbs/breadcrumbs.styles.js +43 -0
  8. package/build/components/breadcrumbs/breadcrumbs.test.d.ts +2 -0
  9. package/build/components/breadcrumbs/breadcrumbs.test.d.ts.map +1 -0
  10. package/build/components/breadcrumbs/breadcrumbs.test.js +72 -0
  11. package/build/components/breadcrumbs/breadcrumbs.types.d.ts +56 -0
  12. package/build/components/breadcrumbs/breadcrumbs.types.d.ts.map +1 -0
  13. package/build/components/breadcrumbs/breadcrumbs.types.js +1 -0
  14. package/build/components/breadcrumbs/breadcrumbs.utils.d.ts +10 -0
  15. package/build/components/breadcrumbs/breadcrumbs.utils.d.ts.map +1 -0
  16. package/build/components/breadcrumbs/breadcrumbs.utils.js +36 -0
  17. package/build/components/breadcrumbs/index.d.ts +3 -0
  18. package/build/components/breadcrumbs/index.d.ts.map +1 -0
  19. package/build/components/breadcrumbs/index.js +1 -0
  20. package/build/components/drawer/drawer-close/drawer-close.d.ts +4 -0
  21. package/build/components/drawer/drawer-close/drawer-close.d.ts.map +1 -0
  22. package/build/components/drawer/drawer-close/drawer-close.js +19 -0
  23. package/build/components/drawer/drawer-close/index.d.ts +2 -0
  24. package/build/components/drawer/drawer-close/index.d.ts.map +1 -0
  25. package/build/components/drawer/drawer-close/index.js +1 -0
  26. package/build/components/drawer/drawer-content/drawer-content.d.ts +4 -0
  27. package/build/components/drawer/drawer-content/drawer-content.d.ts.map +1 -0
  28. package/build/components/drawer/drawer-content/drawer-content.js +41 -0
  29. package/build/components/drawer/drawer-content/index.d.ts +2 -0
  30. package/build/components/drawer/drawer-content/index.d.ts.map +1 -0
  31. package/build/components/drawer/drawer-content/index.js +1 -0
  32. package/build/components/drawer/drawer-header/drawer-header.d.ts +4 -0
  33. package/build/components/drawer/drawer-header/drawer-header.d.ts.map +1 -0
  34. package/build/components/drawer/drawer-header/drawer-header.js +13 -0
  35. package/build/components/drawer/drawer-header/index.d.ts +2 -0
  36. package/build/components/drawer/drawer-header/index.d.ts.map +1 -0
  37. package/build/components/drawer/drawer-header/index.js +1 -0
  38. package/build/components/drawer/drawer-overlay/drawer-overlay.d.ts +4 -0
  39. package/build/components/drawer/drawer-overlay/drawer-overlay.d.ts.map +1 -0
  40. package/build/components/drawer/drawer-overlay/drawer-overlay.js +31 -0
  41. package/build/components/drawer/drawer-overlay/index.d.ts +2 -0
  42. package/build/components/drawer/drawer-overlay/index.d.ts.map +1 -0
  43. package/build/components/drawer/drawer-overlay/index.js +1 -0
  44. package/build/components/drawer/drawer-root/drawer-root.d.ts +4 -0
  45. package/build/components/drawer/drawer-root/drawer-root.d.ts.map +1 -0
  46. package/build/components/drawer/drawer-root/drawer-root.js +50 -0
  47. package/build/components/drawer/drawer-root/index.d.ts +2 -0
  48. package/build/components/drawer/drawer-root/index.d.ts.map +1 -0
  49. package/build/components/drawer/drawer-root/index.js +1 -0
  50. package/build/components/drawer/drawer.context.d.ts +23 -0
  51. package/build/components/drawer/drawer.context.d.ts.map +1 -0
  52. package/build/components/drawer/drawer.context.js +2 -0
  53. package/build/components/drawer/drawer.d.ts +4 -0
  54. package/build/components/drawer/drawer.d.ts.map +1 -0
  55. package/build/components/drawer/drawer.js +19 -0
  56. package/build/components/drawer/drawer.styles.d.ts +6 -0
  57. package/build/components/drawer/drawer.styles.d.ts.map +1 -0
  58. package/build/components/drawer/drawer.styles.js +21 -0
  59. package/build/components/drawer/drawer.test.d.ts +2 -0
  60. package/build/components/drawer/drawer.test.d.ts.map +1 -0
  61. package/build/components/drawer/drawer.test.js +70 -0
  62. package/build/components/drawer/drawer.types.d.ts +116 -0
  63. package/build/components/drawer/drawer.types.d.ts.map +1 -0
  64. package/build/components/drawer/drawer.types.js +1 -0
  65. package/build/components/drawer/index.d.ts +8 -0
  66. package/build/components/drawer/index.d.ts.map +1 -0
  67. package/build/components/drawer/index.js +6 -0
  68. package/build/components/drawer/use-drawer.d.ts +17 -0
  69. package/build/components/drawer/use-drawer.d.ts.map +1 -0
  70. package/build/components/drawer/use-drawer.js +61 -0
  71. package/build/components/index.d.ts +4 -0
  72. package/build/components/index.d.ts.map +1 -1
  73. package/build/components/index.js +4 -0
  74. package/build/components/menu/menu-dropdown/menu-dropdown.d.ts.map +1 -1
  75. package/build/components/menu/menu-dropdown/menu-dropdown.js +3 -2
  76. package/build/components/menu/menu-sub-dropdown/menu-sub-dropdown.d.ts.map +1 -1
  77. package/build/components/menu/menu-sub-dropdown/menu-sub-dropdown.js +2 -1
  78. package/build/components/menu/use-menu.d.ts.map +1 -1
  79. package/build/components/menu/use-menu.js +2 -1
  80. package/build/components/modal/modal-close/modal-close.d.ts.map +1 -1
  81. package/build/components/modal/modal-close/modal-close.js +1 -1
  82. package/build/components/modal/modal-content/modal-content.d.ts.map +1 -1
  83. package/build/components/modal/modal-content/modal-content.js +1 -1
  84. package/build/components/modal/modal-header/modal-header.d.ts.map +1 -1
  85. package/build/components/modal/modal-header/modal-header.js +1 -1
  86. package/build/components/modal/modal-overlay/modal-overlay.d.ts.map +1 -1
  87. package/build/components/modal/modal-overlay/modal-overlay.js +10 -2
  88. package/build/components/modal/modal.test.js +16 -0
  89. package/build/components/modal/modal.types.d.ts +4 -0
  90. package/build/components/modal/modal.types.d.ts.map +1 -1
  91. package/build/components/number-input/number-input.d.ts.map +1 -1
  92. package/build/components/number-input/number-input.js +22 -15
  93. package/build/components/number-input/number-input.test.d.ts +2 -0
  94. package/build/components/number-input/number-input.test.d.ts.map +1 -0
  95. package/build/components/number-input/number-input.test.js +14 -0
  96. package/build/components/number-input/number-input.types.d.ts +2 -2
  97. package/build/components/number-input/number-input.types.d.ts.map +1 -1
  98. package/build/components/popover/popover-dropdown/popover-dropdown.d.ts.map +1 -1
  99. package/build/components/popover/popover-dropdown/popover-dropdown.js +2 -1
  100. package/build/components/popover/use-popover.d.ts.map +1 -1
  101. package/build/components/popover/use-popover.js +2 -1
  102. package/build/components/portal/portal.js +1 -1
  103. package/build/components/segmented-control/index.d.ts +3 -0
  104. package/build/components/segmented-control/index.d.ts.map +1 -0
  105. package/build/components/segmented-control/index.js +1 -0
  106. package/build/components/segmented-control/segmented-control.d.ts +4 -0
  107. package/build/components/segmented-control/segmented-control.d.ts.map +1 -0
  108. package/build/components/segmented-control/segmented-control.js +113 -0
  109. package/build/components/segmented-control/segmented-control.styles.d.ts +9 -0
  110. package/build/components/segmented-control/segmented-control.styles.d.ts.map +1 -0
  111. package/build/components/segmented-control/segmented-control.styles.js +28 -0
  112. package/build/components/segmented-control/segmented-control.test.d.ts +2 -0
  113. package/build/components/segmented-control/segmented-control.test.d.ts.map +1 -0
  114. package/build/components/segmented-control/segmented-control.test.js +81 -0
  115. package/build/components/segmented-control/segmented-control.types.d.ts +49 -0
  116. package/build/components/segmented-control/segmented-control.types.d.ts.map +1 -0
  117. package/build/components/segmented-control/segmented-control.types.js +1 -0
  118. package/build/components/select/select-dropdown/select-dropdown.d.ts.map +1 -1
  119. package/build/components/select/select-dropdown/select-dropdown.js +3 -2
  120. package/build/components/select/select-item/select-item.d.ts.map +1 -1
  121. package/build/components/select/select-item/select-item.js +1 -1
  122. package/build/components/select/select-root/select-root.d.ts.map +1 -1
  123. package/build/components/select/select-root/select-root.js +36 -6
  124. package/build/components/select/select-trigger/select-trigger.d.ts.map +1 -1
  125. package/build/components/select/select-trigger/select-trigger.js +1 -1
  126. package/build/components/select/select.context.d.ts +2 -0
  127. package/build/components/select/select.context.d.ts.map +1 -1
  128. package/build/components/select/select.test.js +17 -0
  129. package/build/components/select/select.types.d.ts +10 -0
  130. package/build/components/select/select.types.d.ts.map +1 -1
  131. package/build/components/select/use-select.d.ts.map +1 -1
  132. package/build/components/select/use-select.js +2 -1
  133. package/build/components/split-pane/index.d.ts +3 -0
  134. package/build/components/split-pane/index.d.ts.map +1 -0
  135. package/build/components/split-pane/index.js +1 -0
  136. package/build/components/split-pane/split-pane.d.ts +4 -0
  137. package/build/components/split-pane/split-pane.d.ts.map +1 -0
  138. package/build/components/split-pane/split-pane.js +201 -0
  139. package/build/components/split-pane/split-pane.styles.d.ts +3 -0
  140. package/build/components/split-pane/split-pane.styles.d.ts.map +1 -0
  141. package/build/components/split-pane/split-pane.styles.js +8 -0
  142. package/build/components/split-pane/split-pane.test.d.ts +2 -0
  143. package/build/components/split-pane/split-pane.test.d.ts.map +1 -0
  144. package/build/components/split-pane/split-pane.test.js +105 -0
  145. package/build/components/split-pane/split-pane.types.d.ts +51 -0
  146. package/build/components/split-pane/split-pane.types.d.ts.map +1 -0
  147. package/build/components/split-pane/split-pane.types.js +1 -0
  148. package/build/components/switch/switch.js +1 -1
  149. package/build/components/table/index.d.ts +9 -0
  150. package/build/components/table/index.d.ts.map +1 -0
  151. package/build/components/table/index.js +7 -0
  152. package/build/components/table/table-body/index.d.ts +2 -0
  153. package/build/components/table/table-body/index.d.ts.map +1 -0
  154. package/build/components/table/table-body/index.js +1 -0
  155. package/build/components/table/table-body/table-body.d.ts +4 -0
  156. package/build/components/table/table-body/table-body.d.ts.map +1 -0
  157. package/build/components/table/table-body/table-body.js +17 -0
  158. package/build/components/table/table-caption/index.d.ts +2 -0
  159. package/build/components/table/table-caption/index.d.ts.map +1 -0
  160. package/build/components/table/table-caption/index.js +1 -0
  161. package/build/components/table/table-caption/table-caption.d.ts +4 -0
  162. package/build/components/table/table-caption/table-caption.d.ts.map +1 -0
  163. package/build/components/table/table-caption/table-caption.js +13 -0
  164. package/build/components/table/table-cell/index.d.ts +2 -0
  165. package/build/components/table/table-cell/index.d.ts.map +1 -0
  166. package/build/components/table/table-cell/index.js +1 -0
  167. package/build/components/table/table-cell/table-cell.d.ts +4 -0
  168. package/build/components/table/table-cell/table-cell.d.ts.map +1 -0
  169. package/build/components/table/table-cell/table-cell.js +13 -0
  170. package/build/components/table/table-head/index.d.ts +2 -0
  171. package/build/components/table/table-head/index.d.ts.map +1 -0
  172. package/build/components/table/table-head/index.js +1 -0
  173. package/build/components/table/table-head/table-head.d.ts +4 -0
  174. package/build/components/table/table-head/table-head.d.ts.map +1 -0
  175. package/build/components/table/table-head/table-head.js +11 -0
  176. package/build/components/table/table-header-cell/index.d.ts +2 -0
  177. package/build/components/table/table-header-cell/index.d.ts.map +1 -0
  178. package/build/components/table/table-header-cell/index.js +1 -0
  179. package/build/components/table/table-header-cell/table-header-cell.d.ts +4 -0
  180. package/build/components/table/table-header-cell/table-header-cell.d.ts.map +1 -0
  181. package/build/components/table/table-header-cell/table-header-cell.js +13 -0
  182. package/build/components/table/table-row/index.d.ts +2 -0
  183. package/build/components/table/table-row/index.d.ts.map +1 -0
  184. package/build/components/table/table-row/index.js +1 -0
  185. package/build/components/table/table-row/table-row.d.ts +4 -0
  186. package/build/components/table/table-row/table-row.d.ts.map +1 -0
  187. package/build/components/table/table-row/table-row.js +11 -0
  188. package/build/components/table/table.context.d.ts +16 -0
  189. package/build/components/table/table.context.d.ts.map +1 -0
  190. package/build/components/table/table.context.js +2 -0
  191. package/build/components/table/table.d.ts +4 -0
  192. package/build/components/table/table.d.ts.map +1 -0
  193. package/build/components/table/table.js +46 -0
  194. package/build/components/table/table.styles.d.ts +16 -0
  195. package/build/components/table/table.styles.d.ts.map +1 -0
  196. package/build/components/table/table.styles.js +39 -0
  197. package/build/components/table/table.test.d.ts +2 -0
  198. package/build/components/table/table.test.d.ts.map +1 -0
  199. package/build/components/table/table.test.js +59 -0
  200. package/build/components/table/table.types.d.ts +113 -0
  201. package/build/components/table/table.types.d.ts.map +1 -0
  202. package/build/components/table/table.types.js +1 -0
  203. package/build/components/tabs/tabs-tab/tabs-tab.d.ts.map +1 -1
  204. package/build/components/tabs/tabs-tab/tabs-tab.js +0 -6
  205. package/build/components/tooltip/tooltip.d.ts.map +1 -1
  206. package/build/components/tooltip/tooltip.js +7 -3
  207. package/build/components/tooltip/use-tooltip.d.ts.map +1 -1
  208. package/build/components/tooltip/use-tooltip.js +2 -1
  209. package/build/components/transition/transition.d.ts.map +1 -1
  210. package/build/components/transition/transition.js +16 -12
  211. package/build/style.css +1 -1
  212. package/package.json +2 -2
  213. package/src/components/breadcrumbs/breadcrumbs.styles.ts +55 -0
  214. package/src/components/breadcrumbs/breadcrumbs.test.tsx +136 -0
  215. package/src/components/breadcrumbs/breadcrumbs.tsx +199 -0
  216. package/src/components/breadcrumbs/breadcrumbs.types.ts +78 -0
  217. package/src/components/breadcrumbs/breadcrumbs.utils.ts +70 -0
  218. package/src/components/breadcrumbs/index.ts +6 -0
  219. package/src/components/drawer/drawer-close/drawer-close.tsx +43 -0
  220. package/src/components/drawer/drawer-close/index.ts +1 -0
  221. package/src/components/drawer/drawer-content/drawer-content.tsx +98 -0
  222. package/src/components/drawer/drawer-content/index.ts +1 -0
  223. package/src/components/drawer/drawer-header/drawer-header.tsx +40 -0
  224. package/src/components/drawer/drawer-header/index.ts +1 -0
  225. package/src/components/drawer/drawer-overlay/drawer-overlay.tsx +86 -0
  226. package/src/components/drawer/drawer-overlay/index.ts +1 -0
  227. package/src/components/drawer/drawer-root/drawer-root.tsx +94 -0
  228. package/src/components/drawer/drawer-root/index.ts +1 -0
  229. package/src/components/drawer/drawer.context.ts +25 -0
  230. package/src/components/drawer/drawer.styles.ts +32 -0
  231. package/src/components/drawer/drawer.test.tsx +166 -0
  232. package/src/components/drawer/drawer.tsx +30 -0
  233. package/src/components/drawer/drawer.types.ts +158 -0
  234. package/src/components/drawer/index.ts +16 -0
  235. package/src/components/drawer/use-drawer.ts +101 -0
  236. package/src/components/index.ts +10 -6
  237. package/src/components/menu/menu-dropdown/menu-dropdown.tsx +4 -3
  238. package/src/components/menu/menu-sub-dropdown/menu-sub-dropdown.tsx +2 -0
  239. package/src/components/menu/use-menu.ts +2 -1
  240. package/src/components/modal/modal-close/modal-close.tsx +1 -5
  241. package/src/components/modal/modal-content/modal-content.tsx +3 -4
  242. package/src/components/modal/modal-header/modal-header.tsx +4 -2
  243. package/src/components/modal/modal-overlay/modal-overlay.tsx +66 -44
  244. package/src/components/modal/modal.test.tsx +124 -88
  245. package/src/components/modal/modal.types.ts +6 -0
  246. package/src/components/modal/use-modal.ts +101 -101
  247. package/src/components/number-input/number-input.test.tsx +22 -0
  248. package/src/components/number-input/number-input.tsx +79 -51
  249. package/src/components/number-input/number-input.types.ts +8 -8
  250. package/src/components/popover/popover-dropdown/popover-dropdown.tsx +2 -0
  251. package/src/components/popover/use-popover.ts +2 -1
  252. package/src/components/portal/portal.tsx +1 -1
  253. package/src/components/segmented-control/index.ts +6 -0
  254. package/src/components/segmented-control/segmented-control.styles.ts +37 -0
  255. package/src/components/segmented-control/segmented-control.test.tsx +152 -0
  256. package/src/components/segmented-control/segmented-control.tsx +245 -0
  257. package/src/components/segmented-control/segmented-control.types.ts +75 -0
  258. package/src/components/select/select-dropdown/select-dropdown.tsx +4 -3
  259. package/src/components/select/select-item/select-item.tsx +1 -2
  260. package/src/components/select/select-root/select-root.tsx +87 -11
  261. package/src/components/select/select-trigger/select-trigger.tsx +2 -0
  262. package/src/components/select/select.context.ts +2 -0
  263. package/src/components/select/select.test.tsx +35 -0
  264. package/src/components/select/select.types.ts +15 -0
  265. package/src/components/select/use-select.ts +2 -1
  266. package/src/components/switch/switch.tsx +1 -1
  267. package/src/components/table/index.ts +24 -0
  268. package/src/components/table/table-body/index.ts +1 -0
  269. package/src/components/table/table-body/table-body.tsx +37 -0
  270. package/src/components/table/table-caption/index.ts +1 -0
  271. package/src/components/table/table-caption/table-caption.tsx +32 -0
  272. package/src/components/table/table-cell/index.ts +1 -0
  273. package/src/components/table/table-cell/table-cell.tsx +33 -0
  274. package/src/components/table/table-head/index.ts +1 -0
  275. package/src/components/table/table-head/table-head.tsx +29 -0
  276. package/src/components/table/table-header-cell/index.ts +1 -0
  277. package/src/components/table/table-header-cell/table-header-cell.tsx +33 -0
  278. package/src/components/table/table-row/index.ts +1 -0
  279. package/src/components/table/table-row/table-row.tsx +30 -0
  280. package/src/components/table/table.context.ts +18 -0
  281. package/src/components/table/table.styles.ts +62 -0
  282. package/src/components/table/table.test.tsx +145 -0
  283. package/src/components/table/table.tsx +91 -0
  284. package/src/components/table/table.types.ts +145 -0
  285. package/src/components/tabs/tabs-tab/tabs-tab.tsx +0 -8
  286. package/src/components/tooltip/tooltip.tsx +7 -1
  287. package/src/components/tooltip/use-tooltip.ts +2 -1
  288. package/src/components/transition/transition.tsx +18 -14
  289. package/src/style.css +0 -1
  290. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,94 @@
1
+ import { useId } from "@refraktor/utils";
2
+ import { useRef } from "react";
3
+ import { RemoveScroll } from "react-remove-scroll";
4
+ import { useTheme } from "../../../theme";
5
+ import { factory, useClassNames, useProps } from "../../../utils";
6
+ import { DrawerProvider } from "../drawer.context";
7
+ import {
8
+ DrawerClassNames,
9
+ DrawerRootFactoryPayload,
10
+ DrawerRootProps
11
+ } from "../drawer.types";
12
+ import { useDrawer } from "../use-drawer";
13
+
14
+ const defaultProps = {
15
+ closeOnClickOutside: true,
16
+ closeOnEscape: true,
17
+ lockScroll: true,
18
+ withinPortal: true,
19
+ radius: "none",
20
+ position: "right",
21
+ size: "md"
22
+ } satisfies Partial<DrawerRootProps>;
23
+
24
+ const DrawerRoot = factory<DrawerRootFactoryPayload>((_props, ref) => {
25
+ const { cx } = useTheme();
26
+ const {
27
+ id,
28
+ children,
29
+ opened,
30
+ defaultOpened,
31
+ onOpenedChange,
32
+ closeOnClickOutside,
33
+ closeOnEscape,
34
+ lockScroll,
35
+ withinPortal,
36
+ radius,
37
+ position,
38
+ size,
39
+ transitionProps,
40
+ className,
41
+ classNames,
42
+ ...props
43
+ } = useProps("Drawer", defaultProps, _props);
44
+ const classes = useClassNames("Drawer", classNames);
45
+
46
+ const _id = useId(id);
47
+ const headerId = `${_id}-header`;
48
+ const contentRef = useRef<HTMLDivElement | null>(null);
49
+
50
+ const drawer = useDrawer({
51
+ opened,
52
+ defaultOpened,
53
+ onOpenedChange,
54
+ closeOnClickOutside,
55
+ closeOnEscape,
56
+ contentRef
57
+ });
58
+
59
+ const getStyles = (part: keyof DrawerClassNames) => classes[part];
60
+
61
+ return (
62
+ <DrawerProvider
63
+ value={{
64
+ drawer,
65
+ closeOnClickOutside,
66
+ lockScroll,
67
+ withinPortal,
68
+ radius,
69
+ position,
70
+ size,
71
+ transitionProps,
72
+ headerId,
73
+ contentRef,
74
+ classNames,
75
+ getStyles
76
+ }}
77
+ >
78
+ <RemoveScroll enabled={drawer.opened && lockScroll}>
79
+ <div
80
+ ref={ref}
81
+ id={_id}
82
+ className={cx(classes.root, className)}
83
+ {...props}
84
+ >
85
+ {children}
86
+ </div>
87
+ </RemoveScroll>
88
+ </DrawerProvider>
89
+ );
90
+ });
91
+
92
+ DrawerRoot.displayName = "@refraktor/core/Drawer.Root";
93
+
94
+ export default DrawerRoot;
@@ -0,0 +1 @@
1
+ export { default as DrawerRoot } from "./drawer-root";
@@ -0,0 +1,25 @@
1
+ import { createSafeContext } from "@refraktor/utils";
2
+ import { RefraktorRadius, RefraktorSize } from "../../theme";
3
+ import { TransitionProps } from "../transition";
4
+ import { DrawerClassNames, DrawerPosition } from "./drawer.types";
5
+ import { UseDrawerReturn } from "./use-drawer";
6
+
7
+ export interface DrawerContextValue {
8
+ drawer: UseDrawerReturn;
9
+ closeOnClickOutside: boolean;
10
+ lockScroll: boolean;
11
+ withinPortal: boolean;
12
+ radius: RefraktorRadius;
13
+ position: DrawerPosition;
14
+ size: RefraktorSize;
15
+ transitionProps?: Omit<TransitionProps, "children" | "mounted">;
16
+ headerId: string;
17
+ contentRef: React.MutableRefObject<HTMLDivElement | null>;
18
+ classNames?: DrawerClassNames;
19
+ getStyles: (part: keyof DrawerClassNames) => string | undefined;
20
+ }
21
+
22
+ export const [DrawerProvider, useDrawerContext] =
23
+ createSafeContext<DrawerContextValue>(
24
+ "Drawer context was not found in tree. Make sure Drawer subcomponents are wrapped with Drawer or DrawerRoot."
25
+ );
@@ -0,0 +1,32 @@
1
+ import { CSSProperties } from "react";
2
+ import { RefraktorSize } from "../../theme";
3
+ import { DrawerPosition } from "./drawer.types";
4
+
5
+ const sizes: Record<RefraktorSize, string> = {
6
+ xs: "16rem",
7
+ sm: "20rem",
8
+ md: "24rem",
9
+ lg: "30rem",
10
+ xl: "36rem"
11
+ };
12
+
13
+ export const getSize = (size: RefraktorSize = "md") => sizes[size];
14
+
15
+ export function getSizeStyles(
16
+ position: DrawerPosition,
17
+ size: RefraktorSize = "md"
18
+ ): CSSProperties {
19
+ const resolvedSize = getSize(size);
20
+
21
+ if (position === "left" || position === "right") {
22
+ return {
23
+ width: resolvedSize,
24
+ maxWidth: "100vw"
25
+ };
26
+ }
27
+
28
+ return {
29
+ height: resolvedSize,
30
+ maxHeight: "100vh"
31
+ };
32
+ }
@@ -0,0 +1,166 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { render, screen, userEvent, waitFor } from "../../vitest";
3
+ import Drawer from "./drawer";
4
+ import { DrawerContent } from "./drawer-content";
5
+ import { DrawerOverlay } from "./drawer-overlay";
6
+ import { DrawerRoot } from "./drawer-root";
7
+
8
+ describe("@refraktor/core/Drawer", () => {
9
+ const transitionProps = {
10
+ duration: 0,
11
+ immediate: true
12
+ } as const;
13
+
14
+ it("renders with compound subcomponents and closes with header close button", async () => {
15
+ const user = userEvent.setup();
16
+
17
+ await render(
18
+ <Drawer defaultOpened transitionProps={transitionProps}>
19
+ <Drawer.Overlay />
20
+
21
+ <Drawer.Content>
22
+ <Drawer.Header text="Edit profile" />
23
+ <p>Drawer body</p>
24
+ </Drawer.Content>
25
+ </Drawer>
26
+ );
27
+
28
+ expect(
29
+ await screen.findByRole("dialog", { name: "Edit profile" })
30
+ ).toBeInTheDocument();
31
+
32
+ await user.click(screen.getByRole("button", { name: "Close" }));
33
+
34
+ await waitFor(() => {
35
+ expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
36
+ });
37
+ });
38
+
39
+ it("calls onOpenedChange when clicking overlay in controlled mode", async () => {
40
+ const user = userEvent.setup();
41
+ const onOpenedChange = vi.fn();
42
+
43
+ await render(
44
+ <Drawer
45
+ opened
46
+ onOpenedChange={onOpenedChange}
47
+ transitionProps={transitionProps}
48
+ >
49
+ <Drawer.Overlay data-testid="overlay" />
50
+ <Drawer.Content>Controlled drawer</Drawer.Content>
51
+ </Drawer>
52
+ );
53
+
54
+ await user.click(await screen.findByTestId("overlay"));
55
+
56
+ expect(onOpenedChange).toHaveBeenCalledWith(false);
57
+ });
58
+
59
+ it("closes on Escape key", async () => {
60
+ const user = userEvent.setup();
61
+
62
+ await render(
63
+ <Drawer defaultOpened transitionProps={transitionProps}>
64
+ <Drawer.Content>Keyboard close</Drawer.Content>
65
+ </Drawer>
66
+ );
67
+
68
+ await screen.findByRole("dialog");
69
+
70
+ await user.keyboard("{Escape}");
71
+
72
+ await waitFor(() => {
73
+ expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
74
+ });
75
+ });
76
+
77
+ it("supports standalone subcomponents with DrawerRoot", async () => {
78
+ await render(
79
+ <DrawerRoot defaultOpened transitionProps={transitionProps}>
80
+ <DrawerOverlay />
81
+ <DrawerContent>Standalone composition</DrawerContent>
82
+ </DrawerRoot>
83
+ );
84
+
85
+ expect(await screen.findByRole("dialog")).toBeInTheDocument();
86
+ });
87
+
88
+ it("applies custom overlay background opacity and blur", async () => {
89
+ await render(
90
+ <Drawer defaultOpened transitionProps={transitionProps}>
91
+ <Drawer.Overlay
92
+ data-testid="overlay"
93
+ backgroundOpacity={0.4}
94
+ blur={6}
95
+ />
96
+ <Drawer.Content>Styled overlay</Drawer.Content>
97
+ </Drawer>
98
+ );
99
+
100
+ const overlay = await screen.findByTestId("overlay");
101
+
102
+ expect(overlay).toHaveStyle({
103
+ backgroundColor: "rgba(0, 0, 0, 0.4)",
104
+ backdropFilter: "blur(6px)"
105
+ });
106
+ });
107
+
108
+ it("locks and unlocks body scroll when enabled", async () => {
109
+ const user = userEvent.setup();
110
+
111
+ await render(
112
+ <Drawer defaultOpened lockScroll transitionProps={transitionProps}>
113
+ <Drawer.Content>
114
+ Scroll locked
115
+ <Drawer.Close />
116
+ </Drawer.Content>
117
+ </Drawer>
118
+ );
119
+
120
+ await waitFor(() => {
121
+ expect(document.body).toHaveAttribute("data-scroll-locked");
122
+ });
123
+
124
+ await user.click(screen.getByRole("button", { name: "Close" }));
125
+
126
+ await waitFor(() => {
127
+ expect(document.body).not.toHaveAttribute("data-scroll-locked");
128
+ });
129
+ });
130
+
131
+ it("supports different positions and predefined sizes", async () => {
132
+ await render(
133
+ <>
134
+ <Drawer
135
+ defaultOpened
136
+ position="left"
137
+ size="sm"
138
+ transitionProps={transitionProps}
139
+ >
140
+ <Drawer.Content data-testid="left-content">
141
+ Left
142
+ </Drawer.Content>
143
+ </Drawer>
144
+
145
+ <Drawer
146
+ defaultOpened
147
+ position="bottom"
148
+ size="xl"
149
+ transitionProps={transitionProps}
150
+ >
151
+ <Drawer.Content data-testid="bottom-content">
152
+ Bottom
153
+ </Drawer.Content>
154
+ </Drawer>
155
+ </>
156
+ );
157
+
158
+ const leftContent = await screen.findByTestId("left-content");
159
+ const bottomContent = await screen.findByTestId("bottom-content");
160
+
161
+ expect(leftContent).toHaveAttribute("data-position", "left");
162
+ expect(leftContent).toHaveStyle({ width: "20rem" });
163
+ expect(bottomContent).toHaveAttribute("data-position", "bottom");
164
+ expect(bottomContent).toHaveStyle({ height: "36rem" });
165
+ });
166
+ });
@@ -0,0 +1,30 @@
1
+ import {
2
+ createClassNamesConfig,
3
+ createComponentConfig,
4
+ factory
5
+ } from "../../utils";
6
+ import { DrawerClose } from "./drawer-close";
7
+ import { DrawerContent } from "./drawer-content";
8
+ import { DrawerHeader } from "./drawer-header";
9
+ import { DrawerOverlay } from "./drawer-overlay";
10
+ import { DrawerRoot } from "./drawer-root";
11
+ import {
12
+ DrawerClassNames,
13
+ DrawerFactoryPayload,
14
+ DrawerProps
15
+ } from "./drawer.types";
16
+
17
+ const Drawer = factory<DrawerFactoryPayload>((props, ref) => {
18
+ return <DrawerRoot {...props} ref={ref} />;
19
+ });
20
+
21
+ Drawer.displayName = "@refraktor/core/Drawer";
22
+ Drawer.configure = createComponentConfig<DrawerProps>();
23
+ Drawer.classNames = createClassNamesConfig<DrawerClassNames>();
24
+ Drawer.Root = DrawerRoot;
25
+ Drawer.Overlay = DrawerOverlay;
26
+ Drawer.Content = DrawerContent;
27
+ Drawer.Header = DrawerHeader;
28
+ Drawer.Close = DrawerClose;
29
+
30
+ export default Drawer;
@@ -0,0 +1,158 @@
1
+ import { ComponentPropsWithoutRef, MouseEvent, ReactNode } from "react";
2
+ import {
3
+ createClassNamesConfig,
4
+ createComponentConfig,
5
+ FactoryPayload
6
+ } from "../../utils";
7
+ import { RefraktorRadius, RefraktorSize } from "../../theme";
8
+ import { TransitionProps } from "../transition";
9
+ import { DrawerRoot } from "./drawer-root";
10
+ import { DrawerOverlay } from "./drawer-overlay";
11
+ import { DrawerContent } from "./drawer-content";
12
+ import { DrawerHeader } from "./drawer-header";
13
+ import { DrawerClose } from "./drawer-close";
14
+
15
+ export type DrawerPosition = "left" | "right" | "top" | "bottom";
16
+
17
+ export type DrawerClassNames = {
18
+ root?: string;
19
+ overlay?: string;
20
+ content?: string;
21
+ header?: string;
22
+ close?: string;
23
+ };
24
+
25
+ export interface DrawerProps extends ComponentPropsWithoutRef<"div"> {
26
+ /** Children containing drawer subcomponents */
27
+ children: ReactNode;
28
+
29
+ /** State of the drawer (controlled) */
30
+ opened?: boolean;
31
+
32
+ /** Initial state of the drawer (uncontrolled) */
33
+ defaultOpened?: boolean;
34
+
35
+ /** Callback called when drawer state changes */
36
+ onOpenedChange?: (opened: boolean) => void;
37
+
38
+ /** Whether to close drawer on overlay/outside click @default `true` */
39
+ closeOnClickOutside?: boolean;
40
+
41
+ /** Whether to close drawer on Escape key @default `true` */
42
+ closeOnEscape?: boolean;
43
+
44
+ /** Whether to lock body scroll while opened @default `true` */
45
+ lockScroll?: boolean;
46
+
47
+ /** Whether to render overlay/content inside portal @default `true` */
48
+ withinPortal?: boolean;
49
+
50
+ /** Radius for drawer content @default `none` */
51
+ radius?: RefraktorRadius;
52
+
53
+ /** Side where drawer appears @default `right` */
54
+ position?: DrawerPosition;
55
+
56
+ /** Drawer size scale (width for left/right, height for top/bottom) @default `md` */
57
+ size?: RefraktorSize;
58
+
59
+ /** Transition props for overlay/content, uses Transition internally */
60
+ transitionProps?: Omit<TransitionProps, "children" | "mounted">;
61
+
62
+ /** Used for editing root class name */
63
+ className?: string;
64
+
65
+ /** Used for styling different parts of the component */
66
+ classNames?: DrawerClassNames;
67
+ }
68
+
69
+ export type DrawerRootProps = DrawerProps;
70
+
71
+ export interface DrawerOverlayProps extends ComponentPropsWithoutRef<"div"> {
72
+ /** Whether clicking the overlay closes drawer @default `true` */
73
+ closeOnClick?: boolean;
74
+
75
+ /** Overlay background opacity @default `0.5` */
76
+ backgroundOpacity?: number;
77
+
78
+ /** Backdrop blur amount in px (or any CSS length) @default `0` */
79
+ blur?: number | string;
80
+
81
+ /** Used for editing root class name */
82
+ className?: string;
83
+ }
84
+
85
+ export interface DrawerContentProps extends ComponentPropsWithoutRef<"div"> {
86
+ /** Drawer body content */
87
+ children: ReactNode;
88
+
89
+ /** Used for editing root class name */
90
+ className?: string;
91
+ }
92
+
93
+ export interface DrawerHeaderProps extends ComponentPropsWithoutRef<"div"> {
94
+ /** Header content */
95
+ children?: ReactNode;
96
+
97
+ /** Shorthand header text */
98
+ text?: ReactNode;
99
+
100
+ /** Whether to show close button inside header @default `true` */
101
+ withClose?: boolean;
102
+
103
+ /** Used for editing root class name */
104
+ className?: string;
105
+ }
106
+
107
+ export interface DrawerCloseProps extends Omit<
108
+ ComponentPropsWithoutRef<"button">,
109
+ "onClick"
110
+ > {
111
+ /** Optional close content (defaults to `x`) */
112
+ children?: ReactNode;
113
+
114
+ /** Click callback fired before closing */
115
+ onClick?: (event: MouseEvent<HTMLButtonElement>) => void;
116
+
117
+ /** Used for editing root class name */
118
+ className?: string;
119
+ }
120
+
121
+ export interface DrawerFactoryPayload extends FactoryPayload {
122
+ props: DrawerProps;
123
+ ref: HTMLDivElement;
124
+ compound: {
125
+ configure: ReturnType<typeof createComponentConfig<DrawerProps>>;
126
+ classNames: ReturnType<typeof createClassNamesConfig<DrawerClassNames>>;
127
+ Root: typeof DrawerRoot;
128
+ Overlay: typeof DrawerOverlay;
129
+ Content: typeof DrawerContent;
130
+ Header: typeof DrawerHeader;
131
+ Close: typeof DrawerClose;
132
+ };
133
+ }
134
+
135
+ export interface DrawerRootFactoryPayload extends FactoryPayload {
136
+ props: DrawerRootProps;
137
+ ref: HTMLDivElement;
138
+ }
139
+
140
+ export interface DrawerOverlayFactoryPayload extends FactoryPayload {
141
+ props: DrawerOverlayProps;
142
+ ref: HTMLDivElement;
143
+ }
144
+
145
+ export interface DrawerContentFactoryPayload extends FactoryPayload {
146
+ props: DrawerContentProps;
147
+ ref: HTMLDivElement;
148
+ }
149
+
150
+ export interface DrawerHeaderFactoryPayload extends FactoryPayload {
151
+ props: DrawerHeaderProps;
152
+ ref: HTMLDivElement;
153
+ }
154
+
155
+ export interface DrawerCloseFactoryPayload extends FactoryPayload {
156
+ props: DrawerCloseProps;
157
+ ref: HTMLButtonElement;
158
+ }
@@ -0,0 +1,16 @@
1
+ export { default as Drawer } from "./drawer";
2
+ export { DrawerRoot } from "./drawer-root";
3
+ export { DrawerOverlay } from "./drawer-overlay";
4
+ export { DrawerContent } from "./drawer-content";
5
+ export { DrawerHeader } from "./drawer-header";
6
+ export { DrawerClose } from "./drawer-close";
7
+ export type {
8
+ DrawerProps,
9
+ DrawerRootProps,
10
+ DrawerOverlayProps,
11
+ DrawerContentProps,
12
+ DrawerHeaderProps,
13
+ DrawerCloseProps,
14
+ DrawerClassNames,
15
+ DrawerPosition
16
+ } from "./drawer.types";
@@ -0,0 +1,101 @@
1
+ import { useUncontrolled } from "@refraktor/utils";
2
+ import { useCallback, useEffect } from "react";
3
+
4
+ interface UseDrawerProps {
5
+ opened?: boolean;
6
+ defaultOpened?: boolean;
7
+ onOpenedChange?: (opened: boolean) => void;
8
+ closeOnClickOutside?: boolean;
9
+ closeOnEscape?: boolean;
10
+ contentRef: React.MutableRefObject<HTMLElement | null>;
11
+ }
12
+
13
+ export interface UseDrawerReturn {
14
+ opened: boolean;
15
+ open: () => void;
16
+ close: () => void;
17
+ toggle: () => void;
18
+ }
19
+
20
+ export function useDrawer(options: UseDrawerProps): UseDrawerReturn {
21
+ const {
22
+ opened,
23
+ defaultOpened,
24
+ onOpenedChange,
25
+ closeOnClickOutside = true,
26
+ closeOnEscape = true,
27
+ contentRef
28
+ } = options;
29
+
30
+ const [isOpen, setIsOpen] = useUncontrolled({
31
+ value: opened,
32
+ defaultValue: defaultOpened,
33
+ finalValue: false,
34
+ onChange: onOpenedChange
35
+ });
36
+
37
+ const open = useCallback(() => {
38
+ setIsOpen(true);
39
+ }, [setIsOpen]);
40
+
41
+ const close = useCallback(() => {
42
+ setIsOpen(false);
43
+ }, [setIsOpen]);
44
+
45
+ const toggle = useCallback(() => {
46
+ setIsOpen(!isOpen);
47
+ }, [isOpen, setIsOpen]);
48
+
49
+ useEffect(() => {
50
+ if (!isOpen || !closeOnEscape) {
51
+ return;
52
+ }
53
+
54
+ const handleKeyDown = (event: KeyboardEvent) => {
55
+ if (event.key === "Escape") {
56
+ setIsOpen(false);
57
+ }
58
+ };
59
+
60
+ document.addEventListener("keydown", handleKeyDown);
61
+
62
+ return () => {
63
+ document.removeEventListener("keydown", handleKeyDown);
64
+ };
65
+ }, [closeOnEscape, isOpen, setIsOpen]);
66
+
67
+ useEffect(() => {
68
+ if (!isOpen || !closeOnClickOutside) {
69
+ return;
70
+ }
71
+
72
+ const handlePointerDown = (event: MouseEvent | TouchEvent) => {
73
+ const target = event.target;
74
+
75
+ if (!(target instanceof Node)) {
76
+ return;
77
+ }
78
+
79
+ if (contentRef.current?.contains(target)) {
80
+ return;
81
+ }
82
+
83
+ setIsOpen(false);
84
+ };
85
+
86
+ document.addEventListener("mousedown", handlePointerDown);
87
+ document.addEventListener("touchstart", handlePointerDown);
88
+
89
+ return () => {
90
+ document.removeEventListener("mousedown", handlePointerDown);
91
+ document.removeEventListener("touchstart", handlePointerDown);
92
+ };
93
+ }, [closeOnClickOutside, contentRef, isOpen, setIsOpen]);
94
+
95
+ return {
96
+ opened: isOpen,
97
+ open,
98
+ close,
99
+ toggle
100
+ };
101
+ }
@@ -1,9 +1,11 @@
1
1
  export * from "./accordion";
2
2
  export * from "./avatar";
3
3
  export * from "./badge";
4
+ export * from "./breadcrumbs";
4
5
  export * from "./button";
5
6
  export * from "./checkbox";
6
7
  export * from "./color-swatch";
8
+ export * from "./drawer";
7
9
  export * from "./input";
8
10
  export * from "./loader";
9
11
  export * from "./modal";
@@ -16,10 +18,12 @@ export * from "./progress";
16
18
  export * from "./progress-circle";
17
19
  export * from "./radio";
18
20
  export * from "./select";
21
+ export * from "./segmented-control";
19
22
  export * from "./slider";
20
- export * from "./switch";
21
- export * from "./tabs";
22
- export * from "./timeline";
23
- export * from "./textarea";
24
- export * from "./tooltip";
25
- export * from "./transition";
23
+ export * from "./switch";
24
+ export * from "./table";
25
+ export * from "./tabs";
26
+ export * from "./timeline";
27
+ export * from "./textarea";
28
+ export * from "./tooltip";
29
+ export * from "./transition";
@@ -166,6 +166,7 @@ const MenuDropdown = factory<MenuDropdownFactoryPayload>(
166
166
  transition="fade"
167
167
  duration={150}
168
168
  mounted={level.menu.opened}
169
+ style={{ position: "relative", zIndex: 1000 }}
169
170
  {...transitionProps}
170
171
  >
171
172
  <div
@@ -174,6 +175,7 @@ const MenuDropdown = factory<MenuDropdownFactoryPayload>(
174
175
  tabIndex={-1}
175
176
  style={{
176
177
  ...level.menu.floatingStyles,
178
+ zIndex: 1000,
177
179
  scrollbarGutter: "auto",
178
180
  ...style
179
181
  }}
@@ -194,16 +196,15 @@ const MenuDropdown = factory<MenuDropdownFactoryPayload>(
194
196
  </Transition>
195
197
  );
196
198
 
197
- const wrappedContent = level.menu.opened ? (
199
+ const wrappedContent = (
198
200
  <FloatingFocusManager
199
201
  context={level.menu.context}
200
202
  modal={false}
201
203
  initialFocus={-1}
204
+ disabled={!level.menu.opened}
202
205
  >
203
206
  {dropdownContent}
204
207
  </FloatingFocusManager>
205
- ) : (
206
- dropdownContent
207
208
  );
208
209
 
209
210
  return withinPortal ? (