@giddaa-housing/ui 1.0.0 → 1.2.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 (331) hide show
  1. package/css/generated/shared.css +1 -1
  2. package/css/giddaa.css +12 -2
  3. package/dist/accordion.d.ts +9 -10
  4. package/dist/accordion.js +41 -87
  5. package/dist/activity-timeline.d.ts +12 -16
  6. package/dist/activity-timeline.js +83 -198
  7. package/dist/alert.d.ts +8 -9
  8. package/dist/alert.js +53 -111
  9. package/dist/auth-layout.d.ts +4 -4
  10. package/dist/auth-layout.js +143 -294
  11. package/dist/avatar.d.ts +6 -6
  12. package/dist/avatar.js +49 -19
  13. package/dist/badge.d.ts +12 -14
  14. package/dist/badge.js +71 -11
  15. package/dist/bar-chart.d.ts +65 -67
  16. package/dist/bar-chart.js +232 -207
  17. package/dist/breadcrumb.d.ts +5 -5
  18. package/dist/breadcrumb.js +56 -118
  19. package/dist/bullet-chart.d.ts +41 -37
  20. package/dist/bullet-chart.js +125 -148
  21. package/dist/button-BZIeyUw6.d.ts +17 -0
  22. package/dist/button-group.d.ts +13 -16
  23. package/dist/button-group.js +39 -88
  24. package/dist/button.d.ts +2 -19
  25. package/dist/button.js +94 -13
  26. package/dist/calendar.d.ts +6 -6
  27. package/dist/calendar.js +138 -17
  28. package/dist/card.d.ts +14 -16
  29. package/dist/card.js +59 -145
  30. package/dist/carousel.d.ts +34 -35
  31. package/dist/carousel.js +335 -20
  32. package/dist/chart.d.ts +90 -63
  33. package/dist/chart.js +573 -28
  34. package/dist/checkbox.d.ts +10 -12
  35. package/dist/checkbox.js +82 -47
  36. package/dist/cn-BI_4DMBf.js +23 -0
  37. package/dist/collapsible.d.ts +7 -8
  38. package/dist/collapsible.js +22 -47
  39. package/dist/combobox.d.ts +10 -10
  40. package/dist/combobox.js +236 -44
  41. package/dist/cta.d.ts +12 -14
  42. package/dist/cta.js +175 -341
  43. package/dist/currency-selector.d.ts +31 -32
  44. package/dist/currency-selector.js +106 -184
  45. package/dist/data-table.d.ts +168 -0
  46. package/dist/data-table.js +676 -0
  47. package/dist/date-picker.d.ts +22 -23
  48. package/dist/date-picker.js +119 -192
  49. package/dist/details-card.d.ts +7 -7
  50. package/dist/details-card.js +104 -253
  51. package/dist/dialog.d.ts +13 -14
  52. package/dist/dialog.js +116 -209
  53. package/dist/dropdown-menu.d.ts +13 -13
  54. package/dist/dropdown-menu.js +180 -37
  55. package/dist/dropzone.d.ts +55 -55
  56. package/dist/dropzone.js +327 -439
  57. package/dist/editorial-card.d.ts +23 -25
  58. package/dist/editorial-card.js +129 -296
  59. package/dist/empty-state.d.ts +8 -9
  60. package/dist/empty-state.js +48 -105
  61. package/dist/field.d.ts +23 -25
  62. package/dist/field.js +110 -221
  63. package/dist/filter.d.ts +118 -0
  64. package/dist/filter.js +775 -0
  65. package/dist/footer.d.ts +8 -15
  66. package/dist/footer.js +197 -400
  67. package/dist/funnel-chart.d.ts +49 -48
  68. package/dist/funnel-chart.js +170 -189
  69. package/dist/gallery-indicator.d.ts +11 -12
  70. package/dist/gallery-indicator.js +75 -12
  71. package/dist/heatmap-chart.d.ts +47 -50
  72. package/dist/heatmap-chart.js +186 -237
  73. package/dist/infotip.d.ts +8 -9
  74. package/dist/infotip.js +33 -59
  75. package/dist/input-CfoEJ8A6.d.ts +12 -0
  76. package/dist/input-group.d.ts +16 -20
  77. package/dist/input-group.js +99 -23
  78. package/dist/input-size-context-C-SFx9sx.d.ts +10 -0
  79. package/dist/input-size-context.d.ts +2 -11
  80. package/dist/input-size-context.js +17 -9
  81. package/dist/input.d.ts +2 -13
  82. package/dist/input.js +27 -11
  83. package/dist/item.d.ts +7 -8
  84. package/dist/item.js +22 -59
  85. package/dist/kpi-card.d.ts +18 -20
  86. package/dist/kpi-card.js +84 -192
  87. package/dist/label.d.ts +6 -6
  88. package/dist/label.js +40 -8
  89. package/dist/line-chart.d.ts +200 -129
  90. package/dist/line-chart.js +330 -105
  91. package/dist/list-item.d.ts +22 -0
  92. package/dist/list-item.js +84 -0
  93. package/dist/logo.d.ts +4 -4
  94. package/dist/logo.js +92 -9
  95. package/dist/map-indicator.d.ts +7 -7
  96. package/dist/map-indicator.js +80 -106
  97. package/dist/match.d.ts +10 -11
  98. package/dist/match.js +62 -107
  99. package/dist/media-gallery-hero.d.ts +40 -42
  100. package/dist/media-gallery-hero.js +182 -343
  101. package/dist/media-player.d.ts +17 -17
  102. package/dist/media-player.js +873 -1348
  103. package/dist/multi-step-form.d.ts +56 -0
  104. package/dist/multi-step-form.js +342 -0
  105. package/dist/number-input.d.ts +34 -34
  106. package/dist/number-input.js +64 -117
  107. package/dist/page-header.d.ts +10 -11
  108. package/dist/page-header.js +34 -79
  109. package/dist/pagination.d.ts +17 -21
  110. package/dist/pagination.js +132 -207
  111. package/dist/password-input.d.ts +5 -13
  112. package/dist/password-input.js +31 -55
  113. package/dist/phone-input.d.ts +19 -20
  114. package/dist/phone-input.js +226 -344
  115. package/dist/photo-gallery.d.ts +19 -19
  116. package/dist/photo-gallery.js +313 -449
  117. package/dist/picker-lzgmsNfG.js +32 -0
  118. package/dist/pie-chart.d.ts +121 -90
  119. package/dist/pie-chart.js +183 -149
  120. package/dist/popover.d.ts +9 -9
  121. package/dist/popover.js +72 -23
  122. package/dist/price-tag.d.ts +26 -27
  123. package/dist/price-tag.js +113 -173
  124. package/dist/progress.d.ts +16 -17
  125. package/dist/progress.js +169 -24
  126. package/dist/property-listing-card.d.ts +14 -17
  127. package/dist/property-listing-card.js +102 -220
  128. package/dist/purchase-option-card.d.ts +79 -0
  129. package/dist/purchase-option-card.js +176 -0
  130. package/dist/radar-chart.d.ts +29 -31
  131. package/dist/radar-chart.js +162 -137
  132. package/dist/radio-group.d.ts +11 -13
  133. package/dist/radio-group.js +46 -60
  134. package/dist/review-block.d.ts +14 -16
  135. package/dist/review-block.js +154 -10
  136. package/dist/rich-text-editor.d.ts +30 -14
  137. package/dist/rich-text-editor.js +592 -716
  138. package/dist/scatter-chart.d.ts +45 -47
  139. package/dist/scatter-chart.js +236 -240
  140. package/dist/search-input.d.ts +8 -16
  141. package/dist/search-input.js +57 -109
  142. package/dist/select.d.ts +8 -8
  143. package/dist/select.js +144 -27
  144. package/dist/separator.d.ts +8 -9
  145. package/dist/separator.js +32 -8
  146. package/dist/sheet.d.ts +11 -11
  147. package/dist/sheet.js +103 -24
  148. package/dist/sidebar.d.ts +32 -37
  149. package/dist/sidebar.js +364 -634
  150. package/dist/size-context-D4mYvcg8.d.ts +10 -0
  151. package/dist/size-context.d.ts +2 -11
  152. package/dist/size-context.js +17 -9
  153. package/dist/skeleton.d.ts +4 -5
  154. package/dist/skeleton.js +12 -8
  155. package/dist/slider.d.ts +8 -9
  156. package/dist/slider.js +64 -135
  157. package/dist/sparkline.d.ts +68 -58
  158. package/dist/sparkline.js +315 -251
  159. package/dist/stepper.d.ts +23 -24
  160. package/dist/stepper.js +149 -246
  161. package/dist/styles.css +1004 -116
  162. package/dist/switch.d.ts +10 -12
  163. package/dist/switch.js +48 -70
  164. package/dist/table-card.d.ts +35 -0
  165. package/dist/table-card.js +125 -0
  166. package/dist/table.d.ts +18 -14
  167. package/dist/table.js +117 -154
  168. package/dist/tabs.d.ts +33 -15
  169. package/dist/tabs.js +110 -18
  170. package/dist/tag.d.ts +21 -23
  171. package/dist/tag.js +103 -159
  172. package/dist/testimonial-block.d.ts +18 -19
  173. package/dist/testimonial-block.js +189 -358
  174. package/dist/textarea-IS_D8pXf.d.ts +11 -0
  175. package/dist/textarea.d.ts +2 -12
  176. package/dist/textarea.js +24 -11
  177. package/dist/time-picker.d.ts +11 -11
  178. package/dist/time-picker.js +245 -302
  179. package/dist/toast.d.ts +16 -18
  180. package/dist/toast.js +154 -205
  181. package/dist/tooltip.d.ts +8 -9
  182. package/dist/tooltip.js +37 -12
  183. package/dist/tree-map.d.ts +59 -62
  184. package/dist/tree-map.js +226 -269
  185. package/dist/use-uncontrolled-CLfM1XbB.js +21 -0
  186. package/dist/waterfall-chart.d.ts +94 -97
  187. package/dist/waterfall-chart.js +455 -552
  188. package/package.json +36 -9
  189. package/dist/accordion.js.map +0 -1
  190. package/dist/activity-timeline.js.map +0 -1
  191. package/dist/alert.js.map +0 -1
  192. package/dist/auth-layout.js.map +0 -1
  193. package/dist/avatar.js.map +0 -1
  194. package/dist/badge.js.map +0 -1
  195. package/dist/bar-chart.js.map +0 -1
  196. package/dist/breadcrumb.js.map +0 -1
  197. package/dist/bullet-chart.js.map +0 -1
  198. package/dist/button-group.js.map +0 -1
  199. package/dist/button.js.map +0 -1
  200. package/dist/calendar.js.map +0 -1
  201. package/dist/card.js.map +0 -1
  202. package/dist/carousel.js.map +0 -1
  203. package/dist/chart.js.map +0 -1
  204. package/dist/checkbox.js.map +0 -1
  205. package/dist/chunk-322YCNVL.js +0 -278
  206. package/dist/chunk-322YCNVL.js.map +0 -1
  207. package/dist/chunk-3ACQVT7A.js +0 -25
  208. package/dist/chunk-3ACQVT7A.js.map +0 -1
  209. package/dist/chunk-3T65TLJX.js +0 -334
  210. package/dist/chunk-3T65TLJX.js.map +0 -1
  211. package/dist/chunk-6ZSGQHH2.js +0 -192
  212. package/dist/chunk-6ZSGQHH2.js.map +0 -1
  213. package/dist/chunk-7TBMLFGW.js +0 -41
  214. package/dist/chunk-7TBMLFGW.js.map +0 -1
  215. package/dist/chunk-B4H6RNDH.js +0 -135
  216. package/dist/chunk-B4H6RNDH.js.map +0 -1
  217. package/dist/chunk-BUXCGZ6X.js +0 -219
  218. package/dist/chunk-BUXCGZ6X.js.map +0 -1
  219. package/dist/chunk-CHII2QHH.js +0 -58
  220. package/dist/chunk-CHII2QHH.js.map +0 -1
  221. package/dist/chunk-DMNOXRRW.js +0 -147
  222. package/dist/chunk-DMNOXRRW.js.map +0 -1
  223. package/dist/chunk-EFSOSSIC.js +0 -130
  224. package/dist/chunk-EFSOSSIC.js.map +0 -1
  225. package/dist/chunk-FZDSVMKY.js +0 -363
  226. package/dist/chunk-FZDSVMKY.js.map +0 -1
  227. package/dist/chunk-GJOFIJS3.js +0 -246
  228. package/dist/chunk-GJOFIJS3.js.map +0 -1
  229. package/dist/chunk-HL3ZSYES.js +0 -23
  230. package/dist/chunk-HL3ZSYES.js.map +0 -1
  231. package/dist/chunk-JVLUBAPB.js +0 -129
  232. package/dist/chunk-JVLUBAPB.js.map +0 -1
  233. package/dist/chunk-KDPYSOYZ.js +0 -64
  234. package/dist/chunk-KDPYSOYZ.js.map +0 -1
  235. package/dist/chunk-KSMDANKI.js +0 -43
  236. package/dist/chunk-KSMDANKI.js.map +0 -1
  237. package/dist/chunk-MEKCCOP5.js +0 -46
  238. package/dist/chunk-MEKCCOP5.js.map +0 -1
  239. package/dist/chunk-NOFXVRWL.js +0 -451
  240. package/dist/chunk-NOFXVRWL.js.map +0 -1
  241. package/dist/chunk-PC5MHNVA.js +0 -171
  242. package/dist/chunk-PC5MHNVA.js.map +0 -1
  243. package/dist/chunk-QKAQZ2GU.js +0 -122
  244. package/dist/chunk-QKAQZ2GU.js.map +0 -1
  245. package/dist/chunk-QZHSHSVV.js +0 -26
  246. package/dist/chunk-QZHSHSVV.js.map +0 -1
  247. package/dist/chunk-RBMK26XD.js +0 -19
  248. package/dist/chunk-RBMK26XD.js.map +0 -1
  249. package/dist/chunk-SFNJGF6M.js +0 -262
  250. package/dist/chunk-SFNJGF6M.js.map +0 -1
  251. package/dist/chunk-UJJNLGTM.js +0 -112
  252. package/dist/chunk-UJJNLGTM.js.map +0 -1
  253. package/dist/chunk-VGR4ZWJ3.js +0 -418
  254. package/dist/chunk-VGR4ZWJ3.js.map +0 -1
  255. package/dist/chunk-XG47P6D4.js +0 -99
  256. package/dist/chunk-XG47P6D4.js.map +0 -1
  257. package/dist/chunk-XZZAHNVM.js +0 -21
  258. package/dist/chunk-XZZAHNVM.js.map +0 -1
  259. package/dist/chunk-Y4TTYVNE.js +0 -36
  260. package/dist/chunk-Y4TTYVNE.js.map +0 -1
  261. package/dist/chunk-YDWIHW6Q.js +0 -69
  262. package/dist/chunk-YDWIHW6Q.js.map +0 -1
  263. package/dist/collapsible.js.map +0 -1
  264. package/dist/combobox.js.map +0 -1
  265. package/dist/cta.js.map +0 -1
  266. package/dist/currency-selector.js.map +0 -1
  267. package/dist/date-picker.js.map +0 -1
  268. package/dist/details-card.js.map +0 -1
  269. package/dist/dialog.js.map +0 -1
  270. package/dist/dropdown-menu.js.map +0 -1
  271. package/dist/dropzone.js.map +0 -1
  272. package/dist/editorial-card.js.map +0 -1
  273. package/dist/empty-state.js.map +0 -1
  274. package/dist/field.js.map +0 -1
  275. package/dist/footer.js.map +0 -1
  276. package/dist/funnel-chart.js.map +0 -1
  277. package/dist/gallery-indicator.js.map +0 -1
  278. package/dist/heatmap-chart.js.map +0 -1
  279. package/dist/infotip.js.map +0 -1
  280. package/dist/input-group.js.map +0 -1
  281. package/dist/input-size-context.js.map +0 -1
  282. package/dist/input.js.map +0 -1
  283. package/dist/item.js.map +0 -1
  284. package/dist/kpi-card.js.map +0 -1
  285. package/dist/label.js.map +0 -1
  286. package/dist/line-chart.js.map +0 -1
  287. package/dist/logo.js.map +0 -1
  288. package/dist/map-indicator.js.map +0 -1
  289. package/dist/match.js.map +0 -1
  290. package/dist/media-gallery-hero.js.map +0 -1
  291. package/dist/media-player.js.map +0 -1
  292. package/dist/number-input.js.map +0 -1
  293. package/dist/page-header.js.map +0 -1
  294. package/dist/pagination.js.map +0 -1
  295. package/dist/password-input.js.map +0 -1
  296. package/dist/phone-input.js.map +0 -1
  297. package/dist/photo-gallery.js.map +0 -1
  298. package/dist/pie-chart.js.map +0 -1
  299. package/dist/popover.js.map +0 -1
  300. package/dist/price-tag.js.map +0 -1
  301. package/dist/progress.js.map +0 -1
  302. package/dist/property-listing-card.js.map +0 -1
  303. package/dist/radar-chart.js.map +0 -1
  304. package/dist/radio-group.js.map +0 -1
  305. package/dist/review-block.js.map +0 -1
  306. package/dist/rich-text-editor.js.map +0 -1
  307. package/dist/scatter-chart.js.map +0 -1
  308. package/dist/search-input.js.map +0 -1
  309. package/dist/select.js.map +0 -1
  310. package/dist/separator.js.map +0 -1
  311. package/dist/sheet.js.map +0 -1
  312. package/dist/sidebar.js.map +0 -1
  313. package/dist/size-context.js.map +0 -1
  314. package/dist/skeleton.js.map +0 -1
  315. package/dist/slider.js.map +0 -1
  316. package/dist/sparkline.js.map +0 -1
  317. package/dist/stepper.js.map +0 -1
  318. package/dist/switch.js.map +0 -1
  319. package/dist/tab-list.d.ts +0 -38
  320. package/dist/tab-list.js +0 -123
  321. package/dist/tab-list.js.map +0 -1
  322. package/dist/table.js.map +0 -1
  323. package/dist/tabs.js.map +0 -1
  324. package/dist/tag.js.map +0 -1
  325. package/dist/testimonial-block.js.map +0 -1
  326. package/dist/textarea.js.map +0 -1
  327. package/dist/time-picker.js.map +0 -1
  328. package/dist/toast.js.map +0 -1
  329. package/dist/tooltip.js.map +0 -1
  330. package/dist/tree-map.js.map +0 -1
  331. package/dist/waterfall-chart.js.map +0 -1
@@ -1,31 +1,13 @@
1
1
  "use client";
2
- import {
3
- Popover,
4
- PopoverContent,
5
- PopoverTrigger
6
- } from "./chunk-JVLUBAPB.js";
7
- import {
8
- DropdownMenu,
9
- DropdownMenuContent,
10
- DropdownMenuRadioGroup,
11
- DropdownMenuRadioItem,
12
- DropdownMenuTrigger
13
- } from "./chunk-3T65TLJX.js";
14
- import {
15
- Input
16
- } from "./chunk-MEKCCOP5.js";
17
- import "./chunk-3ACQVT7A.js";
18
- import {
19
- Button
20
- } from "./chunk-B4H6RNDH.js";
21
- import {
22
- useComponentSize
23
- } from "./chunk-HL3ZSYES.js";
24
- import {
25
- cn
26
- } from "./chunk-Y4TTYVNE.js";
27
-
28
- // src/rich-text-editor.tsx
2
+ import { t as cn } from "./cn-BI_4DMBf.js";
3
+ import { useComponentSize } from "./size-context.js";
4
+ import { Button } from "./button.js";
5
+ import { Input } from "./input.js";
6
+ import { Popover, PopoverContent, PopoverTrigger } from "./popover.js";
7
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger } from "./dropdown-menu.js";
8
+ import { AlignCenter, AlignJustify, AlignLeft, AlignRight, Baseline, Bold, ChevronDown, Code2, ImageIcon, Italic, Link2, List, ListOrdered, Quote, Redo2, Underline, Undo2 } from "lucide-react";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ import * as React from "react";
29
11
  import { Color } from "@tiptap/extension-color";
30
12
  import { Image } from "@tiptap/extension-image";
31
13
  import { Placeholder } from "@tiptap/extension-placeholder";
@@ -33,707 +15,601 @@ import { TextAlign } from "@tiptap/extension-text-align";
33
15
  import { TextStyle } from "@tiptap/extension-text-style";
34
16
  import { EditorContent, useEditor, useEditorState } from "@tiptap/react";
35
17
  import { StarterKit } from "@tiptap/starter-kit";
36
- import {
37
- AlignCenter,
38
- AlignJustify,
39
- AlignLeft,
40
- AlignRight,
41
- Baseline,
42
- Bold,
43
- ChevronDown,
44
- Code2,
45
- ImageIcon,
46
- Italic,
47
- Link2,
48
- List,
49
- ListOrdered,
50
- Quote,
51
- Redo2,
52
- Underline,
53
- Undo2
54
- } from "lucide-react";
55
- import * as React from "react";
56
- import { jsx, jsxs } from "react/jsx-runtime";
57
- var SIZES = {
58
- sm: {
59
- width: "max-w-[420px]",
60
- content: "min-h-[140px]",
61
- contentPad: "px-4 py-3",
62
- text: "text-gdt-xs",
63
- icon: "[&_svg:not([class*='size-'])]:size-3.5",
64
- button: "h-7 min-w-7 px-1",
65
- toolbarPad: "px-2 py-1.5",
66
- toolbarGap: "gap-0.5",
67
- divider: "h-4"
68
- },
69
- md: {
70
- width: "max-w-[520px]",
71
- content: "min-h-[172px]",
72
- contentPad: "px-5 py-4",
73
- text: "text-gdt-sm",
74
- icon: "[&_svg:not([class*='size-'])]:size-4",
75
- button: "h-8 min-w-8 px-1.5",
76
- toolbarPad: "px-2.5 py-2",
77
- toolbarGap: "gap-0.5",
78
- divider: "h-5"
79
- },
80
- lg: {
81
- width: "max-w-[600px]",
82
- content: "min-h-[206px]",
83
- contentPad: "px-6 py-5",
84
- text: "text-gdt-md",
85
- icon: "[&_svg:not([class*='size-'])]:size-[18px]",
86
- button: "h-9 min-w-9 px-2",
87
- toolbarPad: "px-3 py-2.5",
88
- toolbarGap: "gap-1",
89
- divider: "h-6"
90
- }
18
+ //#region src/rich-text-editor.tsx
19
+ const SIZES = {
20
+ sm: {
21
+ content: "min-h-[140px]",
22
+ contentPad: "px-4 py-3",
23
+ text: "text-gdt-xs",
24
+ icon: "[&_svg:not([class*='size-'])]:size-3.5",
25
+ button: "h-7 min-w-7 px-1",
26
+ toolbarPad: "px-2 py-1.5",
27
+ toolbarGap: "gap-0.5",
28
+ divider: "h-4"
29
+ },
30
+ md: {
31
+ content: "min-h-[172px]",
32
+ contentPad: "px-5 py-4",
33
+ text: "text-gdt-sm",
34
+ icon: "[&_svg:not([class*='size-'])]:size-4",
35
+ button: "h-8 min-w-8 px-1.5",
36
+ toolbarPad: "px-2.5 py-2",
37
+ toolbarGap: "gap-0.5",
38
+ divider: "h-5"
39
+ },
40
+ lg: {
41
+ content: "min-h-[206px]",
42
+ contentPad: "px-6 py-5",
43
+ text: "text-gdt-md",
44
+ icon: "[&_svg:not([class*='size-'])]:size-[18px]",
45
+ button: "h-9 min-w-9 px-2",
46
+ toolbarPad: "px-3 py-2.5",
47
+ toolbarGap: "gap-1",
48
+ divider: "h-6"
49
+ }
91
50
  };
92
- var TEXT_COLORS = [
93
- { label: "Default", value: "", swatch: "" },
94
- { label: "Forest", value: "#2f5a2c", swatch: "var(--color-forest-500)" },
95
- { label: "Brass", value: "#b8861a", swatch: "var(--color-brass-400)" },
96
- { label: "Clay", value: "#b2542b", swatch: "var(--color-clay-500)" },
97
- { label: "Moss", value: "#4e4d29", swatch: "var(--color-moss-500)" },
98
- { label: "Stone", value: "#5c5648", swatch: "var(--color-stone-600)" },
99
- { label: "Ink", value: "#1f1c18", swatch: "var(--color-stone-900)" }
51
+ const TEXT_COLORS = [
52
+ {
53
+ label: "Default",
54
+ value: "",
55
+ swatch: ""
56
+ },
57
+ {
58
+ label: "Forest",
59
+ value: "#2f5a2c",
60
+ swatch: "var(--color-forest-500)"
61
+ },
62
+ {
63
+ label: "Brass",
64
+ value: "#b8861a",
65
+ swatch: "var(--color-brass-400)"
66
+ },
67
+ {
68
+ label: "Clay",
69
+ value: "#b2542b",
70
+ swatch: "var(--color-clay-500)"
71
+ },
72
+ {
73
+ label: "Moss",
74
+ value: "#4e4d29",
75
+ swatch: "var(--color-moss-500)"
76
+ },
77
+ {
78
+ label: "Stone",
79
+ value: "#5c5648",
80
+ swatch: "var(--color-stone-600)"
81
+ },
82
+ {
83
+ label: "Ink",
84
+ value: "#1f1c18",
85
+ swatch: "var(--color-stone-900)"
86
+ }
100
87
  ];
101
- var BLOCK_OPTIONS = [
102
- { value: "paragraph", label: "Normal" },
103
- { value: "h1", label: "Heading 1" },
104
- { value: "h2", label: "Heading 2" },
105
- { value: "h3", label: "Heading 3" }
88
+ const BLOCK_OPTIONS = [
89
+ {
90
+ value: "paragraph",
91
+ label: "Normal"
92
+ },
93
+ {
94
+ value: "h1",
95
+ label: "Heading 1"
96
+ },
97
+ {
98
+ value: "h2",
99
+ label: "Heading 2"
100
+ },
101
+ {
102
+ value: "h3",
103
+ label: "Heading 3"
104
+ }
106
105
  ];
107
106
  function toolbarControlClass(tokens, active) {
108
- return cn(
109
- "inline-flex shrink-0 cursor-pointer items-center justify-center rounded-md font-medium text-fg-secondary outline-none transition-colors select-none",
110
- "hover:bg-action-tertiary-hover hover:text-fg-primary",
111
- "focus-visible:ring-2 focus-visible:ring-line-focus",
112
- "disabled:pointer-events-none disabled:opacity-40 data-disabled:pointer-events-none data-disabled:opacity-40",
113
- tokens.button,
114
- tokens.icon,
115
- tokens.text,
116
- active && "bg-action-primary text-fg-on-brand hover:bg-action-primary-hover hover:text-fg-on-brand"
117
- );
107
+ return cn("inline-flex shrink-0 cursor-pointer items-center justify-center rounded-md font-medium text-fg-secondary outline-none transition-colors select-none", "hover:bg-action-tertiary-hover hover:text-fg-primary", "focus-visible:ring-2 focus-visible:ring-line-focus", "disabled:pointer-events-none disabled:opacity-40 data-disabled:pointer-events-none data-disabled:opacity-40", tokens.button, tokens.icon, tokens.text, active && "bg-action-primary text-fg-on-brand hover:bg-action-primary-hover hover:text-fg-on-brand");
118
108
  }
119
- function ToolbarButton({
120
- tokens,
121
- label,
122
- active,
123
- disabled,
124
- onClick,
125
- children
126
- }) {
127
- return /* @__PURE__ */ jsx(
128
- "button",
129
- {
130
- type: "button",
131
- "aria-label": label,
132
- title: label,
133
- "aria-pressed": active,
134
- disabled,
135
- onMouseDown: (event) => event.preventDefault(),
136
- onClick,
137
- className: toolbarControlClass(tokens, active),
138
- children
139
- }
140
- );
109
+ function ToolbarButton({ tokens, label, active, disabled, onClick, children }) {
110
+ return /* @__PURE__ */ jsx("button", {
111
+ type: "button",
112
+ "aria-label": label,
113
+ title: label,
114
+ "aria-pressed": active,
115
+ disabled,
116
+ onMouseDown: (event) => event.preventDefault(),
117
+ onClick,
118
+ className: toolbarControlClass(tokens, active),
119
+ children
120
+ });
141
121
  }
142
122
  function ToolbarDivider({ tokens }) {
143
- return /* @__PURE__ */ jsx(
144
- "span",
145
- {
146
- "aria-hidden": "true",
147
- className: cn("mx-1 w-px shrink-0 self-center bg-line", tokens.divider)
148
- }
149
- );
123
+ return /* @__PURE__ */ jsx("span", {
124
+ "aria-hidden": "true",
125
+ className: cn("mx-1 w-px shrink-0 self-center bg-line", tokens.divider)
126
+ });
150
127
  }
151
- function BlockControl({
152
- tokens,
153
- value,
154
- disabled,
155
- onChange
156
- }) {
157
- const current = BLOCK_OPTIONS.find((option) => option.value === value);
158
- return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
159
- /* @__PURE__ */ jsxs(
160
- DropdownMenuTrigger,
161
- {
162
- disabled,
163
- className: cn(
164
- toolbarControlClass(tokens),
165
- "w-auto justify-between gap-1 px-2"
166
- ),
167
- children: [
168
- /* @__PURE__ */ jsx("span", { className: "whitespace-nowrap", children: current?.label ?? "Normal" }),
169
- /* @__PURE__ */ jsx(ChevronDown, { className: "size-3.5 opacity-70" })
170
- ]
171
- }
172
- ),
173
- /* @__PURE__ */ jsx(DropdownMenuContent, { className: "min-w-40", children: /* @__PURE__ */ jsx(
174
- DropdownMenuRadioGroup,
175
- {
176
- value,
177
- onValueChange: (next) => onChange(next),
178
- children: BLOCK_OPTIONS.map((option) => (
179
- // closeOnClick: radio items keep the menu open by default, which
180
- // leaves the popup backdrop blocking the toolbar after a pick.
181
- /* @__PURE__ */ jsx(
182
- DropdownMenuRadioItem,
183
- {
184
- value: option.value,
185
- closeOnClick: true,
186
- children: option.label
187
- },
188
- option.value
189
- )
190
- ))
191
- }
192
- ) })
193
- ] });
128
+ function BlockControl({ tokens, value, disabled, onChange }) {
129
+ const current = BLOCK_OPTIONS.find((option) => option.value === value);
130
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsxs(DropdownMenuTrigger, {
131
+ disabled,
132
+ className: cn(toolbarControlClass(tokens), "w-auto justify-between gap-1 px-2"),
133
+ children: [/* @__PURE__ */ jsx("span", {
134
+ className: "whitespace-nowrap",
135
+ children: current?.label ?? "Normal"
136
+ }), /* @__PURE__ */ jsx(ChevronDown, { className: "size-3.5 opacity-70" })]
137
+ }), /* @__PURE__ */ jsx(DropdownMenuContent, {
138
+ className: "min-w-40",
139
+ children: /* @__PURE__ */ jsx(DropdownMenuRadioGroup, {
140
+ value,
141
+ onValueChange: (next) => onChange(next),
142
+ children: BLOCK_OPTIONS.map((option) => /* @__PURE__ */ jsx(DropdownMenuRadioItem, {
143
+ value: option.value,
144
+ closeOnClick: true,
145
+ children: option.label
146
+ }, option.value))
147
+ })
148
+ })] });
194
149
  }
195
- function ColorControl({
196
- tokens,
197
- value,
198
- disabled,
199
- onChange
200
- }) {
201
- const [open, setOpen] = React.useState(false);
202
- const active = value !== "";
203
- return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
204
- /* @__PURE__ */ jsx(
205
- PopoverTrigger,
206
- {
207
- disabled,
208
- "aria-label": "Text colour",
209
- title: "Text colour",
210
- onMouseDown: (event) => event.preventDefault(),
211
- className: toolbarControlClass(tokens, false),
212
- children: /* @__PURE__ */ jsxs("span", { className: "relative inline-flex flex-col items-center", children: [
213
- /* @__PURE__ */ jsx(Baseline, { className: active ? "text-fg-brand" : void 0 }),
214
- /* @__PURE__ */ jsx(
215
- "span",
216
- {
217
- "aria-hidden": "true",
218
- className: "mt-px h-0.5 w-3 rounded-full",
219
- style: { backgroundColor: active ? value : "currentColor" }
220
- }
221
- )
222
- ] })
223
- }
224
- ),
225
- /* @__PURE__ */ jsx(
226
- PopoverContent,
227
- {
228
- showArrow: false,
229
- align: "start",
230
- sideOffset: 8,
231
- className: "w-auto py-3",
232
- children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-4 gap-2 px-4", children: TEXT_COLORS.map((color) => {
233
- const isSelected = color.value === value;
234
- return /* @__PURE__ */ jsx(
235
- "button",
236
- {
237
- type: "button",
238
- title: color.label,
239
- "aria-label": color.label,
240
- "aria-pressed": isSelected,
241
- onClick: () => {
242
- onChange(color.value);
243
- setOpen(false);
244
- },
245
- className: cn(
246
- "flex size-7 items-center justify-center rounded-full border transition-[box-shadow,border-color] outline-none",
247
- "hover:border-line-strong focus-visible:ring-2 focus-visible:ring-line-focus",
248
- isSelected ? "border-line-focus ring-2 ring-line-focus/40" : "border-line"
249
- ),
250
- children: /* @__PURE__ */ jsx(
251
- "span",
252
- {
253
- className: cn(
254
- "flex size-5 items-center justify-center rounded-full text-gdt-xs font-bold",
255
- color.value === "" && "text-fg-secondary"
256
- ),
257
- style: color.value ? {
258
- backgroundColor: color.swatch,
259
- color: "var(--color-stone-0, #fff)"
260
- } : void 0,
261
- children: "A"
262
- }
263
- )
264
- },
265
- color.label
266
- );
267
- }) })
268
- }
269
- )
270
- ] });
150
+ function ColorControl({ tokens, value, disabled, onChange }) {
151
+ const [open, setOpen] = React.useState(false);
152
+ const active = value !== "";
153
+ return /* @__PURE__ */ jsxs(Popover, {
154
+ open,
155
+ onOpenChange: setOpen,
156
+ children: [/* @__PURE__ */ jsx(PopoverTrigger, {
157
+ disabled,
158
+ "aria-label": "Text colour",
159
+ title: "Text colour",
160
+ onMouseDown: (event) => event.preventDefault(),
161
+ className: toolbarControlClass(tokens, false),
162
+ children: /* @__PURE__ */ jsxs("span", {
163
+ className: "relative inline-flex flex-col items-center",
164
+ children: [/* @__PURE__ */ jsx(Baseline, { className: active ? "text-fg-brand" : void 0 }), /* @__PURE__ */ jsx("span", {
165
+ "aria-hidden": "true",
166
+ className: "mt-px h-0.5 w-3 rounded-full",
167
+ style: { backgroundColor: active ? value : "currentColor" }
168
+ })]
169
+ })
170
+ }), /* @__PURE__ */ jsx(PopoverContent, {
171
+ showArrow: false,
172
+ align: "start",
173
+ sideOffset: 8,
174
+ className: "w-auto py-3",
175
+ children: /* @__PURE__ */ jsx("div", {
176
+ className: "grid grid-cols-4 gap-2 px-4",
177
+ children: TEXT_COLORS.map((color) => {
178
+ const isSelected = color.value === value;
179
+ return /* @__PURE__ */ jsx("button", {
180
+ type: "button",
181
+ title: color.label,
182
+ "aria-label": color.label,
183
+ "aria-pressed": isSelected,
184
+ onClick: () => {
185
+ onChange(color.value);
186
+ setOpen(false);
187
+ },
188
+ className: cn("flex size-7 items-center justify-center rounded-full border transition-[box-shadow,border-color] outline-none", "hover:border-line-strong focus-visible:ring-2 focus-visible:ring-line-focus", isSelected ? "border-line-focus ring-2 ring-line-focus/40" : "border-line"),
189
+ children: /* @__PURE__ */ jsx("span", {
190
+ className: cn("flex size-5 items-center justify-center rounded-full text-gdt-xs font-bold", color.value === "" && "text-fg-secondary"),
191
+ style: color.value ? {
192
+ backgroundColor: color.swatch,
193
+ color: "var(--color-stone-0, #fff)"
194
+ } : void 0,
195
+ children: "A"
196
+ })
197
+ }, color.label);
198
+ })
199
+ })
200
+ })]
201
+ });
271
202
  }
272
- function LinkControl({
273
- tokens,
274
- active,
275
- currentHref,
276
- disabled,
277
- onApply,
278
- onRemove
279
- }) {
280
- const [open, setOpen] = React.useState(false);
281
- const [href, setHref] = React.useState("");
282
- function handleOpenChange(next) {
283
- if (next) setHref(currentHref);
284
- setOpen(next);
285
- }
286
- function handleSubmit(event) {
287
- event.preventDefault();
288
- const trimmed = href.trim();
289
- if (trimmed) onApply(trimmed);
290
- else onRemove();
291
- setOpen(false);
292
- }
293
- return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: handleOpenChange, children: [
294
- /* @__PURE__ */ jsx(
295
- PopoverTrigger,
296
- {
297
- disabled,
298
- "aria-label": "Insert link",
299
- title: "Insert link",
300
- "aria-pressed": active,
301
- onMouseDown: (event) => event.preventDefault(),
302
- className: toolbarControlClass(tokens, active),
303
- children: /* @__PURE__ */ jsx(Link2, {})
304
- }
305
- ),
306
- /* @__PURE__ */ jsx(PopoverContent, { showArrow: false, align: "start", sideOffset: 8, children: /* @__PURE__ */ jsxs("form", { className: "flex flex-col gap-3 px-4", onSubmit: handleSubmit, children: [
307
- /* @__PURE__ */ jsx(
308
- Input,
309
- {
310
- autoFocus: true,
311
- size: "sm",
312
- type: "url",
313
- placeholder: "https://example.com",
314
- value: href,
315
- onChange: (event) => setHref(event.target.value)
316
- }
317
- ),
318
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
319
- /* @__PURE__ */ jsx(
320
- Button,
321
- {
322
- type: "button",
323
- variant: "tertiary-outline",
324
- size: "sm",
325
- disabled: !active,
326
- onClick: () => {
327
- onRemove();
328
- setOpen(false);
329
- },
330
- children: "Remove"
331
- }
332
- ),
333
- /* @__PURE__ */ jsx(Button, { type: "submit", size: "sm", children: "Apply" })
334
- ] })
335
- ] }) })
336
- ] });
203
+ function LinkControl({ tokens, active, currentHref, disabled, onApply, onRemove }) {
204
+ const [open, setOpen] = React.useState(false);
205
+ const [href, setHref] = React.useState("");
206
+ function handleOpenChange(next) {
207
+ if (next) setHref(currentHref);
208
+ setOpen(next);
209
+ }
210
+ function handleSubmit(event) {
211
+ event.preventDefault();
212
+ const trimmed = href.trim();
213
+ if (trimmed) onApply(trimmed);
214
+ else onRemove();
215
+ setOpen(false);
216
+ }
217
+ return /* @__PURE__ */ jsxs(Popover, {
218
+ open,
219
+ onOpenChange: handleOpenChange,
220
+ children: [/* @__PURE__ */ jsx(PopoverTrigger, {
221
+ disabled,
222
+ "aria-label": "Insert link",
223
+ title: "Insert link",
224
+ "aria-pressed": active,
225
+ onMouseDown: (event) => event.preventDefault(),
226
+ className: toolbarControlClass(tokens, active),
227
+ children: /* @__PURE__ */ jsx(Link2, {})
228
+ }), /* @__PURE__ */ jsx(PopoverContent, {
229
+ showArrow: false,
230
+ align: "start",
231
+ sideOffset: 8,
232
+ children: /* @__PURE__ */ jsxs("form", {
233
+ className: "flex flex-col gap-3 px-4",
234
+ onSubmit: handleSubmit,
235
+ children: [/* @__PURE__ */ jsx(Input, {
236
+ autoFocus: true,
237
+ size: "sm",
238
+ type: "url",
239
+ placeholder: "https://example.com",
240
+ value: href,
241
+ onChange: (event) => setHref(event.target.value)
242
+ }), /* @__PURE__ */ jsxs("div", {
243
+ className: "flex items-center justify-between gap-2",
244
+ children: [/* @__PURE__ */ jsx(Button, {
245
+ type: "button",
246
+ variant: "tertiary-outline",
247
+ size: "sm",
248
+ disabled: !active,
249
+ onClick: () => {
250
+ onRemove();
251
+ setOpen(false);
252
+ },
253
+ children: "Remove"
254
+ }), /* @__PURE__ */ jsx(Button, {
255
+ type: "submit",
256
+ size: "sm",
257
+ children: "Apply"
258
+ })]
259
+ })]
260
+ })
261
+ })]
262
+ });
337
263
  }
338
- function ImageControl({
339
- tokens,
340
- disabled,
341
- onInsert
342
- }) {
343
- const [open, setOpen] = React.useState(false);
344
- const [src, setSrc] = React.useState("");
345
- function handleOpenChange(next) {
346
- if (next) setSrc("");
347
- setOpen(next);
348
- }
349
- function handleSubmit(event) {
350
- event.preventDefault();
351
- const trimmed = src.trim();
352
- if (trimmed) onInsert(trimmed);
353
- setOpen(false);
354
- }
355
- return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: handleOpenChange, children: [
356
- /* @__PURE__ */ jsx(
357
- PopoverTrigger,
358
- {
359
- disabled,
360
- "aria-label": "Insert image",
361
- title: "Insert image",
362
- onMouseDown: (event) => event.preventDefault(),
363
- className: toolbarControlClass(tokens, false),
364
- children: /* @__PURE__ */ jsx(ImageIcon, {})
365
- }
366
- ),
367
- /* @__PURE__ */ jsx(PopoverContent, { showArrow: false, align: "start", sideOffset: 8, children: /* @__PURE__ */ jsxs("form", { className: "flex flex-col gap-3 px-4", onSubmit: handleSubmit, children: [
368
- /* @__PURE__ */ jsx(
369
- Input,
370
- {
371
- autoFocus: true,
372
- size: "sm",
373
- type: "url",
374
- placeholder: "https://example.com/image.jpg",
375
- value: src,
376
- onChange: (event) => setSrc(event.target.value)
377
- }
378
- ),
379
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end", children: /* @__PURE__ */ jsx(Button, { type: "submit", size: "sm", disabled: !src.trim(), children: "Insert" }) })
380
- ] }) })
381
- ] });
264
+ function ImageControl({ tokens, disabled, onInsert }) {
265
+ const [open, setOpen] = React.useState(false);
266
+ const [src, setSrc] = React.useState("");
267
+ function handleOpenChange(next) {
268
+ if (next) setSrc("");
269
+ setOpen(next);
270
+ }
271
+ function handleSubmit(event) {
272
+ event.preventDefault();
273
+ const trimmed = src.trim();
274
+ if (trimmed) onInsert(trimmed);
275
+ setOpen(false);
276
+ }
277
+ return /* @__PURE__ */ jsxs(Popover, {
278
+ open,
279
+ onOpenChange: handleOpenChange,
280
+ children: [/* @__PURE__ */ jsx(PopoverTrigger, {
281
+ disabled,
282
+ "aria-label": "Insert image",
283
+ title: "Insert image",
284
+ onMouseDown: (event) => event.preventDefault(),
285
+ className: toolbarControlClass(tokens, false),
286
+ children: /* @__PURE__ */ jsx(ImageIcon, {})
287
+ }), /* @__PURE__ */ jsx(PopoverContent, {
288
+ showArrow: false,
289
+ align: "start",
290
+ sideOffset: 8,
291
+ children: /* @__PURE__ */ jsxs("form", {
292
+ className: "flex flex-col gap-3 px-4",
293
+ onSubmit: handleSubmit,
294
+ children: [/* @__PURE__ */ jsx(Input, {
295
+ autoFocus: true,
296
+ size: "sm",
297
+ type: "url",
298
+ placeholder: "https://example.com/image.jpg",
299
+ value: src,
300
+ onChange: (event) => setSrc(event.target.value)
301
+ }), /* @__PURE__ */ jsx("div", {
302
+ className: "flex items-center justify-end",
303
+ children: /* @__PURE__ */ jsx(Button, {
304
+ type: "submit",
305
+ size: "sm",
306
+ disabled: !src.trim(),
307
+ children: "Insert"
308
+ })
309
+ })]
310
+ })
311
+ })]
312
+ });
382
313
  }
383
- var ALIGN_OPTIONS = [
384
- { value: "left", label: "Left", Icon: AlignLeft },
385
- { value: "center", label: "Center", Icon: AlignCenter },
386
- { value: "right", label: "Right", Icon: AlignRight },
387
- { value: "justify", label: "Justify", Icon: AlignJustify }
314
+ const ALIGN_OPTIONS = [
315
+ {
316
+ value: "left",
317
+ label: "Left",
318
+ Icon: AlignLeft
319
+ },
320
+ {
321
+ value: "center",
322
+ label: "Center",
323
+ Icon: AlignCenter
324
+ },
325
+ {
326
+ value: "right",
327
+ label: "Right",
328
+ Icon: AlignRight
329
+ },
330
+ {
331
+ value: "justify",
332
+ label: "Justify",
333
+ Icon: AlignJustify
334
+ }
388
335
  ];
389
- function AlignControl({
390
- tokens,
391
- value,
392
- disabled,
393
- onChange
394
- }) {
395
- const current = ALIGN_OPTIONS.find((option) => option.value === value);
396
- const Icon = current?.Icon ?? AlignLeft;
397
- return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
398
- /* @__PURE__ */ jsx(
399
- DropdownMenuTrigger,
400
- {
401
- disabled,
402
- "aria-label": "Text alignment",
403
- title: "Text alignment",
404
- className: toolbarControlClass(tokens, value !== "left"),
405
- children: /* @__PURE__ */ jsx(Icon, {})
406
- }
407
- ),
408
- /* @__PURE__ */ jsx(DropdownMenuContent, { className: "min-w-36", children: /* @__PURE__ */ jsx(
409
- DropdownMenuRadioGroup,
410
- {
411
- value,
412
- onValueChange: (next) => onChange(next),
413
- children: ALIGN_OPTIONS.map(
414
- ({ value: optionValue, label, Icon: OptionIcon }) => /* @__PURE__ */ jsxs(
415
- DropdownMenuRadioItem,
416
- {
417
- value: optionValue,
418
- closeOnClick: true,
419
- children: [
420
- /* @__PURE__ */ jsx(OptionIcon, {}),
421
- label
422
- ]
423
- },
424
- optionValue
425
- )
426
- )
427
- }
428
- ) })
429
- ] });
430
- }
431
- var EMPTY_STATE = {
432
- block: "paragraph",
433
- align: "left",
434
- color: "",
435
- linkHref: "",
436
- isBold: false,
437
- isItalic: false,
438
- isUnderline: false,
439
- isBulletList: false,
440
- isOrderedList: false,
441
- isBlockquote: false,
442
- isCodeBlock: false,
443
- isLink: false,
444
- canUndo: false,
445
- canRedo: false
446
- };
447
- function RichTextEditor({
448
- value,
449
- defaultValue,
450
- onChange,
451
- size,
452
- placeholder = "Start writing, or paste your content here. Format text and add lists, links, and images using the toolbar above.",
453
- disabled = false,
454
- className,
455
- "aria-label": ariaLabel = "Rich text editor"
456
- }) {
457
- const resolvedSize = useComponentSize(size);
458
- const tokens = SIZES[resolvedSize];
459
- const [focused, setFocused] = React.useState(false);
460
- const editor = useEditor({
461
- immediatelyRender: false,
462
- editable: !disabled,
463
- content: value ?? defaultValue ?? "",
464
- extensions: [
465
- StarterKit.configure({
466
- link: {
467
- openOnClick: false,
468
- HTMLAttributes: { rel: "noopener noreferrer nofollow" }
469
- }
470
- }),
471
- TextStyle,
472
- Color,
473
- TextAlign.configure({ types: ["heading", "paragraph"] }),
474
- Image.configure({ inline: false, allowBase64: true }),
475
- Placeholder.configure({ placeholder })
476
- ],
477
- editorProps: {
478
- attributes: {
479
- "aria-label": ariaLabel,
480
- role: "textbox",
481
- "aria-multiline": "true",
482
- class: cn("tiptap focus:outline-none", tokens.text)
483
- }
484
- },
485
- onFocus: () => setFocused(true),
486
- onBlur: () => setFocused(false),
487
- onUpdate: ({ editor: instance }) => onChange?.(instance.getHTML())
488
- });
489
- React.useEffect(() => {
490
- editor?.setEditable(!disabled);
491
- }, [editor, disabled]);
492
- React.useEffect(() => {
493
- if (!editor || value === void 0) return;
494
- if (value !== editor.getHTML()) {
495
- editor.commands.setContent(value, { emitUpdate: false });
496
- }
497
- }, [editor, value]);
498
- const state = useEditorState({
499
- editor,
500
- selector: ({ editor: instance }) => {
501
- if (!instance) return EMPTY_STATE;
502
- const block = instance.isActive("heading", { level: 1 }) ? "h1" : instance.isActive("heading", { level: 2 }) ? "h2" : instance.isActive("heading", { level: 3 }) ? "h3" : "paragraph";
503
- const align = instance.isActive({ textAlign: "center" }) ? "center" : instance.isActive({ textAlign: "right" }) ? "right" : instance.isActive({ textAlign: "justify" }) ? "justify" : "left";
504
- return {
505
- block,
506
- align,
507
- color: instance.getAttributes("textStyle").color ?? "",
508
- linkHref: instance.getAttributes("link").href ?? "",
509
- isBold: instance.isActive("bold"),
510
- isItalic: instance.isActive("italic"),
511
- isUnderline: instance.isActive("underline"),
512
- isBulletList: instance.isActive("bulletList"),
513
- isOrderedList: instance.isActive("orderedList"),
514
- isBlockquote: instance.isActive("blockquote"),
515
- isCodeBlock: instance.isActive("codeBlock"),
516
- isLink: instance.isActive("link"),
517
- canUndo: instance.can().undo(),
518
- canRedo: instance.can().redo()
519
- };
520
- }
521
- });
522
- const s = state ?? EMPTY_STATE;
523
- function setBlock(next) {
524
- if (!editor) return;
525
- const chain = editor.chain().focus();
526
- if (next === "paragraph") chain.setParagraph().run();
527
- else chain.toggleHeading({ level: Number(next[1]) }).run();
528
- }
529
- function setAlign(next) {
530
- editor?.chain().focus().setTextAlign(next).run();
531
- }
532
- function setColor(next) {
533
- if (!editor) return;
534
- if (next) editor.chain().focus().setColor(next).run();
535
- else editor.chain().focus().unsetColor().run();
536
- }
537
- function applyLink(href) {
538
- editor?.chain().focus().extendMarkRange("link").setLink({ href }).run();
539
- }
540
- function removeLink() {
541
- editor?.chain().focus().extendMarkRange("link").unsetLink().run();
542
- }
543
- function insertImage(src) {
544
- editor?.chain().focus().setImage({ src }).run();
545
- }
546
- return /* @__PURE__ */ jsxs(
547
- "div",
548
- {
549
- "data-slot": "rich-text-editor",
550
- "data-disabled": disabled || void 0,
551
- "data-focused": focused || void 0,
552
- className: cn(
553
- "group/editor flex w-full flex-col overflow-hidden rounded-2xl border bg-surface text-fg-primary shadow-1 transition-[border-color,box-shadow]",
554
- disabled ? "border-line-subtle opacity-60" : focused ? "border-line-focus ring-2 ring-line-focus/35" : "border-line hover:border-line-strong",
555
- tokens.width,
556
- className
557
- ),
558
- children: [
559
- /* @__PURE__ */ jsxs(
560
- "div",
561
- {
562
- role: "toolbar",
563
- "aria-label": "Formatting",
564
- "aria-orientation": "horizontal",
565
- className: cn(
566
- "flex flex-wrap items-center bg-surface-raised",
567
- tokens.toolbarPad,
568
- tokens.toolbarGap
569
- ),
570
- children: [
571
- /* @__PURE__ */ jsx(
572
- BlockControl,
573
- {
574
- tokens,
575
- value: s.block,
576
- disabled,
577
- onChange: setBlock
578
- }
579
- ),
580
- /* @__PURE__ */ jsx(
581
- ToolbarButton,
582
- {
583
- tokens,
584
- label: "Bold",
585
- active: s.isBold,
586
- disabled,
587
- onClick: () => editor?.chain().focus().toggleBold().run(),
588
- children: /* @__PURE__ */ jsx(Bold, {})
589
- }
590
- ),
591
- /* @__PURE__ */ jsx(
592
- ToolbarButton,
593
- {
594
- tokens,
595
- label: "Italic",
596
- active: s.isItalic,
597
- disabled,
598
- onClick: () => editor?.chain().focus().toggleItalic().run(),
599
- children: /* @__PURE__ */ jsx(Italic, {})
600
- }
601
- ),
602
- /* @__PURE__ */ jsx(
603
- ToolbarButton,
604
- {
605
- tokens,
606
- label: "Underline",
607
- active: s.isUnderline,
608
- disabled,
609
- onClick: () => editor?.chain().focus().toggleUnderline().run(),
610
- children: /* @__PURE__ */ jsx(Underline, {})
611
- }
612
- ),
613
- /* @__PURE__ */ jsx(
614
- ColorControl,
615
- {
616
- tokens,
617
- value: s.color,
618
- disabled,
619
- onChange: setColor
620
- }
621
- ),
622
- /* @__PURE__ */ jsx(ToolbarDivider, { tokens }),
623
- /* @__PURE__ */ jsx(
624
- ToolbarButton,
625
- {
626
- tokens,
627
- label: "Numbered list",
628
- active: s.isOrderedList,
629
- disabled,
630
- onClick: () => editor?.chain().focus().toggleOrderedList().run(),
631
- children: /* @__PURE__ */ jsx(ListOrdered, {})
632
- }
633
- ),
634
- /* @__PURE__ */ jsx(
635
- ToolbarButton,
636
- {
637
- tokens,
638
- label: "Bullet list",
639
- active: s.isBulletList,
640
- disabled,
641
- onClick: () => editor?.chain().focus().toggleBulletList().run(),
642
- children: /* @__PURE__ */ jsx(List, {})
643
- }
644
- ),
645
- /* @__PURE__ */ jsx(
646
- AlignControl,
647
- {
648
- tokens,
649
- value: s.align,
650
- disabled,
651
- onChange: setAlign
652
- }
653
- ),
654
- /* @__PURE__ */ jsx(ToolbarDivider, { tokens }),
655
- /* @__PURE__ */ jsx(
656
- LinkControl,
657
- {
658
- tokens,
659
- active: s.isLink,
660
- currentHref: s.linkHref,
661
- disabled,
662
- onApply: applyLink,
663
- onRemove: removeLink
664
- }
665
- ),
666
- /* @__PURE__ */ jsx(
667
- ToolbarButton,
668
- {
669
- tokens,
670
- label: "Quote",
671
- active: s.isBlockquote,
672
- disabled,
673
- onClick: () => editor?.chain().focus().toggleBlockquote().run(),
674
- children: /* @__PURE__ */ jsx(Quote, {})
675
- }
676
- ),
677
- /* @__PURE__ */ jsx(
678
- ToolbarButton,
679
- {
680
- tokens,
681
- label: "Code block",
682
- active: s.isCodeBlock,
683
- disabled,
684
- onClick: () => editor?.chain().focus().toggleCodeBlock().run(),
685
- children: /* @__PURE__ */ jsx(Code2, {})
686
- }
687
- ),
688
- /* @__PURE__ */ jsx(
689
- ImageControl,
690
- {
691
- tokens,
692
- disabled,
693
- onInsert: insertImage
694
- }
695
- ),
696
- /* @__PURE__ */ jsx(ToolbarDivider, { tokens }),
697
- /* @__PURE__ */ jsx(
698
- ToolbarButton,
699
- {
700
- tokens,
701
- label: "Undo",
702
- disabled: disabled || !s.canUndo,
703
- onClick: () => editor?.chain().focus().undo().run(),
704
- children: /* @__PURE__ */ jsx(Undo2, {})
705
- }
706
- ),
707
- /* @__PURE__ */ jsx(
708
- ToolbarButton,
709
- {
710
- tokens,
711
- label: "Redo",
712
- disabled: disabled || !s.canRedo,
713
- onClick: () => editor?.chain().focus().redo().run(),
714
- children: /* @__PURE__ */ jsx(Redo2, {})
715
- }
716
- )
717
- ]
718
- }
719
- ),
720
- /* @__PURE__ */ jsx("div", { className: "h-px w-full shrink-0 bg-line-subtle" }),
721
- /* @__PURE__ */ jsx(
722
- EditorContent,
723
- {
724
- editor,
725
- className: cn(
726
- "gdt-rich-text min-w-0 flex-1 overflow-y-auto",
727
- tokens.content,
728
- tokens.contentPad
729
- )
730
- }
731
- )
732
- ]
733
- }
734
- );
336
+ function AlignControl({ tokens, value, disabled, onChange }) {
337
+ const Icon = ALIGN_OPTIONS.find((option) => option.value === value)?.Icon ?? AlignLeft;
338
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
339
+ disabled,
340
+ "aria-label": "Text alignment",
341
+ title: "Text alignment",
342
+ className: toolbarControlClass(tokens, value !== "left"),
343
+ children: /* @__PURE__ */ jsx(Icon, {})
344
+ }), /* @__PURE__ */ jsx(DropdownMenuContent, {
345
+ className: "min-w-36",
346
+ children: /* @__PURE__ */ jsx(DropdownMenuRadioGroup, {
347
+ value,
348
+ onValueChange: (next) => onChange(next),
349
+ children: ALIGN_OPTIONS.map(({ value: optionValue, label, Icon: OptionIcon }) => /* @__PURE__ */ jsxs(DropdownMenuRadioItem, {
350
+ value: optionValue,
351
+ closeOnClick: true,
352
+ children: [/* @__PURE__ */ jsx(OptionIcon, {}), label]
353
+ }, optionValue))
354
+ })
355
+ })] });
735
356
  }
736
- export {
737
- RichTextEditor
357
+ const EMPTY_STATE = {
358
+ block: "paragraph",
359
+ align: "left",
360
+ color: "",
361
+ linkHref: "",
362
+ isBold: false,
363
+ isItalic: false,
364
+ isUnderline: false,
365
+ isBulletList: false,
366
+ isOrderedList: false,
367
+ isBlockquote: false,
368
+ isCodeBlock: false,
369
+ isLink: false,
370
+ canUndo: false,
371
+ canRedo: false
738
372
  };
739
- //# sourceMappingURL=rich-text-editor.js.map
373
+ const RichTextEditor = React.forwardRef(function RichTextEditor({ value, defaultValue, onChange, size, placeholder = "Start writing, or paste your content here. Format text and add lists, links, and images using the toolbar above.", disabled = false, className, id, "aria-label": ariaLabel = "Rich text editor", "aria-invalid": ariaInvalid }, ref) {
374
+ const resolvedSize = useComponentSize(size);
375
+ const tokens = SIZES[resolvedSize];
376
+ const [focused, setFocused] = React.useState(false);
377
+ const invalid = ariaInvalid !== void 0 && ariaInvalid !== false && ariaInvalid !== "false";
378
+ const editor = useEditor({
379
+ immediatelyRender: false,
380
+ editable: !disabled,
381
+ content: value ?? defaultValue ?? "",
382
+ extensions: [
383
+ StarterKit.configure({ link: {
384
+ openOnClick: false,
385
+ HTMLAttributes: { rel: "noopener noreferrer nofollow" }
386
+ } }),
387
+ TextStyle,
388
+ Color,
389
+ TextAlign.configure({ types: ["heading", "paragraph"] }),
390
+ Image.configure({
391
+ inline: false,
392
+ allowBase64: true
393
+ }),
394
+ Placeholder.configure({ placeholder })
395
+ ],
396
+ editorProps: { attributes: {
397
+ "aria-label": ariaLabel,
398
+ role: "textbox",
399
+ "aria-multiline": "true",
400
+ class: cn("tiptap focus:outline-none", tokens.text)
401
+ } },
402
+ onFocus: () => setFocused(true),
403
+ onBlur: () => setFocused(false),
404
+ onUpdate: ({ editor: instance }) => onChange?.(instance.getHTML())
405
+ });
406
+ React.useImperativeHandle(ref, () => ({
407
+ focus: () => {
408
+ editor?.commands.focus();
409
+ },
410
+ blur: () => {
411
+ editor?.commands.blur();
412
+ }
413
+ }), [editor]);
414
+ React.useEffect(() => {
415
+ editor?.setEditable(!disabled);
416
+ }, [editor, disabled]);
417
+ React.useEffect(() => {
418
+ const dom = editor?.view.dom;
419
+ if (!dom) return;
420
+ if (invalid) dom.setAttribute("aria-invalid", "true");
421
+ else dom.removeAttribute("aria-invalid");
422
+ }, [editor, invalid]);
423
+ React.useEffect(() => {
424
+ if (!editor || !id || disabled) return;
425
+ const selector = `label[for="${CSS.escape(id)}"]`;
426
+ const handleLabelClick = (event) => {
427
+ if (event.target?.closest(selector)) editor.commands.focus();
428
+ };
429
+ document.addEventListener("click", handleLabelClick);
430
+ return () => document.removeEventListener("click", handleLabelClick);
431
+ }, [
432
+ editor,
433
+ id,
434
+ disabled
435
+ ]);
436
+ React.useEffect(() => {
437
+ if (!editor || value === void 0) return;
438
+ if (value !== editor.getHTML()) editor.commands.setContent(value, { emitUpdate: false });
439
+ }, [editor, value]);
440
+ const s = useEditorState({
441
+ editor,
442
+ selector: ({ editor: instance }) => {
443
+ if (!instance) return EMPTY_STATE;
444
+ return {
445
+ block: instance.isActive("heading", { level: 1 }) ? "h1" : instance.isActive("heading", { level: 2 }) ? "h2" : instance.isActive("heading", { level: 3 }) ? "h3" : "paragraph",
446
+ align: instance.isActive({ textAlign: "center" }) ? "center" : instance.isActive({ textAlign: "right" }) ? "right" : instance.isActive({ textAlign: "justify" }) ? "justify" : "left",
447
+ color: instance.getAttributes("textStyle").color ?? "",
448
+ linkHref: instance.getAttributes("link").href ?? "",
449
+ isBold: instance.isActive("bold"),
450
+ isItalic: instance.isActive("italic"),
451
+ isUnderline: instance.isActive("underline"),
452
+ isBulletList: instance.isActive("bulletList"),
453
+ isOrderedList: instance.isActive("orderedList"),
454
+ isBlockquote: instance.isActive("blockquote"),
455
+ isCodeBlock: instance.isActive("codeBlock"),
456
+ isLink: instance.isActive("link"),
457
+ canUndo: instance.can().undo(),
458
+ canRedo: instance.can().redo()
459
+ };
460
+ }
461
+ }) ?? EMPTY_STATE;
462
+ function setBlock(next) {
463
+ if (!editor) return;
464
+ const chain = editor.chain().focus();
465
+ if (next === "paragraph") chain.setParagraph().run();
466
+ else chain.toggleHeading({ level: Number(next[1]) }).run();
467
+ }
468
+ function setAlign(next) {
469
+ editor?.chain().focus().setTextAlign(next).run();
470
+ }
471
+ function setColor(next) {
472
+ if (!editor) return;
473
+ if (next) editor.chain().focus().setColor(next).run();
474
+ else editor.chain().focus().unsetColor().run();
475
+ }
476
+ function applyLink(href) {
477
+ editor?.chain().focus().extendMarkRange("link").setLink({ href }).run();
478
+ }
479
+ function removeLink() {
480
+ editor?.chain().focus().extendMarkRange("link").unsetLink().run();
481
+ }
482
+ function insertImage(src) {
483
+ editor?.chain().focus().setImage({ src }).run();
484
+ }
485
+ return /* @__PURE__ */ jsxs("div", {
486
+ id,
487
+ "data-slot": "rich-text-editor",
488
+ "data-disabled": disabled || void 0,
489
+ "data-focused": focused || void 0,
490
+ "data-invalid": invalid || void 0,
491
+ "aria-invalid": invalid || void 0,
492
+ className: cn("group/editor flex w-full flex-col overflow-hidden rounded-2xl border bg-surface text-fg-primary shadow-1 transition-[border-color,box-shadow]", disabled ? "border-line-subtle opacity-60" : invalid ? focused ? "border-line-danger ring-2 ring-line-danger/35" : "border-line-danger" : focused ? "border-line-focus ring-2 ring-line-focus/35" : "border-line hover:border-line-strong", className),
493
+ children: [
494
+ /* @__PURE__ */ jsxs("div", {
495
+ role: "toolbar",
496
+ "aria-label": "Formatting",
497
+ "aria-orientation": "horizontal",
498
+ className: cn("flex flex-wrap items-center bg-surface-raised", tokens.toolbarPad, tokens.toolbarGap),
499
+ children: [
500
+ /* @__PURE__ */ jsx(BlockControl, {
501
+ tokens,
502
+ value: s.block,
503
+ disabled,
504
+ onChange: setBlock
505
+ }),
506
+ /* @__PURE__ */ jsx(ToolbarButton, {
507
+ tokens,
508
+ label: "Bold",
509
+ active: s.isBold,
510
+ disabled,
511
+ onClick: () => editor?.chain().focus().toggleBold().run(),
512
+ children: /* @__PURE__ */ jsx(Bold, {})
513
+ }),
514
+ /* @__PURE__ */ jsx(ToolbarButton, {
515
+ tokens,
516
+ label: "Italic",
517
+ active: s.isItalic,
518
+ disabled,
519
+ onClick: () => editor?.chain().focus().toggleItalic().run(),
520
+ children: /* @__PURE__ */ jsx(Italic, {})
521
+ }),
522
+ /* @__PURE__ */ jsx(ToolbarButton, {
523
+ tokens,
524
+ label: "Underline",
525
+ active: s.isUnderline,
526
+ disabled,
527
+ onClick: () => editor?.chain().focus().toggleUnderline().run(),
528
+ children: /* @__PURE__ */ jsx(Underline, {})
529
+ }),
530
+ /* @__PURE__ */ jsx(ColorControl, {
531
+ tokens,
532
+ value: s.color,
533
+ disabled,
534
+ onChange: setColor
535
+ }),
536
+ /* @__PURE__ */ jsx(ToolbarDivider, { tokens }),
537
+ /* @__PURE__ */ jsx(ToolbarButton, {
538
+ tokens,
539
+ label: "Numbered list",
540
+ active: s.isOrderedList,
541
+ disabled,
542
+ onClick: () => editor?.chain().focus().toggleOrderedList().run(),
543
+ children: /* @__PURE__ */ jsx(ListOrdered, {})
544
+ }),
545
+ /* @__PURE__ */ jsx(ToolbarButton, {
546
+ tokens,
547
+ label: "Bullet list",
548
+ active: s.isBulletList,
549
+ disabled,
550
+ onClick: () => editor?.chain().focus().toggleBulletList().run(),
551
+ children: /* @__PURE__ */ jsx(List, {})
552
+ }),
553
+ /* @__PURE__ */ jsx(AlignControl, {
554
+ tokens,
555
+ value: s.align,
556
+ disabled,
557
+ onChange: setAlign
558
+ }),
559
+ /* @__PURE__ */ jsx(ToolbarDivider, { tokens }),
560
+ /* @__PURE__ */ jsx(LinkControl, {
561
+ tokens,
562
+ active: s.isLink,
563
+ currentHref: s.linkHref,
564
+ disabled,
565
+ onApply: applyLink,
566
+ onRemove: removeLink
567
+ }),
568
+ /* @__PURE__ */ jsx(ToolbarButton, {
569
+ tokens,
570
+ label: "Quote",
571
+ active: s.isBlockquote,
572
+ disabled,
573
+ onClick: () => editor?.chain().focus().toggleBlockquote().run(),
574
+ children: /* @__PURE__ */ jsx(Quote, {})
575
+ }),
576
+ /* @__PURE__ */ jsx(ToolbarButton, {
577
+ tokens,
578
+ label: "Code block",
579
+ active: s.isCodeBlock,
580
+ disabled,
581
+ onClick: () => editor?.chain().focus().toggleCodeBlock().run(),
582
+ children: /* @__PURE__ */ jsx(Code2, {})
583
+ }),
584
+ /* @__PURE__ */ jsx(ImageControl, {
585
+ tokens,
586
+ disabled,
587
+ onInsert: insertImage
588
+ }),
589
+ /* @__PURE__ */ jsx(ToolbarDivider, { tokens }),
590
+ /* @__PURE__ */ jsx(ToolbarButton, {
591
+ tokens,
592
+ label: "Undo",
593
+ disabled: disabled || !s.canUndo,
594
+ onClick: () => editor?.chain().focus().undo().run(),
595
+ children: /* @__PURE__ */ jsx(Undo2, {})
596
+ }),
597
+ /* @__PURE__ */ jsx(ToolbarButton, {
598
+ tokens,
599
+ label: "Redo",
600
+ disabled: disabled || !s.canRedo,
601
+ onClick: () => editor?.chain().focus().redo().run(),
602
+ children: /* @__PURE__ */ jsx(Redo2, {})
603
+ })
604
+ ]
605
+ }),
606
+ /* @__PURE__ */ jsx("div", { className: "h-px w-full shrink-0 bg-line-subtle" }),
607
+ /* @__PURE__ */ jsx(EditorContent, {
608
+ editor,
609
+ className: cn("gdt-rich-text min-w-0 flex-1 overflow-y-auto", tokens.content, tokens.contentPad)
610
+ })
611
+ ]
612
+ });
613
+ });
614
+ //#endregion
615
+ export { RichTextEditor };