@px-ui/ui 1.0.10 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (286) hide show
  1. package/dist/{avatar-CbuG-kqF.d.ts → avatar-DTxH_yTY.d.ts} +6 -6
  2. package/dist/{avatar-CbuG-kqF.d.ts.map → avatar-DTxH_yTY.d.ts.map} +1 -1
  3. package/dist/{avatar-Bb0tx0Hn.js → avatar-DnDnGmSj.js} +3 -3
  4. package/dist/{avatar-Bb0tx0Hn.js.map → avatar-DnDnGmSj.js.map} +1 -1
  5. package/dist/{button-BkzvdmIX.d.ts → button-Cfd9X6pX.d.ts} +7 -7
  6. package/dist/{button-BkzvdmIX.d.ts.map → button-Cfd9X6pX.d.ts.map} +1 -1
  7. package/dist/{button-hBUFMmsZ.js → button-DnHwqwy0.js} +2 -2
  8. package/dist/{button-hBUFMmsZ.js.map → button-DnHwqwy0.js.map} +1 -1
  9. package/dist/checkbox-CwkX29tL.js +22 -0
  10. package/dist/checkbox-CwkX29tL.js.map +1 -0
  11. package/dist/collapsible-DsrYXIW5.js +28 -0
  12. package/dist/collapsible-DsrYXIW5.js.map +1 -0
  13. package/dist/{combobox-CHkmVNZ2.js → combobox-5IAivvXw.js} +8 -8
  14. package/dist/{combobox-CHkmVNZ2.js.map → combobox-5IAivvXw.js.map} +1 -1
  15. package/dist/{combobox-C5txQ2La.d.ts → combobox-BBMYGrI2.d.ts} +19 -19
  16. package/dist/{combobox-C5txQ2La.d.ts.map → combobox-BBMYGrI2.d.ts.map} +1 -1
  17. package/dist/components/accordion.d.ts +5 -5
  18. package/dist/components/accordion.d.ts.map +1 -1
  19. package/dist/components/accordion.js +1 -1
  20. package/dist/components/alert-dialog.d.ts +14 -14
  21. package/dist/components/alert-dialog.js +2 -2
  22. package/dist/components/alert.d.ts +7 -7
  23. package/dist/components/alert.js +1 -1
  24. package/dist/components/aspect-ratio.d.ts +2 -2
  25. package/dist/components/aspect-ratio.d.ts.map +1 -1
  26. package/dist/components/aspect-ratio.js +1 -1
  27. package/dist/components/attachment.d.ts +64 -0
  28. package/dist/components/attachment.d.ts.map +1 -0
  29. package/dist/components/attachment.js +107 -0
  30. package/dist/components/attachment.js.map +1 -0
  31. package/dist/components/avatar-group.d.ts +4 -4
  32. package/dist/components/avatar-group.d.ts.map +1 -1
  33. package/dist/components/avatar-group.js +4 -4
  34. package/dist/components/avatar.d.ts +1 -1
  35. package/dist/components/avatar.js +3 -3
  36. package/dist/components/badge.d.ts +1 -1
  37. package/dist/components/badge.js +1 -1
  38. package/dist/components/breadcrumb.d.ts +7 -7
  39. package/dist/components/breadcrumb.js +1 -1
  40. package/dist/components/bubble.d.ts +39 -0
  41. package/dist/components/bubble.d.ts.map +1 -0
  42. package/dist/components/bubble.js +76 -0
  43. package/dist/components/bubble.js.map +1 -0
  44. package/dist/components/button-group.d.ts +6 -6
  45. package/dist/components/button-group.js +2 -2
  46. package/dist/components/button.d.ts +1 -1
  47. package/dist/components/button.js +2 -2
  48. package/dist/components/calendar.d.ts +4 -4
  49. package/dist/components/calendar.js +2 -2
  50. package/dist/components/card.d.ts +8 -8
  51. package/dist/components/card.js +1 -1
  52. package/dist/components/carousel.d.ts +7 -7
  53. package/dist/components/carousel.js +2 -2
  54. package/dist/components/chart.d.ts +5 -5
  55. package/dist/components/chart.js +1 -1
  56. package/dist/components/checkbox.d.ts +2 -2
  57. package/dist/components/checkbox.d.ts.map +1 -1
  58. package/dist/components/checkbox.js +3 -21
  59. package/dist/components/collapsible.d.ts +4 -4
  60. package/dist/components/collapsible.js +3 -27
  61. package/dist/components/combobox.d.ts +2 -2
  62. package/dist/components/combobox.js +11 -11
  63. package/dist/components/command.d.ts +11 -11
  64. package/dist/components/command.js +6 -6
  65. package/dist/components/context-menu.d.ts +16 -16
  66. package/dist/components/context-menu.d.ts.map +1 -1
  67. package/dist/components/context-menu.js +1 -1
  68. package/dist/components/currency-select-field.d.ts +4 -4
  69. package/dist/components/currency-select-field.js +11 -11
  70. package/dist/components/dialog.d.ts +11 -11
  71. package/dist/components/dialog.js +3 -3
  72. package/dist/components/direction.js +1 -1
  73. package/dist/components/drawer.d.ts +11 -11
  74. package/dist/components/drawer.js +1 -1
  75. package/dist/components/dropdown-menu.d.ts +1 -1
  76. package/dist/components/dropdown-menu.js +2 -2
  77. package/dist/components/editor-output.d.ts +87 -0
  78. package/dist/components/editor-output.d.ts.map +1 -0
  79. package/dist/components/editor-output.js +158 -0
  80. package/dist/components/editor-output.js.map +1 -0
  81. package/dist/components/empty.d.ts +9 -9
  82. package/dist/components/empty.js +3 -61
  83. package/dist/components/field.d.ts +15 -15
  84. package/dist/components/field.js +3 -3
  85. package/dist/components/file-upload-field.d.ts +3 -3
  86. package/dist/components/file-upload-field.js +5 -5
  87. package/dist/components/file-upload.d.ts +3 -3
  88. package/dist/components/file-upload.js +4 -4
  89. package/dist/components/hover-card.d.ts +4 -4
  90. package/dist/components/hover-card.js +1 -1
  91. package/dist/components/icon.d.ts +83 -0
  92. package/dist/components/icon.d.ts.map +1 -0
  93. package/dist/components/icon.js +188 -0
  94. package/dist/components/icon.js.map +1 -0
  95. package/dist/components/input-group.d.ts +9 -9
  96. package/dist/components/input-group.js +5 -5
  97. package/dist/components/input-otp.d.ts +5 -5
  98. package/dist/components/input-otp.js +1 -1
  99. package/dist/components/input.d.ts +1 -1
  100. package/dist/components/input.js +2 -2
  101. package/dist/components/item.d.ts +14 -14
  102. package/dist/components/item.d.ts.map +1 -1
  103. package/dist/components/item.js +2 -2
  104. package/dist/components/kbd.d.ts +3 -3
  105. package/dist/components/kbd.js +1 -1
  106. package/dist/components/label.d.ts +1 -1
  107. package/dist/components/label.js +2 -2
  108. package/dist/components/marker.d.ts +27 -0
  109. package/dist/components/marker.d.ts.map +1 -0
  110. package/dist/components/marker.js +46 -0
  111. package/dist/components/marker.js.map +1 -0
  112. package/dist/components/menubar.d.ts +18 -18
  113. package/dist/components/menubar.d.ts.map +1 -1
  114. package/dist/components/menubar.js +7 -7
  115. package/dist/components/menubar.js.map +1 -1
  116. package/dist/components/message-scroller.d.ts +36 -0
  117. package/dist/components/message-scroller.d.ts.map +1 -0
  118. package/dist/components/message-scroller.js +63 -0
  119. package/dist/components/message-scroller.js.map +1 -0
  120. package/dist/components/message.d.ts +34 -0
  121. package/dist/components/message.d.ts.map +1 -0
  122. package/dist/components/message.js +52 -0
  123. package/dist/components/message.js.map +1 -0
  124. package/dist/components/native-select.d.ts +4 -4
  125. package/dist/components/native-select.js +1 -1
  126. package/dist/components/navigation-menu.d.ts +11 -11
  127. package/dist/components/navigation-menu.js +1 -1
  128. package/dist/components/pagination.d.ts +9 -9
  129. package/dist/components/pagination.d.ts.map +1 -1
  130. package/dist/components/pagination.js +2 -2
  131. package/dist/components/phone-input.d.ts +2 -2
  132. package/dist/components/phone-input.js +1 -1
  133. package/dist/components/popover.d.ts +7 -7
  134. package/dist/components/popover.d.ts.map +1 -1
  135. package/dist/components/popover.js +2 -2
  136. package/dist/components/progress.d.ts +6 -6
  137. package/dist/components/progress.js +1 -1
  138. package/dist/components/radio-group.d.ts +3 -3
  139. package/dist/components/radio-group.js +1 -1
  140. package/dist/components/resizable.d.ts +4 -4
  141. package/dist/components/resizable.js +1 -1
  142. package/dist/components/rich-text-editor.d.ts +204 -0
  143. package/dist/components/rich-text-editor.d.ts.map +1 -0
  144. package/dist/components/rich-text-editor.js +359 -0
  145. package/dist/components/rich-text-editor.js.map +1 -0
  146. package/dist/components/scroll-area.d.ts +13 -3
  147. package/dist/components/scroll-area.d.ts.map +1 -1
  148. package/dist/components/scroll-area.js +3 -38
  149. package/dist/components/select.d.ts +10 -10
  150. package/dist/components/select.js +1 -1
  151. package/dist/components/separator.d.ts +1 -1
  152. package/dist/components/separator.js +2 -2
  153. package/dist/components/sheet.d.ts +9 -9
  154. package/dist/components/sheet.js +3 -3
  155. package/dist/components/sidebar.d.ts +26 -26
  156. package/dist/components/sidebar.d.ts.map +1 -1
  157. package/dist/components/sidebar.js +8 -8
  158. package/dist/components/skeleton.d.ts +2 -2
  159. package/dist/components/skeleton.js +2 -2
  160. package/dist/components/slider.d.ts +2 -2
  161. package/dist/components/slider.js +1 -1
  162. package/dist/components/sortable-list.d.ts +153 -0
  163. package/dist/components/sortable-list.d.ts.map +1 -0
  164. package/dist/components/sortable-list.js +191 -0
  165. package/dist/components/sortable-list.js.map +1 -0
  166. package/dist/components/spinner.d.ts +2 -2
  167. package/dist/components/spinner.js +2 -2
  168. package/dist/components/stepper.d.ts +171 -0
  169. package/dist/components/stepper.d.ts.map +1 -0
  170. package/dist/components/stepper.js +281 -0
  171. package/dist/components/stepper.js.map +1 -0
  172. package/dist/components/switch.d.ts +2 -2
  173. package/dist/components/switch.js +1 -1
  174. package/dist/components/table.d.ts +9 -9
  175. package/dist/components/table.js +1 -1
  176. package/dist/components/tabs.d.ts +8 -8
  177. package/dist/components/tabs.d.ts.map +1 -1
  178. package/dist/components/tabs.js +1 -1
  179. package/dist/components/textarea.d.ts +2 -2
  180. package/dist/components/textarea.js +2 -2
  181. package/dist/components/toast.d.ts +1 -1
  182. package/dist/components/toast.js +2 -2
  183. package/dist/components/toggle-group.d.ts +4 -4
  184. package/dist/components/toggle-group.js +2 -2
  185. package/dist/components/toggle.d.ts +1 -1
  186. package/dist/components/toggle.js +2 -2
  187. package/dist/components/tooltip.d.ts +1 -1
  188. package/dist/components/tooltip.js +2 -2
  189. package/dist/components/tree-select.d.ts +192 -0
  190. package/dist/components/tree-select.d.ts.map +1 -0
  191. package/dist/components/tree-select.js +421 -0
  192. package/dist/components/tree-select.js.map +1 -0
  193. package/dist/{dialog-DrdXva1a.js → dialog-DuGJUPQl.js} +3 -3
  194. package/dist/{dialog-DrdXva1a.js.map → dialog-DuGJUPQl.js.map} +1 -1
  195. package/dist/{dropdown-menu-CcumvwhM.js → dropdown-menu-BWEfcvmP.js} +19 -19
  196. package/dist/{dropdown-menu-CcumvwhM.js.map → dropdown-menu-BWEfcvmP.js.map} +1 -1
  197. package/dist/{dropdown-menu-BC7zFA2L.d.ts → dropdown-menu-DGgfWYrK.d.ts} +17 -17
  198. package/dist/{dropdown-menu-BC7zFA2L.d.ts.map → dropdown-menu-DGgfWYrK.d.ts.map} +1 -1
  199. package/dist/empty-U4zrLmFU.js +62 -0
  200. package/dist/empty-U4zrLmFU.js.map +1 -0
  201. package/dist/{file-upload-DoGu67Bu.d.ts → file-upload-BvAtAxLc.d.ts} +10 -10
  202. package/dist/{file-upload-DoGu67Bu.d.ts.map → file-upload-BvAtAxLc.d.ts.map} +1 -1
  203. package/dist/{file-upload-DeCIv13t.js → file-upload-DU5FAkHm.js} +4 -4
  204. package/dist/{file-upload-DeCIv13t.js.map → file-upload-DU5FAkHm.js.map} +1 -1
  205. package/dist/hooks/use-async-options.d.ts +1 -1
  206. package/dist/hooks/use-async-options.js +1 -1
  207. package/dist/hooks/use-debounce.js +1 -1
  208. package/dist/hooks/use-file-upload.d.ts +1 -1
  209. package/dist/hooks/use-file-upload.js +1 -1
  210. package/dist/hooks/use-infinite-scroll.d.ts +1 -1
  211. package/dist/hooks/use-infinite-scroll.js +2 -2
  212. package/dist/hooks/use-intersection-observer.d.ts +1 -1
  213. package/dist/hooks/use-intersection-observer.js +1 -1
  214. package/dist/hooks/use-mobile.js +1 -1
  215. package/dist/{input-CoP6CeA5.d.ts → input-BExbcSu4.d.ts} +3 -3
  216. package/dist/input-BExbcSu4.d.ts.map +1 -0
  217. package/dist/{input-group-DqEkmpXW.js → input-group-B5PMRYld.js} +5 -5
  218. package/dist/{input-group-DqEkmpXW.js.map → input-group-B5PMRYld.js.map} +1 -1
  219. package/dist/{input-8jqdnUZl.js → input-jIoNIdLQ.js} +2 -2
  220. package/dist/{input-8jqdnUZl.js.map → input-jIoNIdLQ.js.map} +1 -1
  221. package/dist/label-BFg2hxuL.d.ts +11 -0
  222. package/dist/label-BFg2hxuL.d.ts.map +1 -0
  223. package/dist/{label-AaH9ZYCZ.js → label-DsRhOKY_.js} +2 -2
  224. package/dist/{label-AaH9ZYCZ.js.map → label-DsRhOKY_.js.map} +1 -1
  225. package/dist/lib/utils.js +1 -1
  226. package/dist/{popover-C9D43EuT.js → popover-BGkU46G7.js} +2 -2
  227. package/dist/{popover-C9D43EuT.js.map → popover-BGkU46G7.js.map} +1 -1
  228. package/dist/providers/px-ui-provider.d.ts +4 -4
  229. package/dist/providers/px-ui-provider.d.ts.map +1 -1
  230. package/dist/providers/px-ui-provider.js +4 -4
  231. package/dist/scroll-area-mNVMQ0Of.js +40 -0
  232. package/dist/scroll-area-mNVMQ0Of.js.map +1 -0
  233. package/dist/{separator-BS3ilczC.js → separator-D0bew2D_.js} +2 -2
  234. package/dist/{separator-BS3ilczC.js.map → separator-D0bew2D_.js.map} +1 -1
  235. package/dist/{separator-D0hWdzUT.d.ts → separator-Df76guaT.d.ts} +3 -3
  236. package/dist/{separator-D0hWdzUT.d.ts.map → separator-Df76guaT.d.ts.map} +1 -1
  237. package/dist/{sheet-CLjNDrfL.js → sheet-BB23q6wd.js} +3 -3
  238. package/dist/{sheet-CLjNDrfL.js.map → sheet-BB23q6wd.js.map} +1 -1
  239. package/dist/{skeleton-BcIxI5Wq.js → skeleton-knxLhbA5.js} +2 -2
  240. package/dist/{skeleton-BcIxI5Wq.js.map → skeleton-knxLhbA5.js.map} +1 -1
  241. package/dist/{spinner-Bo0sUZEg.js → spinner-9MdgLDTZ.js} +2 -2
  242. package/dist/{spinner-Bo0sUZEg.js.map → spinner-9MdgLDTZ.js.map} +1 -1
  243. package/dist/styles.css +665 -1
  244. package/dist/{textarea-Cq0o323P.js → textarea-hZg0gA8u.js} +2 -2
  245. package/dist/{textarea-Cq0o323P.js.map → textarea-hZg0gA8u.js.map} +1 -1
  246. package/dist/{toast-COWAQbIk.js → toast-BdxoP8vz.js} +2 -2
  247. package/dist/{toast-COWAQbIk.js.map → toast-BdxoP8vz.js.map} +1 -1
  248. package/dist/{toast-DkzzdXGU.d.ts → toast-C5FRpq1P.d.ts} +4 -4
  249. package/dist/{toast-DkzzdXGU.d.ts.map → toast-C5FRpq1P.d.ts.map} +1 -1
  250. package/dist/{toggle-lqIyJptS.js → toggle-BZXrLBLK.js} +2 -2
  251. package/dist/{toggle-lqIyJptS.js.map → toggle-BZXrLBLK.js.map} +1 -1
  252. package/dist/{toggle-Dq3ftPFj.d.ts → toggle-CyTngkhT.d.ts} +6 -6
  253. package/dist/{toggle-Dq3ftPFj.d.ts.map → toggle-CyTngkhT.d.ts.map} +1 -1
  254. package/dist/{tooltip-DBoqfN9z.d.ts → tooltip-CkX3CD71.d.ts} +6 -6
  255. package/dist/{tooltip-DBoqfN9z.d.ts.map → tooltip-CkX3CD71.d.ts.map} +1 -1
  256. package/dist/{tooltip-DkPxCJIL.js → tooltip-Dsfn_zZD.js} +2 -2
  257. package/dist/{tooltip-DkPxCJIL.js.map → tooltip-Dsfn_zZD.js.map} +1 -1
  258. package/dist/{use-async-options-Cu5T43vj.d.ts → use-async-options-DdyHJxHh.d.ts} +1 -1
  259. package/dist/{use-async-options-Cu5T43vj.d.ts.map → use-async-options-DdyHJxHh.d.ts.map} +1 -1
  260. package/dist/{use-async-options-CcsImGX4.js → use-async-options-tueAuVs_.js} +1 -1
  261. package/dist/{use-async-options-CcsImGX4.js.map → use-async-options-tueAuVs_.js.map} +1 -1
  262. package/dist/{use-debounce-_qaEZqtt.js → use-debounce-7gIeOwla.js} +1 -1
  263. package/dist/{use-debounce-_qaEZqtt.js.map → use-debounce-7gIeOwla.js.map} +1 -1
  264. package/dist/{use-file-upload-yy-xLBtn.d.ts → use-file-upload-Bc7CyQ7O.d.ts} +1 -1
  265. package/dist/{use-file-upload-yy-xLBtn.d.ts.map → use-file-upload-Bc7CyQ7O.d.ts.map} +1 -1
  266. package/dist/{use-file-upload-Dxrej28u.js → use-file-upload-DQD1vY_Z.js} +1 -1
  267. package/dist/{use-file-upload-Dxrej28u.js.map → use-file-upload-DQD1vY_Z.js.map} +1 -1
  268. package/dist/{use-infinite-scroll-CpbhGGT5.js → use-infinite-scroll-HpeMA2MK.js} +2 -2
  269. package/dist/{use-infinite-scroll-CpbhGGT5.js.map → use-infinite-scroll-HpeMA2MK.js.map} +1 -1
  270. package/dist/{use-intersection-observer-C2xDq2SW.d.ts → use-intersection-observer-DNPextJs.d.ts} +1 -1
  271. package/dist/{use-intersection-observer-C2xDq2SW.d.ts.map → use-intersection-observer-DNPextJs.d.ts.map} +1 -1
  272. package/dist/{use-intersection-observer-CZfnep4z.js → use-intersection-observer-rlKEjyL1.js} +1 -1
  273. package/dist/{use-intersection-observer-CZfnep4z.js.map → use-intersection-observer-rlKEjyL1.js.map} +1 -1
  274. package/dist/{use-mobile-l5ebOdQl.js → use-mobile-DUqQzj2D.js} +1 -1
  275. package/dist/{use-mobile-l5ebOdQl.js.map → use-mobile-DUqQzj2D.js.map} +1 -1
  276. package/dist/{utils-mWJR2N24.js → utils-DUlptRpf.js} +1 -1
  277. package/dist/{utils-mWJR2N24.js.map → utils-DUlptRpf.js.map} +1 -1
  278. package/package.json +81 -1
  279. package/dist/components/checkbox.js.map +0 -1
  280. package/dist/components/collapsible.js.map +0 -1
  281. package/dist/components/empty.js.map +0 -1
  282. package/dist/components/scroll-area.js.map +0 -1
  283. package/dist/input-CoP6CeA5.d.ts.map +0 -1
  284. package/dist/label-Dw4Hcz5k.d.ts +0 -11
  285. package/dist/label-Dw4Hcz5k.d.ts.map +0 -1
  286. /package/dist/{direction-BKSh6e6q.js → direction-DFPbwDSF.js} +0 -0
@@ -0,0 +1,359 @@
1
+ "use client";
2
+
3
+ import { t as cn } from "../utils-DUlptRpf.js";
4
+ import { t as Button } from "../button-DnHwqwy0.js";
5
+ import { n as PopoverContent, o as PopoverTrigger, t as Popover } from "../popover-BGkU46G7.js";
6
+ import { t as Separator } from "../separator-D0bew2D_.js";
7
+ import { t as Input } from "../input-jIoNIdLQ.js";
8
+ import { t as Toggle } from "../toggle-BZXrLBLK.js";
9
+ import { BoldIcon, ItalicIcon, LinkIcon, ListIcon, ListOrderedIcon, UnlinkIcon } from "lucide-react";
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+ import * as React$1 from "react";
12
+ import { EditorContent, useEditor, useEditorState } from "@tiptap/react";
13
+ import StarterKit from "@tiptap/starter-kit";
14
+
15
+ //#region src/components/rich-text-editor.tsx
16
+ const SAFE_LINK_SCHEMES = [
17
+ "http",
18
+ "https",
19
+ "mailto",
20
+ "tel",
21
+ "ftp"
22
+ ];
23
+ function isSafeHref(url) {
24
+ const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(url)?.[1]?.toLowerCase();
25
+ return scheme === void 0 || SAFE_LINK_SCHEMES.includes(scheme);
26
+ }
27
+ function RichTextToolbar({ editor, disabled }) {
28
+ const state = useEditorState({
29
+ editor,
30
+ selector: ({ editor: e }) => ({
31
+ isBold: e.isActive("bold"),
32
+ isItalic: e.isActive("italic"),
33
+ isBulletList: e.isActive("bulletList"),
34
+ isOrderedList: e.isActive("orderedList"),
35
+ isLinkActive: e.isActive("link"),
36
+ canBold: e.can().chain().focus().toggleBold().run(),
37
+ canItalic: e.can().chain().focus().toggleItalic().run()
38
+ })
39
+ });
40
+ const [linkOpen, setLinkOpen] = React$1.useState(false);
41
+ const [linkUrl, setLinkUrl] = React$1.useState("");
42
+ const [linkError, setLinkError] = React$1.useState(false);
43
+ const linkErrorId = React$1.useId();
44
+ const openLinkForm = React$1.useCallback((open) => {
45
+ if (open) {
46
+ const previous = editor.getAttributes("link").href;
47
+ setLinkUrl(previous ?? "https://");
48
+ setLinkError(false);
49
+ }
50
+ setLinkOpen(open);
51
+ }, [editor]);
52
+ const applyLink = React$1.useCallback(() => {
53
+ const url = linkUrl.trim();
54
+ if (url === "") editor.chain().focus().extendMarkRange("link").unsetLink().run();
55
+ else {
56
+ if (!isSafeHref(url)) {
57
+ setLinkError(true);
58
+ return;
59
+ }
60
+ editor.chain().focus().extendMarkRange("link").setLink({ href: url }).run();
61
+ }
62
+ setLinkOpen(false);
63
+ }, [editor, linkUrl]);
64
+ return /* @__PURE__ */ jsxs("div", {
65
+ "data-slot": "rich-text-editor-toolbar",
66
+ role: "toolbar",
67
+ "aria-label": "Formatting",
68
+ "aria-orientation": "horizontal",
69
+ className: "flex flex-wrap items-center gap-1 border-b border-border bg-muted/30 p-1",
70
+ children: [
71
+ /* @__PURE__ */ jsx(Toggle, {
72
+ size: "sm",
73
+ "aria-label": "Bold",
74
+ title: "Bold",
75
+ pressed: state.isBold,
76
+ disabled: disabled || !state.canBold,
77
+ onPressedChange: () => editor.chain().focus().toggleBold().run(),
78
+ children: /* @__PURE__ */ jsx(BoldIcon, {})
79
+ }),
80
+ /* @__PURE__ */ jsx(Toggle, {
81
+ size: "sm",
82
+ "aria-label": "Italic",
83
+ title: "Italic",
84
+ pressed: state.isItalic,
85
+ disabled: disabled || !state.canItalic,
86
+ onPressedChange: () => editor.chain().focus().toggleItalic().run(),
87
+ children: /* @__PURE__ */ jsx(ItalicIcon, {})
88
+ }),
89
+ /* @__PURE__ */ jsx(Separator, {
90
+ orientation: "vertical",
91
+ className: "mx-0.5 h-5 self-center"
92
+ }),
93
+ /* @__PURE__ */ jsx(Toggle, {
94
+ size: "sm",
95
+ "aria-label": "Bullet list",
96
+ title: "Bullet list",
97
+ pressed: state.isBulletList,
98
+ disabled,
99
+ onPressedChange: () => editor.chain().focus().toggleBulletList().run(),
100
+ children: /* @__PURE__ */ jsx(ListIcon, {})
101
+ }),
102
+ /* @__PURE__ */ jsx(Toggle, {
103
+ size: "sm",
104
+ "aria-label": "Ordered list",
105
+ title: "Ordered list",
106
+ pressed: state.isOrderedList,
107
+ disabled,
108
+ onPressedChange: () => editor.chain().focus().toggleOrderedList().run(),
109
+ children: /* @__PURE__ */ jsx(ListOrderedIcon, {})
110
+ }),
111
+ /* @__PURE__ */ jsx(Separator, {
112
+ orientation: "vertical",
113
+ className: "mx-0.5 h-5 self-center"
114
+ }),
115
+ /* @__PURE__ */ jsxs(Popover, {
116
+ open: linkOpen,
117
+ onOpenChange: openLinkForm,
118
+ children: [/* @__PURE__ */ jsx(PopoverTrigger, { render: /* @__PURE__ */ jsx(Toggle, {
119
+ size: "sm",
120
+ "aria-label": "Link",
121
+ title: "Add or edit link",
122
+ pressed: state.isLinkActive,
123
+ disabled,
124
+ children: /* @__PURE__ */ jsx(LinkIcon, {})
125
+ }) }), /* @__PURE__ */ jsx(PopoverContent, {
126
+ align: "start",
127
+ className: "w-72 gap-3",
128
+ children: /* @__PURE__ */ jsxs("form", {
129
+ className: "flex flex-col gap-3",
130
+ onSubmit: (event) => {
131
+ event.preventDefault();
132
+ applyLink();
133
+ },
134
+ children: [
135
+ /* @__PURE__ */ jsx(Input, {
136
+ autoFocus: true,
137
+ type: "url",
138
+ "aria-label": "Link URL",
139
+ "aria-invalid": linkError || void 0,
140
+ "aria-describedby": linkError ? linkErrorId : void 0,
141
+ placeholder: "https://example.com",
142
+ value: linkUrl,
143
+ onChange: (event) => {
144
+ setLinkUrl(event.target.value);
145
+ if (linkError) setLinkError(false);
146
+ }
147
+ }),
148
+ linkError ? /* @__PURE__ */ jsx("p", {
149
+ id: linkErrorId,
150
+ role: "alert",
151
+ className: "text-xs text-destructive",
152
+ children: "Enter a valid URL (http, https, mailto, tel)."
153
+ }) : null,
154
+ /* @__PURE__ */ jsxs("div", {
155
+ className: "flex justify-end gap-2",
156
+ children: [/* @__PURE__ */ jsx(Button, {
157
+ type: "button",
158
+ variant: "outline",
159
+ size: "sm",
160
+ onClick: () => setLinkOpen(false),
161
+ children: "Cancel"
162
+ }), /* @__PURE__ */ jsx(Button, {
163
+ type: "submit",
164
+ size: "sm",
165
+ children: "Apply"
166
+ })]
167
+ })
168
+ ]
169
+ })
170
+ })]
171
+ }),
172
+ /* @__PURE__ */ jsx(Button, {
173
+ type: "button",
174
+ variant: "ghost",
175
+ size: "icon-sm",
176
+ "aria-label": "Remove link",
177
+ title: "Remove link",
178
+ disabled: disabled || !state.isLinkActive,
179
+ onClick: () => editor.chain().focus().extendMarkRange("link").unsetLink().run(),
180
+ children: /* @__PURE__ */ jsx(UnlinkIcon, {})
181
+ })
182
+ ]
183
+ });
184
+ }
185
+ /**
186
+ * A minimal WYSIWYG rich-text editor built on Tiptap (`@tiptap/react` +
187
+ * `@tiptap/starter-kit`). Supports bold, italic, bullet/ordered lists, and
188
+ * links via a compact toolbar.
189
+ *
190
+ * The stored format is **HTML**: pass HTML in via `value` (controlled) or
191
+ * `defaultValue` (uncontrolled), and read HTML out via `onValueChange`.
192
+ *
193
+ * Supported formatting is deliberately scoped to what the toolbar exposes:
194
+ * paragraphs, bold, italic, bullet/ordered lists, and links. StarterKit nodes
195
+ * with no toolbar control (headings, blockquote, strike, code/code blocks,
196
+ * horizontal rules) are disabled so the editor, toolbar, and `EditorOutput`
197
+ * stay in agreement. Opt back into any of them — or add your own (images,
198
+ * mentions, …) — via the `extensions` prop, and reach the underlying instance
199
+ * with `onCreate` to build a custom toolbar.
200
+ *
201
+ * Output handling:
202
+ * - Tiptap only round-trips the tags its configured extensions understand —
203
+ * **unsupported tags/attributes are dropped** on parse.
204
+ * - The emitted HTML is unsanitized. Render stored content through a
205
+ * sanitizing `EditorOutput` component (DOMPurify) rather than injecting it
206
+ * raw.
207
+ *
208
+ * Field integration: the editable surface is a `<div role="textbox">`, not a
209
+ * labelable form control, so associate labels/help text with `aria-labelledby`
210
+ * / `aria-describedby` (not `<FieldLabel htmlFor>`).
211
+ *
212
+ * SSR-safe: uses `immediatelyRender: false` so the first paint matches the
213
+ * server render and avoids hydration mismatches.
214
+ *
215
+ * @example
216
+ * ```tsx
217
+ * function JobDescription() {
218
+ * const [html, setHtml] = React.useState("<p>Initial <strong>copy</strong></p>");
219
+ * return (
220
+ * <RichTextEditor
221
+ * value={html}
222
+ * onValueChange={setHtml}
223
+ * placeholder="Describe the role…"
224
+ * aria-label="Job description"
225
+ * />
226
+ * );
227
+ * }
228
+ *
229
+ * // Render the stored HTML elsewhere (sanitized):
230
+ * // <EditorOutput html={html} />
231
+ * ```
232
+ */
233
+ function RichTextEditor({ value, defaultValue = "", onValueChange, placeholder = "Write something…", disabled = false, editable = true, className, contentClassName, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, "aria-describedby": ariaDescribedby, "aria-required": ariaRequired, id, name, "aria-invalid": ariaInvalid, extensions: extraExtensions, onCreate }) {
234
+ const isControlled = value !== void 0;
235
+ const isEditable = editable && !disabled;
236
+ const isInvalid = ariaInvalid === true || ariaInvalid === "true" ? true : ariaInvalid === false || ariaInvalid === "false" || ariaInvalid == null ? void 0 : ariaInvalid;
237
+ const isRequired = ariaRequired === true || ariaRequired === "true";
238
+ const editor = useEditor({
239
+ immediatelyRender: false,
240
+ editable: isEditable,
241
+ extensions: [StarterKit.configure({
242
+ heading: false,
243
+ blockquote: false,
244
+ strike: false,
245
+ code: false,
246
+ codeBlock: false,
247
+ horizontalRule: false,
248
+ link: {
249
+ openOnClick: false,
250
+ autolink: true,
251
+ HTMLAttributes: {
252
+ rel: "noopener noreferrer nofollow",
253
+ target: "_blank"
254
+ }
255
+ }
256
+ }), ...extraExtensions ?? []],
257
+ content: isControlled ? value : defaultValue,
258
+ editorProps: { attributes: {
259
+ class: cn("min-h-32 w-full px-3 py-2 text-sm text-foreground outline-none", "[&_a]:text-primary [&_a]:underline [&_a]:underline-offset-4", "[&_ul]:my-2 [&_ul]:list-disc [&_ul]:ps-5", "[&_ol]:my-2 [&_ol]:list-decimal [&_ol]:ps-5", "[&_li]:my-0.5", "[&_p]:my-1.5 [&_p:first-child]:mt-0 [&_p:last-child]:mb-0", contentClassName),
260
+ role: "textbox",
261
+ "aria-multiline": "true",
262
+ ...ariaLabel ? { "aria-label": ariaLabel } : {},
263
+ ...ariaLabelledby ? { "aria-labelledby": ariaLabelledby } : {},
264
+ ...ariaDescribedby ? { "aria-describedby": ariaDescribedby } : {},
265
+ ...isRequired ? { "aria-required": "true" } : {},
266
+ ...id ? { id } : {},
267
+ ...isInvalid ? { "aria-invalid": String(isInvalid) } : {}
268
+ } },
269
+ onCreate: ({ editor: instance }) => {
270
+ onCreate?.(instance);
271
+ },
272
+ onUpdate: ({ editor: instance }) => {
273
+ const html = instance.getHTML();
274
+ setSerializedHtml(html);
275
+ onValueChange?.(html);
276
+ }
277
+ });
278
+ const [serializedHtml, setSerializedHtml] = React$1.useState(() => isControlled ? value ?? "" : defaultValue);
279
+ React$1.useEffect(() => {
280
+ if (!editor || !isControlled) return;
281
+ if (value !== editor.getHTML()) {
282
+ editor.commands.setContent(value ?? "", { emitUpdate: false });
283
+ setSerializedHtml(value ?? "");
284
+ }
285
+ }, [
286
+ editor,
287
+ isControlled,
288
+ value
289
+ ]);
290
+ React$1.useEffect(() => {
291
+ editor?.setEditable(isEditable);
292
+ }, [editor, isEditable]);
293
+ React$1.useEffect(() => {
294
+ const dom = editor?.view.dom;
295
+ if (!dom) return;
296
+ const reflect = (name$1, value$1) => {
297
+ if (value$1 == null || value$1 === "") dom.removeAttribute(name$1);
298
+ else dom.setAttribute(name$1, value$1);
299
+ };
300
+ reflect("id", id);
301
+ reflect("aria-label", ariaLabel);
302
+ reflect("aria-labelledby", ariaLabelledby);
303
+ reflect("aria-describedby", ariaDescribedby);
304
+ reflect("aria-required", isRequired ? "true" : void 0);
305
+ reflect("aria-invalid", isInvalid ? String(isInvalid) : void 0);
306
+ }, [
307
+ editor,
308
+ id,
309
+ ariaLabel,
310
+ ariaLabelledby,
311
+ ariaDescribedby,
312
+ isRequired,
313
+ isInvalid
314
+ ]);
315
+ const [isEmpty, setIsEmpty] = React$1.useState(true);
316
+ React$1.useEffect(() => {
317
+ if (!editor) return;
318
+ const update = () => setIsEmpty(editor.isEmpty);
319
+ update();
320
+ editor.on("update", update);
321
+ editor.on("create", update);
322
+ return () => {
323
+ editor.off("update", update);
324
+ editor.off("create", update);
325
+ };
326
+ }, [editor]);
327
+ const showPlaceholder = Boolean(placeholder) && isEmpty && isEditable;
328
+ return /* @__PURE__ */ jsxs("div", {
329
+ "data-slot": "rich-text-editor",
330
+ "data-disabled": disabled || void 0,
331
+ "data-invalid": isInvalid || void 0,
332
+ "aria-disabled": disabled || void 0,
333
+ className: cn("flex w-full flex-col overflow-hidden rounded-md border border-input bg-background shadow-xs", "focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/50", "data-[invalid=true]:border-destructive data-[invalid=true]:ring-3 data-[invalid=true]:ring-destructive/20", disabled && "pointer-events-none opacity-50", className),
334
+ children: [
335
+ editor && isEditable ? /* @__PURE__ */ jsx(RichTextToolbar, {
336
+ editor,
337
+ disabled
338
+ }) : null,
339
+ /* @__PURE__ */ jsxs("div", {
340
+ className: "relative",
341
+ children: [showPlaceholder ? /* @__PURE__ */ jsx("span", {
342
+ "aria-hidden": "true",
343
+ className: "pointer-events-none absolute top-2 left-3 text-sm text-muted-foreground select-none",
344
+ children: placeholder
345
+ }) : null, /* @__PURE__ */ jsx(EditorContent, { editor })]
346
+ }),
347
+ name ? /* @__PURE__ */ jsx("input", {
348
+ type: "hidden",
349
+ name,
350
+ value: serializedHtml,
351
+ disabled
352
+ }) : null
353
+ ]
354
+ });
355
+ }
356
+
357
+ //#endregion
358
+ export { RichTextEditor };
359
+ //# sourceMappingURL=rich-text-editor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rich-text-editor.js","names":["React","value","name"],"sources":["../../src/components/rich-text-editor.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport {\n EditorContent,\n useEditor,\n useEditorState,\n type Editor,\n type Extensions,\n} from \"@tiptap/react\";\nimport StarterKit from \"@tiptap/starter-kit\";\nimport {\n BoldIcon,\n ItalicIcon,\n LinkIcon,\n ListIcon,\n ListOrderedIcon,\n UnlinkIcon,\n} from \"lucide-react\";\n\nimport { cn } from \"@px-ui/ui/lib/utils\";\nimport { Button } from \"@px-ui/ui/components/button\";\nimport { Input } from \"@px-ui/ui/components/input\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@px-ui/ui/components/popover\";\nimport { Separator } from \"@px-ui/ui/components/separator\";\nimport { Toggle } from \"@px-ui/ui/components/toggle\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface RichTextEditorProps {\n /**\n * The current HTML value. Provide this together with `onValueChange` for a\n * controlled editor. The string is parsed by Tiptap on mount and on every\n * external change, so it must be valid HTML.\n *\n * Note: Tiptap only understands the tags produced by the configured\n * extensions (`<p>`, `<strong>`, `<em>`, `<ul>`/`<ol>`/`<li>`, `<a>`,\n * line breaks). **Any unsupported tag or attribute is silently dropped**\n * when the HTML is parsed back into the document. Round-tripping arbitrary\n * HTML is therefore lossy by design.\n *\n * @default \"\"\n */\n value?: string;\n\n /**\n * Initial HTML for an uncontrolled editor. Ignored when `value` is provided.\n * Use this when you only need the final value (e.g. read it on submit) and\n * do not want to re-sync on every keystroke.\n *\n * @default \"\"\n */\n defaultValue?: string;\n\n /**\n * Called on every document change with the serialized HTML string. This is\n * the canonical stored format for the editor.\n *\n * The emitted HTML is **not** sanitized for rendering. When you later render\n * stored content as HTML, pass it through your sanitizing `EditorOutput`\n * component (or an equivalent DOMPurify pass) before injecting it into the\n * DOM — never `dangerouslySetInnerHTML` raw editor output.\n */\n onValueChange?: (html: string) => void;\n\n /**\n * Placeholder shown while the document is empty.\n * @default \"Write something…\"\n */\n placeholder?: string;\n\n /**\n * Disables the editor and toolbar entirely. Visually dimmed and\n * non-interactive. Alias-friendly with `editable`; `disabled` wins when both\n * are set.\n * @default false\n */\n disabled?: boolean;\n\n /**\n * Whether the content is editable. Set to `false` to render the content as a\n * read-only rich-text view (toolbar hidden) while keeping the styled output.\n * @default true\n */\n editable?: boolean;\n\n /**\n * Additional className applied to the editor wrapper (the bordered shell that\n * contains the toolbar and the content area).\n */\n className?: string;\n\n /**\n * Additional className applied to the contenteditable content area.\n */\n contentClassName?: string;\n\n /** Accessible label for the editor region. */\n \"aria-label\"?: string;\n\n /**\n * Id(s) of the element(s) that label the editor. **Prefer this over\n * `htmlFor` for `Field` integration:** the editable surface is a\n * `<div role=\"textbox\">`, which is *not* a labelable element, so a native\n * `<FieldLabel htmlFor={id}>` does **not** associate (clicking it won't focus\n * the editor, and its text is not exposed as the accessible name). Instead\n * give the label an `id` and pass it here:\n *\n * ```tsx\n * <Field>\n * <FieldLabel id=\"bio-label\">Bio</FieldLabel>\n * <RichTextEditor aria-labelledby=\"bio-label\" aria-describedby=\"bio-help\" />\n * <FieldDescription id=\"bio-help\">Markdown shortcuts supported.</FieldDescription>\n * </Field>\n * ```\n */\n \"aria-labelledby\"?: string;\n\n /**\n * Id(s) of the element(s) that describe the editor (e.g. a `FieldDescription`\n * or `FieldError`). Forwarded onto the editable surface so validation and\n * help text are announced, mirroring `Input`/`Textarea`.\n */\n \"aria-describedby\"?: string;\n\n /**\n * Marks the control as required. Forwarded as `aria-required` on the editable\n * surface (the contenteditable region cannot use the native `required`\n * attribute).\n */\n \"aria-required\"?: boolean | \"true\" | \"false\";\n\n /**\n * Id for the editable region. Useful as a target for `aria-labelledby`/\n * `aria-describedby` references or for testing. Note: pairing it with a\n * native `<FieldLabel htmlFor>` will **not** associate the label, because the\n * editable surface is a `<div role=\"textbox\">` rather than a form control —\n * use `aria-labelledby` instead (see above).\n */\n id?: string;\n\n /**\n * Name for the form field. Because the contenteditable surface is not a\n * form-associated element, the editor renders a hidden `<input>` carrying\n * this `name` and the current editor HTML, so the value serializes in native\n * forms / `FormData` like `Input`/`Textarea`.\n */\n name?: string;\n\n /**\n * Marks the control invalid. Forwarded as `aria-invalid` on the editable\n * surface (and `data-invalid` on the wrapper) so `Field` validation styling\n * applies, mirroring `Input`/`Textarea`.\n */\n \"aria-invalid\"?: boolean | \"true\" | \"false\" | \"grammar\" | \"spelling\";\n\n /**\n * Additional Tiptap extensions appended to the built-in set (configured\n * `StarterKit` + link). Use this to opt back into formatting the default\n * toolbar omits (e.g. `Heading`, `Image`, a mention plugin). Applied on mount\n * only — changing it later does not reconfigure the live editor.\n *\n * Note: re-enabling a node here means the toolbar won't expose a control for\n * it and the built-in content styles won't cover it; pair it with\n * `contentClassName` styling and your own toolbar (via `onCreate`) as needed.\n */\n extensions?: Extensions;\n\n /**\n * Called once with the Tiptap {@link Editor} instance after it is created\n * (client-side, since `immediatelyRender` is `false`). Use this to drive the\n * editor imperatively or to build a custom toolbar alongside the default one.\n */\n onCreate?: (editor: Editor) => void;\n}\n\n// ============================================================================\n// Toolbar\n// ============================================================================\n\ninterface RichTextToolbarProps {\n editor: Editor;\n disabled: boolean;\n}\n\n// Reject dangerous URL schemes (javascript:, data:, vbscript:, …) at input\n// time so they can't be stored on the link mark. Scheme-less values (relative\n// paths, anchors) and the safe schemes below are allowed.\nconst SAFE_LINK_SCHEMES = [\"http\", \"https\", \"mailto\", \"tel\", \"ftp\"];\nfunction isSafeHref(url: string): boolean {\n const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(url)?.[1]?.toLowerCase();\n // No explicit scheme → relative/anchor, treated as safe.\n return scheme === undefined || SAFE_LINK_SCHEMES.includes(scheme);\n}\n\nfunction RichTextToolbar({ editor, disabled }: RichTextToolbarProps) {\n // Subscribe only to the slice of editor state the toolbar renders from.\n // useEditorState re-renders this component when (and only when) any of these\n // selected values change — replacing the manual transaction/selectionUpdate\n // forceUpdate plumbing.\n const state = useEditorState({\n editor,\n selector: ({ editor: e }) => ({\n isBold: e.isActive(\"bold\"),\n isItalic: e.isActive(\"italic\"),\n isBulletList: e.isActive(\"bulletList\"),\n isOrderedList: e.isActive(\"orderedList\"),\n isLinkActive: e.isActive(\"link\"),\n canBold: e.can().chain().focus().toggleBold().run(),\n canItalic: e.can().chain().focus().toggleItalic().run(),\n }),\n });\n\n const [linkOpen, setLinkOpen] = React.useState(false);\n const [linkUrl, setLinkUrl] = React.useState(\"\");\n const [linkError, setLinkError] = React.useState(false);\n // Unique per toolbar instance so multiple editors on one page don't collide.\n const linkErrorId = React.useId();\n\n // Seed the input with the existing href whenever the popover opens.\n const openLinkForm = React.useCallback(\n (open: boolean) => {\n if (open) {\n const previous = editor.getAttributes(\"link\").href as\n | string\n | undefined;\n setLinkUrl(previous ?? \"https://\");\n setLinkError(false);\n }\n setLinkOpen(open);\n },\n [editor]\n );\n\n const applyLink = React.useCallback(() => {\n const url = linkUrl.trim();\n // Empty string clears the link.\n if (url === \"\") {\n editor.chain().focus().extendMarkRange(\"link\").unsetLink().run();\n } else {\n // Block unsafe schemes (e.g. javascript:) before they reach the document.\n if (!isSafeHref(url)) {\n setLinkError(true);\n return;\n }\n editor.chain().focus().extendMarkRange(\"link\").setLink({ href: url }).run();\n }\n setLinkOpen(false);\n }, [editor, linkUrl]);\n\n return (\n <div\n data-slot=\"rich-text-editor-toolbar\"\n role=\"toolbar\"\n aria-label=\"Formatting\"\n aria-orientation=\"horizontal\"\n className=\"flex flex-wrap items-center gap-1 border-b border-border bg-muted/30 p-1\"\n >\n <Toggle\n size=\"sm\"\n aria-label=\"Bold\"\n title=\"Bold\"\n pressed={state.isBold}\n disabled={disabled || !state.canBold}\n onPressedChange={() => editor.chain().focus().toggleBold().run()}\n >\n <BoldIcon />\n </Toggle>\n\n <Toggle\n size=\"sm\"\n aria-label=\"Italic\"\n title=\"Italic\"\n pressed={state.isItalic}\n disabled={disabled || !state.canItalic}\n onPressedChange={() => editor.chain().focus().toggleItalic().run()}\n >\n <ItalicIcon />\n </Toggle>\n\n <Separator\n orientation=\"vertical\"\n className=\"mx-0.5 h-5 self-center\"\n />\n\n <Toggle\n size=\"sm\"\n aria-label=\"Bullet list\"\n title=\"Bullet list\"\n pressed={state.isBulletList}\n disabled={disabled}\n onPressedChange={() => editor.chain().focus().toggleBulletList().run()}\n >\n <ListIcon />\n </Toggle>\n\n <Toggle\n size=\"sm\"\n aria-label=\"Ordered list\"\n title=\"Ordered list\"\n pressed={state.isOrderedList}\n disabled={disabled}\n onPressedChange={() => editor.chain().focus().toggleOrderedList().run()}\n >\n <ListOrderedIcon />\n </Toggle>\n\n <Separator\n orientation=\"vertical\"\n className=\"mx-0.5 h-5 self-center\"\n />\n\n <Popover open={linkOpen} onOpenChange={openLinkForm}>\n <PopoverTrigger\n render={\n <Toggle\n size=\"sm\"\n aria-label=\"Link\"\n title=\"Add or edit link\"\n pressed={state.isLinkActive}\n disabled={disabled}\n >\n <LinkIcon />\n </Toggle>\n }\n />\n <PopoverContent align=\"start\" className=\"w-72 gap-3\">\n <form\n className=\"flex flex-col gap-3\"\n onSubmit={(event) => {\n event.preventDefault();\n applyLink();\n }}\n >\n <Input\n autoFocus\n type=\"url\"\n aria-label=\"Link URL\"\n aria-invalid={linkError || undefined}\n aria-describedby={linkError ? linkErrorId : undefined}\n placeholder=\"https://example.com\"\n value={linkUrl}\n onChange={(event) => {\n setLinkUrl(event.target.value);\n if (linkError) setLinkError(false);\n }}\n />\n {linkError ? (\n <p\n id={linkErrorId}\n role=\"alert\"\n className=\"text-xs text-destructive\"\n >\n Enter a valid URL (http, https, mailto, tel).\n </p>\n ) : null}\n <div className=\"flex justify-end gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setLinkOpen(false)}\n >\n Cancel\n </Button>\n <Button type=\"submit\" size=\"sm\">\n Apply\n </Button>\n </div>\n </form>\n </PopoverContent>\n </Popover>\n\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label=\"Remove link\"\n title=\"Remove link\"\n disabled={disabled || !state.isLinkActive}\n onClick={() =>\n editor.chain().focus().extendMarkRange(\"link\").unsetLink().run()\n }\n >\n <UnlinkIcon />\n </Button>\n </div>\n );\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\n/**\n * A minimal WYSIWYG rich-text editor built on Tiptap (`@tiptap/react` +\n * `@tiptap/starter-kit`). Supports bold, italic, bullet/ordered lists, and\n * links via a compact toolbar.\n *\n * The stored format is **HTML**: pass HTML in via `value` (controlled) or\n * `defaultValue` (uncontrolled), and read HTML out via `onValueChange`.\n *\n * Supported formatting is deliberately scoped to what the toolbar exposes:\n * paragraphs, bold, italic, bullet/ordered lists, and links. StarterKit nodes\n * with no toolbar control (headings, blockquote, strike, code/code blocks,\n * horizontal rules) are disabled so the editor, toolbar, and `EditorOutput`\n * stay in agreement. Opt back into any of them — or add your own (images,\n * mentions, …) — via the `extensions` prop, and reach the underlying instance\n * with `onCreate` to build a custom toolbar.\n *\n * Output handling:\n * - Tiptap only round-trips the tags its configured extensions understand —\n * **unsupported tags/attributes are dropped** on parse.\n * - The emitted HTML is unsanitized. Render stored content through a\n * sanitizing `EditorOutput` component (DOMPurify) rather than injecting it\n * raw.\n *\n * Field integration: the editable surface is a `<div role=\"textbox\">`, not a\n * labelable form control, so associate labels/help text with `aria-labelledby`\n * / `aria-describedby` (not `<FieldLabel htmlFor>`).\n *\n * SSR-safe: uses `immediatelyRender: false` so the first paint matches the\n * server render and avoids hydration mismatches.\n *\n * @example\n * ```tsx\n * function JobDescription() {\n * const [html, setHtml] = React.useState(\"<p>Initial <strong>copy</strong></p>\");\n * return (\n * <RichTextEditor\n * value={html}\n * onValueChange={setHtml}\n * placeholder=\"Describe the role…\"\n * aria-label=\"Job description\"\n * />\n * );\n * }\n *\n * // Render the stored HTML elsewhere (sanitized):\n * // <EditorOutput html={html} />\n * ```\n */\nexport function RichTextEditor({\n value,\n defaultValue = \"\",\n onValueChange,\n placeholder = \"Write something…\",\n disabled = false,\n editable = true,\n className,\n contentClassName,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledby,\n \"aria-describedby\": ariaDescribedby,\n \"aria-required\": ariaRequired,\n id,\n name,\n \"aria-invalid\": ariaInvalid,\n extensions: extraExtensions,\n onCreate,\n}: RichTextEditorProps) {\n const isControlled = value !== undefined;\n const isEditable = editable && !disabled;\n const isInvalid =\n ariaInvalid === true || ariaInvalid === \"true\"\n ? true\n : ariaInvalid === false || ariaInvalid === \"false\" || ariaInvalid == null\n ? undefined\n : ariaInvalid;\n const isRequired = ariaRequired === true || ariaRequired === \"true\";\n\n const editor = useEditor({\n // SSR-safe: defer the first render to the client so the server-rendered\n // markup and the hydrated DOM agree.\n immediatelyRender: false,\n editable: isEditable,\n extensions: [\n StarterKit.configure({\n // Keep the enabled node/mark set in lock-step with the toolbar and the\n // editor's content styles below. StarterKit enables these by default\n // (incl. their markdown input rules and paste handling), but the\n // minimal toolbar exposes no control for them and the content area\n // doesn't style them — so disable them to avoid users creating content\n // they can't toggle and that renders differently here than in\n // `EditorOutput`. Opt back in via the `extensions` prop when needed.\n heading: false,\n blockquote: false,\n strike: false,\n code: false,\n codeBlock: false,\n horizontalRule: false,\n link: {\n openOnClick: false,\n autolink: true,\n HTMLAttributes: {\n rel: \"noopener noreferrer nofollow\",\n target: \"_blank\",\n },\n },\n }),\n ...(extraExtensions ?? []),\n ],\n content: isControlled ? value : defaultValue,\n editorProps: {\n attributes: {\n // px-ui styling for the contenteditable surface. Design tokens only.\n class: cn(\n \"min-h-32 w-full px-3 py-2 text-sm text-foreground outline-none\",\n \"[&_a]:text-primary [&_a]:underline [&_a]:underline-offset-4\",\n \"[&_ul]:my-2 [&_ul]:list-disc [&_ul]:ps-5\",\n \"[&_ol]:my-2 [&_ol]:list-decimal [&_ol]:ps-5\",\n \"[&_li]:my-0.5\",\n \"[&_p]:my-1.5 [&_p:first-child]:mt-0 [&_p:last-child]:mb-0\",\n contentClassName\n ),\n role: \"textbox\",\n \"aria-multiline\": \"true\",\n ...(ariaLabel ? { \"aria-label\": ariaLabel } : {}),\n ...(ariaLabelledby ? { \"aria-labelledby\": ariaLabelledby } : {}),\n ...(ariaDescribedby ? { \"aria-describedby\": ariaDescribedby } : {}),\n ...(isRequired ? { \"aria-required\": \"true\" } : {}),\n ...(id ? { id } : {}),\n ...(isInvalid ? { \"aria-invalid\": String(isInvalid) } : {}),\n },\n },\n onCreate: ({ editor: instance }) => {\n onCreate?.(instance);\n },\n onUpdate: ({ editor: instance }) => {\n const html = instance.getHTML();\n setSerializedHtml(html);\n onValueChange?.(html);\n },\n });\n\n // Mirror of the editor's HTML, kept in sync so the hidden form input below\n // serializes the live value. The contenteditable surface is not\n // form-associated, so a real <input> is what actually participates in native\n // form submission / FormData.\n const [serializedHtml, setSerializedHtml] = React.useState(\n () => (isControlled ? (value ?? \"\") : defaultValue)\n );\n\n // Keep a controlled editor in sync when `value` changes from the outside,\n // without clobbering the user's cursor while they type.\n React.useEffect(() => {\n if (!editor || !isControlled) return;\n const current = editor.getHTML();\n if (value !== current) {\n editor.commands.setContent(value ?? \"\", { emitUpdate: false });\n // setContent with emitUpdate:false skips onUpdate, so mirror the new\n // value onto the hidden input explicitly.\n setSerializedHtml(value ?? \"\");\n }\n }, [editor, isControlled, value]);\n\n // Reflect disabled/editable changes onto the live instance.\n React.useEffect(() => {\n editor?.setEditable(isEditable);\n }, [editor, isEditable]);\n\n // Keep the editable surface's identity/ARIA attributes in sync. The values\n // passed to `useEditor` only apply on mount, so reflect later changes\n // (label, description, required, invalid toggling) directly onto the DOM\n // node.\n React.useEffect(() => {\n const dom = editor?.view.dom as HTMLElement | undefined;\n if (!dom) return;\n const reflect = (name: string, value: string | undefined) => {\n if (value == null || value === \"\") dom.removeAttribute(name);\n else dom.setAttribute(name, value);\n };\n reflect(\"id\", id);\n reflect(\"aria-label\", ariaLabel);\n reflect(\"aria-labelledby\", ariaLabelledby);\n reflect(\"aria-describedby\", ariaDescribedby);\n reflect(\"aria-required\", isRequired ? \"true\" : undefined);\n reflect(\"aria-invalid\", isInvalid ? String(isInvalid) : undefined);\n }, [\n editor,\n id,\n ariaLabel,\n ariaLabelledby,\n ariaDescribedby,\n isRequired,\n isInvalid,\n ]);\n\n // Track empty state so the placeholder overlay can show/hide without\n // depending on the (uninstalled) Tiptap Placeholder extension.\n const [isEmpty, setIsEmpty] = React.useState(true);\n React.useEffect(() => {\n if (!editor) return;\n const update = () => setIsEmpty(editor.isEmpty);\n update();\n editor.on(\"update\", update);\n editor.on(\"create\", update);\n return () => {\n editor.off(\"update\", update);\n editor.off(\"create\", update);\n };\n }, [editor]);\n\n const showPlaceholder = Boolean(placeholder) && isEmpty && isEditable;\n\n return (\n <div\n data-slot=\"rich-text-editor\"\n data-disabled={disabled || undefined}\n data-invalid={isInvalid || undefined}\n aria-disabled={disabled || undefined}\n className={cn(\n \"flex w-full flex-col overflow-hidden rounded-md border border-input bg-background shadow-xs\",\n \"focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/50\",\n \"data-[invalid=true]:border-destructive data-[invalid=true]:ring-3 data-[invalid=true]:ring-destructive/20\",\n disabled && \"pointer-events-none opacity-50\",\n className\n )}\n >\n {editor && isEditable ? (\n <RichTextToolbar editor={editor} disabled={disabled} />\n ) : null}\n <div className=\"relative\">\n {showPlaceholder ? (\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute top-2 left-3 text-sm text-muted-foreground select-none\"\n >\n {placeholder}\n </span>\n ) : null}\n <EditorContent editor={editor} />\n </div>\n {/* Form-association: the contenteditable surface is not a form control,\n so mirror the editor's HTML onto a real hidden input that serializes\n in native forms / FormData under the provided `name`. */}\n {name ? (\n <input\n type=\"hidden\"\n name={name}\n value={serializedHtml}\n disabled={disabled}\n />\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,17 +1,27 @@
1
- import * as react_jsx_runtime181 from "react/jsx-runtime";
1
+ import * as react_jsx_runtime333 from "react/jsx-runtime";
2
2
  import { ScrollArea as ScrollArea$1 } from "@base-ui/react/scroll-area";
3
3
 
4
4
  //#region src/components/scroll-area.d.ts
5
5
  declare function ScrollArea({
6
6
  className,
7
7
  children,
8
+ viewportProps,
8
9
  ...props
9
- }: ScrollArea$1.Root.Props): react_jsx_runtime181.JSX.Element;
10
+ }: ScrollArea$1.Root.Props & {
11
+ /**
12
+ * Props forwarded to the scroll viewport (the element that actually
13
+ * scrolls). Use this to size the viewport — e.g.
14
+ * `viewportProps={{ style: { maxHeight: "16rem" } }}` — since a `max-height`
15
+ * belongs on the viewport, not the root: the viewport carries `overflow`,
16
+ * and a `height: 100%` viewport cannot resolve against an auto-height root.
17
+ */
18
+ viewportProps?: ScrollArea$1.Viewport.Props;
19
+ }): react_jsx_runtime333.JSX.Element;
10
20
  declare function ScrollBar({
11
21
  className,
12
22
  orientation,
13
23
  ...props
14
- }: ScrollArea$1.Scrollbar.Props): react_jsx_runtime181.JSX.Element;
24
+ }: ScrollArea$1.Scrollbar.Props): react_jsx_runtime333.JSX.Element;
15
25
  //#endregion
16
26
  export { ScrollArea, ScrollBar };
17
27
  //# sourceMappingURL=scroll-area.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scroll-area.d.ts","names":[],"sources":["../../src/components/scroll-area.tsx"],"sourcesContent":[],"mappings":";;;;iBAKS,UAAA;;;;GAIN,YAAA,CAAoB,IAAA,CAAK,QAAK,oBAAA,CAAA,GAAA,CAAA;iBAmBxB,SAAA;;;;GAIN,YAAA,CAAoB,SAAA,CAAU,QAAK,oBAAA,CAAA,GAAA,CAAA"}
1
+ {"version":3,"file":"scroll-area.d.ts","names":[],"sources":["../../src/components/scroll-area.tsx"],"sourcesContent":[],"mappings":";;;;iBAKS,UAAA;;;;;GAKN,YAAA,CAAoB,IAAA,CAAK;;;AATkD;;;;;EAiB5D,aAAoB,CAAA,EAApB,YAAA,CAAoB,QAAA,CAAS,KAAA;CAC9C,CAAA,EAAA,oBAAA,CAAA,GAAA,CAAA,OAAA;iBAuBQ,SAAA,CAvBR;EAAA,SAAA;EAAA,WAAA;EAAA,GAAA;AAAA,CAAA,EA2BE,YAAA,CAAoB,SAAA,CAAU,KA3BhC,CAAA,EA2BqC,oBAAA,CAAA,GAAA,CAAA,OA3BrC"}
@@ -1,39 +1,4 @@
1
- import { t as cn } from "../utils-mWJR2N24.js";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import "react";
4
- import { ScrollArea as ScrollArea$1 } from "@base-ui/react/scroll-area";
1
+ import "../utils-DUlptRpf.js";
2
+ import { n as ScrollBar, t as ScrollArea } from "../scroll-area-mNVMQ0Of.js";
5
3
 
6
- //#region src/components/scroll-area.tsx
7
- function ScrollArea({ className, children, ...props }) {
8
- return /* @__PURE__ */ jsxs(ScrollArea$1.Root, {
9
- "data-slot": "scroll-area",
10
- className: cn("relative", className),
11
- ...props,
12
- children: [
13
- /* @__PURE__ */ jsx(ScrollArea$1.Viewport, {
14
- "data-slot": "scroll-area-viewport",
15
- className: "size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1",
16
- children
17
- }),
18
- /* @__PURE__ */ jsx(ScrollBar, {}),
19
- /* @__PURE__ */ jsx(ScrollArea$1.Corner, {})
20
- ]
21
- });
22
- }
23
- function ScrollBar({ className, orientation = "vertical", ...props }) {
24
- return /* @__PURE__ */ jsx(ScrollArea$1.Scrollbar, {
25
- "data-slot": "scroll-area-scrollbar",
26
- "data-orientation": orientation,
27
- orientation,
28
- className: cn("flex touch-none p-px transition-colors select-none data-horizontal:h-2.5 data-horizontal:flex-col data-horizontal:border-t data-horizontal:border-t-transparent data-vertical:h-full data-vertical:w-2.5 data-vertical:border-s data-vertical:border-s-transparent", className),
29
- ...props,
30
- children: /* @__PURE__ */ jsx(ScrollArea$1.Thumb, {
31
- "data-slot": "scroll-area-thumb",
32
- className: "relative flex-1 rounded-full bg-border"
33
- })
34
- });
35
- }
36
-
37
- //#endregion
38
- export { ScrollArea, ScrollBar };
39
- //# sourceMappingURL=scroll-area.js.map
4
+ export { ScrollArea, ScrollBar };
@@ -1,4 +1,4 @@
1
- import * as react_jsx_runtime202 from "react/jsx-runtime";
1
+ import * as react_jsx_runtime299 from "react/jsx-runtime";
2
2
  import * as React$1 from "react";
3
3
  import { Select as Select$1 } from "@base-ui/react/select";
4
4
 
@@ -7,11 +7,11 @@ declare const Select: typeof Select$1.Root;
7
7
  declare function SelectGroup({
8
8
  className,
9
9
  ...props
10
- }: Select$1.Group.Props): react_jsx_runtime202.JSX.Element;
10
+ }: Select$1.Group.Props): react_jsx_runtime299.JSX.Element;
11
11
  declare function SelectValue({
12
12
  className,
13
13
  ...props
14
- }: Select$1.Value.Props): react_jsx_runtime202.JSX.Element;
14
+ }: Select$1.Value.Props): react_jsx_runtime299.JSX.Element;
15
15
  declare function SelectTrigger({
16
16
  className,
17
17
  size,
@@ -19,7 +19,7 @@ declare function SelectTrigger({
19
19
  ...props
20
20
  }: Select$1.Trigger.Props & {
21
21
  size?: "sm" | "default";
22
- }): react_jsx_runtime202.JSX.Element;
22
+ }): react_jsx_runtime299.JSX.Element;
23
23
  declare function SelectContent({
24
24
  className,
25
25
  children,
@@ -29,28 +29,28 @@ declare function SelectContent({
29
29
  alignOffset,
30
30
  alignItemWithTrigger,
31
31
  ...props
32
- }: Select$1.Popup.Props & Pick<Select$1.Positioner.Props, "align" | "alignOffset" | "side" | "sideOffset" | "alignItemWithTrigger">): react_jsx_runtime202.JSX.Element;
32
+ }: Select$1.Popup.Props & Pick<Select$1.Positioner.Props, "align" | "alignOffset" | "side" | "sideOffset" | "alignItemWithTrigger">): react_jsx_runtime299.JSX.Element;
33
33
  declare function SelectLabel({
34
34
  className,
35
35
  ...props
36
- }: Select$1.GroupLabel.Props): react_jsx_runtime202.JSX.Element;
36
+ }: Select$1.GroupLabel.Props): react_jsx_runtime299.JSX.Element;
37
37
  declare function SelectItem({
38
38
  className,
39
39
  children,
40
40
  ...props
41
- }: Select$1.Item.Props): react_jsx_runtime202.JSX.Element;
41
+ }: Select$1.Item.Props): react_jsx_runtime299.JSX.Element;
42
42
  declare function SelectSeparator({
43
43
  className,
44
44
  ...props
45
- }: Select$1.Separator.Props): react_jsx_runtime202.JSX.Element;
45
+ }: Select$1.Separator.Props): react_jsx_runtime299.JSX.Element;
46
46
  declare function SelectScrollUpButton({
47
47
  className,
48
48
  ...props
49
- }: React$1.ComponentProps<typeof Select$1.ScrollUpArrow>): react_jsx_runtime202.JSX.Element;
49
+ }: React$1.ComponentProps<typeof Select$1.ScrollUpArrow>): react_jsx_runtime299.JSX.Element;
50
50
  declare function SelectScrollDownButton({
51
51
  className,
52
52
  ...props
53
- }: React$1.ComponentProps<typeof Select$1.ScrollDownArrow>): react_jsx_runtime202.JSX.Element;
53
+ }: React$1.ComponentProps<typeof Select$1.ScrollDownArrow>): react_jsx_runtime299.JSX.Element;
54
54
  //#endregion
55
55
  export { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue };
56
56
  //# sourceMappingURL=select.d.ts.map
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { t as cn } from "../utils-mWJR2N24.js";
3
+ import { t as cn } from "../utils-DUlptRpf.js";
4
4
  import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
6
  import "react";
@@ -1,2 +1,2 @@
1
- import { t as Separator } from "../separator-D0hWdzUT.js";
1
+ import { t as Separator } from "../separator-Df76guaT.js";
2
2
  export { Separator };
@@ -1,4 +1,4 @@
1
- import "../utils-mWJR2N24.js";
2
- import { t as Separator } from "../separator-BS3ilczC.js";
1
+ import "../utils-DUlptRpf.js";
2
+ import { t as Separator } from "../separator-D0bew2D_.js";
3
3
 
4
4
  export { Separator };
@@ -1,17 +1,17 @@
1
- import * as react_jsx_runtime211 from "react/jsx-runtime";
1
+ import * as react_jsx_runtime320 from "react/jsx-runtime";
2
2
  import * as React$1 from "react";
3
3
  import { Dialog } from "@base-ui/react/dialog";
4
4
 
5
5
  //#region src/components/sheet.d.ts
6
6
  declare function Sheet({
7
7
  ...props
8
- }: Dialog.Root.Props): react_jsx_runtime211.JSX.Element;
8
+ }: Dialog.Root.Props): react_jsx_runtime320.JSX.Element;
9
9
  declare function SheetTrigger({
10
10
  ...props
11
- }: Dialog.Trigger.Props): react_jsx_runtime211.JSX.Element;
11
+ }: Dialog.Trigger.Props): react_jsx_runtime320.JSX.Element;
12
12
  declare function SheetClose({
13
13
  ...props
14
- }: Dialog.Close.Props): react_jsx_runtime211.JSX.Element;
14
+ }: Dialog.Close.Props): react_jsx_runtime320.JSX.Element;
15
15
  declare function SheetContent({
16
16
  className,
17
17
  children,
@@ -21,23 +21,23 @@ declare function SheetContent({
21
21
  }: Dialog.Popup.Props & {
22
22
  side?: "top" | "right" | "bottom" | "left";
23
23
  showCloseButton?: boolean;
24
- }): react_jsx_runtime211.JSX.Element;
24
+ }): react_jsx_runtime320.JSX.Element;
25
25
  declare function SheetHeader({
26
26
  className,
27
27
  ...props
28
- }: React$1.ComponentProps<"div">): react_jsx_runtime211.JSX.Element;
28
+ }: React$1.ComponentProps<"div">): react_jsx_runtime320.JSX.Element;
29
29
  declare function SheetFooter({
30
30
  className,
31
31
  ...props
32
- }: React$1.ComponentProps<"div">): react_jsx_runtime211.JSX.Element;
32
+ }: React$1.ComponentProps<"div">): react_jsx_runtime320.JSX.Element;
33
33
  declare function SheetTitle({
34
34
  className,
35
35
  ...props
36
- }: Dialog.Title.Props): react_jsx_runtime211.JSX.Element;
36
+ }: Dialog.Title.Props): react_jsx_runtime320.JSX.Element;
37
37
  declare function SheetDescription({
38
38
  className,
39
39
  ...props
40
- }: Dialog.Description.Props): react_jsx_runtime211.JSX.Element;
40
+ }: Dialog.Description.Props): react_jsx_runtime320.JSX.Element;
41
41
  //#endregion
42
42
  export { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger };
43
43
  //# sourceMappingURL=sheet.d.ts.map
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
- import "../utils-mWJR2N24.js";
4
- import "../button-hBUFMmsZ.js";
5
- import { a as SheetFooter, c as SheetTrigger, i as SheetDescription, n as SheetClose, o as SheetHeader, r as SheetContent, s as SheetTitle, t as Sheet } from "../sheet-CLjNDrfL.js";
3
+ import "../utils-DUlptRpf.js";
4
+ import "../button-DnHwqwy0.js";
5
+ import { a as SheetFooter, c as SheetTrigger, i as SheetDescription, n as SheetClose, o as SheetHeader, r as SheetContent, s as SheetTitle, t as Sheet } from "../sheet-BB23q6wd.js";
6
6
 
7
7
  export { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger };