xertica-ui 2.1.2 → 2.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (402) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +1 -1
  3. package/assets/xertica-logo.svg +37 -37
  4. package/assets/xertica-x-logo.svg +20 -20
  5. package/bin/cli.ts +1 -1
  6. package/bin/generate-tokens.ts +13 -7
  7. package/components/assistant/index.ts +6 -6
  8. package/components/assistant/xertica-assistant/index.ts +2 -0
  9. package/components/assistant/xertica-assistant/use-assistant.ts +564 -0
  10. package/components/assistant/xertica-assistant/xertica-assistant.stories.tsx +200 -0
  11. package/components/assistant/xertica-assistant/xertica-assistant.tsx +183 -474
  12. package/components/blocks/card-patterns/ActivityCard.tsx +72 -72
  13. package/components/blocks/card-patterns/FeatureCard.tsx +100 -100
  14. package/components/blocks/card-patterns/NotificationCard.tsx +127 -127
  15. package/components/blocks/card-patterns/ProfileCard.tsx +84 -84
  16. package/components/blocks/card-patterns/ProjectCard.tsx +89 -89
  17. package/components/blocks/card-patterns/QuickActionCard.tsx +62 -62
  18. package/components/blocks/card-patterns/card-patterns.stories.tsx +445 -445
  19. package/components/blocks/card-patterns/index.ts +17 -17
  20. package/components/blocks/index.ts +1 -1
  21. package/components/brand/index.ts +6 -6
  22. package/components/brand/xertica-provider/XerticaProvider.tsx +48 -48
  23. package/components/brand/xertica-provider/xertica-provider.mdx +61 -61
  24. package/components/brand/xertica-provider/xertica-provider.test.tsx +52 -52
  25. package/components/examples/MapExamples.tsx +282 -282
  26. package/components/examples/SimpleFilterableMap.tsx +191 -191
  27. package/components/examples/index.ts +51 -51
  28. package/components/figma/ImageWithFallback.tsx +27 -27
  29. package/components/hooks/index.ts +7 -7
  30. package/components/index.ts +5 -5
  31. package/components/layout/header/header.test.tsx +8 -8
  32. package/components/layout/header/header.tsx +4 -4
  33. package/components/layout/index.ts +2 -2
  34. package/components/layout/sidebar/index.ts +2 -0
  35. package/components/layout/sidebar/sidebar.mdx +1 -1
  36. package/components/layout/sidebar/sidebar.stories.tsx +160 -8
  37. package/components/layout/sidebar/sidebar.test.tsx +11 -11
  38. package/components/layout/sidebar/sidebar.tsx +610 -471
  39. package/components/layout/sidebar/use-sidebar.ts +113 -0
  40. package/components/media/FloatingMediaWrapper.tsx +11 -11
  41. package/components/media/audio-player/AudioPlayer.tsx +22 -22
  42. package/components/media/index.ts +3 -3
  43. package/components/pages/home-content/HomeContent.tsx +7 -7
  44. package/components/pages/home-content/home-content.mdx +62 -62
  45. package/components/pages/home-page/HomePage.stories.tsx +39 -39
  46. package/components/pages/home-page/HomePage.tsx +1 -1
  47. package/components/pages/home-page/home-page.mdx +53 -53
  48. package/components/pages/index.ts +8 -8
  49. package/components/pages/template-content/TemplateContent.tsx +5 -5
  50. package/components/pages/template-content/template-content.mdx +61 -61
  51. package/components/pages/template-page/TemplatePage.stories.tsx +39 -39
  52. package/components/pages/template-page/TemplatePage.tsx +5 -5
  53. package/components/pages/template-page/template-page.mdx +53 -53
  54. package/components/public-api-smoke.test.tsx +52 -52
  55. package/components/shared/assistant-utils.ts +43 -43
  56. package/components/shared/layout-constants.ts +1 -1
  57. package/components/ui/accordion/accordion.mdx +8 -8
  58. package/components/ui/accordion/accordion.stories.tsx +53 -53
  59. package/components/ui/alert/alert.mdx +8 -8
  60. package/components/ui/alert-dialog/alert-dialog.mdx +8 -8
  61. package/components/ui/aspect-ratio/aspect-ratio.mdx +8 -8
  62. package/components/ui/assistant-chart/assistant-chart.mdx +8 -8
  63. package/components/ui/avatar/avatar.mdx +8 -8
  64. package/components/ui/badge/badge.mdx +8 -8
  65. package/components/ui/badge/badge.tsx +9 -9
  66. package/components/ui/breadcrumb/breadcrumb.mdx +8 -8
  67. package/components/ui/button/button.mdx +8 -8
  68. package/components/ui/calendar/calendar.mdx +8 -8
  69. package/components/ui/calendar/calendar.tsx +258 -258
  70. package/components/ui/card/card.mdx +8 -8
  71. package/components/ui/card/card.stories.tsx +245 -245
  72. package/components/ui/carousel/carousel.mdx +8 -8
  73. package/components/ui/chart/chart.mdx +8 -8
  74. package/components/ui/chart/chart.stories.tsx +1303 -344
  75. package/components/ui/chart/chart.test.tsx +154 -154
  76. package/components/ui/chart/chart.tsx +2367 -1494
  77. package/components/ui/checkbox/checkbox.mdx +8 -8
  78. package/components/ui/checkbox/checkbox.stories.tsx +20 -20
  79. package/components/ui/collapsible/collapsible.mdx +8 -8
  80. package/components/ui/command/command.mdx +8 -8
  81. package/components/ui/context-menu/context-menu.mdx +8 -8
  82. package/components/ui/dialog/dialog.mdx +8 -8
  83. package/components/ui/drawer/drawer.mdx +8 -8
  84. package/components/ui/dropdown-menu/dropdown-menu.mdx +8 -8
  85. package/components/ui/empty/empty.mdx +8 -8
  86. package/components/ui/file-upload/file-upload.mdx +8 -8
  87. package/components/ui/file-upload/file-upload.stories.tsx +100 -0
  88. package/components/ui/file-upload/file-upload.tsx +14 -74
  89. package/components/ui/file-upload/index.ts +1 -0
  90. package/components/ui/file-upload/use-file-upload.ts +181 -0
  91. package/components/ui/google-maps-loader/google-maps-loader.tsx +2 -2
  92. package/components/ui/hover-card/hover-card.mdx +8 -8
  93. package/components/ui/input/input.mdx +8 -8
  94. package/components/ui/input-otp/input-otp.mdx +8 -8
  95. package/components/ui/input-otp/input-otp.stories.tsx +6 -6
  96. package/components/ui/label/label.mdx +8 -8
  97. package/components/ui/map/map.mdx +8 -8
  98. package/components/ui/map/map.stories.tsx +51 -51
  99. package/components/ui/map/map.tsx +2 -2
  100. package/components/ui/menubar/menubar.mdx +8 -8
  101. package/components/ui/navigation-menu/navigation-menu.mdx +8 -8
  102. package/components/ui/notification-badge/notification-badge.mdx +8 -8
  103. package/components/ui/pagination/index.ts +2 -0
  104. package/components/ui/pagination/pagination.mdx +8 -8
  105. package/components/ui/pagination/pagination.stories.tsx +94 -0
  106. package/components/ui/pagination/use-pagination.ts +194 -0
  107. package/components/ui/popover/popover.mdx +8 -8
  108. package/components/ui/progress/progress.mdx +8 -8
  109. package/components/ui/progress/progress.tsx +68 -68
  110. package/components/ui/radio-group/radio-group.mdx +8 -8
  111. package/components/ui/rating/rating.mdx +8 -8
  112. package/components/ui/resizable/resizable.mdx +8 -8
  113. package/components/ui/rich-text-editor/index.ts +2 -0
  114. package/components/ui/rich-text-editor/rich-text-editor.stories.tsx +129 -1
  115. package/components/ui/rich-text-editor/rich-text-editor.tsx +86 -305
  116. package/components/ui/rich-text-editor/use-rich-text-editor.ts +439 -0
  117. package/components/ui/route-map/route-map.mdx +8 -8
  118. package/components/ui/route-map/route-map.stories.tsx +54 -54
  119. package/components/ui/route-map/route-map.tsx +2 -2
  120. package/components/ui/scroll-area/scroll-area.mdx +8 -8
  121. package/components/ui/search/search.mdx +8 -8
  122. package/components/ui/select/select.mdx +8 -8
  123. package/components/ui/select/select.stories.tsx +9 -9
  124. package/components/ui/separator/separator.mdx +8 -8
  125. package/components/ui/sheet/sheet.mdx +8 -8
  126. package/components/ui/sheet/sheet.stories.tsx +95 -95
  127. package/components/ui/simple-map/simple-map.mdx +8 -8
  128. package/components/ui/simple-map/simple-map.stories.tsx +48 -48
  129. package/components/ui/skeleton/skeleton.mdx +8 -8
  130. package/components/ui/slider/slider.mdx +8 -8
  131. package/components/ui/sonner/sonner.mdx +8 -8
  132. package/components/ui/stats-card/stats-card.mdx +8 -8
  133. package/components/ui/stepper/index.ts +3 -1
  134. package/components/ui/stepper/stepper.mdx +8 -8
  135. package/components/ui/stepper/stepper.stories.tsx +116 -0
  136. package/components/ui/stepper/stepper.tsx +4 -4
  137. package/components/ui/stepper/use-stepper.ts +137 -0
  138. package/components/ui/switch/switch.mdx +8 -8
  139. package/components/ui/switch/switch.stories.tsx +20 -20
  140. package/components/ui/table/table.mdx +8 -8
  141. package/components/ui/tabs/tabs.mdx +8 -8
  142. package/components/ui/tabs/tabs.stories.tsx +26 -26
  143. package/components/ui/textarea/textarea.mdx +8 -8
  144. package/components/ui/timeline/timeline.mdx +8 -8
  145. package/components/ui/toggle/toggle.mdx +8 -8
  146. package/components/ui/toggle-group/toggle-group.mdx +8 -8
  147. package/components/ui/tooltip/tooltip.mdx +8 -8
  148. package/components/ui/tree-view/index.ts +4 -1
  149. package/components/ui/tree-view/tree-view.mdx +8 -8
  150. package/components/ui/tree-view/tree-view.stories.tsx +110 -4
  151. package/components/ui/tree-view/tree-view.tsx +17 -125
  152. package/components/ui/tree-view/use-tree-view.ts +229 -0
  153. package/components.json +1512 -1512
  154. package/contexts/ApiKeyContext.tsx +72 -72
  155. package/contexts/BrandColorsContext.tsx +26 -26
  156. package/contexts/LanguageContext.tsx +13 -13
  157. package/contexts/LayoutContext.test.tsx +11 -11
  158. package/contexts/LayoutContext.tsx +29 -29
  159. package/contexts/ThemeContext.tsx +26 -26
  160. package/contexts/theme-data.ts +4 -4
  161. package/dist/{AssistantChart-CVzmmhx4.js → AssistantChart-C_hwFRRr.js} +4 -4
  162. package/dist/{AssistantChart-BAx9VQvb.cjs → AssistantChart-CldVCVDe.cjs} +311 -94
  163. package/dist/{AssistantChart-CVko2A1W.js → AssistantChart-Cu3m7RBo.js} +314 -97
  164. package/dist/{AssistantChart-9w31gdAb.cjs → AssistantChart-DoZCyS5r.cjs} +4 -4
  165. package/dist/AudioPlayer-B1lt5cPl.cjs +989 -0
  166. package/dist/AudioPlayer-BZ7bibzU.cjs +982 -0
  167. package/dist/AudioPlayer-C12BjQBV.cjs +997 -0
  168. package/dist/AudioPlayer-DMcG_c7L.js +990 -0
  169. package/dist/AudioPlayer-DcFKRJE_.js +998 -0
  170. package/dist/AudioPlayer-e8LfNoqO.js +983 -0
  171. package/dist/{xertica-assistant-Qp3ydksa.cjs → CodeBlock-7TTgmdGG.cjs} +263 -51
  172. package/dist/{xertica-assistant-gnCJdcZY.js → CodeBlock-BeSt1h5P.js} +219 -7
  173. package/dist/CodeBlock-BgfYL_rD.cjs +2094 -0
  174. package/dist/CodeBlock-BlcqlA9M.cjs +2094 -0
  175. package/dist/CodeBlock-Bnmeu5ez.cjs +2094 -0
  176. package/dist/CodeBlock-BtfPlbAI.js +2078 -0
  177. package/dist/CodeBlock-CIySIuYr.js +2078 -0
  178. package/dist/CodeBlock-CuPtUM-7.cjs +2094 -0
  179. package/dist/CodeBlock-D6ffWXgc.js +2078 -0
  180. package/dist/CodeBlock-D8dcwbit.cjs +2094 -0
  181. package/dist/CodeBlock-DMZrFnlw.cjs +2094 -0
  182. package/dist/CodeBlock-DlBehYN8.js +2078 -0
  183. package/dist/CodeBlock-DnYNI8rQ.js +2078 -0
  184. package/dist/CodeBlock-DvKWbSnE.cjs +2094 -0
  185. package/dist/CodeBlock-DwMCfkFY.js +2078 -0
  186. package/dist/CodeBlock-Dy6CNYyj.js +2078 -0
  187. package/dist/CodeBlock-U1pPOQI7.cjs +2094 -0
  188. package/dist/CodeBlock-f_GpNhEB.js +2078 -0
  189. package/dist/CodeBlock-oB6u8nI1.js +2078 -0
  190. package/dist/CodeBlock-tZC31B73.cjs +2094 -0
  191. package/dist/ImageWithFallback-CGtidP6B.cjs +4542 -0
  192. package/dist/ImageWithFallback-lsg3pdFg.js +4508 -0
  193. package/dist/LanguageSelector-B5YfbHra.js +231 -0
  194. package/dist/LanguageSelector-D6uacAIM.cjs +230 -0
  195. package/dist/LayoutContext-BAql6ZRY.js +97 -0
  196. package/dist/LayoutContext-BvK-ggDa.cjs +96 -0
  197. package/dist/ThemeContext-BoH4NLfN.js +734 -0
  198. package/dist/{ThemeContext-BbBNoFTG.js → ThemeContext-C2EwAPDt.js} +2 -2
  199. package/dist/ThemeContext-r69W20Xg.cjs +733 -0
  200. package/dist/{ThemeContext-Cmr8Ex8H.cjs → ThemeContext-vTjumZeM.cjs} +2 -2
  201. package/dist/{VerifyEmailPage-BE-L9mB7.js → VerifyEmailPage-C0c2e5n0.js} +7 -7
  202. package/dist/{VerifyEmailPage-DMBh4NM9.cjs → VerifyEmailPage-CYXtbKi3.cjs} +1 -1
  203. package/dist/{VerifyEmailPage-CR7kb5df.cjs → VerifyEmailPage-Cwi3kbol.cjs} +7 -7
  204. package/dist/{VerifyEmailPage-CdYPSJoO.js → VerifyEmailPage-DvMLZgFt.js} +1 -1
  205. package/dist/XerticaOrbe-KL1RBHzw.cjs +1354 -0
  206. package/dist/XerticaOrbe-zwS1p2a8.js +1355 -0
  207. package/dist/XerticaProvider-6btlAlzc.js +17 -0
  208. package/dist/XerticaProvider-BNoNOxQ5.cjs +16 -0
  209. package/dist/XerticaProvider-BlY2limY.cjs +38 -0
  210. package/dist/{XerticaProvider-BITjgC5p.js → XerticaProvider-CEoWMTxu.js} +2 -2
  211. package/dist/{XerticaProvider-By8q3Roe.cjs → XerticaProvider-CllrbMEJ.cjs} +2 -2
  212. package/dist/XerticaProvider-DDuiIcKo.js +39 -0
  213. package/dist/XerticaProvider-cI9hSs27.cjs +38 -0
  214. package/dist/XerticaProvider-hSwhNQex.js +39 -0
  215. package/dist/{alert-dialog-yckpaOpy.cjs → alert-dialog-DSKByiKZ.cjs} +3 -3
  216. package/dist/{alert-dialog-iDe5VE5o.js → alert-dialog-s-vmNkJ_.js} +3 -3
  217. package/dist/assistant.cjs.js +2 -1
  218. package/dist/assistant.es.js +3 -2
  219. package/dist/brand.cjs.js +1 -1
  220. package/dist/brand.es.js +1 -1
  221. package/dist/breadcrumb-CqJ7bHY5.js +161 -0
  222. package/dist/breadcrumb-m9Hb2_XN.cjs +177 -0
  223. package/dist/cli.js +14 -8
  224. package/dist/components/assistant/xertica-assistant/index.d.ts +2 -0
  225. package/dist/components/assistant/xertica-assistant/use-assistant.d.ts +126 -0
  226. package/dist/components/assistant/xertica-assistant/xertica-assistant.d.ts +7 -2
  227. package/dist/components/blocks/audio-player/AudioPlayer.d.ts +35 -0
  228. package/dist/components/blocks/audio-player/index.d.ts +1 -0
  229. package/dist/components/blocks/document-editor/DocumentEditor.d.ts +26 -0
  230. package/dist/components/blocks/document-editor/index.d.ts +1 -0
  231. package/dist/components/blocks/podcast-player/PodcastPlayer.d.ts +41 -0
  232. package/dist/components/blocks/podcast-player/index.d.ts +1 -0
  233. package/dist/components/layout/sidebar/index.d.ts +2 -0
  234. package/dist/components/layout/sidebar/sidebar.d.ts +80 -0
  235. package/dist/components/layout/sidebar/use-sidebar.d.ts +22 -0
  236. package/dist/components/shared/layout-constants.d.ts +1 -1
  237. package/dist/components/ui/button/button.d.ts +1 -1
  238. package/dist/components/ui/chart/chart.d.ts +162 -5
  239. package/dist/components/ui/file-upload/file-upload.d.ts +2 -0
  240. package/dist/components/ui/file-upload/index.d.ts +1 -0
  241. package/dist/components/ui/file-upload/use-file-upload.d.ts +49 -0
  242. package/dist/components/ui/pagination/index.d.ts +2 -0
  243. package/dist/components/ui/pagination/use-pagination.d.ts +78 -0
  244. package/dist/components/ui/rich-text-editor/index.d.ts +2 -0
  245. package/dist/components/ui/rich-text-editor/use-rich-text-editor.d.ts +107 -0
  246. package/dist/components/ui/stepper/index.d.ts +3 -1
  247. package/dist/components/ui/stepper/stepper.d.ts +2 -2
  248. package/dist/components/ui/stepper/use-stepper.d.ts +60 -0
  249. package/dist/components/ui/tree-view/index.d.ts +4 -1
  250. package/dist/components/ui/tree-view/tree-view.d.ts +4 -6
  251. package/dist/components/ui/tree-view/use-tree-view.d.ts +60 -0
  252. package/dist/dropdown-menu-BDB5CmQs.cjs +247 -0
  253. package/dist/dropdown-menu-DQidbKBD.js +231 -0
  254. package/dist/google-maps-loader-BFWp6VPd.js +287 -0
  255. package/dist/{google-maps-loader-t2IlYBzw.js → google-maps-loader-CTYySAun.js} +4 -0
  256. package/dist/{google-maps-loader-BqsYL48U.cjs → google-maps-loader-Y-QkD-Li.cjs} +5 -0
  257. package/dist/google-maps-loader-eS3uQ5TA.cjs +287 -0
  258. package/dist/header-Cgy6vYPk.cjs +731 -0
  259. package/dist/header-DRlT4jgI.js +715 -0
  260. package/dist/header-Dux00SI4.cjs +731 -0
  261. package/dist/header-EkGKXPsD.js +715 -0
  262. package/dist/header-WfEywpyc.cjs +731 -0
  263. package/dist/header-tifNQn2U.js +715 -0
  264. package/dist/hooks.cjs.js +1 -1
  265. package/dist/hooks.es.js +1 -1
  266. package/dist/index-BhapVLVj.js +8 -0
  267. package/dist/{index-D3RLKRAs.cjs → index-COtD8bRW.cjs} +1 -1
  268. package/dist/index-D6fxYEY8.cjs +7 -0
  269. package/dist/index-DW5tYe26.js +8 -0
  270. package/dist/index.cjs.js +19 -8
  271. package/dist/index.es.js +39 -28
  272. package/dist/index.umd.js +1043 -470
  273. package/dist/input-2R4loU86.js +127 -0
  274. package/dist/input-DWANSKGb.cjs +145 -0
  275. package/dist/layout.cjs.js +89 -1
  276. package/dist/layout.es.js +90 -2
  277. package/dist/pages.cjs.js +1 -1
  278. package/dist/pages.es.js +1 -1
  279. package/dist/rich-text-editor-0mraWT5y.cjs +2376 -0
  280. package/dist/rich-text-editor-B6jMRLzk.cjs +1939 -0
  281. package/dist/rich-text-editor-B8_oYcIR.js +1730 -0
  282. package/dist/rich-text-editor-B9UbSXNb.js +1203 -0
  283. package/dist/rich-text-editor-BYuRBNBU.js +2373 -0
  284. package/dist/rich-text-editor-Bb9pySTs.cjs +2374 -0
  285. package/dist/rich-text-editor-BcL6L3cm.cjs +2374 -0
  286. package/dist/rich-text-editor-BoVZYtTs.cjs +2391 -0
  287. package/dist/rich-text-editor-CPV1lEPH.cjs +1748 -0
  288. package/dist/rich-text-editor-CoKqbCtu.cjs +1799 -0
  289. package/dist/rich-text-editor-Cw56T_mB.js +2356 -0
  290. package/dist/rich-text-editor-Cyt8qs2b.js +1921 -0
  291. package/dist/rich-text-editor-D6H84OcX.cjs +1220 -0
  292. package/dist/rich-text-editor-D76gD-QI.js +2328 -0
  293. package/dist/rich-text-editor-DKkokOnA.js +1781 -0
  294. package/dist/rich-text-editor-DNsdpN64.cjs +2359 -0
  295. package/dist/rich-text-editor-DfG8bCyY.js +2358 -0
  296. package/dist/rich-text-editor-DgF8s7xW.js +2949 -0
  297. package/dist/rich-text-editor-Dxjw31Z4.js +2341 -0
  298. package/dist/rich-text-editor-DzP0Epmb.js +2356 -0
  299. package/dist/rich-text-editor-mWoaSCE4.cjs +2966 -0
  300. package/dist/rich-text-editor-skplNlBM.cjs +2345 -0
  301. package/dist/select-Bkbr0f-Z.cjs +162 -0
  302. package/dist/select-CvIVdX2n.js +145 -0
  303. package/dist/sidebar-CK_0ZQHj.cjs +803 -0
  304. package/dist/sidebar-CUuOvYhK.js +787 -0
  305. package/dist/slider-Bc5Hd0y1.js +56 -0
  306. package/dist/slider-N7hFFj6X.cjs +73 -0
  307. package/dist/tooltip-Ded96neP.cjs +137 -0
  308. package/dist/tooltip-HDOoD2-0.js +120 -0
  309. package/dist/ui.cjs.js +14 -4
  310. package/dist/ui.es.js +26 -16
  311. package/dist/use-mobile-B0hNy_Y6.cjs +4303 -0
  312. package/dist/use-mobile-BXuYROXM.js +4202 -0
  313. package/dist/use-mobile-Bbd51ASU.cjs +4392 -0
  314. package/dist/use-mobile-Bk6CX-TC.js +4359 -0
  315. package/dist/use-mobile-BvYdisLP.js +4202 -0
  316. package/dist/use-mobile-BzuxjzNX.cjs +4392 -0
  317. package/dist/use-mobile-CG2-SdXV.cjs +4235 -0
  318. package/dist/use-mobile-CKb5pqTs.js +4269 -0
  319. package/dist/use-mobile-CYuAuGDl.js +4202 -0
  320. package/dist/use-mobile-CaENcqm-.js +4508 -0
  321. package/dist/use-mobile-CbrYgJGJ.js +4203 -0
  322. package/dist/use-mobile-DMOvImGQ.cjs +4542 -0
  323. package/dist/use-mobile-DRB3BQgD.cjs +4235 -0
  324. package/dist/use-mobile-DZvv7QMR.js +4359 -0
  325. package/dist/use-mobile-DdI_TXam.cjs +4235 -0
  326. package/dist/use-mobile-DlceKf8a.js +4359 -0
  327. package/dist/use-mobile-DsOnow1o.cjs +4236 -0
  328. package/dist/use-mobile-Kcj6jSnK.cjs +4392 -0
  329. package/dist/use-mobile-bnKcua_i.js +4202 -0
  330. package/dist/use-mobile-ncXBeE2z.cjs +4235 -0
  331. package/dist/{xertica-assistant-B1IaHXnB.cjs → xertica-assistant-dyP7KHM5.cjs} +533 -392
  332. package/dist/{xertica-assistant-DPsESB6t.js → xertica-assistant-yX1CFBBo.js} +535 -394
  333. package/dist/xertica-ui.css +2 -2
  334. package/docs/ai-usage.md +28 -10
  335. package/docs/architecture.md +76 -0
  336. package/docs/components/assistant.md +159 -0
  337. package/docs/components/calendar.md +154 -154
  338. package/docs/components/card-patterns.md +337 -337
  339. package/docs/components/card.md +235 -235
  340. package/docs/components/chart.md +354 -39
  341. package/docs/components/file-upload.md +119 -2
  342. package/docs/components/map.md +84 -84
  343. package/docs/components/pagination.md +187 -0
  344. package/docs/components/rich-text-editor.md +164 -0
  345. package/docs/components/sidebar.md +153 -4
  346. package/docs/components/stepper.md +157 -12
  347. package/docs/components/tree-view.md +164 -6
  348. package/docs/components/xertica-provider.md +24 -24
  349. package/docs/decision-tree.md +287 -287
  350. package/docs/getting-started.md +1 -1
  351. package/docs/guidelines.md +14 -8
  352. package/docs/layout.md +2 -2
  353. package/docs/llms.md +4 -4
  354. package/guidelines/Guidelines.md +252 -250
  355. package/hooks/useTheme.ts +3 -3
  356. package/imports/Podcast.tsx +388 -388
  357. package/imports/XerticaAi.tsx +45 -45
  358. package/imports/XerticaX.tsx +19 -19
  359. package/imports/svg-aueiaqngck.ts +11 -11
  360. package/imports/svg-v9krss1ozd.ts +16 -16
  361. package/imports/svg-vhrdofe3qe.ts +5 -5
  362. package/llms-compact.txt +327 -327
  363. package/llms.txt +160 -160
  364. package/package.json +203 -203
  365. package/styles/xertica/app-overrides/chat.css +61 -61
  366. package/styles/xertica/app-overrides/scrollbar.css +33 -33
  367. package/styles/xertica/integrations/google-maps.css +76 -76
  368. package/styles/xertica/integrations/sonner.css +73 -73
  369. package/styles/xertica/tokens.css +41 -12
  370. package/templates/CLAUDE.md +182 -172
  371. package/templates/guidelines/Guidelines.md +325 -313
  372. package/templates/package.json +3 -3
  373. package/templates/src/features/auth/index.ts +4 -4
  374. package/templates/src/features/auth/ui/AuthPageShell.tsx +34 -34
  375. package/templates/src/features/auth/ui/ForgotPasswordContent.tsx +70 -70
  376. package/templates/src/features/auth/ui/LoginContent.tsx +90 -90
  377. package/templates/src/features/auth/ui/ResetPasswordContent.tsx +151 -151
  378. package/templates/src/features/auth/ui/SocialLoginButtons.tsx +59 -59
  379. package/templates/src/features/auth/ui/VerifyEmailContent.tsx +82 -82
  380. package/templates/src/features/home/index.ts +1 -1
  381. package/templates/src/features/home/ui/HomeContent.tsx +100 -100
  382. package/templates/src/features/template/index.ts +5 -5
  383. package/templates/src/features/template/ui/CrudTemplate.tsx +3 -3
  384. package/templates/src/features/template/ui/DashboardTemplate.tsx +3 -3
  385. package/templates/src/features/template/ui/FormTemplate.tsx +120 -120
  386. package/templates/src/features/template/ui/LoginTemplate.tsx +3 -3
  387. package/templates/src/pages/AssistantPage.tsx +328 -328
  388. package/templates/src/pages/ForgotPasswordPage.tsx +6 -6
  389. package/templates/src/pages/HomePage.tsx +57 -57
  390. package/templates/src/pages/LoginPage.tsx +10 -10
  391. package/templates/src/pages/ResetPasswordPage.tsx +6 -6
  392. package/templates/src/pages/TemplatePage.tsx +30 -30
  393. package/templates/src/pages/VerifyEmailPage.tsx +6 -6
  394. package/templates/src/shared/config/navigation.ts +20 -20
  395. package/templates/src/shared/lib/auth.ts +20 -20
  396. package/templates/src/shared/types/auth.ts +3 -3
  397. package/templates/src/styles/xertica/tokens.css +39 -10
  398. package/templates/tsconfig.json +5 -5
  399. package/utils/gemini.ts +140 -140
  400. package/dist/VerifyEmailPage-Bae2cBXT.cjs +0 -2827
  401. package/dist/VerifyEmailPage-CbgjOF0v.js +0 -2828
  402. package/dist/index-CkTUgOwX.js +0 -8
@@ -10,14 +10,14 @@ import * as CheckboxStories from './checkbox.stories';
10
10
 
11
11
  <Primary />
12
12
 
13
- ---
14
-
15
- ## Variations
16
-
17
- <Stories />
18
-
19
- ---
20
-
13
+ ---
14
+
15
+ ## Variations
16
+
17
+ <Stories />
18
+
19
+ ---
20
+
21
21
  ## AI Best Practices
22
22
 
23
23
  > [!IMPORTANT]
@@ -1,5 +1,5 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react';
2
- import { expect, userEvent, within } from 'storybook/test';
2
+ import { expect, userEvent, within } from 'storybook/test';
3
3
  import { Checkbox } from './checkbox';
4
4
  import { Label } from '../label';
5
5
  import React from 'react';
@@ -82,22 +82,22 @@ export const Sizes: Story = {
82
82
  </div>
83
83
  </div>
84
84
  ),
85
- };
86
-
87
- export const Toggle: Story = {
88
- render: () => (
89
- <div className="flex items-center space-x-2">
90
- <Checkbox id="play-check" />
91
- <Label htmlFor="play-check">Accept terms</Label>
92
- </div>
93
- ),
94
- play: async ({ canvasElement }) => {
95
- const canvas = within(canvasElement);
96
- const checkbox = canvas.getByRole('checkbox');
97
- await expect(checkbox).not.toBeChecked();
98
- await userEvent.click(checkbox);
99
- await expect(checkbox).toBeChecked();
100
- await userEvent.click(checkbox);
101
- await expect(checkbox).not.toBeChecked();
102
- },
103
- };
85
+ };
86
+
87
+ export const Toggle: Story = {
88
+ render: () => (
89
+ <div className="flex items-center space-x-2">
90
+ <Checkbox id="play-check" />
91
+ <Label htmlFor="play-check">Accept terms</Label>
92
+ </div>
93
+ ),
94
+ play: async ({ canvasElement }) => {
95
+ const canvas = within(canvasElement);
96
+ const checkbox = canvas.getByRole('checkbox');
97
+ await expect(checkbox).not.toBeChecked();
98
+ await userEvent.click(checkbox);
99
+ await expect(checkbox).toBeChecked();
100
+ await userEvent.click(checkbox);
101
+ await expect(checkbox).not.toBeChecked();
102
+ },
103
+ };
@@ -10,14 +10,14 @@ import * as CollapsibleStories from './collapsible.stories';
10
10
 
11
11
  <Primary />
12
12
 
13
- ---
14
-
15
- ## Variations
16
-
17
- <Stories />
18
-
19
- ---
20
-
13
+ ---
14
+
15
+ ## Variations
16
+
17
+ <Stories />
18
+
19
+ ---
20
+
21
21
  ## AI Best Practices
22
22
 
23
23
  > [!IMPORTANT]
@@ -10,14 +10,14 @@ import * as CommandStories from './command.stories';
10
10
 
11
11
  <Primary />
12
12
 
13
- ---
14
-
15
- ## Variations
16
-
17
- <Stories />
18
-
19
- ---
20
-
13
+ ---
14
+
15
+ ## Variations
16
+
17
+ <Stories />
18
+
19
+ ---
20
+
21
21
  ## AI Best Practices
22
22
 
23
23
  > [!IMPORTANT]
@@ -10,14 +10,14 @@ import * as ContextMenuStories from './context-menu.stories';
10
10
 
11
11
  <Primary />
12
12
 
13
- ---
14
-
15
- ## Variations
16
-
17
- <Stories />
18
-
19
- ---
20
-
13
+ ---
14
+
15
+ ## Variations
16
+
17
+ <Stories />
18
+
19
+ ---
20
+
21
21
  ## AI Best Practices
22
22
 
23
23
  > [!IMPORTANT]
@@ -10,14 +10,14 @@ import * as DialogStories from './dialog.stories';
10
10
 
11
11
  <Primary />
12
12
 
13
- ---
14
-
15
- ## Variations
16
-
17
- <Stories />
18
-
19
- ---
20
-
13
+ ---
14
+
15
+ ## Variations
16
+
17
+ <Stories />
18
+
19
+ ---
20
+
21
21
  ## AI Best Practices
22
22
 
23
23
  > [!IMPORTANT]
@@ -10,14 +10,14 @@ import * as DrawerStories from './drawer.stories';
10
10
 
11
11
  <Primary />
12
12
 
13
- ---
14
-
15
- ## Variations
16
-
17
- <Stories />
18
-
19
- ---
20
-
13
+ ---
14
+
15
+ ## Variations
16
+
17
+ <Stories />
18
+
19
+ ---
20
+
21
21
  ## AI Best Practices
22
22
 
23
23
  > [!IMPORTANT]
@@ -10,14 +10,14 @@ import * as DropdownMenuStories from './dropdown-menu.stories';
10
10
 
11
11
  <Primary />
12
12
 
13
- ---
14
-
15
- ## Variations
16
-
17
- <Stories />
18
-
19
- ---
20
-
13
+ ---
14
+
15
+ ## Variations
16
+
17
+ <Stories />
18
+
19
+ ---
20
+
21
21
  ## AI Best Practices
22
22
 
23
23
  > [!IMPORTANT]
@@ -10,14 +10,14 @@ import * as EmptyStories from './empty.stories';
10
10
 
11
11
  <Primary />
12
12
 
13
- ---
14
-
15
- ## Variations
16
-
17
- <Stories />
18
-
19
- ---
20
-
13
+ ---
14
+
15
+ ## Variations
16
+
17
+ <Stories />
18
+
19
+ ---
20
+
21
21
  ## AI Best Practices
22
22
 
23
23
  > [!IMPORTANT]
@@ -10,14 +10,14 @@ import * as FileUploadStories from './file-upload.stories';
10
10
 
11
11
  <Primary />
12
12
 
13
- ---
14
-
15
- ## Variations
16
-
17
- <Stories />
18
-
19
- ---
20
-
13
+ ---
14
+
15
+ ## Variations
16
+
17
+ <Stories />
18
+
19
+ ---
20
+
21
21
  ## AI Best Practices
22
22
 
23
23
  > [!IMPORTANT]
@@ -1,6 +1,8 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react';
2
2
  import { FileUpload } from './file-upload';
3
+ import { useFileUpload } from './use-file-upload';
3
4
  import React from 'react';
5
+ import { Upload, X, FileIcon, AlertCircle } from 'lucide-react';
4
6
 
5
7
  const meta: Meta<typeof FileUpload> = {
6
8
  title: 'UI/FileUpload',
@@ -51,3 +53,101 @@ export const ImageOnly: Story = {
51
53
  </div>
52
54
  ),
53
55
  };
56
+
57
+ /**
58
+ * ## useFileUpload — Headless Hook
59
+ *
60
+ * Use `useFileUpload` when you need the full drag-and-drop logic but want to
61
+ * render a completely custom drop-zone UI. The hook returns all state and
62
+ * handlers; you wire them to whatever markup you like.
63
+ *
64
+ * ```tsx
65
+ * import { useFileUpload } from '@xertica/ui/file-upload';
66
+ *
67
+ * const {
68
+ * files, dragActive, errorMessage, inputRef,
69
+ * handleDrag, handleDrop, handleChange, removeFile, openFileDialog,
70
+ * } = useFileUpload({ maxFiles: 3, maxSize: 10 * 1024 * 1024 });
71
+ * ```
72
+ */
73
+ export const HeadlessHook: Story = {
74
+ name: 'useFileUpload (headless)',
75
+ render: () => {
76
+ const {
77
+ files,
78
+ dragActive,
79
+ errorMessage,
80
+ inputRef,
81
+ handleDrag,
82
+ handleDrop,
83
+ handleChange,
84
+ removeFile,
85
+ openFileDialog,
86
+ } = useFileUpload({
87
+ maxFiles: 3,
88
+ maxSize: 2 * 1024 * 1024, // 2MB
89
+ onFilesChange: (f) => console.log('files changed', f),
90
+ });
91
+
92
+ return (
93
+ <div className="w-[500px] space-y-3">
94
+ {/* Custom drop-zone — completely different from the default FileUpload UI */}
95
+ <div
96
+ onDragEnter={handleDrag}
97
+ onDragLeave={handleDrag}
98
+ onDragOver={handleDrag}
99
+ onDrop={handleDrop}
100
+ onClick={openFileDialog}
101
+ className={[
102
+ 'flex cursor-pointer flex-col items-center gap-2 rounded-xl border-2 border-dashed p-10 text-center transition-all',
103
+ dragActive
104
+ ? 'border-blue-500 bg-blue-50 text-blue-700'
105
+ : 'border-gray-300 bg-gray-50 text-gray-500 hover:border-gray-400',
106
+ ].join(' ')}
107
+ >
108
+ <Upload className="h-8 w-8" />
109
+ <p className="text-sm font-medium">
110
+ {dragActive ? 'Drop files here…' : 'Drag files or click to browse'}
111
+ </p>
112
+ <p className="text-xs text-gray-400">Up to 3 files · Max 2 MB each</p>
113
+ <input
114
+ ref={inputRef}
115
+ type="file"
116
+ className="hidden"
117
+ multiple
118
+ onChange={handleChange}
119
+ />
120
+ </div>
121
+
122
+ {errorMessage && (
123
+ <div className="flex items-center gap-2 rounded-lg bg-red-50 px-3 py-2 text-sm text-red-600">
124
+ <AlertCircle className="h-4 w-4 shrink-0" />
125
+ {errorMessage}
126
+ </div>
127
+ )}
128
+
129
+ {files.length > 0 && (
130
+ <ul className="space-y-1">
131
+ {files.map((file, i) => (
132
+ <li
133
+ key={i}
134
+ className="flex items-center justify-between rounded-lg border bg-white px-3 py-2 text-sm"
135
+ >
136
+ <span className="flex items-center gap-2">
137
+ <FileIcon className="h-4 w-4 text-gray-400" />
138
+ {file.name}
139
+ </span>
140
+ <button
141
+ onClick={() => removeFile(i)}
142
+ className="text-gray-400 hover:text-red-500"
143
+ >
144
+ <X className="h-4 w-4" />
145
+ </button>
146
+ </li>
147
+ ))}
148
+ </ul>
149
+ )}
150
+ </div>
151
+ );
152
+ },
153
+ };
@@ -2,6 +2,7 @@ import * as React from "react";
2
2
  import { Upload, X, FileIcon, AlertCircle } from "lucide-react";
3
3
  import { cn } from "../../shared/utils";
4
4
  import { Button } from "../button";
5
+ import { useFileUpload } from "./use-file-upload";
5
6
 
6
7
  interface FileUploadProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'onError'> {
7
8
  onFilesChange?: (files: File[]) => void;
@@ -20,6 +21,8 @@ interface FileUploadProps extends Omit<React.InputHTMLAttributes<HTMLInputElemen
20
21
  * for file uploads. Supports click-to-browse and drag-and-drop. Shows a preview
21
22
  * list of selected files with per-file remove buttons.
22
23
  *
24
+ * Headless logic is available via `useFileUpload` for custom drop-zone UIs.
25
+ *
23
26
  * @ai-rules
24
27
  * 1. Use `onFilesChange` to capture the selected files array in your form state.
25
28
  * 2. `maxFiles` defaults to 1 (single file). Set to a higher number for multi-upload.
@@ -39,80 +42,17 @@ const FileUpload = React.forwardRef<HTMLDivElement, FileUploadProps>(
39
42
  disabled,
40
43
  ...props
41
44
  }, ref) => {
42
- const [files, setFiles] = React.useState<File[]>([]);
43
- const [dragActive, setDragActive] = React.useState(false);
44
- const [errorMessage, setErrorMessage] = React.useState<string | null>(null);
45
- const inputRef = React.useRef<HTMLInputElement>(null);
46
-
47
- const handleFiles = (newFiles: FileList | null) => {
48
- if (!newFiles) return;
49
- setErrorMessage(null);
50
-
51
- const filesArray = Array.from(newFiles);
52
-
53
- const oversized = filesArray.filter(f => f.size > maxSize);
54
- const validFiles = filesArray.filter(f => f.size <= maxSize);
55
-
56
- if (oversized.length > 0) {
57
- const limitMB = (maxSize / 1024 / 1024).toFixed(0);
58
- setErrorMessage(`${oversized.length} file(s) exceed the ${limitMB}MB limit and were not added.`);
59
- onError?.(oversized, 'size');
60
- }
61
-
62
- const merged = maxFiles === 1
63
- ? validFiles.slice(0, 1)
64
- : [...files, ...validFiles].slice(0, maxFiles);
65
-
66
- const countRejected = maxFiles === 1
67
- ? validFiles.slice(1)
68
- : [...files, ...validFiles].slice(maxFiles);
69
-
70
- if (countRejected.length > 0) {
71
- setErrorMessage(`Only ${maxFiles} file(s) allowed. ${countRejected.length} file(s) were not added.`);
72
- onError?.(countRejected, 'count');
73
- }
74
-
75
- setFiles(merged);
76
- onFilesChange?.(merged);
77
- };
78
-
79
- const handleDrag = (e: React.DragEvent) => {
80
- e.preventDefault();
81
- e.stopPropagation();
82
- if (e.type === "dragenter" || e.type === "dragover") {
83
- setDragActive(true);
84
- } else if (e.type === "dragleave") {
85
- setDragActive(false);
86
- }
87
- };
88
-
89
- const handleDrop = (e: React.DragEvent) => {
90
- e.preventDefault();
91
- e.stopPropagation();
92
- setDragActive(false);
93
- if (disabled) return;
94
- handleFiles(e.dataTransfer.files);
95
- };
96
-
97
- const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
98
- e.preventDefault();
99
- if (disabled) return;
100
- handleFiles(e.target.files);
101
- };
102
-
103
- const removeFile = (index: number) => {
104
- const updatedFiles = files.filter((_, i) => i !== index);
105
- setFiles(updatedFiles);
106
- onFilesChange?.(updatedFiles);
107
- if (updatedFiles.length === 0) setErrorMessage(null);
108
- };
109
-
110
- const openFileDialog = () => {
111
- if (!disabled) {
112
- setErrorMessage(null);
113
- inputRef.current?.click();
114
- }
115
- };
45
+ const {
46
+ files,
47
+ dragActive,
48
+ errorMessage,
49
+ inputRef,
50
+ handleDrag,
51
+ handleDrop,
52
+ handleChange,
53
+ removeFile,
54
+ openFileDialog,
55
+ } = useFileUpload({ maxFiles, maxSize, onFilesChange, onError, disabled });
116
56
 
117
57
  return (
118
58
  <div ref={ref} className={cn("w-full", className)}>
@@ -1 +1,2 @@
1
1
  export * from './file-upload';
2
+ export * from './use-file-upload';
@@ -0,0 +1,181 @@
1
+ import { useState, useRef, useCallback } from 'react';
2
+
3
+ // ─────────────────────────────────────────────────────────────────────────────
4
+ // Types
5
+ // ─────────────────────────────────────────────────────────────────────────────
6
+
7
+ export interface UseFileUploadProps {
8
+ /** Maximum number of files allowed. @default 1 */
9
+ maxFiles?: number;
10
+ /** Maximum file size in bytes. @default 5MB */
11
+ maxSize?: number;
12
+ /** Called with the current accepted file list whenever it changes. */
13
+ onFilesChange?: (files: File[]) => void;
14
+ /** Called when files are rejected due to size or count limits. */
15
+ onError?: (rejectedFiles: File[], reason: 'size' | 'count') => void;
16
+ /** Whether the upload area is disabled. */
17
+ disabled?: boolean;
18
+ }
19
+
20
+ export interface UseFileUploadReturn {
21
+ // ── State ─────────────────────────────────────────────────────────────────
22
+ /** Currently accepted files. */
23
+ files: File[];
24
+ /** Whether a drag operation is currently active over the drop zone. */
25
+ dragActive: boolean;
26
+ /** Inline error message, or `null` when there is no error. */
27
+ errorMessage: string | null;
28
+
29
+ // ── Refs ──────────────────────────────────────────────────────────────────
30
+ /** Attach to the hidden `<input type="file">` element. */
31
+ inputRef: React.RefObject<HTMLInputElement>;
32
+
33
+ // ── Handlers ──────────────────────────────────────────────────────────────
34
+ /** Process a `FileList` from any source (input change, drop, paste, etc.). */
35
+ handleFiles: (newFiles: FileList | null) => void;
36
+ /** Drag enter / over / leave handler — attach to all three events. */
37
+ handleDrag: (e: React.DragEvent) => void;
38
+ /** Drop handler — attach to the drop zone element. */
39
+ handleDrop: (e: React.DragEvent) => void;
40
+ /** Input `onChange` handler — attach to the hidden `<input>`. */
41
+ handleChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
42
+ /** Remove a file by its index in the `files` array. */
43
+ removeFile: (index: number) => void;
44
+ /** Programmatically open the native file picker dialog. */
45
+ openFileDialog: () => void;
46
+ }
47
+
48
+ // ─────────────────────────────────────────────────────────────────────────────
49
+ // Hook
50
+ // ─────────────────────────────────────────────────────────────────────────────
51
+
52
+ /**
53
+ * Headless hook for drag-and-drop file upload logic.
54
+ *
55
+ * @description
56
+ * Encapsulates all stateful behaviour for a file upload area: file validation
57
+ * (size and count limits), drag-active tracking, error messaging, and the
58
+ * hidden-input ref. Pair with any custom drop-zone UI.
59
+ *
60
+ * @example
61
+ * ```tsx
62
+ * const { files, dragActive, errorMessage, inputRef, handleDrag, handleDrop, handleChange, removeFile, openFileDialog } =
63
+ * useFileUpload({ maxFiles: 3, maxSize: 10 * 1024 * 1024 });
64
+ * ```
65
+ */
66
+ export function useFileUpload({
67
+ maxFiles = 1,
68
+ maxSize = 5 * 1024 * 1024,
69
+ onFilesChange,
70
+ onError,
71
+ disabled = false,
72
+ }: UseFileUploadProps = {}): UseFileUploadReturn {
73
+ const [files, setFiles] = useState<File[]>([]);
74
+ const [dragActive, setDragActive] = useState(false);
75
+ const [errorMessage, setErrorMessage] = useState<string | null>(null);
76
+ const inputRef = useRef<HTMLInputElement>(null);
77
+
78
+ const handleFiles = useCallback(
79
+ (newFiles: FileList | null) => {
80
+ if (!newFiles) return;
81
+ setErrorMessage(null);
82
+
83
+ const filesArray = Array.from(newFiles);
84
+
85
+ const oversized = filesArray.filter(f => f.size > maxSize);
86
+ const validFiles = filesArray.filter(f => f.size <= maxSize);
87
+
88
+ if (oversized.length > 0) {
89
+ const limitMB = (maxSize / 1024 / 1024).toFixed(0);
90
+ setErrorMessage(
91
+ `${oversized.length} file(s) exceed the ${limitMB}MB limit and were not added.`
92
+ );
93
+ onError?.(oversized, 'size');
94
+ }
95
+
96
+ const merged =
97
+ maxFiles === 1
98
+ ? validFiles.slice(0, 1)
99
+ : [...files, ...validFiles].slice(0, maxFiles);
100
+
101
+ const countRejected =
102
+ maxFiles === 1
103
+ ? validFiles.slice(1)
104
+ : [...files, ...validFiles].slice(maxFiles);
105
+
106
+ if (countRejected.length > 0) {
107
+ setErrorMessage(
108
+ `Only ${maxFiles} file(s) allowed. ${countRejected.length} file(s) were not added.`
109
+ );
110
+ onError?.(countRejected, 'count');
111
+ }
112
+
113
+ setFiles(merged);
114
+ onFilesChange?.(merged);
115
+ },
116
+ // eslint-disable-next-line react-hooks/exhaustive-deps
117
+ [files, maxFiles, maxSize, onError, onFilesChange]
118
+ );
119
+
120
+ const handleDrag = useCallback((e: React.DragEvent) => {
121
+ e.preventDefault();
122
+ e.stopPropagation();
123
+ if (e.type === 'dragenter' || e.type === 'dragover') {
124
+ setDragActive(true);
125
+ } else if (e.type === 'dragleave') {
126
+ setDragActive(false);
127
+ }
128
+ }, []);
129
+
130
+ const handleDrop = useCallback(
131
+ (e: React.DragEvent) => {
132
+ e.preventDefault();
133
+ e.stopPropagation();
134
+ setDragActive(false);
135
+ if (disabled) return;
136
+ handleFiles(e.dataTransfer.files);
137
+ },
138
+ [disabled, handleFiles]
139
+ );
140
+
141
+ const handleChange = useCallback(
142
+ (e: React.ChangeEvent<HTMLInputElement>) => {
143
+ e.preventDefault();
144
+ if (disabled) return;
145
+ handleFiles(e.target.files);
146
+ },
147
+ [disabled, handleFiles]
148
+ );
149
+
150
+ const removeFile = useCallback(
151
+ (index: number) => {
152
+ setFiles(prev => {
153
+ const updated = prev.filter((_, i) => i !== index);
154
+ onFilesChange?.(updated);
155
+ if (updated.length === 0) setErrorMessage(null);
156
+ return updated;
157
+ });
158
+ },
159
+ [onFilesChange]
160
+ );
161
+
162
+ const openFileDialog = useCallback(() => {
163
+ if (!disabled) {
164
+ setErrorMessage(null);
165
+ inputRef.current?.click();
166
+ }
167
+ }, [disabled]);
168
+
169
+ return {
170
+ files,
171
+ dragActive,
172
+ errorMessage,
173
+ inputRef,
174
+ handleFiles,
175
+ handleDrag,
176
+ handleDrop,
177
+ handleChange,
178
+ removeFile,
179
+ openFileDialog,
180
+ };
181
+ }
@@ -38,7 +38,7 @@ function getInitialApiKey(): string | undefined {
38
38
 
39
39
  if (typeof window === 'undefined') return undefined;
40
40
 
41
- const savedKey = window.localStorage?.getItem('xertica-googlemaps-api-key');
41
+ const savedKey = window.localStorage?.getItem('xertica-googlemaps-api-key');
42
42
 
43
43
  if (savedKey && savedKey.trim().length > 0) {
44
44
  return savedKey;
@@ -442,4 +442,4 @@ resolve();
442
442
  }
443
443
 
444
444
  // Alias for backwards compatibility
445
- export const GoogleMapsProvider = GoogleMapsLoaderProvider;
445
+ export const GoogleMapsProvider = GoogleMapsLoaderProvider;