@g4rcez/components 4.1.1 → 4.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 (310) hide show
  1. package/dist/components/core/button.d.ts +77 -0
  2. package/dist/components/core/button.d.ts.map +1 -0
  3. package/dist/components/core/button.jsx +79 -0
  4. package/dist/components/core/heading.d.ts +3 -0
  5. package/dist/components/core/heading.d.ts.map +1 -0
  6. package/dist/components/core/heading.jsx +4 -0
  7. package/dist/components/core/polymorph.d.ts +10 -0
  8. package/dist/components/core/polymorph.d.ts.map +1 -0
  9. package/dist/components/core/polymorph.jsx +5 -0
  10. package/dist/components/core/render-on-view.d.ts +7 -0
  11. package/dist/components/core/render-on-view.d.ts.map +1 -0
  12. package/dist/components/core/render-on-view.jsx +31 -0
  13. package/dist/components/core/resizable.d.ts +3 -0
  14. package/dist/components/core/resizable.d.ts.map +1 -0
  15. package/dist/components/core/resizable.jsx +51 -0
  16. package/dist/components/core/slot.d.ts +16 -0
  17. package/dist/components/core/slot.d.ts.map +1 -0
  18. package/dist/components/core/slot.jsx +156 -0
  19. package/dist/components/core/tag.d.ts +35 -0
  20. package/dist/components/core/tag.d.ts.map +1 -0
  21. package/dist/components/core/tag.jsx +51 -0
  22. package/dist/components/core/typography.d.ts +25 -0
  23. package/dist/components/core/typography.d.ts.map +1 -0
  24. package/dist/components/core/typography.jsx +18 -0
  25. package/dist/components/display/alert.d.ts +28 -0
  26. package/dist/components/display/alert.d.ts.map +1 -0
  27. package/dist/components/display/alert.jsx +61 -0
  28. package/dist/components/display/calendar.d.ts +42 -0
  29. package/dist/components/display/calendar.d.ts.map +1 -0
  30. package/dist/components/display/calendar.jsx +299 -0
  31. package/dist/components/display/card.d.ts +29 -0
  32. package/dist/components/display/card.d.ts.map +1 -0
  33. package/dist/components/display/card.jsx +43 -0
  34. package/dist/components/display/empty.d.ts +8 -0
  35. package/dist/components/display/empty.d.ts.map +1 -0
  36. package/dist/components/display/empty.jsx +11 -0
  37. package/dist/components/display/list.d.ts +16 -0
  38. package/dist/components/display/list.d.ts.map +1 -0
  39. package/dist/components/display/list.jsx +81 -0
  40. package/dist/components/display/notifications.d.ts +27 -0
  41. package/dist/components/display/notifications.d.ts.map +1 -0
  42. package/dist/components/display/notifications.jsx +126 -0
  43. package/dist/components/display/progress.d.ts +13 -0
  44. package/dist/components/display/progress.d.ts.map +1 -0
  45. package/dist/components/display/progress.jsx +11 -0
  46. package/dist/components/display/shortcut.d.ts +4 -0
  47. package/dist/components/display/shortcut.d.ts.map +1 -0
  48. package/dist/components/display/shortcut.jsx +23 -0
  49. package/dist/components/display/skeleton.d.ts +12 -0
  50. package/dist/components/display/skeleton.d.ts.map +1 -0
  51. package/dist/components/display/skeleton.jsx +19 -0
  52. package/dist/components/display/spinner.d.ts +5 -0
  53. package/dist/components/display/spinner.d.ts.map +1 -0
  54. package/dist/components/display/spinner.jsx +11 -0
  55. package/dist/components/display/stats.d.ts +12 -0
  56. package/dist/components/display/stats.d.ts.map +1 -0
  57. package/dist/components/display/stats.jsx +20 -0
  58. package/dist/components/display/step.d.ts +24 -0
  59. package/dist/components/display/step.d.ts.map +1 -0
  60. package/dist/components/display/step.jsx +131 -0
  61. package/dist/components/display/tabs.d.ts +24 -0
  62. package/dist/components/display/tabs.d.ts.map +1 -0
  63. package/dist/components/display/tabs.jsx +125 -0
  64. package/dist/components/display/timeline.d.ts +10 -0
  65. package/dist/components/display/timeline.d.ts.map +1 -0
  66. package/dist/components/display/timeline.jsx +25 -0
  67. package/dist/components/floating/command-palette.d.ts +49 -0
  68. package/dist/components/floating/command-palette.d.ts.map +1 -0
  69. package/dist/components/floating/command-palette.jsx +197 -0
  70. package/dist/components/floating/dropdown.d.ts +15 -0
  71. package/dist/components/floating/dropdown.d.ts.map +1 -0
  72. package/dist/components/floating/dropdown.jsx +56 -0
  73. package/dist/components/floating/expand.d.ts +11 -0
  74. package/dist/components/floating/expand.d.ts.map +1 -0
  75. package/dist/components/floating/expand.jsx +44 -0
  76. package/dist/components/floating/menu.d.ts +52 -0
  77. package/dist/components/floating/menu.d.ts.map +1 -0
  78. package/dist/components/floating/menu.jsx +147 -0
  79. package/dist/components/floating/modal.d.ts +60 -0
  80. package/dist/components/floating/modal.d.ts.map +1 -0
  81. package/dist/components/floating/modal.jsx +301 -0
  82. package/dist/components/floating/toolbar.d.ts +6 -0
  83. package/dist/components/floating/toolbar.d.ts.map +1 -0
  84. package/dist/components/floating/toolbar.jsx +5 -0
  85. package/dist/components/floating/tooltip.d.ts +17 -0
  86. package/dist/components/floating/tooltip.d.ts.map +1 -0
  87. package/dist/components/floating/tooltip.jsx +58 -0
  88. package/dist/components/floating/wizard.d.ts +26 -0
  89. package/dist/components/floating/wizard.d.ts.map +1 -0
  90. package/dist/components/floating/wizard.jsx +161 -0
  91. package/dist/components/form/autocomplete.d.ts +16 -0
  92. package/dist/components/form/autocomplete.d.ts.map +1 -0
  93. package/dist/components/form/autocomplete.jsx +278 -0
  94. package/dist/components/form/checkbox.d.ts +12 -0
  95. package/dist/components/form/checkbox.d.ts.map +1 -0
  96. package/dist/components/form/checkbox.jsx +12 -0
  97. package/dist/components/form/date-picker.d.ts +10 -0
  98. package/dist/components/form/date-picker.d.ts.map +1 -0
  99. package/dist/components/form/date-picker.jsx +115 -0
  100. package/dist/components/form/file-upload.d.ts +15 -0
  101. package/dist/components/form/file-upload.d.ts.map +1 -0
  102. package/dist/components/form/file-upload.jsx +134 -0
  103. package/dist/components/form/form.d.ts +3 -0
  104. package/dist/components/form/form.d.ts.map +1 -0
  105. package/dist/components/form/form.jsx +10 -0
  106. package/dist/components/form/formReset.d.ts +2 -0
  107. package/dist/components/form/formReset.d.ts.map +1 -0
  108. package/dist/components/form/formReset.jsx +17 -0
  109. package/dist/components/form/free-text.d.ts +11 -0
  110. package/dist/components/form/free-text.d.ts.map +1 -0
  111. package/dist/components/form/free-text.jsx +41 -0
  112. package/dist/components/form/input-field.d.ts +34 -0
  113. package/dist/components/form/input-field.d.ts.map +1 -0
  114. package/dist/components/form/input-field.jsx +58 -0
  115. package/dist/components/form/input.d.ts +52 -0
  116. package/dist/components/form/input.d.ts.map +1 -0
  117. package/dist/components/form/input.jsx +36 -0
  118. package/dist/components/form/multi-select.d.ts +19 -0
  119. package/dist/components/form/multi-select.d.ts.map +1 -0
  120. package/dist/components/form/multi-select.jsx +336 -0
  121. package/dist/components/form/radiobox.d.ts +7 -0
  122. package/dist/components/form/radiobox.d.ts.map +1 -0
  123. package/dist/components/form/radiobox.jsx +6 -0
  124. package/dist/components/form/select.d.ts +13 -0
  125. package/dist/components/form/select.d.ts.map +1 -0
  126. package/dist/components/form/select.jsx +42 -0
  127. package/dist/components/form/slider.d.ts +7 -0
  128. package/dist/components/form/slider.d.ts.map +1 -0
  129. package/dist/components/form/slider.jsx +45 -0
  130. package/dist/components/form/switch.d.ts +9 -0
  131. package/dist/components/form/switch.d.ts.map +1 -0
  132. package/dist/components/form/switch.jsx +46 -0
  133. package/dist/components/form/task-list.d.ts +3 -0
  134. package/dist/components/form/task-list.d.ts.map +1 -0
  135. package/dist/components/form/task-list.jsx +26 -0
  136. package/dist/components/form/textarea.d.ts +6 -0
  137. package/dist/components/form/textarea.d.ts.map +1 -0
  138. package/dist/components/form/textarea.jsx +12 -0
  139. package/dist/components/index.d.ts +45 -0
  140. package/dist/components/index.d.ts.map +1 -0
  141. package/dist/components/index.js +44 -0
  142. package/dist/components/page-calendar/calendar-header.d.ts +16 -0
  143. package/dist/components/page-calendar/calendar-header.d.ts.map +1 -0
  144. package/dist/components/page-calendar/calendar-header.jsx +83 -0
  145. package/dist/components/page-calendar/day-view.d.ts +12 -0
  146. package/dist/components/page-calendar/day-view.d.ts.map +1 -0
  147. package/dist/components/page-calendar/day-view.jsx +94 -0
  148. package/dist/components/page-calendar/event-pill.d.ts +9 -0
  149. package/dist/components/page-calendar/event-pill.d.ts.map +1 -0
  150. package/dist/components/page-calendar/event-pill.jsx +25 -0
  151. package/dist/components/page-calendar/index.d.ts +4 -0
  152. package/dist/components/page-calendar/index.d.ts.map +1 -0
  153. package/dist/components/page-calendar/index.js +2 -0
  154. package/dist/components/page-calendar/month-view.d.ts +11 -0
  155. package/dist/components/page-calendar/month-view.d.ts.map +1 -0
  156. package/dist/components/page-calendar/month-view.jsx +46 -0
  157. package/dist/components/page-calendar/page-calendar.d.ts +18 -0
  158. package/dist/components/page-calendar/page-calendar.d.ts.map +1 -0
  159. package/dist/components/page-calendar/page-calendar.jsx +41 -0
  160. package/dist/components/page-calendar/page-calendar.types.d.ts +18 -0
  161. package/dist/components/page-calendar/page-calendar.types.d.ts.map +1 -0
  162. package/dist/components/page-calendar/page-calendar.types.js +1 -0
  163. package/dist/components/page-calendar/page-calendar.utils.d.ts +24 -0
  164. package/dist/components/page-calendar/page-calendar.utils.d.ts.map +1 -0
  165. package/dist/components/page-calendar/page-calendar.utils.js +93 -0
  166. package/dist/components/page-calendar/week-view.d.ts +11 -0
  167. package/dist/components/page-calendar/week-view.d.ts.map +1 -0
  168. package/dist/components/page-calendar/week-view.jsx +71 -0
  169. package/dist/components/table/filter.d.ts +42 -0
  170. package/dist/components/table/filter.d.ts.map +1 -0
  171. package/dist/components/table/filter.jsx +141 -0
  172. package/dist/components/table/group.d.ts +17 -0
  173. package/dist/components/table/group.d.ts.map +1 -0
  174. package/dist/components/table/group.jsx +68 -0
  175. package/dist/components/table/index.d.ts +19 -0
  176. package/dist/components/table/index.d.ts.map +1 -0
  177. package/dist/components/table/index.jsx +60 -0
  178. package/dist/components/table/inner-table.d.ts +29 -0
  179. package/dist/components/table/inner-table.d.ts.map +1 -0
  180. package/dist/components/table/inner-table.jsx +102 -0
  181. package/dist/components/table/metadata.d.ts +4 -0
  182. package/dist/components/table/metadata.d.ts.map +1 -0
  183. package/dist/components/table/metadata.jsx +36 -0
  184. package/dist/components/table/pagination.d.ts +5 -0
  185. package/dist/components/table/pagination.d.ts.map +1 -0
  186. package/dist/components/table/pagination.jsx +74 -0
  187. package/dist/components/table/row.d.ts +11 -0
  188. package/dist/components/table/row.d.ts.map +1 -0
  189. package/dist/components/table/row.jsx +49 -0
  190. package/dist/components/table/sort.d.ts +28 -0
  191. package/dist/components/table/sort.d.ts.map +1 -0
  192. package/dist/components/table/sort.jsx +109 -0
  193. package/dist/components/table/table-lib.d.ts +135 -0
  194. package/dist/components/table/table-lib.d.ts.map +1 -0
  195. package/dist/components/table/table-lib.js +83 -0
  196. package/dist/components/table/table.context.d.ts +10 -0
  197. package/dist/components/table/table.context.d.ts.map +1 -0
  198. package/dist/components/table/table.context.jsx +4 -0
  199. package/dist/components/table/thead.d.ts +9 -0
  200. package/dist/components/table/thead.d.ts.map +1 -0
  201. package/dist/components/table/thead.jsx +103 -0
  202. package/dist/config/context.d.ts +21 -0
  203. package/dist/config/context.d.ts.map +1 -0
  204. package/dist/config/context.js +12 -0
  205. package/dist/config/default-translations.d.ts +94 -0
  206. package/dist/config/default-translations.d.ts.map +1 -0
  207. package/dist/config/default-translations.jsx +87 -0
  208. package/dist/config/default-tweaks.d.ts +13 -0
  209. package/dist/config/default-tweaks.d.ts.map +1 -0
  210. package/dist/config/default-tweaks.js +4 -0
  211. package/dist/constants.d.ts +3 -0
  212. package/dist/constants.d.ts.map +1 -0
  213. package/dist/constants.js +2 -0
  214. package/dist/hooks/use-click-outside.d.ts +3 -0
  215. package/dist/hooks/use-click-outside.d.ts.map +1 -0
  216. package/dist/hooks/use-click-outside.js +17 -0
  217. package/dist/hooks/use-color-parser.d.ts +2 -0
  218. package/dist/hooks/use-color-parser.d.ts.map +1 -0
  219. package/dist/hooks/use-color-parser.js +9 -0
  220. package/dist/hooks/use-components-provider.d.ts +15 -0
  221. package/dist/hooks/use-components-provider.d.ts.map +1 -0
  222. package/dist/hooks/use-components-provider.jsx +22 -0
  223. package/dist/hooks/use-debounce.d.ts +5 -0
  224. package/dist/hooks/use-debounce.d.ts.map +1 -0
  225. package/dist/hooks/use-debounce.js +12 -0
  226. package/dist/hooks/use-floating-ref.d.ts +2 -0
  227. package/dist/hooks/use-floating-ref.d.ts.map +1 -0
  228. package/dist/hooks/use-floating-ref.js +6 -0
  229. package/dist/hooks/use-form.d.ts +394 -0
  230. package/dist/hooks/use-form.d.ts.map +1 -0
  231. package/dist/hooks/use-form.js +563 -0
  232. package/dist/hooks/use-hover.d.ts +3 -0
  233. package/dist/hooks/use-hover.d.ts.map +1 -0
  234. package/dist/hooks/use-hover.js +18 -0
  235. package/dist/hooks/use-input-id.d.ts +4 -0
  236. package/dist/hooks/use-input-id.d.ts.map +1 -0
  237. package/dist/hooks/use-input-id.js +5 -0
  238. package/dist/hooks/use-is-coarse-device.d.ts +2 -0
  239. package/dist/hooks/use-is-coarse-device.d.ts.map +1 -0
  240. package/dist/hooks/use-is-coarse-device.js +12 -0
  241. package/dist/hooks/use-locale.d.ts +3 -0
  242. package/dist/hooks/use-locale.d.ts.map +1 -0
  243. package/dist/hooks/use-locale.js +10 -0
  244. package/dist/hooks/use-media-query.d.ts +2 -0
  245. package/dist/hooks/use-media-query.d.ts.map +1 -0
  246. package/dist/hooks/use-media-query.js +25 -0
  247. package/dist/hooks/use-on-event.d.ts +4 -0
  248. package/dist/hooks/use-on-event.d.ts.map +1 -0
  249. package/dist/hooks/use-on-event.js +7 -0
  250. package/dist/hooks/use-parent.d.ts +3 -0
  251. package/dist/hooks/use-parent.d.ts.map +1 -0
  252. package/dist/hooks/use-parent.js +21 -0
  253. package/dist/hooks/use-preferences.d.ts +2 -0
  254. package/dist/hooks/use-preferences.d.ts.map +1 -0
  255. package/dist/hooks/use-preferences.js +23 -0
  256. package/dist/hooks/use-previous.d.ts +2 -0
  257. package/dist/hooks/use-previous.d.ts.map +1 -0
  258. package/dist/hooks/use-previous.js +9 -0
  259. package/dist/hooks/use-reactive.d.ts +2 -0
  260. package/dist/hooks/use-reactive.d.ts.map +1 -0
  261. package/dist/hooks/use-reactive.js +9 -0
  262. package/dist/hooks/use-remove-scroll.d.ts +4 -0
  263. package/dist/hooks/use-remove-scroll.d.ts.map +1 -0
  264. package/dist/hooks/use-remove-scroll.js +48 -0
  265. package/dist/hooks/use-resize-observer.d.ts +2 -0
  266. package/dist/hooks/use-resize-observer.d.ts.map +1 -0
  267. package/dist/hooks/use-resize-observer.js +17 -0
  268. package/dist/hooks/use-stable-ref.d.ts +2 -0
  269. package/dist/hooks/use-stable-ref.d.ts.map +1 -0
  270. package/dist/hooks/use-stable-ref.js +9 -0
  271. package/dist/hooks/use-swipe.d.ts +8 -0
  272. package/dist/hooks/use-swipe.d.ts.map +1 -0
  273. package/dist/hooks/use-swipe.js +17 -0
  274. package/dist/hooks/use-translations.d.ts +92 -0
  275. package/dist/hooks/use-translations.d.ts.map +1 -0
  276. package/dist/hooks/use-translations.js +9 -0
  277. package/dist/hooks/use-tweaks.d.ts +3 -0
  278. package/dist/hooks/use-tweaks.d.ts.map +1 -0
  279. package/dist/hooks/use-tweaks.js +9 -0
  280. package/dist/hooks/use-window-size.d.ts +5 -0
  281. package/dist/hooks/use-window-size.d.ts.map +1 -0
  282. package/dist/hooks/use-window-size.js +14 -0
  283. package/dist/index-DDeQW0JW.js.map +1 -1
  284. package/dist/index.d.ts +22 -0
  285. package/dist/index.d.ts.map +1 -0
  286. package/dist/index.js +20 -8231
  287. package/dist/index.js.map +1 -1
  288. package/dist/lib/combi-keys.d.ts +15 -0
  289. package/dist/lib/combi-keys.d.ts.map +1 -0
  290. package/dist/lib/combi-keys.js +60 -0
  291. package/dist/lib/dict.d.ts +9 -0
  292. package/dist/lib/dict.d.ts.map +1 -0
  293. package/dist/lib/dict.js +28 -0
  294. package/dist/lib/dom.d.ts +20 -0
  295. package/dist/lib/dom.d.ts.map +1 -0
  296. package/dist/lib/dom.js +66 -0
  297. package/dist/lib/fns.d.ts +11 -0
  298. package/dist/lib/fns.d.ts.map +1 -0
  299. package/dist/lib/fns.js +46 -0
  300. package/dist/lib/fzf.d.ts +16 -0
  301. package/dist/lib/fzf.d.ts.map +1 -0
  302. package/dist/lib/fzf.js +115 -0
  303. package/dist/lib/keyboard-area.d.ts +16 -0
  304. package/dist/lib/keyboard-area.d.ts.map +1 -0
  305. package/dist/lib/keyboard-area.js +14 -0
  306. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  307. package/dist/types.d.ts +26 -0
  308. package/dist/types.d.ts.map +1 -0
  309. package/dist/types.js +1 -0
  310. package/package.json +1 -1
@@ -0,0 +1,16 @@
1
+ import React from "react";
2
+ import { Label } from "../../types";
3
+ import { InputFieldProps } from "./input-field";
4
+ import { type OptionProps } from "./select";
5
+ export type AutocompleteItemProps = OptionProps & {
6
+ Render?: React.FC<OptionProps>;
7
+ };
8
+ export type AutocompleteProps = Omit<InputFieldProps<"input">, "value"> & {
9
+ title?: string;
10
+ value?: string;
11
+ emptyMessage?: Label;
12
+ dynamicOption?: boolean;
13
+ options: AutocompleteItemProps[];
14
+ };
15
+ export declare const Autocomplete: React.ForwardRefExoticComponent<Omit<AutocompleteProps, "ref"> & React.RefAttributes<HTMLInputElement>>;
16
+ //# sourceMappingURL=autocomplete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autocomplete.d.ts","sourceRoot":"","sources":["../../../src/components/form/autocomplete.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAkG,MAAM,OAAO,CAAC;AASvH,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAc,eAAe,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,MAAM,qBAAqB,GAAG,WAAW,GAAG;IAAE,MAAM,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAAC,CAAA;CAAE,CAAC;AAErF,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,GAAG;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE,qBAAqB,EAAE,CAAC;CACpC,CAAC;AAgCF,eAAO,MAAM,YAAY,yGAkYxB,CAAC"}
@@ -0,0 +1,278 @@
1
+ "use client";
2
+ import { autoPlacement, autoUpdate, FloatingFocusManager, FloatingPortal, offset, size, useDismiss, useFloating, useInteractions, useListNavigation, useRole, useTransitionStyles, } from "@floating-ui/react";
3
+ import { CaretDownIcon } from "@phosphor-icons/react";
4
+ import { AnimatePresence, motion } from "motion/react";
5
+ import React, { forwardRef, Fragment, useEffect, useMemo, useRef, useState } from "react";
6
+ import { flushSync } from "react-dom";
7
+ import { Virtuoso } from "react-virtuoso";
8
+ import { Is } from "sidekicker";
9
+ import { useRemoveScroll } from "../../hooks/use-remove-scroll";
10
+ import { useTranslations } from "../../hooks/use-translations";
11
+ import { css, dispatchInput, getRemainingSize, initializeInputDataset, synthesizeChangeEvent } from "../../lib/dom";
12
+ import { safeRegex } from "../../lib/fns";
13
+ import { fzf } from "../../lib/fzf";
14
+ import { InputField } from "./input-field";
15
+ const Frag = (props) => <Fragment>{props.children}</Fragment>;
16
+ const transitionStyles = {
17
+ duration: 200,
18
+ open: { transform: "scaleY(1)", opacity: 1 },
19
+ close: { transform: "scaleY(0)", opacity: 0 },
20
+ initial: { transform: "scaleY(0)", opacity: 0.2 },
21
+ };
22
+ const List = forwardRef(function VirtualList({ context, ...props }, ref) {
23
+ return (<motion.ul {...props} ref={ref} className="max-h-96 w-full overscroll-contain rounded-lg">
24
+ <AnimatePresence>{props.children}</AnimatePresence>
25
+ </motion.ul>);
26
+ });
27
+ const Item = forwardRef(function VirtualItem({ item, context, ...props }, ref) {
28
+ return <motion.li {...props} ref={ref} className="first:rounded-t-lg last:rounded-t-lg"/>;
29
+ });
30
+ const components = { List, Item };
31
+ const EMPTY_NODES = [];
32
+ const MIN_SIZE = 40;
33
+ export const Autocomplete = forwardRef(({ left, error, right, loading, options, container, rightLabel, interactive, emptyMessage, optionalText, labelClassName, feedback = null, hideLeft = false, required = false, dynamicOption = false, ...props }, externalRef) => {
34
+ const scroller = useRef(null);
35
+ const fieldset = useRef(null);
36
+ const virtuoso = useRef(null);
37
+ const defaults = props.value ?? props.defaultValue ?? "";
38
+ const translation = useTranslations();
39
+ const [open, setOpen] = useState(false);
40
+ const [shadow, setShadow] = useState("");
41
+ const [value, setValue] = useState(defaults);
42
+ const [label, setLabel] = useState(() => options.find((x) => x.value === defaults)?.label ?? defaults);
43
+ const [index, setIndex] = useState(null);
44
+ const listRef = useRef(EMPTY_NODES);
45
+ const [, tick] = useState(0);
46
+ const removeScrollRef = useRemoveScroll(open, "block-only");
47
+ const innerOptions = useMemo(() => (dynamicOption && shadow !== "" ? [{ value: shadow, label: shadow, "data-dynamic": "true" }, ...options] : options), [dynamicOption, shadow, options]);
48
+ const openDropdown = () => flushSync(() => setOpen(true));
49
+ const list = useMemo(() => shadow
50
+ ? fzf(innerOptions, "value", [
51
+ { key: "value", value: shadow },
52
+ { key: "label", value: shadow },
53
+ ])
54
+ : innerOptions, [innerOptions, shadow]);
55
+ const [h, setH] = useState(() => Math.min(320, MIN_SIZE * options.length));
56
+ const setClosed = () => {
57
+ setOpen(false);
58
+ setH(0);
59
+ };
60
+ const displayList = useMemo(() => list.filter((x) => x.hidden !== true), [list]);
61
+ const pattern = useMemo(() => dynamicOption ? undefined : `^(${options.map((x) => `${safeRegex(x.value)}${x.label ? "|" + safeRegex(x.label) : ""}`).join("|")})$`, [dynamicOption, options]);
62
+ const { x, y, strategy, refs, context, placement } = useFloating({
63
+ open,
64
+ transform: true,
65
+ onOpenChange: setOpen,
66
+ placement: "bottom-start",
67
+ whileElementsMounted: autoUpdate,
68
+ middleware: [
69
+ offset(4),
70
+ autoPlacement({ allowedPlacements: ["top-start", "bottom-start"], alignment: "start" }),
71
+ size({
72
+ padding: 10,
73
+ elementContext: "reference",
74
+ apply(args) {
75
+ const DEFAULT_SIZE = getRemainingSize(refs.reference.current, window.innerHeight);
76
+ const mw = `${fieldset.current?.getBoundingClientRect().width || DEFAULT_SIZE}px`;
77
+ Object.assign(args.elements.floating.style, { width: mw, maxWidth: mw });
78
+ },
79
+ }),
80
+ ],
81
+ });
82
+ const transitions = useTransitionStyles(context, transitionStyles);
83
+ const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions([
84
+ useRole(context, { role: "listbox" }),
85
+ useDismiss(context),
86
+ useListNavigation(context, {
87
+ cols: 0,
88
+ listRef,
89
+ loop: true,
90
+ virtual: true,
91
+ allowEscape: true,
92
+ activeIndex: index,
93
+ selectedIndex: index,
94
+ focusItemOnOpen: "auto",
95
+ openOnArrowKeyDown: true,
96
+ scrollItemIntoView: true,
97
+ }),
98
+ ]);
99
+ useEffect(() => {
100
+ if (props.value) {
101
+ const item = options.find((x) => x.value === props.value);
102
+ if (item) {
103
+ setLabel(item.label ?? item.value);
104
+ setValue(props.value);
105
+ }
106
+ }
107
+ }, [props.value, options.length]);
108
+ useEffect(() => {
109
+ const input = refs.reference.current;
110
+ if (!input)
111
+ return;
112
+ return initializeInputDataset(input);
113
+ }, []);
114
+ useEffect(() => {
115
+ if (!open)
116
+ return;
117
+ const id = requestAnimationFrame(() => tick((n) => n + 1));
118
+ return () => cancelAnimationFrame(id);
119
+ }, [open]);
120
+ useEffect(() => {
121
+ if (!open) {
122
+ setH(0);
123
+ return;
124
+ }
125
+ const id = setTimeout(() => setH(Math.min(320, displayList.length * MIN_SIZE)), 100);
126
+ return () => clearTimeout(id);
127
+ }, [open, displayList.length]);
128
+ const onSelect = (opt, i) => {
129
+ setValue(opt.value);
130
+ const input = refs.reference.current;
131
+ if (!input)
132
+ return;
133
+ input?.setAttribute("data-value", opt.value);
134
+ input.value = opt.value;
135
+ const event = new Event("change", { bubbles: false, cancelable: true });
136
+ input.dispatchEvent(event);
137
+ if (props.onChange)
138
+ props.onChange(synthesizeChangeEvent(input));
139
+ setLabel(opt.label ?? "");
140
+ setClosed();
141
+ setShadow("");
142
+ setIndex(i);
143
+ };
144
+ const onChange = (event) => {
145
+ const value = event.target.value;
146
+ setShadow(value);
147
+ if (!open && value === "")
148
+ return setOpen(true);
149
+ event.target.name = props.name || "";
150
+ return value ? setOpen(true) : props.onChange?.(event);
151
+ };
152
+ const onCaretDownClick = () => {
153
+ openDropdown();
154
+ setShadow("");
155
+ refs.reference.current?.focus();
156
+ };
157
+ const onFocus = () => {
158
+ setIndex((prev) => (prev === null ? 0 : prev));
159
+ openDropdown();
160
+ setShadow("");
161
+ };
162
+ const onClose = () => {
163
+ refs.reference.current?.setAttribute("data-value", "");
164
+ setShadow("");
165
+ setValue("");
166
+ setLabel("");
167
+ dispatchInput(refs.reference.current);
168
+ setClosed();
169
+ };
170
+ const id = props.id || props.name;
171
+ const shadowId = `${id}-shadow`;
172
+ const isEmpty = displayList.length === 0;
173
+ const isTopPlacement = placement === "top" || placement === "top-start";
174
+ return (<InputField {...props} left={left} error={error} id={shadowId} form={props.form} loading={loading} name={props.name} hideLeft={hideLeft} required={required} title={props.title} container={container} rightLabel={rightLabel} interactive={interactive} optionalText={optionalText} componentName="autocomplete" labelClassName={labelClassName} placeholder={props.placeholder} ref={fieldset} feedback={open && isTopPlacement ? props.title : feedback} right={<span className="flex items-center gap-0.5">
175
+ {right}
176
+ <button type="button" className="p-2 transition-colors link:text-primary md:p-1" onClick={onCaretDownClick}>
177
+ <CaretDownIcon size={20}/>
178
+ <span className="sr-only">{translation.inputCaretDown}</span>
179
+ </button>
180
+ {value ? (<button type="button" onClick={onClose} aria-label={translation.inputCloseValue} className="p-2 transition-colors link:text-danger md:p-1">
181
+ <svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
182
+ <path d="M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z" fill="currentColor" fillRule="evenodd" clipRule="evenodd"/>
183
+ </svg>
184
+ </button>) : null}
185
+ </span>}>
186
+ <input data-shadow="true" {...getReferenceProps({
187
+ ...props,
188
+ onFocus,
189
+ pattern,
190
+ onChange,
191
+ id: shadowId,
192
+ name: shadowId,
193
+ ref: refs.setReference,
194
+ onClick: (e) => e.currentTarget.focus(),
195
+ onKeyDown(event) {
196
+ if (event.key === "Escape") {
197
+ event.currentTarget.blur();
198
+ return setClosed();
199
+ }
200
+ if (!open)
201
+ return;
202
+ if (event.key === "ArrowDown") {
203
+ let next = Is.number(index) ? index + 1 : 0;
204
+ if (next > displayList.length - 1)
205
+ next = 0;
206
+ virtuoso.current?.scrollIntoView({ index: next });
207
+ return setIndex(next);
208
+ }
209
+ if (event.key === "ArrowUp") {
210
+ let next = Is.number(index) ? index - 1 : displayList.length - 1;
211
+ if (next < 0)
212
+ next = displayList.length - 1;
213
+ virtuoso.current?.scrollIntoView({ index: next });
214
+ return setIndex(next);
215
+ }
216
+ if (event.key === "Enter") {
217
+ if (index !== null && displayList[index]) {
218
+ event.preventDefault();
219
+ return onSelect(displayList[index], index);
220
+ }
221
+ if (displayList.length === 1) {
222
+ event.preventDefault();
223
+ return onSelect(displayList[0], 0);
224
+ }
225
+ }
226
+ },
227
+ })} data-value={value} data-error={!!error} data-name={id} data-target={id} required={required} value={open ? shadow : options.length === 0 ? "" : label || value} aria-autocomplete="list" autoComplete="off" className={css("input placeholder-input-mask group h-input-height w-full flex-1", "rounded-md bg-transparent px-input-x py-input-y text-foreground", "outline-none transition-colors focus:ring-2 focus:ring-inset focus:ring-primary", "group-error:text-danger group-error:placeholder-input-mask-error", "text-base group-focus-within:border-primary group-hover:border-primary", props.className)}/>
228
+ <input id={id} name={id} type="hidden" data-origin={id} ref={externalRef} required={required} defaultValue={props.value || value || undefined}/>
229
+ <FloatingPortal preserveTabOrder>
230
+ {open ? (<FloatingFocusManager modal guards returnFocus={false} context={context} initialFocus={-1} visuallyHiddenDismiss>
231
+ <motion.div {...getFloatingProps({
232
+ ref: refs.setFloating,
233
+ style: { ...transitions.styles, left: x, top: y ?? 0, position: strategy, height: "auto" },
234
+ })} initial={false} data-floating="true" animate={{ height: isEmpty ? "auto" : h }} onAnimationComplete={() => {
235
+ if (!open) {
236
+ setH(0);
237
+ return;
238
+ }
239
+ const li = refs.floating.current?.querySelector("li");
240
+ const sum = (li?.getBoundingClientRect().height ?? MIN_SIZE) * displayList.length;
241
+ flushSync(() => setH(Math.min(320, sum + 2)));
242
+ }} className={css("shadow-floating isolate z-floating m-0 max-h-80 origin-[top_center] list-none overscroll-contain rounded-b-lg rounded-t-lg border border-floating-border bg-floating-background p-0 text-foreground ease-in-out", isTopPlacement ? "origin-[bottom_center]" : "origin-[top_center]")}>
243
+ {isEmpty ? (<div className="w-full border-b border-tooltip-border">
244
+ <span className="flex w-full justify-between p-2 text-left text-disabled">
245
+ {emptyMessage || translation.autocompleteEmpty}
246
+ </span>
247
+ </div>) : null}
248
+ <Virtuoso overscan={40} ref={virtuoso} hidden={isEmpty} data={displayList} style={{ height: h }} defaultItemHeight={MIN_SIZE} components={components} scrollerRef={(e) => {
249
+ scroller.current = e;
250
+ removeScrollRef.current = e;
251
+ }} className="border-floating max-h-full overscroll-contain rounded-lg bg-floating-background p-0 text-foreground" itemContent={(i, option) => {
252
+ const Label = option.Render ?? Frag;
253
+ const active = value === option.value || value === option.label;
254
+ const selected = index === i;
255
+ const children = option.label ?? option.value;
256
+ return (<button data-value={option.value} {...getItemProps({
257
+ ref: (node) => {
258
+ listRef.current[i] = node;
259
+ },
260
+ role: "option",
261
+ type: "button",
262
+ "aria-checked": active,
263
+ "aria-current": active,
264
+ "aria-selected": active,
265
+ "aria-disabled": option.disabled,
266
+ onClick: () => onSelect(option, i),
267
+ className: `cursor-pointer min-h-10 hover:bg-floating-hover w-full p-2 text-left ${active ? "bg-primary-hover text-primary-foreground" : ""} ${selected ? "bg-floating-hover text-floating-foreground" : ""}`,
268
+ })}>
269
+ <Label {...option} ref={undefined} label={option.label} value={option.value}>
270
+ {children}
271
+ </Label>
272
+ </button>);
273
+ }}/>
274
+ </motion.div>
275
+ </FloatingFocusManager>) : null}
276
+ </FloatingPortal>
277
+ </InputField>);
278
+ });
@@ -0,0 +1,12 @@
1
+ import React from "react";
2
+ import { Override } from "../../types";
3
+ export type CheckboxProps = Override<React.PropsWithChildren<React.ComponentProps<"input">>, {
4
+ error?: string;
5
+ asTask?: boolean;
6
+ loading?: boolean;
7
+ container?: string;
8
+ labelClassName?: string;
9
+ size?: "medium" | "large";
10
+ }>;
11
+ export declare const Checkbox: React.ForwardRefExoticComponent<Omit<CheckboxProps, "ref"> & React.RefAttributes<HTMLInputElement>>;
12
+ //# sourceMappingURL=checkbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkbox.d.ts","sourceRoot":"","sources":["../../../src/components/form/checkbox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAE1C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,MAAM,MAAM,aAAa,GAAG,QAAQ,CAChC,KAAK,CAAC,iBAAiB,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,EACtD;IACI,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;CAC7B,CACJ,CAAC;AAEF,eAAO,MAAM,QAAQ,qGAiCpB,CAAC"}
@@ -0,0 +1,12 @@
1
+ import React, { forwardRef } from "react";
2
+ import { css } from "../../lib/dom";
3
+ export const Checkbox = forwardRef(({ children, asTask = false, labelClassName, loading, error, className = "", size, container, ...props }, ref) => {
4
+ const d = props.disabled || loading;
5
+ return (<label aria-disabled={d} data-disabled={d} data-task={asTask} data-component="checkbox" className={css("group flex w-fit flex-wrap items-center font-normal data-[disabled=true]:cursor-not-allowed", asTask ? "group-checkbox-checked:line-through" : "", container)}>
6
+ <input {...props} ref={ref} disabled={d} type="checkbox" data-task={asTask} className={css("form-checkbox mr-2 inline-block size-4 appearance-none rounded border-card-border bg-origin-border text-primary focus:ring-primary disabled:opacity-70 group-aria-disabled:cursor-not-allowed", className)}/>
7
+ {children}
8
+ <span data-name="checkbox-label" className={css("min-w-full flex-1 text-xs text-danger empty:mt-0 empty:hidden", labelClassName)}>
9
+ {error}
10
+ </span>
11
+ </label>);
12
+ });
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import { Override } from "../../types";
3
+ import { CalendarProps } from "../display/calendar";
4
+ import { InputProps } from "./input";
5
+ export type DatePickerProps = Omit<Override<InputProps, CalendarProps & {
6
+ floating?: boolean;
7
+ clickToClose?: boolean;
8
+ }>, "currency">;
9
+ export declare const DatePicker: React.ForwardRefExoticComponent<Omit<DatePickerProps, "ref"> & React.RefAttributes<HTMLInputElement>>;
10
+ //# sourceMappingURL=date-picker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-picker.d.ts","sourceRoot":"","sources":["../../../src/components/form/date-picker.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAoE,MAAM,OAAO,CAAC;AAIzF,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAY,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAS,UAAU,EAAE,MAAM,SAAS,CAAC;AAE5C,MAAM,MAAM,eAAe,GAAG,IAAI,CAC9B,QAAQ,CACJ,UAAU,EACV,aAAa,GAAG;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B,CACJ,EACD,UAAU,CACb,CAAC;AAkDF,eAAO,MAAM,UAAU,uGAsItB,CAAC"}
@@ -0,0 +1,115 @@
1
+ "use client";
2
+ import { format, isValid, parse, startOfDay } from "date-fns";
3
+ import { CalendarIcon } from "@phosphor-icons/react";
4
+ import React, { forwardRef, Fragment, useEffect, useId, useMemo, useState } from "react";
5
+ import { Is } from "sidekicker";
6
+ import { useLocale } from "../../hooks/use-locale";
7
+ import { useTranslations } from "../../hooks/use-translations";
8
+ import { Calendar } from "../display/calendar";
9
+ import { Dropdown } from "../floating/dropdown";
10
+ import { Input } from "./input";
11
+ const fixedDate = new Date(1970, 11, 31);
12
+ const parts = {
13
+ year: () => [/\d/, /\d/, /\d/, /\d/],
14
+ month: () => [/\d/, /\d/],
15
+ day: () => [/\d/, /\d/],
16
+ hour: () => [/\d/, /\d/],
17
+ minute: () => [/\d/, /\d/],
18
+ literal: (str) => str.split(""),
19
+ };
20
+ const placeholders = {
21
+ day: () => "dd",
22
+ hour: () => "HH",
23
+ month: () => "MM",
24
+ minute: () => "mm",
25
+ year: () => "yyyy",
26
+ literal: (str) => str,
27
+ };
28
+ const partValues = {
29
+ literal: (_, str) => str,
30
+ year: (date) => date.getFullYear().toString(),
31
+ day: (date) => date.getDate().toString().padStart(2, "0"),
32
+ hour: (date) => date.getHours().toString().padStart(2, "0"),
33
+ minute: (date) => date.getMinutes().toString().padStart(2, "0"),
34
+ month: (date) => (date.getMonth() + 1).toString().padStart(2, "0"),
35
+ };
36
+ const formatParts = (datetimeFormat, date) => {
37
+ try {
38
+ return datetimeFormat.formatToParts(date).map((x) => {
39
+ if (x.type === "literal" && x.value === ", ") {
40
+ return { type: x.type, value: " " };
41
+ }
42
+ return x;
43
+ });
44
+ }
45
+ catch (e) {
46
+ return [];
47
+ }
48
+ };
49
+ const DATE_TIME_FORMAT = { day: "numeric", month: "numeric", year: "numeric", hour: "numeric", minute: "numeric" };
50
+ const DATE_FORMAT = { day: "numeric", month: "numeric", year: "numeric" };
51
+ export const DatePicker = forwardRef(({ date, locale: inputLocal, disabledDate, onChange, markToday, clickToClose, floating = true, type, ...props }, externalRef) => {
52
+ const locale = useLocale(inputLocal);
53
+ const labelId = useId();
54
+ const translation = useTranslations();
55
+ const datetimeFormat = useMemo(() => new Intl.DateTimeFormat(locale, type === "datetime" ? DATE_TIME_FORMAT : DATE_FORMAT), [locale, type]);
56
+ const [innerDate, setInnerDate] = useState(date || undefined);
57
+ const [open, setOpen] = useState(false);
58
+ const mask = formatParts(datetimeFormat, fixedDate).flatMap((x) => Is.keyof(parts, x.type) ? parts[x.type](x.value) : []);
59
+ const placeholder = useMemo(() => {
60
+ return formatParts(datetimeFormat, fixedDate).reduce((acc, x) => acc + (Is.keyof(placeholders, x.type) ? placeholders[x.type](x.value) : ""), "");
61
+ }, [datetimeFormat]);
62
+ const isoDateEffect = date?.toISOString();
63
+ const [value, setValue] = useState(!innerDate
64
+ ? ""
65
+ : formatParts(datetimeFormat, innerDate).reduce((acc, x) => acc + (Is.keyof(parts, x.type) ? partValues[x.type](innerDate, x.value) : ""), ""));
66
+ const onChangeDateInput = (e) => {
67
+ const v = e.target.value;
68
+ setValue(v);
69
+ if (mask.length === v.length) {
70
+ const matches = mask.every((x, i) => {
71
+ const c = v.charAt(i);
72
+ return typeof x === "string" ? c === x : x.test(c);
73
+ });
74
+ if (matches) {
75
+ const parsed = parse(v, placeholder, new Date());
76
+ const d = type === "datetime" ? parsed : startOfDay(parsed);
77
+ setInnerDate(d);
78
+ return onChange?.(d);
79
+ }
80
+ }
81
+ setInnerDate(undefined);
82
+ return onChange?.(undefined);
83
+ };
84
+ useEffect(() => {
85
+ if (isValid(date)) {
86
+ setInnerDate(date);
87
+ setValue(format(date, placeholder));
88
+ }
89
+ }, [isoDateEffect, placeholder]);
90
+ const onChangeDate = (d) => {
91
+ setInnerDate(d);
92
+ onChange?.(d);
93
+ if (clickToClose)
94
+ setOpen(false);
95
+ if (d)
96
+ return setValue(format(d, placeholder));
97
+ return setValue("");
98
+ };
99
+ const validDate = isValid(innerDate);
100
+ const htmlValue = validDate ? innerDate.toISOString() : undefined;
101
+ const CalendarComponent = (<Calendar {...props} type={type} locale={locale} changeOnlyOnClick markToday={markToday} onChange={onChangeDate} disabledDate={disabledDate} date={validDate ? innerDate : undefined}/>);
102
+ return (<Fragment>
103
+ <Input {...props} mask={mask} value={value} id={undefined} name={undefined} data-value={htmlValue} formNoValidate={!open} data-target={props.name} data-component="date-picker" onChange={onChangeDateInput} required={props.required ?? true} error={open ? undefined : props.error} placeholder={props.placeholder || translation.datepickerPlaceholder(placeholder)} right={floating ? (<Fragment>
104
+ <input data-origin={props.name} defaultValue={htmlValue} form={props.form} hidden id={props.name} name={props.name} ref={externalRef} type="date"/>
105
+ <Dropdown open={open} onChange={setOpen} buttonProps={{ "aria-describedby": labelId }} trigger={<span aria-labelledby={labelId}>
106
+ <span id={labelId} className="sr-only">
107
+ {translation.datePickerCalendarButtonLabel}
108
+ </span>
109
+ <CalendarIcon />
110
+ </span>}>
111
+ {CalendarComponent}
112
+ </Dropdown>
113
+ </Fragment>) : null}/>
114
+ </Fragment>);
115
+ });
@@ -0,0 +1,15 @@
1
+ import React from "react";
2
+ import { DropzoneProps } from "react-dropzone";
3
+ import { Override } from "sidekicker";
4
+ type Props = Override<React.ComponentProps<"input">, DropzoneProps> & {
5
+ files?: File[];
6
+ idle?: React.ReactElement;
7
+ File?: React.FC<{
8
+ file: File;
9
+ }>;
10
+ onDrop?: (file: File[]) => void;
11
+ onDeleteFile?: (file: File) => void;
12
+ };
13
+ export declare const FileUpload: ({ idle, onDeleteFile, File, onDrop, ...props }: Props) => React.JSX.Element;
14
+ export {};
15
+ //# sourceMappingURL=file-upload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-upload.d.ts","sourceRoot":"","sources":["../../../src/components/form/file-upload.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAmE,MAAM,OAAO,CAAC;AACxF,OAAO,EAAE,aAAa,EAAe,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAatC,KAAK,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC,GAAG;IAClE,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,IAAI,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC;IAC1B,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,CAAC,CAAC;IAChC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IAChC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CACvC,CAAC;AAkJF,eAAO,MAAM,UAAU,GAAI,gDAA8D,KAAK,sBA+B7F,CAAC"}
@@ -0,0 +1,134 @@
1
+ "use client";
2
+ import { WaveformIcon, FileIcon, FileCodeIcon, FileTextIcon, FileVideoIcon, FolderIcon, FolderOpenIcon, TableIcon, XIcon, } from "@phosphor-icons/react";
3
+ import prettyBytes from "pretty-bytes";
4
+ import React, { createContext, Fragment, useContext, useEffect, useState } from "react";
5
+ import { useDropzone } from "react-dropzone";
6
+ import { useTranslations } from "../../hooks/use-translations";
7
+ import { Modal } from "../floating/modal";
8
+ const Context = createContext([null, () => { }]);
9
+ const useFileManager = () => useContext(Context);
10
+ const getMimeType = (file) => {
11
+ if (file.type.startsWith("image/"))
12
+ return "img";
13
+ if (file.type.startsWith("audio/"))
14
+ return "audio";
15
+ if (file.type.startsWith("video/"))
16
+ return "video";
17
+ return file.type;
18
+ };
19
+ const extensionMap = {
20
+ csv: TableIcon,
21
+ xls: TableIcon,
22
+ mov: FileVideoIcon,
23
+ mp4: FileVideoIcon,
24
+ xlsx: TableIcon,
25
+ pdf: FileTextIcon,
26
+ txt: FileTextIcon,
27
+ json: FileCodeIcon,
28
+ mp3: WaveformIcon,
29
+ };
30
+ const ItemViewer = (props) => {
31
+ const [, setManager] = useFileManager();
32
+ const [info, setInfo] = useState({ url: "", type: "", size: "" });
33
+ useEffect(() => {
34
+ const file = props.file;
35
+ const url = URL.createObjectURL(file);
36
+ setInfo({ url, type: getMimeType(file), size: prettyBytes(file.size) });
37
+ return () => URL.revokeObjectURL(url);
38
+ }, [props.file]);
39
+ const onViewFile = (e) => {
40
+ e.stopPropagation();
41
+ e.preventDefault();
42
+ setManager({ ...info, file: props.file });
43
+ };
44
+ const onDeleteFile = (e) => {
45
+ e.preventDefault();
46
+ e.stopPropagation();
47
+ props.onDeleteFile?.(props.file);
48
+ };
49
+ const fileName = props.file.name;
50
+ const Icon = extensionMap[props.file.name.split(".").at(-1)] ?? FileIcon;
51
+ const Element = info.type === "img" ? <img src={info.url} className="w-full object-contain" alt={props.file.name}/> : <Icon size={48}/>;
52
+ return (<li className="flex w-full flex-row justify-between gap-4 border-b border-card-border last:border-b-transparent">
53
+ <div className="flex flex-col gap-4">
54
+ <div className="flex flex-row items-center gap-4">
55
+ <button type="button" onClick={onViewFile} aria-label={`View ${fileName}`} className="m-2 flex size-16 max-w-16 items-center justify-center overflow-hidden">
56
+ {Element}
57
+ </button>
58
+ <div className="flex flex-col items-start justify-start text-left">
59
+ <span>{props.file.name}</span>
60
+ <span className="text-sm italic">{info.size}</span>
61
+ </div>
62
+ </div>
63
+ {props.File ? (<div className="min-w-full flex-1">
64
+ <props.File file={props.file}/>
65
+ </div>) : null}
66
+ </div>
67
+ <div className="align-start flex justify-start py-4 transition-colors duration-300 ease-linear hover:text-danger-hover">
68
+ <button onClick={onDeleteFile} type="button" aria-label={`Remove ${fileName}`} className="flex size-6 items-center justify-center">
69
+ <XIcon size={16} aria-hidden="true"/>
70
+ </button>
71
+ </div>
72
+ </li>);
73
+ };
74
+ const FilesList = (props) => (<ul className="w-full space-y-8">
75
+ {props.files.map((file) => {
76
+ return <ItemViewer File={props.File} onDeleteFile={props.onDeleteFile} key={file.name} file={file}/>;
77
+ })}
78
+ </ul>);
79
+ const Idle = (props) => {
80
+ const t = useTranslations();
81
+ const Icon = props.dragging ? FolderOpenIcon : FolderIcon;
82
+ return (<div className="flex flex-col items-center justify-center">
83
+ <div className="flex flex-col items-center justify-center gap-2">
84
+ <Icon className="text-primary" size={80}/>
85
+ </div>
86
+ <div className="my-4 flex flex-col items-center gap-1">
87
+ <p>{t.uploadIdle}</p>
88
+ <button className="text-primary underline" type="button">
89
+ {t.uploadIdleButton}
90
+ </button>
91
+ </div>
92
+ </div>);
93
+ };
94
+ const InteractiveArea = (props) => {
95
+ if (props.isDragActive)
96
+ return <Idle files={props.files} dragging/>;
97
+ if (props.files.length > 0) {
98
+ return <FilesList File={props.File} onDeleteFile={props.onDeleteFile} files={props.files}/>;
99
+ }
100
+ return <Fragment>{props.idle}</Fragment>;
101
+ };
102
+ const DefaultIdle = <Idle dragging={false}/>;
103
+ const FileViewer = (props) => {
104
+ const file = props.item.file;
105
+ const type = props.item.type;
106
+ return (<div className="flex flex-col gap-4">
107
+ <p className="text-lg font-medium">{props.item.file.name}</p>
108
+ <p className="text-base">{props.item.size}</p>
109
+ {type === "img" ? (<img className="container inline-block w-full max-w-96" src={props.item.url} alt={file.name}/>) : type === "video" ? (<video className="container block w-full max-w-96" src={props.item.url} controls muted/>) : type === "audio" ? (<figure>
110
+ <audio controls src={props.item.url}></audio>
111
+ </figure>) : null}
112
+ </div>);
113
+ };
114
+ export const FileUpload = ({ idle = DefaultIdle, onDeleteFile, File, onDrop, ...props }) => {
115
+ const t = useTranslations();
116
+ const state = useState(null);
117
+ const [files, setFiles] = useState([]);
118
+ const items = props.files ?? files;
119
+ const close = () => state[1](null);
120
+ const drop = (x) => {
121
+ onDrop?.(x);
122
+ setFiles((prev) => prev.concat(x));
123
+ };
124
+ const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop: drop });
125
+ return (<Context.Provider value={state}>
126
+ <Modal overlayClickClose title={t.uploadDialogTitle} ariaTitle={t.uploadDialogTitle} open={state[0] !== null} onChange={close}>
127
+ {state[0] ? <FileViewer item={state[0]}/> : null}
128
+ </Modal>
129
+ <div {...getRootProps()} aria-label={t.fileUploadZoneLabel} data-active={items ? items.length > 0 : false} className="flex flex-col items-center justify-center rounded-lg border border-card-border p-6 text-foreground data-[active=true]:border-solid data-[active=false]:border-dashed data-[active=true]:border-transparent data-[active=true]:bg-card-background">
130
+ <input {...getInputProps(props)} name={props.name} id={props.name}/>
131
+ <InteractiveArea File={File} onDeleteFile={onDeleteFile} isDragActive={isDragActive} idle={idle} files={items}/>
132
+ </div>
133
+ </Context.Provider>);
134
+ };
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ export declare const Form: (props: React.ComponentProps<"form">) => React.JSX.Element;
3
+ //# sourceMappingURL=form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../../src/components/form/form.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,eAAO,MAAM,IAAI,GAAI,OAAO,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,sBAOvD,CAAC"}
@@ -0,0 +1,10 @@
1
+ "use client";
2
+ import React from "react";
3
+ export const Form = (props) => {
4
+ const onSubmit = (e) => {
5
+ e.persist();
6
+ e.preventDefault();
7
+ props.onSubmit?.(e);
8
+ };
9
+ return <form {...props} onSubmit={onSubmit}/>;
10
+ };
@@ -0,0 +1,2 @@
1
+ export declare const formReset: (form?: HTMLFormElement | null) => void;
2
+ //# sourceMappingURL=formReset.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formReset.d.ts","sourceRoot":"","sources":["../../../src/components/form/formReset.tsx"],"names":[],"mappings":"AAEA,eAAO,MAAM,SAAS,GAAI,OAAO,eAAe,GAAG,IAAI,SAatD,CAAC"}