@donotdev/crud 0.0.31 → 0.1.1

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 (326) hide show
  1. package/LICENSE.md +3 -3
  2. package/dist/CrudService.d.ts +13 -4
  3. package/dist/CrudService.d.ts.map +1 -1
  4. package/dist/CrudService.js +2 -2
  5. package/dist/CrudStore.d.ts +1 -1
  6. package/dist/CrudStore.d.ts.map +1 -1
  7. package/dist/CrudStore.js +1 -1
  8. package/dist/FieldRegistry.d.ts +2 -12
  9. package/dist/FieldRegistry.d.ts.map +1 -1
  10. package/dist/FieldRegistry.js +1 -1
  11. package/dist/adapters/FunctionsAdapter.d.ts +3 -3
  12. package/dist/adapters/FunctionsAdapter.d.ts.map +1 -1
  13. package/dist/adapters/FunctionsAdapter.js +1 -1
  14. package/dist/adapters/index.d.ts +1 -1
  15. package/dist/builtinFieldTypes.d.ts +1 -1
  16. package/dist/components/CrudButton.d.ts +1 -0
  17. package/dist/components/CrudButton.d.ts.map +1 -1
  18. package/dist/components/CrudButton.js +1 -1
  19. package/dist/components/CrudCard.d.ts +1 -1
  20. package/dist/components/CrudCard.d.ts.map +1 -1
  21. package/dist/components/CrudCard.js +1 -1
  22. package/dist/components/DateFilter.js +1 -1
  23. package/dist/components/DisplayFieldRenderer.d.ts +2 -1
  24. package/dist/components/DisplayFieldRenderer.d.ts.map +1 -1
  25. package/dist/components/DisplayFieldRenderer.js +1 -1
  26. package/dist/components/DisplayThumbnail.d.ts +1 -9
  27. package/dist/components/DisplayThumbnail.d.ts.map +1 -1
  28. package/dist/components/DisplayThumbnail.js +1 -1
  29. package/dist/components/EntityFilters.d.ts +1 -0
  30. package/dist/components/EntityFilters.d.ts.map +1 -1
  31. package/dist/components/EntityFilters.js +1 -1
  32. package/dist/components/FormFieldRenderer.d.ts +1 -0
  33. package/dist/components/FormFieldRenderer.d.ts.map +1 -1
  34. package/dist/components/FormFieldRenderer.js +1 -1
  35. package/dist/components/FormLayout.d.ts +2 -1
  36. package/dist/components/FormLayout.d.ts.map +1 -1
  37. package/dist/components/FormLayout.js +1 -1
  38. package/dist/components/controlled/complex/ControlledAddressField.js +1 -1
  39. package/dist/components/controlled/complex/ControlledDateField.d.ts.map +1 -1
  40. package/dist/components/controlled/complex/ControlledDateField.js +1 -1
  41. package/dist/components/controlled/complex/ControlledFieldArrayField.js +1 -1
  42. package/dist/components/controlled/complex/ControlledGeoPointField.js +1 -1
  43. package/dist/components/controlled/complex/ControlledMapField.js +1 -1
  44. package/dist/components/controlled/complex/ControlledMultiInputField.js +1 -1
  45. package/dist/components/controlled/complex/ControlledRichTextField.js +1 -1
  46. package/dist/components/controlled/complex/ControlledTimestampField.d.ts.map +1 -1
  47. package/dist/components/controlled/complex/ControlledTimestampField.js +1 -1
  48. package/dist/components/controlled/complex/index.js +1 -1
  49. package/dist/components/controlled/file/ControlledDocumentField.js +1 -1
  50. package/dist/components/controlled/file/ControlledFileField.js +1 -1
  51. package/dist/components/controlled/file/ControlledImageField.js +1 -1
  52. package/dist/components/controlled/file/ControlledMultiDocumentField.js +1 -1
  53. package/dist/components/controlled/file/ControlledMultiFileField.js +1 -1
  54. package/dist/components/controlled/file/ControlledMultiImageField.js +1 -1
  55. package/dist/components/controlled/file/index.js +1 -1
  56. package/dist/components/controlled/index.js +1 -1
  57. package/dist/components/controlled/input/ControlledCheckboxField.js +1 -1
  58. package/dist/components/controlled/input/ControlledCurrencyField.js +1 -1
  59. package/dist/components/controlled/input/ControlledDurationField.js +1 -1
  60. package/dist/components/controlled/input/ControlledGdprConsentField.js +1 -1
  61. package/dist/components/controlled/input/ControlledNumberField.js +1 -1
  62. package/dist/components/controlled/input/ControlledPasswordField.js +1 -1
  63. package/dist/components/controlled/input/ControlledPhoneField.js +1 -1
  64. package/dist/components/controlled/input/ControlledPriceField.js +1 -1
  65. package/dist/components/controlled/input/ControlledRangeField.js +1 -1
  66. package/dist/components/controlled/input/ControlledRatingField.js +1 -1
  67. package/dist/components/controlled/input/ControlledSwitchField.js +1 -1
  68. package/dist/components/controlled/input/ControlledTextField.d.ts +5 -5
  69. package/dist/components/controlled/input/ControlledTextField.d.ts.map +1 -1
  70. package/dist/components/controlled/input/ControlledTextField.js +1 -1
  71. package/dist/components/controlled/input/ControlledTextareaField.js +1 -1
  72. package/dist/components/controlled/input/index.js +1 -1
  73. package/dist/components/controlled/select/ControlledComboboxField.js +1 -1
  74. package/dist/components/controlled/select/ControlledDropdownField.d.ts +2 -4
  75. package/dist/components/controlled/select/ControlledDropdownField.d.ts.map +1 -1
  76. package/dist/components/controlled/select/ControlledDropdownField.js +1 -1
  77. package/dist/components/controlled/select/ControlledMultiDropdownField.d.ts +2 -4
  78. package/dist/components/controlled/select/ControlledMultiDropdownField.d.ts.map +1 -1
  79. package/dist/components/controlled/select/ControlledMultiDropdownField.js +1 -1
  80. package/dist/components/controlled/select/ControlledRadioField.d.ts +2 -4
  81. package/dist/components/controlled/select/ControlledRadioField.d.ts.map +1 -1
  82. package/dist/components/controlled/select/ControlledRadioField.js +1 -1
  83. package/dist/components/controlled/select/ControlledReferenceField.js +1 -1
  84. package/dist/components/controlled/select/ControlledYearField.js +1 -1
  85. package/dist/components/controlled/select/index.js +1 -1
  86. package/dist/components/controlled/types.js +1 -1
  87. package/dist/components/fields/display/AvatarFieldDisplay.d.ts +1 -1
  88. package/dist/components/fields/display/AvatarFieldDisplay.js +1 -1
  89. package/dist/components/fields/display/BadgeFieldDisplay.d.ts +1 -1
  90. package/dist/components/fields/display/BadgeFieldDisplay.js +1 -1
  91. package/dist/components/fields/display/ButtonFieldDisplay.d.ts +2 -2
  92. package/dist/components/fields/display/ButtonFieldDisplay.js +1 -1
  93. package/dist/components/fields/display/CheckboxFieldDisplay.d.ts +1 -1
  94. package/dist/components/fields/display/CheckboxFieldDisplay.js +1 -1
  95. package/dist/components/fields/display/DateFieldDisplay.d.ts +1 -1
  96. package/dist/components/fields/display/DateFieldDisplay.d.ts.map +1 -1
  97. package/dist/components/fields/display/DateFieldDisplay.js +1 -1
  98. package/dist/components/fields/display/DropdownDisplay.d.ts +1 -1
  99. package/dist/components/fields/display/DropdownDisplay.js +1 -1
  100. package/dist/components/fields/display/FileFieldDisplay.d.ts +1 -1
  101. package/dist/components/fields/display/FileFieldDisplay.js +1 -1
  102. package/dist/components/fields/display/GeoPointFieldDisplay.d.ts +1 -1
  103. package/dist/components/fields/display/GeoPointFieldDisplay.js +1 -1
  104. package/dist/components/fields/display/HiddenFieldDisplay.d.ts +2 -2
  105. package/dist/components/fields/display/HiddenFieldDisplay.js +1 -1
  106. package/dist/components/fields/display/ImageFieldDisplay.d.ts +1 -1
  107. package/dist/components/fields/display/ImageFieldDisplay.js +1 -1
  108. package/dist/components/fields/display/LinkFieldDisplay.d.ts +1 -1
  109. package/dist/components/fields/display/LinkFieldDisplay.js +1 -1
  110. package/dist/components/fields/display/MapFieldDisplay.d.ts +1 -1
  111. package/dist/components/fields/display/MapFieldDisplay.js +1 -1
  112. package/dist/components/fields/display/MultiDropdownDisplay.d.ts +1 -1
  113. package/dist/components/fields/display/MultiDropdownDisplay.js +1 -1
  114. package/dist/components/fields/display/MultiInputTextFieldDisplay.d.ts +1 -1
  115. package/dist/components/fields/display/MultiInputTextFieldDisplay.js +1 -1
  116. package/dist/components/fields/display/NumberFieldDisplay.d.ts +1 -1
  117. package/dist/components/fields/display/NumberFieldDisplay.d.ts.map +1 -1
  118. package/dist/components/fields/display/NumberFieldDisplay.js +1 -1
  119. package/dist/components/fields/display/PasswordFieldDisplay.d.ts +1 -1
  120. package/dist/components/fields/display/PasswordFieldDisplay.js +1 -1
  121. package/dist/components/fields/display/PhoneNumberDisplay.d.ts +1 -1
  122. package/dist/components/fields/display/PhoneNumberDisplay.js +1 -1
  123. package/dist/components/fields/display/RadioFieldDisplay.d.ts +1 -1
  124. package/dist/components/fields/display/RadioFieldDisplay.js +1 -1
  125. package/dist/components/fields/display/RangeFieldDisplay.d.ts +1 -1
  126. package/dist/components/fields/display/RangeFieldDisplay.js +1 -1
  127. package/dist/components/fields/display/ReferenceFieldDisplay.d.ts +1 -1
  128. package/dist/components/fields/display/ReferenceFieldDisplay.js +1 -1
  129. package/dist/components/fields/display/RichTextDisplay.d.ts +1 -1
  130. package/dist/components/fields/display/RichTextDisplay.js +2 -2
  131. package/dist/components/fields/display/TextAreaDisplay.d.ts +1 -1
  132. package/dist/components/fields/display/TextAreaDisplay.js +1 -1
  133. package/dist/components/fields/display/TextFieldDisplay.d.ts +1 -1
  134. package/dist/components/fields/display/TextFieldDisplay.js +1 -1
  135. package/dist/components/fields/display/TimestampFieldDisplay.d.ts +1 -1
  136. package/dist/components/fields/display/TimestampFieldDisplay.d.ts.map +1 -1
  137. package/dist/components/fields/display/TimestampFieldDisplay.js +1 -1
  138. package/dist/components/fields/display/index.d.ts +1 -1
  139. package/dist/components/fields/display/index.js +1 -1
  140. package/dist/components/form/fields/AddressFieldComponent.js +1 -1
  141. package/dist/components/form/fields/AvatarFieldComponent.d.ts +2 -2
  142. package/dist/components/form/fields/AvatarFieldComponent.js +1 -1
  143. package/dist/components/form/fields/BadgeFieldComponent.d.ts +2 -2
  144. package/dist/components/form/fields/BadgeFieldComponent.js +1 -1
  145. package/dist/components/form/fields/ButtonFieldComponent.js +1 -1
  146. package/dist/components/form/fields/CheckboxFieldComponent.d.ts +1 -1
  147. package/dist/components/form/fields/CheckboxFieldComponent.js +1 -1
  148. package/dist/components/form/fields/ComboboxComponent.d.ts +1 -1
  149. package/dist/components/form/fields/ComboboxComponent.js +1 -1
  150. package/dist/components/form/fields/CurrencyFieldComponent.d.ts +1 -1
  151. package/dist/components/form/fields/CurrencyFieldComponent.d.ts.map +1 -1
  152. package/dist/components/form/fields/CurrencyFieldComponent.js +1 -1
  153. package/dist/components/form/fields/DateFieldComponent.d.ts +3 -3
  154. package/dist/components/form/fields/DateFieldComponent.d.ts.map +1 -1
  155. package/dist/components/form/fields/DateFieldComponent.js +1 -1
  156. package/dist/components/form/fields/DocumentFieldComponent.js +1 -1
  157. package/dist/components/form/fields/DropdownComponent.d.ts +1 -1
  158. package/dist/components/form/fields/DropdownComponent.js +1 -1
  159. package/dist/components/form/fields/DurationFieldComponent.js +1 -1
  160. package/dist/components/form/fields/FileFieldComponent.js +1 -1
  161. package/dist/components/form/fields/GdprConsentFieldComponent.d.ts +1 -1
  162. package/dist/components/form/fields/GdprConsentFieldComponent.js +1 -1
  163. package/dist/components/form/fields/GeoPointFieldComponent.d.ts +1 -1
  164. package/dist/components/form/fields/GeoPointFieldComponent.js +1 -1
  165. package/dist/components/form/fields/HiddenFieldComponent.d.ts +1 -1
  166. package/dist/components/form/fields/HiddenFieldComponent.js +1 -1
  167. package/dist/components/form/fields/ImageFieldComponent.d.ts.map +1 -1
  168. package/dist/components/form/fields/ImageFieldComponent.js +1 -1
  169. package/dist/components/form/fields/MapFieldComponent.js +1 -1
  170. package/dist/components/form/fields/MultiDropdownComponent.d.ts +1 -1
  171. package/dist/components/form/fields/MultiDropdownComponent.js +1 -1
  172. package/dist/components/form/fields/MultiInputTextFieldComponent.js +1 -1
  173. package/dist/components/form/fields/NumberFieldComponent.d.ts +1 -1
  174. package/dist/components/form/fields/NumberFieldComponent.js +1 -1
  175. package/dist/components/form/fields/PasswordFieldComponent.d.ts +1 -1
  176. package/dist/components/form/fields/PasswordFieldComponent.js +1 -1
  177. package/dist/components/form/fields/PhoneNumberComponent.d.ts +1 -1
  178. package/dist/components/form/fields/PhoneNumberComponent.js +1 -1
  179. package/dist/components/form/fields/PriceFieldComponent.js +1 -1
  180. package/dist/components/form/fields/RadioFieldComponent.js +1 -1
  181. package/dist/components/form/fields/RangeFieldComponent.d.ts +1 -1
  182. package/dist/components/form/fields/RangeFieldComponent.js +1 -1
  183. package/dist/components/form/fields/RatingFieldComponent.d.ts +1 -1
  184. package/dist/components/form/fields/RatingFieldComponent.js +1 -1
  185. package/dist/components/form/fields/ReferenceFieldComponent.js +1 -1
  186. package/dist/components/form/fields/RichTextComponent.d.ts +1 -1
  187. package/dist/components/form/fields/RichTextComponent.js +1 -1
  188. package/dist/components/form/fields/SwitchFieldComponent.d.ts +1 -1
  189. package/dist/components/form/fields/SwitchFieldComponent.js +1 -1
  190. package/dist/components/form/fields/TextAreaComponent.d.ts +1 -1
  191. package/dist/components/form/fields/TextAreaComponent.js +1 -1
  192. package/dist/components/form/fields/TextFieldComponent.d.ts +4 -4
  193. package/dist/components/form/fields/TextFieldComponent.d.ts.map +1 -1
  194. package/dist/components/form/fields/TextFieldComponent.js +1 -1
  195. package/dist/components/form/fields/TimestampFieldComponent.d.ts +2 -2
  196. package/dist/components/form/fields/TimestampFieldComponent.d.ts.map +1 -1
  197. package/dist/components/form/fields/TimestampFieldComponent.js +1 -1
  198. package/dist/components/form/fields/index.d.ts +1 -1
  199. package/dist/components/form/fields/index.js +1 -1
  200. package/dist/components/form/fields/internal/TiptapEditor.d.ts +1 -1
  201. package/dist/components/form/fields/internal/TiptapEditor.js +2 -2
  202. package/dist/components/form/fields/types.d.ts +1 -1
  203. package/dist/components/form/index.d.ts +1 -1
  204. package/dist/components/form/internal/ImageViewerDialog.js +1 -1
  205. package/dist/components/index.d.ts +1 -1
  206. package/dist/components/index.js +1 -1
  207. package/dist/contexts/UploadContext.d.ts +1 -0
  208. package/dist/contexts/UploadContext.d.ts.map +1 -1
  209. package/dist/contexts/UploadContext.js +1 -1
  210. package/dist/contexts/index.js +1 -1
  211. package/dist/fieldTypeRegistry.d.ts.map +1 -1
  212. package/dist/fieldTypeRegistry.js +1 -1
  213. package/dist/fieldTypeRegistry.store.d.ts.map +1 -1
  214. package/dist/fieldTypeRegistry.store.js +1 -1
  215. package/dist/fieldTypeRegistry.types.d.ts +4 -0
  216. package/dist/fieldTypeRegistry.types.d.ts.map +1 -1
  217. package/dist/forms/hooks/index.d.ts +1 -1
  218. package/dist/forms/hooks/index.js +1 -1
  219. package/dist/forms/hooks/useController.js +1 -1
  220. package/dist/forms/hooks/useEntityField.d.ts +1 -1
  221. package/dist/forms/hooks/useEntityField.js +1 -1
  222. package/dist/forms/hooks/useEntityForm.d.ts.map +1 -1
  223. package/dist/forms/hooks/useEntityForm.js +1 -1
  224. package/dist/forms/index.d.ts +1 -1
  225. package/dist/forms/index.js +1 -1
  226. package/dist/forms/types.d.ts +12 -7
  227. package/dist/forms/types.d.ts.map +1 -1
  228. package/dist/forms/utils/buildInitialValues.d.ts.map +1 -1
  229. package/dist/forms/utils/buildInitialValues.js +1 -1
  230. package/dist/forms/utils/getFieldsForOperation.d.ts +2 -2
  231. package/dist/forms/utils/getFieldsForOperation.d.ts.map +1 -1
  232. package/dist/forms/utils/getFieldsForOperation.js +1 -1
  233. package/dist/forms/utils/index.d.ts +1 -1
  234. package/dist/forms/utils/index.js +1 -1
  235. package/dist/forms/utils/isFieldEditable.d.ts +8 -2
  236. package/dist/forms/utils/isFieldEditable.d.ts.map +1 -1
  237. package/dist/forms/utils/isFieldEditable.js +1 -1
  238. package/dist/forms/utils/translateFieldLabel.d.ts +3 -3
  239. package/dist/forms/utils/translateFieldLabel.js +1 -1
  240. package/dist/forms/utils/validateEntity.d.ts +1 -1
  241. package/dist/forms/utils/validateEntity.js +1 -1
  242. package/dist/hooks/index.d.ts +2 -0
  243. package/dist/hooks/index.d.ts.map +1 -1
  244. package/dist/hooks/index.js +1 -1
  245. package/dist/hooks/useCrudFilters.d.ts +2 -0
  246. package/dist/hooks/useCrudFilters.d.ts.map +1 -1
  247. package/dist/hooks/useCrudFilters.js +1 -1
  248. package/dist/hooks/useCrudPageSize.d.ts +29 -0
  249. package/dist/hooks/useCrudPageSize.d.ts.map +1 -0
  250. package/dist/hooks/useCrudPageSize.js +1 -0
  251. package/dist/hooks/useEntityFavorites.d.ts +2 -0
  252. package/dist/hooks/useEntityFavorites.d.ts.map +1 -1
  253. package/dist/hooks/useEntityFavorites.js +1 -1
  254. package/dist/hooks/useFieldConditions.js +1 -1
  255. package/dist/hooks/useFileUpload.d.ts.map +1 -1
  256. package/dist/hooks/useFileUpload.js +1 -1
  257. package/dist/hooks/useReferenceResolver.d.ts +1 -1
  258. package/dist/hooks/useReferenceResolver.d.ts.map +1 -1
  259. package/dist/hooks/useReferenceResolver.js +1 -1
  260. package/dist/hooks/useRelatedItems.d.ts +2 -0
  261. package/dist/hooks/useRelatedItems.d.ts.map +1 -1
  262. package/dist/hooks/useRelatedItems.js +1 -1
  263. package/dist/hooks/useUnsavedChangesWarning.js +1 -1
  264. package/dist/index.d.ts +4 -4
  265. package/dist/index.d.ts.map +1 -1
  266. package/dist/index.js +1 -1
  267. package/dist/registerBuiltinFieldTypes.d.ts.map +1 -1
  268. package/dist/registerBuiltinFieldTypes.js +1 -1
  269. package/dist/stores/FormStore.d.ts +2 -0
  270. package/dist/stores/FormStore.d.ts.map +1 -1
  271. package/dist/stores/FormStore.js +1 -1
  272. package/dist/stores/UploadStore.d.ts +9 -3
  273. package/dist/stores/UploadStore.d.ts.map +1 -1
  274. package/dist/stores/UploadStore.js +1 -1
  275. package/dist/stores/index.d.ts +1 -1
  276. package/dist/stores/index.js +1 -1
  277. package/dist/symbol-index.json +1 -0
  278. package/dist/tsconfig.tsbuildinfo +1 -1
  279. package/dist/types.d.ts +10 -4
  280. package/dist/types.d.ts.map +1 -1
  281. package/dist/types.js +1 -1
  282. package/dist/useBaseCrudList.js +1 -1
  283. package/dist/useCrud.d.ts +1 -0
  284. package/dist/useCrud.d.ts.map +1 -1
  285. package/dist/useCrud.js +1 -1
  286. package/dist/useCrudCardList.d.ts +5 -3
  287. package/dist/useCrudCardList.d.ts.map +1 -1
  288. package/dist/useCrudCardList.js +1 -1
  289. package/dist/useCrudList.d.ts +5 -3
  290. package/dist/useCrudList.d.ts.map +1 -1
  291. package/dist/useCrudList.js +1 -1
  292. package/dist/utils/clientListProcessing.d.ts +22 -3
  293. package/dist/utils/clientListProcessing.d.ts.map +1 -1
  294. package/dist/utils/clientListProcessing.js +1 -1
  295. package/dist/utils/collections.d.ts +6 -6
  296. package/dist/utils/collections.js +1 -1
  297. package/dist/utils/fileStorage.d.ts +2 -0
  298. package/dist/utils/fileStorage.d.ts.map +1 -1
  299. package/dist/utils/fileStorage.js +1 -1
  300. package/dist/utils/imageProcessing.d.ts +1 -1
  301. package/dist/utils/imageProcessing.d.ts.map +1 -1
  302. package/dist/utils/imageProcessing.js +1 -1
  303. package/dist/utils/imageStorage.d.ts +2 -0
  304. package/dist/utils/imageStorage.d.ts.map +1 -1
  305. package/dist/utils/imageStorage.js +1 -1
  306. package/dist/utils/imageUtils.d.ts +1 -1
  307. package/dist/utils/imageUtils.js +1 -1
  308. package/dist/utils/matchesFilter.d.ts.map +1 -1
  309. package/dist/utils/matchesFilter.js +1 -1
  310. package/dist/utils/mergeWithOptimistic.js +1 -1
  311. package/dist/utils/sanitizeHtml.d.ts +0 -5
  312. package/dist/utils/sanitizeHtml.d.ts.map +1 -1
  313. package/dist/utils/sanitizeHtml.js +1 -1
  314. package/dist/utils/scopeUtils.js +1 -1
  315. package/dist/utils/uploadValidation.d.ts +1 -1
  316. package/dist/utils/uploadValidation.js +1 -1
  317. package/dist/workflows/WorkflowPersistence.d.ts +1 -1
  318. package/dist/workflows/WorkflowPersistence.js +1 -1
  319. package/dist/workflows/defineWorkflow.d.ts +1 -1
  320. package/dist/workflows/index.d.ts +1 -1
  321. package/dist/workflows/index.js +1 -1
  322. package/dist/workflows/useEntityWorkflow.js +1 -1
  323. package/guidelines/COMPONENTS.md +234 -0
  324. package/guidelines/CRUD.md +340 -0
  325. package/guidelines/GOTCHAS.md +46 -0
  326. package/package.json +7 -4
@@ -1 +1 @@
1
- "use client";import{jsx as p,jsxs as f}from"react/jsx-runtime";import{Text as m,Stack as b,ImageGallery as V,Rating as L,CopyToClipboard as w}from"@donotdev/components";import{formatCurrency as F}from"@donotdev/core";import{ControlledCheckboxField as k,ControlledComboboxField as $,ControlledDateField as h,ControlledDropdownField as I,ControlledFileField as N,ControlledMultiFileField as M,ControlledDocumentField as P,ControlledMultiDocumentField as R,ControlledGeoPointField as B,ControlledImageField as _,ControlledMapField as E,ControlledMultiDropdownField as U,ControlledMultiInputField as H,ControlledNumberField as K,ControlledPasswordField as Y,ControlledPhoneField as G,ControlledRangeField as O,ControlledRatingField as J,ControlledDurationField as W,ControlledRadioField as q,ControlledReferenceField as Q,ControlledYearField as X,ControlledTextField as g,ControlledTextareaField as Z,ControlledRichTextField as ee,ControlledTimestampField as te,ControlledAddressField as re,ControlledFieldArrayField as oe,ControlledSwitchField as ne,ControlledMultiImageField as le,ControlledGdprConsentField as ae,ControlledCurrencyField as ie,ControlledPriceField as ce}from"./components/controlled";import{AvatarFieldComponent as se,BadgeFieldComponent as pe,ButtonFieldComponent as A,HiddenFieldComponent as de,TextAreaComponent as ue,RichTextComponent as ye,TextFieldComponent as T}from"./components/form/fields";import{translateLabel as v}from"./forms/utils";import{sanitizeHtml as fe}from"./utils/sanitizeHtml";function d(e){return e?p("span",{style:{color:"var(--muted-foreground)"},children:"\u2014"}):p(m,{variant:"muted",children:"\u2014"})}const i={timestamp:(e,a,r,o)=>{const t=o?.compact??!1;if(e==null||e==="")return d(t);try{return(e instanceof Date?e:new Date(e)).toLocaleString()}catch{return String(e)}},date:(e,a,r,o)=>{const t=o?.compact??!1;if(e==null||e==="")return d(t);try{return(e instanceof Date?e:new Date(e)).toLocaleDateString()}catch{return String(e)}},"datetime-local":(e,a,r,o)=>{const t=o?.compact??!1;if(e==null||e==="")return d(t);try{return(e instanceof Date?e:new Date(e)).toLocaleString()}catch{return String(e)}},time:(e,a,r,o)=>{const t=o?.compact??!1;if(e==null||e==="")return d(t);try{return(e instanceof Date?e:new Date(e)).toLocaleTimeString()}catch{return String(e)}},week:(e,a,r,o)=>{const t=o?.compact??!1;return e==null||e===""?d(t):String(e)},month:(e,a,r,o)=>{const t=o?.compact??!1;return e==null||e===""?d(t):String(e)},boolean:(e,a,r)=>e?"Yes":"No",checkbox:(e,a,r)=>e?"Yes":"No",switch:(e,a,r)=>{const o=a.options?.fieldSpecific;if(o){const t=o.uncheckedValue??!1,n=o.checkedValue??!0;if(e===n&&o.checkedLabel)return v(o.checkedLabel,r);if(e===t&&o.uncheckedLabel)return v(o.uncheckedLabel,r)}return e?"Yes":"No"},year:(e,a,r)=>String(e),number:e=>e==null||e===""?"\u2014":typeof e=="number"?e.toLocaleString():String(e),currency:(e,a,r)=>{if(e==null||isNaN(e))return"";const o=(a.options||{}).fieldSpecific?.currency||"EUR";return F(e,o)},price:(e,a,r,o)=>{const t=o?.compact??!1,n=o?.asString??!1,l=e!=null&&typeof e=="number"?{amount:e,currency:"EUR",vatIncluded:!0,discountPercent:0}:e;if(l==null||typeof l!="object")return d(t);const c=l.amount;if(c==null||isNaN(c))return d(t);const s=l.currency||"EUR",y=l.vatIncluded??!0,u=l.discountPercent??0,x=u>0?c*(1-u/100):c,C=y?` ${r("crud:price.vatIncluded",{defaultValue:"VAT Incl."})}`:"";if(u>0){const z=F(c,s),S=F(x,s),j=` ${r("crud:price.discountPercent",{percent:Math.round(u),defaultValue:"-{{percent}}%"})}`;return n?`${S}${C}${j}`:t?f(m,{variant:"success",weight:"bold",children:[S,C,j]}):f(b,{direction:"column",gap:"tight",align:"end",children:[p(m,{variant:"muted",style:{textDecoration:"line-through",fontSize:"var(--font-size-sm)"},children:z}),f(m,{variant:"success",weight:"bold",children:[S,C]})]})}return`${F(c,s)}${C}`},range:(e,a,r)=>typeof e=="number"?e.toLocaleString():String(e),rating:(e,a,r,o)=>{const t=o?.compact??!1;if(e==null)return d(t);const n=typeof e=="number"?e:parseFloat(e);if(isNaN(n))return d(t);const l=a.validation?.max??5;return p(L,{value:n,max:l,readonly:!0,"aria-label":`${n} out of ${l} stars`})},duration:(e,a,r,o)=>{const t=o?.compact??!1;if(e==null)return d(t);const n=typeof e=="number"?e:parseInt(String(e),10);if(Number.isNaN(n))return d(t);if(n===0)return r("crud:duration.zero",{defaultValue:"\u2014"});if(n<60)return r("crud:duration.minutes",{count:n,defaultValue:`${n} min`});const l=Math.floor(n/60),c=n%60;return r("crud:duration.hoursMinutes",{hours:l,minutes:c,defaultValue:c===0?`${l}h`:`${l}h ${c}min`})},gdprConsent:(e,a,r,o)=>{const t=o?.compact??!1;if(!e||typeof e!="object")return d(t);const n=e.gdprConsent===!0,l=e.gdprConsentDate,c=e.gdprConsentVersion,s=r("crud:gdprConsent.display.yes",{defaultValue:"Consented"}),y=r("crud:gdprConsent.display.no",{defaultValue:"Not consented"});if(!n)return y;const u=[s];if(l)try{const x=new Date(l);u.push(x.toLocaleDateString())}catch{u.push(l)}return c&&u.push(`v${c}`),u.join(" \xB7 ")},select:(e,a,r)=>{const o=a.validation?.options;if(Array.isArray(o)){const t=o.find(n=>n.value===e)?.label;return t?v(t,r):String(e)}return String(e)},radio:(e,a,r)=>{const o=a.validation?.options;if(Array.isArray(o)){const t=o.find(n=>n.value===e)?.label;return t?v(t,r):String(e)}return String(e)},combobox:(e,a,r)=>{const o=a.validation?.options;if(Array.isArray(o)){const t=o.find(n=>n.value===e)?.label;return t?v(t,r):String(e)}return String(e)},multiselect:(e,a,r)=>{if(Array.isArray(e)){const o=a.validation?.options;if(Array.isArray(o))return e.map(t=>{const n=o.find(l=>l.value===t)?.label;return n?v(n,r):t}).join(", ")}return String(e)},image:(e,a,r,o)=>{const t=o?.compact??!1;return e==null||e===""?d(t):typeof e=="string"?p("img",{src:e,alt:a.label||"",style:{width:t?"40px":void 0,height:t?"40px":void 0,maxWidth:t?void 0:"200px",maxHeight:t?void 0:"150px",objectFit:"cover",borderRadius:"var(--radius-sm)"}}):d(t)},images:(e,a,r,o)=>{const t=o?.compact??!1;if(!Array.isArray(e)||e.length===0)return d(t);const n=e[0],l=typeof n=="object"&&n.thumbUrl?n.thumbUrl:n;return t?f("div",{style:{display:"flex",alignItems:"center",gap:"var(--gap-xs)"},children:[p("img",{src:l,alt:"",style:{width:"40px",height:"40px",objectFit:"cover",borderRadius:"var(--radius-sm)"}}),e.length>1&&f("span",{style:{fontSize:"var(--font-size-xs)",color:"var(--muted-foreground)"},children:["+",e.length-1]})]}):p(V,{images:e,altPrefix:a.label||"Image"})},files:(e,a,r,o)=>{const t=o?.compact??!1;return!Array.isArray(e)||e.length===0?d(t):p(b,{gap:"tight",children:e.map((n,l)=>f("a",{href:n.url||n,target:"_blank",rel:"noopener noreferrer",style:{color:"var(--primary)",textDecoration:"none",display:"flex",alignItems:"center",fontSize:"var(--font-size-sm)"},children:[n.filename||`File ${l+1}`,n.size&&f(m,{level:"caption",variant:"muted",style:{marginLeft:"var(--gap-sm)"},children:["(",Math.round(n.size/1024)," KB)"]})]},l))})},documents:(e,a,r,o)=>{const t=o?.compact??!1;return!Array.isArray(e)||e.length===0?d(t):p(b,{gap:"tight",children:e.map((n,l)=>f("a",{href:n.url||n,target:"_blank",rel:"noopener noreferrer",style:{color:"var(--primary)",textDecoration:"none",display:"flex",alignItems:"center",fontSize:"var(--font-size-sm)"},children:[n.filename||`File ${l+1}`,n.size&&f(m,{level:"caption",variant:"muted",style:{marginLeft:"var(--gap-sm)"},children:["(",Math.round(n.size/1024)," KB)"]})]},l))})},file:(e,a,r,o)=>{const t=o?.compact??!1;if(!e)return d(t);const n=typeof e=="string"?e:e.url,l=typeof e=="string"?"View file":e.filename||"View file";return f("a",{href:n,target:"_blank",rel:"noopener noreferrer",style:{color:"var(--primary)",textDecoration:"none"},children:[l,typeof e=="object"&&e.size&&f("span",{style:{color:"var(--muted-foreground)",marginLeft:"var(--gap-sm)"},children:["(",Math.round(e.size/1024)," KB)"]})]})},document:(e,a,r,o)=>{const t=o?.compact??!1;if(!e)return d(t);const n=typeof e=="string"?e:e.url,l=typeof e=="string"?"View file":e.filename||"View file";return f("a",{href:n,target:"_blank",rel:"noopener noreferrer",style:{color:"var(--primary)",textDecoration:"none"},children:[l,typeof e=="object"&&e.size&&f("span",{style:{color:"var(--muted-foreground)",marginLeft:"var(--gap-sm)"},children:["(",Math.round(e.size/1024)," KB)"]})]})},reference:(e,a,r,o)=>{const t=o?.compact??!1;if(!e)return d(t);const n=a.validation?.reference;if(o?.referenceData&&typeof n=="string"){const l=o.referenceData[n]?.[String(e)];if(l)return l}if(typeof e=="object"&&e!==null){const l=e.displayName||e.name||e.id||String(e);return String(l)}return String(e)},geopoint:(e,a,r,o)=>{const t=o?.compact??!1;return e&&typeof e=="object"&&"lat"in e&&"lng"in e?`${e.lat.toFixed(6)}, ${e.lng.toFixed(6)}`:d(t)},address:(e,a,r)=>e&&typeof e=="object"&&"formatted_address"in e?e.formatted_address:String(e),map:(e,a,r,o)=>{const t=o?.compact??!1;if(e&&typeof e=="object"){const n=Object.entries(e);return n.length===0?d(t):f(b,{direction:"column",gap:"tight",children:[n.slice(0,5).map(([l,c])=>f(m,{style:{fontSize:"var(--font-size-sm)"},children:[f("strong",{children:[l,":"]})," ",String(c)]},l)),n.length>5&&f(m,{variant:"muted",children:["+",n.length-5," more"]})]})}return d(t)},array:(e,a,r,o)=>{const t=o?.compact??!1;return Array.isArray(e)?e.length===0?d(t):e.join(", "):d(t)},"field-array":(e,a,r,o)=>{const t=o?.compact??!1;if(!Array.isArray(e)||e.length===0)return d(t);const n=a.options?.fieldSpecific?.fields;return e.map(l=>{if(typeof l!="object"||l==null)return"";const c=l;return(n?n.map(s=>s.name):Object.keys(c)).map(s=>c[s]).filter(s=>s!=null&&s!=="").map(s=>typeof s=="object"?JSON.stringify(s):String(s)).join(" \xB7 ")}).filter(Boolean).join(", ")},password:()=>"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",email:(e,a,r)=>f(b,{direction:"row",gap:"tight",align:"center",children:[p("a",{href:`mailto:${e}`,style:{color:"var(--primary)",flex:1},onClick:o=>o.stopPropagation(),children:e}),p(w,{text:e,tooltipText:r("crud:copyToClipboard",{defaultValue:"Copy to clipboard"}),ariaLabel:r("crud:actions.copyEmail",{defaultValue:"Copy email"}),onClick:o=>o.stopPropagation()})]}),tel:(e,a,r)=>f(b,{direction:"row",gap:"tight",align:"center",children:[p("a",{href:`tel:${e}`,style:{color:"var(--primary)",flex:1},onClick:o=>o.stopPropagation(),children:e}),p(w,{text:e,tooltipText:r("crud:copyToClipboard",{defaultValue:"Copy to clipboard"}),ariaLabel:r("crud:actions.copyPhone",{defaultValue:"Copy phone"}),onClick:o=>o.stopPropagation()})]}),iban:(e,a,r,o)=>{const t=o?.compact??!1;return e?f(b,{direction:"row",gap:"tight",align:"center",children:[p(m,{style:{flex:1},children:e}),p(w,{text:e,tooltipText:r("crud:copyToClipboard",{defaultValue:"Copy to clipboard"}),ariaLabel:r("crud:actions.copyIban",{defaultValue:"Copy IBAN"}),onClick:n=>n.stopPropagation()})]}):d(t)},url:(e,a,r)=>p("a",{href:e,target:"_blank",rel:"noopener noreferrer",style:{color:"var(--primary)"},children:e}),color:(e,a,r)=>f(b,{direction:"row",gap:"tight",align:"center",children:[p("div",{style:{width:"20px",height:"20px",backgroundColor:e,borderRadius:"var(--radius-sm)",border:"1px solid var(--border)"}}),p(m,{children:e})]}),textarea:(e,a,r)=>String(e),text:(e,a,r)=>String(e),richtext:(e,a,r,o)=>{const t=o?.compact??!1;return e&&typeof e=="string"?t?e.replace(/<[^>]*>/g,"").trim()||p("span",{style:{color:"var(--muted-foreground)"},children:"\u2014"}):p("div",{dangerouslySetInnerHTML:{__html:fe(e)},style:{padding:"var(--gap-sm)",fontSize:"var(--font-size-sm)",lineHeight:"1.6"}}):d(t)}};function me(e){return e.type==="avatar"}function ge(e){return e.type==="badge"}let D=!1;function be(e,a){if(D)return;D=!0;const r=o=>{const{type:t,components:n}=o;n&&a.registerComponent(t,n.controlled,n.uncontrolled),e.set(t,o)};r({type:"text",filterable:!0,filterType:"text",valueType:"string",displayFormatter:i.text,components:{controlled:g,uncontrolled:o=>{const{value:t,onChange:n,label:l,error:c,config:s}=o;return p(T,{label:l||"",value:typeof t=="string"?t:"",onChange:y=>{const u=y.target.value;n(u)},error:c,...s.options})}}}),r({type:"email",filterable:!0,filterType:"text",valueType:"string",displayFormatter:i.email,components:{controlled:g,uncontrolled:o=>{const{value:t,onChange:n,label:l,error:c,config:s}=o;return p(T,{label:l||"",value:typeof t=="string"?t:"",onChange:y=>{const u=y.target.value;n(u)},error:c,type:"email",...s.options})}}}),r({type:"url",filterable:!0,filterType:"text",valueType:"string",displayFormatter:i.url,components:{controlled:g,uncontrolled:o=>{const{value:t,onChange:n,label:l,error:c,config:s}=o;return p(T,{label:l||"",value:typeof t=="string"?t:"",onChange:y=>{const u=y.target.value;n(u)},error:c,type:"url",...s.options})}}}),r({type:"color",filterable:!0,filterType:"text",valueType:"string",displayFormatter:i.color,components:{controlled:g,uncontrolled:o=>{const{value:t,onChange:n,label:l,error:c,config:s}=o;return p(T,{label:l||"",value:typeof t=="string"?t:"",onChange:y=>{const u=y.target.value;n(u)},error:c,type:"color",...s.options})}}}),r({type:"textarea",filterable:!0,filterType:"text",valueType:"string",displayFormatter:i.textarea,components:{controlled:Z,uncontrolled:o=>{const{value:t,onChange:n,label:l,error:c,config:s}=o;return p(ue,{label:l||"",value:typeof t=="string"?t:"",onChange:y=>{const u=y.target.value;n(u)},error:c,...s.options})}}}),r({type:"richtext",filterable:!0,filterType:"text",valueType:"string",displayFormatter:i.richtext,components:{controlled:ee,uncontrolled:o=>{const{value:t,onChange:n,label:l,error:c,config:s}=o;return p(ye,{label:l||"",value:typeof t=="string"?t:"",onChange:y=>{const u=y.target.value;n(u)},error:c,...s.options})}}}),r({type:"password",filterable:!1,filterType:"none",valueType:"string",displayFormatter:i.password,components:{controlled:Y}}),r({type:"tel",filterable:!0,filterType:"text",valueType:"string",displayFormatter:i.tel,components:{controlled:G}}),r({type:"iban",filterable:!0,filterType:"text",valueType:"string",displayFormatter:i.iban,components:{controlled:g,uncontrolled:o=>{const{value:t,onChange:n,label:l,error:c,config:s}=o;return p(T,{label:l||"",value:typeof t=="string"?t:"",onChange:y=>{const u=y.target.value.replace(/\s/g,"").toUpperCase();n(u)},error:c,...s.options})}}}),r({type:"number",filterable:!0,filterType:"range",valueType:"number",displayFormatter:i.number,components:{controlled:K}}),r({type:"currency",filterable:!0,filterType:"range",valueType:"number",displayFormatter:i.currency,components:{controlled:ie}}),r({type:"price",filterable:!0,filterType:"range",valueType:"object",displayFormatter:i.price,components:{controlled:ce}}),r({type:"range",filterable:!0,filterType:"range",valueType:"number",displayFormatter:i.range,components:{controlled:O}}),r({type:"year",filterable:!0,filterType:"range",valueType:"number",displayFormatter:i.year,components:{controlled:X}}),r({type:"rating",filterable:!0,filterType:"rating",valueType:"number",displayFormatter:i.rating,components:{controlled:J}}),r({type:"duration",filterable:!0,filterType:"range",valueType:"number",displayFormatter:i.duration,components:{controlled:W}}),r({type:"boolean",filterable:!0,filterType:"select",valueType:"boolean",displayFormatter:i.boolean,components:{controlled:k}}),r({type:"checkbox",filterable:!0,filterType:"select",valueType:"boolean",displayFormatter:i.checkbox,components:{controlled:k}}),r({type:"gdprConsent",filterable:!0,filterType:"select",valueType:"object",displayFormatter:i.gdprConsent,components:{controlled:ae}}),r({type:"switch",filterable:!0,filterType:"select",valueType:"boolean",displayFormatter:i.switch,components:{controlled:ne}}),r({type:"date",filterable:!0,filterType:"range",valueType:"date",displayFormatter:i.date,components:{controlled:h}}),r({type:"datetime-local",filterable:!0,filterType:"range",valueType:"date",displayFormatter:i["datetime-local"],components:{controlled:h}}),r({type:"time",filterable:!0,filterType:"range",valueType:"date",displayFormatter:i.time,components:{controlled:h}}),r({type:"week",filterable:!0,filterType:"range",valueType:"date",displayFormatter:i.week,components:{controlled:h}}),r({type:"month",filterable:!0,filterType:"range",valueType:"date",displayFormatter:i.month,components:{controlled:h}}),r({type:"timestamp",filterable:!0,filterType:"range",valueType:"date",displayFormatter:i.timestamp,components:{controlled:te}}),r({type:"file",filterable:!1,filterType:"none",valueType:"object",displayFormatter:i.file,components:{controlled:N}}),r({type:"files",filterable:!1,filterType:"none",valueType:"array",displayFormatter:i.files,components:{controlled:M}}),r({type:"document",filterable:!1,filterType:"none",valueType:"object",displayFormatter:i.document,components:{controlled:P}}),r({type:"documents",filterable:!1,filterType:"none",valueType:"array",displayFormatter:i.documents,components:{controlled:R}}),r({type:"image",filterable:!1,filterType:"none",valueType:"object",displayFormatter:i.image,components:{controlled:_}}),r({type:"images",filterable:!1,filterType:"none",valueType:"array",displayFormatter:i.images,components:{controlled:le}}),r({type:"geopoint",filterable:!1,filterType:"none",valueType:"object",displayFormatter:i.geopoint,components:{controlled:B}}),r({type:"address",filterable:!0,filterType:"address",valueType:"object",displayFormatter:i.address,components:{controlled:re}}),r({type:"map",filterable:!1,filterType:"none",valueType:"object",displayFormatter:i.map,components:{controlled:E}}),r({type:"array",filterable:!1,filterType:"none",valueType:"array",displayFormatter:i.array,components:{controlled:H}}),r({type:"field-array",filterable:!1,filterType:"none",valueType:"array",displayFormatter:i["field-array"],components:{controlled:oe}}),r({type:"select",filterable:!0,filterType:"select",valueType:"string",displayFormatter:i.select,components:{controlled:I}}),r({type:"combobox",filterable:!0,filterType:"select",valueType:"string",displayFormatter:i.combobox,components:{controlled:$}}),r({type:"multiselect",filterable:!0,filterType:"multiselect",valueType:"array",displayFormatter:i.multiselect,components:{controlled:U}}),r({type:"radio",filterable:!0,filterType:"select",valueType:"string",displayFormatter:i.radio,components:{controlled:q}}),r({type:"reference",filterable:!0,filterType:"text",valueType:"string",displayFormatter:i.reference,components:{controlled:Q}}),r({type:"hidden",filterable:!1,filterType:"none",valueType:"string",components:{controlled:g,uncontrolled:o=>{const{name:t,value:n}=o;return p(de,{name:t,value:typeof n=="string"?n:""})}}}),r({type:"avatar",filterable:!1,filterType:"none",valueType:"string",components:{controlled:g,uncontrolled:o=>{const{value:t,onChange:n,error:l,config:c,t:s}=o;if(!me(c))throw new Error("Invalid config type for avatar field");return p(se,{config:c,value:typeof t=="string"?t:"",onChange:y=>{n(y)},error:!!l,helperText:l||void 0,t:s,...c.options})}}}),r({type:"badge",filterable:!1,filterType:"none",valueType:"string",components:{controlled:g,uncontrolled:o=>{const{value:t,onChange:n,error:l,config:c,t:s}=o;if(!ge(c))throw new Error("Invalid config type for badge field");return p(pe,{config:c,value:typeof t=="string"?t:"",onChange:y=>{n(y)},error:!!l,helperText:l||void 0,t:s,...c.options})}}}),r({type:"submit",filterable:!1,filterType:"none",valueType:"string",components:{controlled:g,uncontrolled:o=>{const{name:t,label:n,config:l}=o;return p(A,{label:n||t,type:"submit",onClick:()=>{},...l.options})}}}),r({type:"reset",filterable:!1,filterType:"none",valueType:"string",components:{controlled:g,uncontrolled:o=>{const{name:t,label:n,config:l}=o;return p(A,{label:n||t,type:"reset",onClick:()=>{},...l.options})}}})}export{be as registerAllBuiltinFieldTypes};
1
+ "use client";import{jsx as s,jsxs as y}from"react/jsx-runtime";import{Text as g,Stack as h,ImageGallery as N,Rating as I,CopyToClipboard as j}from"@donotdev/components";import{formatCurrency as V,sanitizeHref as C}from"@donotdev/core";import{ControlledCheckboxField as A,ControlledComboboxField as $,ControlledDateField as F,ControlledDropdownField as _,ControlledFileField as M,ControlledMultiFileField as P,ControlledDocumentField as R,ControlledMultiDocumentField as B,ControlledGeoPointField as v,ControlledImageField as E,ControlledMapField as H,ControlledMultiDropdownField as O,ControlledMultiInputField as U,ControlledNumberField as K,ControlledPasswordField as Y,ControlledPhoneField as G,ControlledRangeField as J,ControlledRatingField as W,ControlledDurationField as q,ControlledRadioField as Q,ControlledReferenceField as X,ControlledYearField as Z,ControlledTextField as b,ControlledTextareaField as ee,ControlledRichTextField as te,ControlledTimestampField as re,ControlledAddressField as ne,ControlledFieldArrayField as oe,ControlledSwitchField as le,ControlledMultiImageField as ie,ControlledGdprConsentField as ae,ControlledCurrencyField as ce,ControlledPriceField as se}from"./components/controlled";import{AvatarFieldComponent as pe,BadgeFieldComponent as de,ButtonFieldComponent as D,HiddenFieldComponent as fe,TextAreaComponent as ue,RichTextComponent as ye,TextFieldComponent as x}from"./components/form/fields";import{translateLabel as T}from"./forms/utils";import{sanitizeHtml as me}from"./utils/sanitizeHtml";function p(e){return e?s("span",{style:{color:"var(--muted-foreground)"},children:"\u2014"}):s(g,{variant:"muted",children:"\u2014"})}const c={timestamp:(e,i,r,t)=>{const n=t?.compact??!1;if(e==null||e==="")return p(n);try{return(e instanceof Date?e:new Date(e)).toLocaleString(t?.locale)}catch{return String(e)}},date:(e,i,r,t)=>{const n=t?.compact??!1;if(e==null||e==="")return p(n);try{return(e instanceof Date?e:new Date(e)).toLocaleDateString(t?.locale)}catch{return String(e)}},"datetime-local":(e,i,r,t)=>{const n=t?.compact??!1;if(e==null||e==="")return p(n);try{return(e instanceof Date?e:new Date(e)).toLocaleString(t?.locale)}catch{return String(e)}},time:(e,i,r,t)=>{const n=t?.compact??!1;if(e==null||e==="")return p(n);try{return(e instanceof Date?e:new Date(e)).toLocaleTimeString(t?.locale)}catch{return String(e)}},week:(e,i,r,t)=>{const n=t?.compact??!1;return e==null||e===""?p(n):String(e)},month:(e,i,r,t)=>{const n=t?.compact??!1;return e==null||e===""?p(n):String(e)},boolean:(e,i,r)=>e?"Yes":"No",checkbox:(e,i,r)=>e?"Yes":"No",switch:(e,i,r)=>{const t=i.options?.fieldSpecific;if(t){const n=t.uncheckedValue??!1,o=t.checkedValue??!0;if(e===o&&t.checkedLabel)return T(t.checkedLabel,r);if(e===n&&t.uncheckedLabel)return T(t.uncheckedLabel,r)}return e?"Yes":"No"},year:(e,i,r)=>String(e),number:(e,i,r,t)=>e==null||e===""?"\u2014":typeof e=="number"?e.toLocaleString(t?.locale):String(e),currency:(e,i,r)=>{if(e==null||e===""||Number.isNaN(Number(e)))return"";const o=(i.options||{}).fieldSpecific?.currency||"EUR";return V(e,o)},price:(e,i,r,t)=>{const n=t?.compact??!1,o=t?.asString??!1,l=e!=null&&typeof e=="number"?{amount:e,currency:"EUR",vatIncluded:!0,discountPercent:0}:e;if(l==null||typeof l!="object")return p(n);const a=l.amount;if(a==null||a===""||Number.isNaN(Number(a)))return p(n);const f=l.currency||"EUR",u=l.vatIncluded??!0,d=l.discountPercent??0,m=d>0?a*(1-d/100):a,S=u?` ${r("crud:price.vatIncluded",{defaultValue:"VAT Incl."})}`:"";if(d>0){const L=V(a,f),w=V(m,f),k=` ${r("crud:price.discountPercent",{percent:Math.round(d),defaultValue:"-{{percent}}%"})}`;return o?`${w}${S}${k}`:n?y(g,{variant:"success",weight:"bold",children:[w,S,k]}):y(h,{direction:"column",gap:"tight",align:"end",children:[s(g,{variant:"muted",style:{textDecoration:"line-through",fontSize:"var(--font-size-sm)"},children:L}),y(g,{variant:"success",weight:"bold",children:[w,S]})]})}return`${V(a,f)}${S}`},range:(e,i,r,t)=>typeof e=="number"?e.toLocaleString(t?.locale):String(e),rating:(e,i,r,t)=>{const n=t?.compact??!1;if(e==null)return p(n);const o=typeof e=="number"?e:parseFloat(e);if(isNaN(o))return p(n);const l=i.validation?.max??5;return s(I,{value:o,max:l,readonly:!0,"aria-label":`${o} out of ${l} stars`})},duration:(e,i,r,t)=>{const n=t?.compact??!1;if(e==null)return p(n);const o=typeof e=="number"?e:parseInt(String(e),10);if(Number.isNaN(o))return p(n);if(o===0)return r("crud:duration.zero",{defaultValue:"\u2014"});if(o<60)return r("crud:duration.minutes",{count:o,defaultValue:`${o} min`});const l=Math.floor(o/60),a=o%60;return r("crud:duration.hoursMinutes",{hours:l,minutes:a,defaultValue:a===0?`${l}h`:`${l}h ${a}min`})},gdprConsent:(e,i,r,t)=>{const n=t?.compact??!1;if(!e||typeof e!="object")return p(n);const o=e.gdprConsent===!0,l=e.gdprConsentDate,a=e.gdprConsentVersion,f=r("crud:gdprConsent.display.yes",{defaultValue:"Consented"}),u=r("crud:gdprConsent.display.no",{defaultValue:"Not consented"});if(!o)return u;const d=[f];if(l)try{const m=new Date(l);d.push(m.toLocaleDateString(t?.locale))}catch{d.push(l)}return a&&d.push(`v${a}`),d.join(" \xB7 ")},select:(e,i,r)=>{const t=i.validation?.options;if(Array.isArray(t)){const o=t.find(l=>l.value===e)?.label;return o?T(o,r):String(e)}return String(e)},radio:(e,i,r)=>{const t=i.validation?.options;if(Array.isArray(t)){const o=t.find(l=>l.value===e)?.label;return o?T(o,r):String(e)}return String(e)},combobox:(e,i,r)=>{const t=i.validation?.options;if(Array.isArray(t)){const o=t.find(l=>l.value===e)?.label;return o?T(o,r):String(e)}return String(e)},multiselect:(e,i,r)=>{if(Array.isArray(e)){const t=i.validation?.options;if(Array.isArray(t))return e.map(o=>{const a=t.find(f=>f.value===o)?.label;return a?T(a,r):o}).join(", ")}return String(e)},image:(e,i,r,t)=>{const n=t?.compact??!1;return e==null||e===""?p(n):typeof e=="string"?s("img",{src:C(e),alt:i.label||"",style:{width:n?"40px":void 0,height:n?"40px":void 0,maxWidth:n?void 0:"200px",maxHeight:n?void 0:"150px",objectFit:"cover",borderRadius:"var(--radius-sm)"}}):p(n)},images:(e,i,r,t)=>{const n=t?.compact??!1;if(!Array.isArray(e)||e.length===0)return p(n);const o=e[0],l=typeof o=="object"&&o.thumbUrl?o.thumbUrl:o;return n?y("div",{style:{display:"flex",alignItems:"center",gap:"var(--gap-xs)"},children:[s("img",{src:C(l),alt:"",style:{width:"40px",height:"40px",objectFit:"cover",borderRadius:"var(--radius-sm)"}}),e.length>1&&y("span",{style:{fontSize:"var(--font-size-xs)",color:"var(--muted-foreground)"},children:["+",e.length-1]})]}):s(N,{images:e,altPrefix:i.label||"Image"})},files:(e,i,r,t)=>{const n=t?.compact??!1;return!Array.isArray(e)||e.length===0?p(n):s(h,{gap:"tight",children:e.map((o,l)=>y("a",{href:C(o.url||o),target:"_blank",rel:"noopener noreferrer",style:{color:"var(--primary)",textDecoration:"none",display:"flex",alignItems:"center",fontSize:"var(--font-size-sm)"},children:[o.filename||`File ${l+1}`,o.size&&y(g,{level:"caption",variant:"muted",style:{marginLeft:"var(--gap-sm)"},children:["(",Math.round(o.size/1024)," KB)"]})]},l))})},documents:(e,i,r,t)=>{const n=t?.compact??!1;return!Array.isArray(e)||e.length===0?p(n):s(h,{gap:"tight",children:e.map((o,l)=>y("a",{href:C(o.url||o),target:"_blank",rel:"noopener noreferrer",style:{color:"var(--primary)",textDecoration:"none",display:"flex",alignItems:"center",fontSize:"var(--font-size-sm)"},children:[o.filename||`File ${l+1}`,o.size&&y(g,{level:"caption",variant:"muted",style:{marginLeft:"var(--gap-sm)"},children:["(",Math.round(o.size/1024)," KB)"]})]},l))})},file:(e,i,r,t)=>{const n=t?.compact??!1;if(!e)return p(n);const o=typeof e=="string"?e:e.url,l=typeof e=="string"?"View file":e.filename||"View file";return y("a",{href:o,target:"_blank",rel:"noopener noreferrer",style:{color:"var(--primary)",textDecoration:"none"},children:[l,typeof e=="object"&&e.size&&y("span",{style:{color:"var(--muted-foreground)",marginLeft:"var(--gap-sm)"},children:["(",Math.round(e.size/1024)," KB)"]})]})},document:(e,i,r,t)=>{const n=t?.compact??!1;if(!e)return p(n);const o=typeof e=="string"?e:e.url,l=typeof e=="string"?"View file":e.filename||"View file";return y("a",{href:o,target:"_blank",rel:"noopener noreferrer",style:{color:"var(--primary)",textDecoration:"none"},children:[l,typeof e=="object"&&e.size&&y("span",{style:{color:"var(--muted-foreground)",marginLeft:"var(--gap-sm)"},children:["(",Math.round(e.size/1024)," KB)"]})]})},reference:(e,i,r,t)=>{const n=t?.compact??!1;if(!e)return p(n);const o=i.validation?.reference;if(t?.referenceData&&typeof o=="string"){const l=t.referenceData[o]?.[String(e)];if(l)return l}if(typeof e=="object"&&e!==null){const l=e.displayName||e.name||e.id||String(e);return String(l)}return String(e)},geopoint:(e,i,r,t)=>{const n=t?.compact??!1;return e&&typeof e=="object"&&"lat"in e&&"lng"in e?`${e.lat.toFixed(6)}, ${e.lng.toFixed(6)}`:p(n)},address:(e,i,r)=>e&&typeof e=="object"&&"formatted_address"in e?e.formatted_address:String(e),map:(e,i,r,t)=>{const n=t?.compact??!1;if(e&&typeof e=="object"){const o=Object.entries(e);return o.length===0?p(n):y(h,{direction:"column",gap:"tight",children:[o.slice(0,5).map(([l,a])=>y(g,{style:{fontSize:"var(--font-size-sm)"},children:[y("strong",{children:[l,":"]})," ",String(a)]},l)),o.length>5&&y(g,{variant:"muted",children:["+",o.length-5," more"]})]})}return p(n)},array:(e,i,r,t)=>{const n=t?.compact??!1;return Array.isArray(e)?e.length===0?p(n):e.join(", "):p(n)},"field-array":(e,i,r,t)=>{const n=t?.compact??!1;if(!Array.isArray(e)||e.length===0)return p(n);const o=i.options?.fieldSpecific?.fields;return e.map(l=>{if(typeof l!="object"||l==null)return"";const a=l;return(o?o.map(u=>u.name):Object.keys(a)).map(u=>a[u]).filter(u=>u!=null&&u!=="").map(u=>typeof u=="object"?JSON.stringify(u):String(u)).join(" \xB7 ")}).filter(Boolean).join(", ")},password:()=>"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",email:(e,i,r)=>y(h,{direction:"row",gap:"tight",align:"center",children:[s("a",{href:`mailto:${e}`,style:{color:"var(--primary)",flex:1},onClick:t=>t.stopPropagation(),children:e}),s(j,{text:e,tooltipText:r("crud:copyToClipboard",{defaultValue:"Copy to clipboard"}),ariaLabel:r("crud:actions.copyEmail",{defaultValue:"Copy email"}),onClick:t=>t.stopPropagation()})]}),tel:(e,i,r)=>y(h,{direction:"row",gap:"tight",align:"center",children:[s("a",{href:`tel:${e}`,style:{color:"var(--primary)",flex:1},onClick:t=>t.stopPropagation(),children:e}),s(j,{text:e,tooltipText:r("crud:copyToClipboard",{defaultValue:"Copy to clipboard"}),ariaLabel:r("crud:actions.copyPhone",{defaultValue:"Copy phone"}),onClick:t=>t.stopPropagation()})]}),iban:(e,i,r,t)=>{const n=t?.compact??!1;return e?y(h,{direction:"row",gap:"tight",align:"center",children:[s(g,{style:{flex:1},children:e}),s(j,{text:e,tooltipText:r("crud:copyToClipboard",{defaultValue:"Copy to clipboard"}),ariaLabel:r("crud:actions.copyIban",{defaultValue:"Copy IBAN"})})]}):p(n)},url:(e,i,r)=>{const t=C(e);return t?s("a",{href:t,target:"_blank",rel:"noopener noreferrer",style:{color:"var(--primary)"},children:e}):s(g,{children:e})},color:(e,i,r)=>y(h,{direction:"row",gap:"tight",align:"center",children:[s("div",{style:{width:"20px",height:"20px",backgroundColor:e,borderRadius:"var(--radius-sm)",border:"1px solid var(--border)"}}),s(g,{children:e})]}),textarea:(e,i,r)=>String(e),text:(e,i,r)=>String(e),richtext:(e,i,r,t)=>{const n=t?.compact??!1;return e&&typeof e=="string"?n?e.replace(/<[^>]*>/g,"").trim()||s("span",{style:{color:"var(--muted-foreground)"},children:"\u2014"}):s("div",{dangerouslySetInnerHTML:{__html:me(e)},style:{padding:"var(--gap-sm)",fontSize:"var(--font-size-sm)",lineHeight:"1.6"}}):p(n)}};function ge(e){return e.type==="avatar"}function be(e){return e.type==="badge"}let z=!1;function we(e,i){if(z)return;z=!0;const r=t=>{const{type:n,components:o}=t;o&&i.registerComponent(n,o.controlled,o.uncontrolled),e.set(n,t)};r({type:"text",filterable:!0,filterType:"text",valueType:"string",displayFormatter:c.text,components:{controlled:b,uncontrolled:t=>{const{value:n,onChange:o,label:l,error:a,config:f}=t;return s(x,{label:l||"",value:typeof n=="string"?n:"",onChange:d=>{const m=d.target.value;o(m)},error:a,...f.options})}}}),r({type:"email",filterable:!0,filterType:"text",valueType:"string",displayFormatter:c.email,components:{controlled:b,uncontrolled:t=>{const{value:n,onChange:o,label:l,error:a,config:f}=t;return s(x,{label:l||"",value:typeof n=="string"?n:"",onChange:d=>{const m=d.target.value;o(m)},error:a,type:"email",...f.options})}}}),r({type:"url",filterable:!0,filterType:"text",valueType:"string",displayFormatter:c.url,components:{controlled:b,uncontrolled:t=>{const{value:n,onChange:o,label:l,error:a,config:f}=t;return s(x,{label:l||"",value:typeof n=="string"?n:"",onChange:d=>{const m=d.target.value;o(m)},error:a,type:"url",...f.options})}}}),r({type:"color",filterable:!0,filterType:"text",valueType:"string",displayFormatter:c.color,components:{controlled:b,uncontrolled:t=>{const{value:n,onChange:o,label:l,error:a,config:f}=t;return s(x,{label:l||"",value:typeof n=="string"?n:"",onChange:d=>{const m=d.target.value;o(m)},error:a,type:"color",...f.options})}}}),r({type:"textarea",filterable:!0,filterType:"text",valueType:"string",displayFormatter:c.textarea,components:{controlled:ee,uncontrolled:t=>{const{value:n,onChange:o,label:l,error:a,config:f}=t;return s(ue,{label:l||"",value:typeof n=="string"?n:"",onChange:d=>{const m=d.target.value;o(m)},error:a,...f.options})}}}),r({type:"richtext",filterable:!0,filterType:"text",valueType:"string",displayFormatter:c.richtext,components:{controlled:te,uncontrolled:t=>{const{value:n,onChange:o,label:l,error:a,config:f}=t;return s(ye,{label:l||"",value:typeof n=="string"?n:"",onChange:d=>{const m=d.target.value;o(m)},error:a,...f.options})}}}),r({type:"password",filterable:!1,filterType:"none",valueType:"string",displayFormatter:c.password,components:{controlled:Y}}),r({type:"tel",filterable:!0,filterType:"text",valueType:"string",displayFormatter:c.tel,components:{controlled:G}}),r({type:"iban",filterable:!0,filterType:"text",valueType:"string",displayFormatter:c.iban,components:{controlled:b,uncontrolled:t=>{const{value:n,onChange:o,label:l,error:a,config:f}=t;return s(x,{label:l||"",value:typeof n=="string"?n:"",onChange:d=>{const m=d.target.value.replace(/\s/g,"").toUpperCase();o(m)},error:a,...f.options})}}}),r({type:"number",filterable:!0,filterType:"range",valueType:"number",displayFormatter:c.number,components:{controlled:K}}),r({type:"currency",filterable:!0,filterType:"range",valueType:"number",displayFormatter:c.currency,components:{controlled:ce}}),r({type:"price",filterable:!0,filterType:"range",valueType:"object",displayFormatter:c.price,components:{controlled:se}}),r({type:"range",filterable:!0,filterType:"range",valueType:"number",displayFormatter:c.range,components:{controlled:J}}),r({type:"year",filterable:!0,filterType:"range",valueType:"number",displayFormatter:c.year,components:{controlled:Z}}),r({type:"rating",filterable:!0,filterType:"rating",valueType:"number",displayFormatter:c.rating,components:{controlled:W}}),r({type:"duration",filterable:!0,filterType:"range",valueType:"number",displayFormatter:c.duration,components:{controlled:q}}),r({type:"boolean",filterable:!0,filterType:"select",valueType:"boolean",displayFormatter:c.boolean,components:{controlled:A}}),r({type:"checkbox",filterable:!0,filterType:"select",valueType:"boolean",displayFormatter:c.checkbox,components:{controlled:A}}),r({type:"gdprConsent",filterable:!0,filterType:"select",valueType:"object",displayFormatter:c.gdprConsent,components:{controlled:ae}}),r({type:"switch",filterable:!0,filterType:"select",valueType:"boolean",displayFormatter:c.switch,components:{controlled:le}}),r({type:"date",filterable:!0,filterType:"range",valueType:"date",displayFormatter:c.date,components:{controlled:F}}),r({type:"datetime-local",filterable:!0,filterType:"range",valueType:"date",displayFormatter:c["datetime-local"],components:{controlled:F}}),r({type:"time",filterable:!0,filterType:"range",valueType:"date",displayFormatter:c.time,components:{controlled:F}}),r({type:"week",filterable:!0,filterType:"range",valueType:"date",displayFormatter:c.week,components:{controlled:F}}),r({type:"month",filterable:!0,filterType:"range",valueType:"date",displayFormatter:c.month,components:{controlled:F}}),r({type:"timestamp",filterable:!0,filterType:"range",valueType:"date",displayFormatter:c.timestamp,components:{controlled:re}}),r({type:"file",filterable:!1,filterType:"none",valueType:"object",displayFormatter:c.file,components:{controlled:M}}),r({type:"files",filterable:!1,filterType:"none",valueType:"array",displayFormatter:c.files,components:{controlled:P}}),r({type:"document",filterable:!1,filterType:"none",valueType:"object",displayFormatter:c.document,components:{controlled:R}}),r({type:"documents",filterable:!1,filterType:"none",valueType:"array",displayFormatter:c.documents,components:{controlled:B}}),r({type:"image",filterable:!1,filterType:"none",valueType:"object",displayFormatter:c.image,components:{controlled:E}}),r({type:"images",filterable:!1,filterType:"none",valueType:"array",displayFormatter:c.images,components:{controlled:ie}}),r({type:"geopoint",filterable:!1,filterType:"none",valueType:"object",displayFormatter:c.geopoint,components:{controlled:v}}),r({type:"address",filterable:!0,filterType:"address",valueType:"object",displayFormatter:c.address,components:{controlled:ne}}),r({type:"map",filterable:!1,filterType:"none",valueType:"object",displayFormatter:c.map,components:{controlled:H}}),r({type:"array",filterable:!1,filterType:"none",valueType:"array",displayFormatter:c.array,components:{controlled:U}}),r({type:"field-array",filterable:!1,filterType:"none",valueType:"array",displayFormatter:c["field-array"],components:{controlled:oe}}),r({type:"select",filterable:!0,filterType:"select",valueType:"string",displayFormatter:c.select,components:{controlled:_}}),r({type:"combobox",filterable:!0,filterType:"select",valueType:"string",displayFormatter:c.combobox,components:{controlled:$}}),r({type:"multiselect",filterable:!0,filterType:"multiselect",valueType:"array",displayFormatter:c.multiselect,components:{controlled:O}}),r({type:"radio",filterable:!0,filterType:"select",valueType:"string",displayFormatter:c.radio,components:{controlled:Q}}),r({type:"reference",filterable:!0,filterType:"text",valueType:"string",displayFormatter:c.reference,components:{controlled:X}}),r({type:"hidden",filterable:!1,filterType:"none",valueType:"string",components:{controlled:b,uncontrolled:t=>{const{name:n,value:o}=t;return s(fe,{name:n,value:typeof o=="string"?o:""})}}}),r({type:"avatar",filterable:!1,filterType:"none",valueType:"string",components:{controlled:b,uncontrolled:t=>{const{value:n,onChange:o,error:l,config:a,t:f}=t;if(!ge(a))throw new Error("Invalid config type for avatar field");return s(pe,{config:a,value:typeof n=="string"?n:"",onChange:d=>{o(d)},error:!!l,helperText:l||void 0,t:f,...a.options})}}}),r({type:"badge",filterable:!1,filterType:"none",valueType:"string",components:{controlled:b,uncontrolled:t=>{const{value:n,onChange:o,error:l,config:a,t:f}=t;if(!be(a))throw new Error("Invalid config type for badge field");return s(de,{config:a,value:typeof n=="string"?n:"",onChange:d=>{o(d)},error:!!l,helperText:l||void 0,t:f,...a.options})}}}),r({type:"submit",filterable:!1,filterType:"none",valueType:"string",components:{controlled:b,uncontrolled:t=>{const{name:n,label:o,config:l}=t;return s(D,{label:o||n,type:"submit",onClick:()=>{},...l.options})}}}),r({type:"reset",filterable:!1,filterType:"none",valueType:"string",components:{controlled:b,uncontrolled:t=>{const{name:n,label:o,config:l}=t;return s(D,{label:o||n,type:"reset",onClick:()=>{},...l.options})}}})}export{we as registerAllBuiltinFieldTypes};
@@ -35,6 +35,8 @@ export interface FormStoreActions {
35
35
  setSuccess: (formId: string) => void;
36
36
  /** Set error state */
37
37
  setError: (formId: string, error: string) => void;
38
+ /** Dismiss error and reset to idle */
39
+ dismissError: (formId: string) => void;
38
40
  /** Reset form to idle state */
39
41
  reset: (formId: string) => void;
40
42
  /** Clean up form state (on unmount) */
@@ -1 +1 @@
1
- {"version":3,"file":"FormStore.d.ts","sourceRoot":"","sources":["../../src/stores/FormStore.ts"],"names":[],"mappings":"AAkBA;;;GAGG;AACH,MAAM,MAAM,UAAU,GAClB,MAAM,GACN,WAAW,GACX,YAAY,GACZ,YAAY,GACZ,SAAS,GACT,OAAO,CAAC;AAEZ;;GAEG;AACH,UAAU,SAAS;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAE/B,8EAA8E;IAC9E,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,wCAAwC;IACxC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,2BAA2B;IAC3B,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,qDAAqD;IACrD,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,wBAAwB;IACxB,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,sBAAsB;IACtB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,+BAA+B;IAC/B,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,uCAAuC;IACvC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAGlC,2BAA2B;IAC3B,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACvD,iCAAiC;IACjC,aAAa,EAAE,MAAM,OAAO,CAAC;IAC7B,6BAA6B;IAC7B,eAAe,EAAE,MAAM,MAAM,EAAE,CAAC;IAGhC,sBAAsB;IACtB,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,UAAU,CAAC;IAC1C,4CAA4C;IAC5C,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,0BAA0B;IAC1B,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IAC9C,wBAAwB;IACxB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC5C,6BAA6B;IAC7B,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;CACzC;AASD;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,2IAoMvB,CAAC;AAMH;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,MAAM,KAAG,UACiB,CAAC;AAEjE;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,MAAM,KAAG,OAQ5C,CAAC;AAEL;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,QAAQ,MAAM,KAAG,MACgB,CAAC;AAEpE;;GAEG;AACH,eAAO,MAAM,YAAY,GAAI,QAAQ,MAAM,KAAG,MAAM,GAAG,IACM,CAAC;AAE9D;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,MAAM,KAAG,OACgB,CAAC;AAEjE;;GAEG;AACH,eAAO,MAAM,gBAAgB,QAAO,OACwC,CAAC"}
1
+ {"version":3,"file":"FormStore.d.ts","sourceRoot":"","sources":["../../src/stores/FormStore.ts"],"names":[],"mappings":"AAkBA;;;GAGG;AACH,MAAM,MAAM,UAAU,GAClB,MAAM,GACN,WAAW,GACX,YAAY,GACZ,YAAY,GACZ,SAAS,GACT,OAAO,CAAC;AAEZ;;GAEG;AACH,UAAU,SAAS;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAE/B,8EAA8E;IAC9E,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,wCAAwC;IACxC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,2BAA2B;IAC3B,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,qDAAqD;IACrD,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,wBAAwB;IACxB,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,sBAAsB;IACtB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,sCAAsC;IACtC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,+BAA+B;IAC/B,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,uCAAuC;IACvC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAGlC,2BAA2B;IAC3B,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACvD,iCAAiC;IACjC,aAAa,EAAE,MAAM,OAAO,CAAC;IAC7B,6BAA6B;IAC7B,eAAe,EAAE,MAAM,MAAM,EAAE,CAAC;IAGhC,sBAAsB;IACtB,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,UAAU,CAAC;IAC1C,4CAA4C;IAC5C,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,0BAA0B;IAC1B,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IAC9C,wBAAwB;IACxB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC5C,6BAA6B;IAC7B,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;CACzC;AASD;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,2IAyRvB,CAAC;AAMH;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,MAAM,KAAG,UACiB,CAAC;AAEjE;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,MAAM,KAAG,OAQ5C,CAAC;AAEL;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,QAAQ,MAAM,KAAG,MACgB,CAAC;AAEpE;;GAEG;AACH,eAAO,MAAM,YAAY,GAAI,QAAQ,MAAM,KAAG,MAAM,GAAG,IACM,CAAC;AAE9D;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,MAAM,KAAG,OACgB,CAAC;AAEjE;;GAEG;AACH,eAAO,MAAM,gBAAgB,QAAO,OACwC,CAAC"}
@@ -1 +1 @@
1
- "use client";import{createDoNotDevStore as l}from"@donotdev/core";const i={status:"idle",error:null,uploadProgress:0,isDirty:!1},a=l({name:"form-store",createStore:(o,t)=>{const m=new Map;return{forms:{},startSubmit:r=>{o(s=>{const e=s.forms[r]||i;return{forms:{...s.forms,[r]:{...e,status:"uploading",error:null,uploadProgress:0}}}})},setUploading:(r,s)=>{o(e=>{const u=e.forms[r]||i;return{forms:{...e.forms,[r]:{...u,status:"uploading",uploadProgress:Math.min(100,Math.max(0,s))}}}})},setValidating:r=>{o(s=>{const e=s.forms[r]||i;return{forms:{...s.forms,[r]:{...e,status:"validating",uploadProgress:100}}}})},setSubmitting:r=>{o(s=>{const e=s.forms[r]||i;return{forms:{...s.forms,[r]:{...e,status:"submitting"}}}})},setSuccess:r=>{o(u=>{const n=u.forms[r]||i;return{forms:{...u.forms,[r]:{...n,status:"success",error:null}}}});const s=m.get(r);s!==void 0&&clearTimeout(s);const e=setTimeout(()=>{m.delete(r),t().reset(r)},1500);m.set(r,e)},setError:(r,s)=>{t().reset(r)},reset:r=>{o(s=>({forms:{...s.forms,[r]:{...i}}}))},setIsDirty:(r,s)=>{o(e=>{const u=e.forms[r]||i;return{forms:{...e.forms,[r]:{...u,isDirty:s}}}})},hasDirtyForms:()=>{const r=t().forms;return Object.values(r).some(s=>s.isDirty)},getDirtyFormIds:()=>{const r=t().forms;return Object.entries(r).filter(([s,e])=>e.isDirty).map(([s])=>s)},cleanup:r=>{const s=m.get(r);s!==void 0&&(clearTimeout(s),m.delete(r)),o(e=>{const{[r]:u,...n}=e.forms;return{forms:n}})},getStatus:r=>t().forms[r]?.status??"idle",isLoading:r=>{const s=t().forms[r]?.status??"idle";return s==="uploading"||s==="validating"||s==="submitting"},getUploadProgress:r=>t().forms[r]?.uploadProgress??0,getError:r=>t().forms[r]?.error??null,getIsDirty:r=>t().forms[r]?.isDirty??!1}}}),f=o=>a(t=>t.forms[o]?.status??"idle"),g=o=>a(t=>{const m=t.forms[o]?.status??"idle";return m==="uploading"||m==="validating"||m==="submitting"}),c=o=>a(t=>t.forms[o]?.uploadProgress??0),d=o=>a(t=>t.forms[o]?.error??null),p=o=>a(t=>t.forms[o]?.isDirty??!1),D=()=>a(o=>Object.values(o.forms).some(t=>t.isDirty));export{d as useFormError,p as useFormIsDirty,g as useFormLoading,f as useFormStatus,a as useFormStore,D as useHasDirtyForms,c as useUploadProgress};
1
+ "use client";import{createDoNotDevStore as T}from"@donotdev/core";const a={status:"idle",error:null,uploadProgress:0,isDirty:!1},m=T({name:"form-store",createStore:(o,t)=>{const i=new Map,l=new Map,u=new Map,d=45e3,g=s=>{for(const r of[i,l,u]){const e=r.get(s);e!==void 0&&(clearTimeout(e),r.delete(s))}};return{forms:{},startSubmit:s=>{o(n=>{const c=n.forms[s]||a;return{forms:{...n.forms,[s]:{...c,status:"uploading",error:null,uploadProgress:0}}}});const r=u.get(s);r!==void 0&&clearTimeout(r);const e=setTimeout(()=>{u.delete(s);const n=t().forms[s];n&&(n.status==="uploading"||n.status==="validating"||n.status==="submitting")&&t().setError(s,"Operation timed out. Please try again.")},d);u.set(s,e)},setUploading:(s,r)=>{o(e=>{const n=e.forms[s]||a;return{forms:{...e.forms,[s]:{...n,status:"uploading",uploadProgress:Math.min(100,Math.max(0,r))}}}})},setValidating:s=>{o(r=>{const e=r.forms[s]||a;return{forms:{...r.forms,[s]:{...e,status:"validating",uploadProgress:100}}}})},setSubmitting:s=>{o(r=>{const e=r.forms[s]||a;return{forms:{...r.forms,[s]:{...e,status:"submitting"}}}})},setSuccess:s=>{const r=u.get(s);r!==void 0&&(clearTimeout(r),u.delete(s)),o(c=>{const f=c.forms[s]||a;return{forms:{...c.forms,[s]:{...f,status:"success",error:null}}}});const e=i.get(s);e!==void 0&&clearTimeout(e);const n=setTimeout(()=>{i.delete(s),t().forms[s]?.status==="success"&&t().reset(s)},1500);i.set(s,n)},setError:(s,r)=>{const e=u.get(s);e!==void 0&&(clearTimeout(e),u.delete(s));const n=i.get(s);n!==void 0&&(clearTimeout(n),i.delete(s)),o(p=>({forms:{...p.forms,[s]:{...p.forms[s]||a,status:"error",error:r}}}));const c=l.get(s);c!==void 0&&clearTimeout(c);const f=setTimeout(()=>{l.delete(s),t().forms[s]?.status==="error"&&t().reset(s)},5e3);l.set(s,f)},dismissError:s=>{const r=l.get(s);r!==void 0&&(clearTimeout(r),l.delete(s)),t().forms[s]?.status==="error"&&t().reset(s)},reset:s=>{g(s),o(r=>({forms:{...r.forms,[s]:{...a}}}))},setIsDirty:(s,r)=>{o(e=>{const n=e.forms[s]||a;return{forms:{...e.forms,[s]:{...n,isDirty:r}}}})},hasDirtyForms:()=>{const s=t().forms;return Object.values(s).some(r=>r.isDirty)},getDirtyFormIds:()=>{const s=t().forms;return Object.entries(s).filter(([r,e])=>e.isDirty).map(([r])=>r)},cleanup:s=>{g(s),o(r=>{const{[s]:e,...n}=r.forms;return{forms:n}})},getStatus:s=>t().forms[s]?.status??"idle",isLoading:s=>{const r=t().forms[s]?.status??"idle";return r==="uploading"||r==="validating"||r==="submitting"},getUploadProgress:s=>t().forms[s]?.uploadProgress??0,getError:s=>t().forms[s]?.error??null,getIsDirty:s=>t().forms[s]?.isDirty??!1}}}),D=o=>m(t=>t.forms[o]?.status??"idle"),y=o=>m(t=>{const i=t.forms[o]?.status??"idle";return i==="uploading"||i==="validating"||i==="submitting"}),h=o=>m(t=>t.forms[o]?.uploadProgress??0),F=o=>m(t=>t.forms[o]?.error??null),S=o=>m(t=>t.forms[o]?.isDirty??!1),b=()=>m(o=>Object.values(o.forms).some(t=>t.isDirty));export{F as useFormError,S as useFormIsDirty,y as useFormLoading,D as useFormStatus,m as useFormStore,b as useHasDirtyForms,h as useUploadProgress};
@@ -12,9 +12,9 @@ interface FieldUploadState {
12
12
  }
13
13
  /**
14
14
  * Upload function signature
15
- * Called with progress callback for real-time updates
15
+ * Called with progress callback and optional abort signal for cancellation
16
16
  */
17
- export type UploadFunction = (onProgress?: (progress: number) => void) => Promise<void>;
17
+ export type UploadFunction = (onProgress?: (progress: number) => void, signal?: AbortSignal) => Promise<void>;
18
18
  /**
19
19
  * Check pending function signature
20
20
  * Returns true if the upload function has pending files to upload
@@ -32,10 +32,14 @@ export interface UploadStoreState {
32
32
  checkPendingFunctions: Record<string, Record<string, CheckPendingFunction>>;
33
33
  /** Retry attempts: formId -> fieldName -> attempts */
34
34
  retryAttempts: Record<string, Record<string, number>>;
35
+ /** Active abort controllers: formId -> AbortController */
36
+ abortControllers: Record<string, AbortController>;
35
37
  /** Max retries per field (default: 3) */
36
38
  maxRetries: number;
37
39
  /** Base retry delay in ms (default: 1000) */
38
40
  retryDelay: number;
41
+ /** Upload timeout per field in ms (default: 30000) */
42
+ uploadTimeout: number;
39
43
  }
40
44
  /**
41
45
  * Upload store actions interface
@@ -60,7 +64,9 @@ export interface UploadStoreActions {
60
64
  /** Clean up form state (on unmount) */
61
65
  cleanup: (formId: string) => void;
62
66
  /** Upload all registered files for a form */
63
- uploadAll: (formId: string) => Promise<void>;
67
+ uploadAll: (formId: string, signal?: AbortSignal) => Promise<void>;
68
+ /** Abort all in-flight uploads for a form */
69
+ abortAll: (formId: string) => void;
64
70
  /** Check if any uploads are pending for a form */
65
71
  hasPendingUploads: (formId: string) => boolean;
66
72
  /** Get upload status for a field */
@@ -1 +1 @@
1
- {"version":3,"file":"UploadStore.d.ts","sourceRoot":"","sources":["../../src/stores/UploadStore.ts"],"names":[],"mappings":"AAeA;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,OAAO,CAAC;AAEvE;;GAEG;AACH,UAAU,gBAAgB;IACxB,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,CAC3B,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,KACpC,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,OAAO,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAC1D,mEAAmE;IACnE,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC;IAChE,qEAAqE;IACrE,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAAC;IAC5E,sDAAsD;IACtD,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACtD,yCAAyC;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAEjC,8CAA8C;IAC9C,cAAc,EAAE,CACd,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,cAAc,EACxB,YAAY,CAAC,EAAE,oBAAoB,KAChC,IAAI,CAAC;IACV,qDAAqD;IACrD,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAG9D,+BAA+B;IAC/B,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,+BAA+B;IAC/B,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3E,8BAA8B;IAC9B,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5D,4BAA4B;IAC5B,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvE,qCAAqC;IACrC,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,mCAAmC;IACnC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,uCAAuC;IACvC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAGlC,6CAA6C;IAC7C,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,kDAAkD;IAClD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAG/C,oCAAoC;IACpC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,YAAY,CAAC;IAC/D,sCAAsC;IACtC,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3D,qDAAqD;IACrD,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IAC7C,gDAAgD;IAChD,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IACzC,4BAA4B;IAC5B,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CAChE;AAQD;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,+IA+TzB,CAAC;AAMH;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,KAAG,MAU9C,CAAC;AAEL;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,MAAM,KAAG,OAQ5C,CAAC;AAEL;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,EAAE,WAAW,MAAM,KAAG,MACS,CAAC;AAE/E;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,MAAM,EACd,WAAW,MAAM,KAChB,YAGA,CAAC"}
1
+ {"version":3,"file":"UploadStore.d.ts","sourceRoot":"","sources":["../../src/stores/UploadStore.ts"],"names":[],"mappings":"AAeA;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,OAAO,CAAC;AAEvE;;GAEG;AACH,UAAU,gBAAgB;IACxB,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,CAC3B,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,EACvC,MAAM,CAAC,EAAE,WAAW,KACjB,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,OAAO,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAC1D,mEAAmE;IACnE,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC;IAChE,qEAAqE;IACrE,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAAC;IAC5E,sDAAsD;IACtD,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACtD,0DAA0D;IAC1D,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAClD,yCAAyC;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAEjC,8CAA8C;IAC9C,cAAc,EAAE,CACd,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,cAAc,EACxB,YAAY,CAAC,EAAE,oBAAoB,KAChC,IAAI,CAAC;IACV,qDAAqD;IACrD,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAG9D,+BAA+B;IAC/B,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,+BAA+B;IAC/B,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3E,8BAA8B;IAC9B,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5D,4BAA4B;IAC5B,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvE,qCAAqC;IACrC,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,mCAAmC;IACnC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,uCAAuC;IACvC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAGlC,6CAA6C;IAC7C,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,6CAA6C;IAC7C,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,kDAAkD;IAClD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAG/C,oCAAoC;IACpC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,YAAY,CAAC;IAC/D,sCAAsC;IACtC,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3D,qDAAqD;IACrD,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IAC7C,gDAAgD;IAChD,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IACzC,4BAA4B;IAC5B,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CAChE;AAQD;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,+IAuZzB,CAAC;AAMH;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,KAAG,MAU9C,CAAC;AAEL;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,MAAM,KAAG,OAQ5C,CAAC;AAEL;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,EAAE,WAAW,MAAM,KAAG,MACS,CAAC;AAE/E;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,MAAM,EACd,WAAW,MAAM,KAChB,YAGA,CAAC"}
@@ -1 +1 @@
1
- "use client";import{createDoNotDevStore as F}from"@donotdev/core";const m={status:"idle",progress:0,error:null},d=F({name:"upload-store",createStore:(a,n)=>({uploads:{},uploadFunctions:{},checkPendingFunctions:{},retryAttempts:{},maxRetries:3,retryDelay:1e3,registerUpload:(s,e,t,o)=>{a(r=>({uploadFunctions:{...r.uploadFunctions,[s]:{...r.uploadFunctions[s]||{},[e]:t}},checkPendingFunctions:{...r.checkPendingFunctions,[s]:{...r.checkPendingFunctions[s]||{},[e]:o||(()=>!1)}}}))},unregisterUpload:(s,e)=>{a(t=>{const o=t.uploadFunctions[s],r=t.checkPendingFunctions[s];if(!o)return t;const{[e]:l,...p}=o,{[e]:u,...i}=r||{},{[e]:g,...h}=t.retryAttempts[s]||{};return{uploadFunctions:{...t.uploadFunctions,[s]:p},checkPendingFunctions:{...t.checkPendingFunctions,[s]:i},retryAttempts:{...t.retryAttempts,[s]:h}}})},startUpload:(s,e)=>{a(t=>({uploads:{...t.uploads,[s]:{...t.uploads[s]||{},[e]:{status:"uploading",progress:0,error:null}}}}))},setProgress:(s,e,t)=>{a(o=>{const r=o.uploads[s]?.[e]||m;return{uploads:{...o.uploads,[s]:{...o.uploads[s]||{},[e]:{...r,progress:Math.min(100,Math.max(0,t))}}}}})},completeUpload:(s,e)=>{a(t=>{const o=t.uploads[s]?.[e]||m;return{uploads:{...t.uploads,[s]:{...t.uploads[s]||{},[e]:{...o,status:"complete",progress:100}}}}})},failUpload:(s,e,t)=>{a(o=>{const r=o.uploads[s]?.[e]||m;return{uploads:{...o.uploads,[s]:{...o.uploads[s]||{},[e]:{...r,status:"error",error:t}}}}})},resetUpload:(s,e)=>{a(t=>({uploads:{...t.uploads,[s]:{...t.uploads[s]||{},[e]:{...m}}}}))},resetForm:s=>{a(e=>({uploads:{...e.uploads,[s]:{}}}))},cleanup:s=>{a(e=>{const{[s]:t,...o}=e.uploads,{[s]:r,...l}=e.uploadFunctions,{[s]:p,...u}=e.checkPendingFunctions,{[s]:i,...g}=e.retryAttempts;return{uploads:o,uploadFunctions:l,checkPendingFunctions:u,retryAttempts:g}})},uploadAll:async s=>{const e=n().uploadFunctions[s];if(!e)return;const t=Object.entries(e);if(t.length===0)return;const o=async(r,l,p=1)=>{n().startUpload(s,r);try{await l(u=>{n().setProgress(s,r,u)}),n().completeUpload(s,r),a(u=>({retryAttempts:{...u.retryAttempts,[s]:{...u.retryAttempts[s]||{},[r]:0}}}))}catch(u){const i=u instanceof Error?u.message:"Upload failed",g=n().maxRetries;if((n().retryAttempts[s]?.[r]??0)<g){a(c=>({retryAttempts:{...c.retryAttempts,[s]:{...c.retryAttempts[s]||{},[r]:(c.retryAttempts[s]?.[r]??0)+1}}}));const h=n().retryDelay*Math.pow(2,p-1);return await new Promise(c=>setTimeout(c,h)),o(r,l,p+1)}else throw n().failUpload(s,r,i),u}};await Promise.all(t.map(async([r,l])=>{await o(r,l)}))},hasPendingUploads:s=>{const e=n(),t=e.uploadFunctions[s],o=e.checkPendingFunctions[s];return t?Object.entries(t).some(([r,l])=>{const p=o?.[r];return p?p():!0}):!1},getStatus:(s,e)=>n().uploads[s]?.[e]?.status??"idle",getProgress:(s,e)=>n().uploads[s]?.[e]?.progress??0,getTotalProgress:s=>{const e=n().uploads[s];if(!e)return 100;const t=Object.values(e);if(t.length===0)return 100;const o=t.reduce((r,l)=>r+l.progress,0);return Math.round(o/t.length)},isUploading:s=>{const e=n().uploads[s];return e?Object.values(e).some(t=>t.status==="uploading"):!1},getError:(s,e)=>n().uploads[s]?.[e]?.error??null})}),y=a=>d(n=>{const s=n.uploads[a];if(!s)return 100;const e=Object.values(s);if(e.length===0)return 100;const t=e.reduce((o,r)=>o+r.progress,0);return Math.round(t/e.length)}),P=a=>d(n=>{const s=n.uploads[a];return s?Object.values(s).some(e=>e.status==="uploading"):!1}),A=(a,n)=>d(s=>s.uploads[a]?.[n]?.progress??0),U=(a,n)=>d(s=>s.uploads[a]?.[n]?.status??"idle");export{A as useFieldProgress,U as useFieldUploadStatus,P as useIsUploading,y as useTotalProgress,d as useUploadStore};
1
+ "use client";import{createDoNotDevStore as k}from"@donotdev/core";const b={status:"idle",progress:0,error:null},P=k({name:"upload-store",createStore:(l,r)=>({uploads:{},uploadFunctions:{},checkPendingFunctions:{},retryAttempts:{},abortControllers:{},maxRetries:3,retryDelay:1e3,uploadTimeout:3e4,registerUpload:(t,o,n,e)=>{l(s=>({uploadFunctions:{...s.uploadFunctions,[t]:{...s.uploadFunctions[t]||{},[o]:n}},checkPendingFunctions:{...s.checkPendingFunctions,[t]:{...s.checkPendingFunctions[t]||{},[o]:e||(()=>!1)}}}))},unregisterUpload:(t,o)=>{l(n=>{const e=n.uploadFunctions[t],s=n.checkPendingFunctions[t];if(!e)return n;const{[o]:c,...i}=e,{[o]:u,...p}=s||{},{[o]:g,...a}=n.retryAttempts[t]||{};return{uploadFunctions:{...n.uploadFunctions,[t]:i},checkPendingFunctions:{...n.checkPendingFunctions,[t]:p},retryAttempts:{...n.retryAttempts,[t]:a}}})},startUpload:(t,o)=>{l(n=>({uploads:{...n.uploads,[t]:{...n.uploads[t]||{},[o]:{status:"uploading",progress:0,error:null}}}}))},setProgress:(t,o,n)=>{l(e=>{const s=e.uploads[t]?.[o]||b;return{uploads:{...e.uploads,[t]:{...e.uploads[t]||{},[o]:{...s,progress:Math.min(100,Math.max(0,n))}}}}})},completeUpload:(t,o)=>{l(n=>{const e=n.uploads[t]?.[o]||b;return{uploads:{...n.uploads,[t]:{...n.uploads[t]||{},[o]:{...e,status:"complete",progress:100}}}}})},failUpload:(t,o,n)=>{l(e=>{const s=e.uploads[t]?.[o]||b;return{uploads:{...e.uploads,[t]:{...e.uploads[t]||{},[o]:{...s,status:"error",error:n}}}}})},resetUpload:(t,o)=>{l(n=>({uploads:{...n.uploads,[t]:{...n.uploads[t]||{},[o]:{...b}}}}))},resetForm:t=>{l(o=>({uploads:{...o.uploads,[t]:{}}}))},cleanup:t=>{l(o=>{const n=o.abortControllers[t];n&&n.abort();const{[t]:e,...s}=o.uploads,{[t]:c,...i}=o.uploadFunctions,{[t]:u,...p}=o.checkPendingFunctions,{[t]:g,...a}=o.retryAttempts,{[t]:U,...d}=o.abortControllers;return{uploads:s,uploadFunctions:i,checkPendingFunctions:p,retryAttempts:a,abortControllers:d}})},uploadAll:async(t,o)=>{const e=r().uploadFunctions[t];if(!e)return;const s=Object.entries(e);if(s.length===0)return;const c=new AbortController;if(o?.aborted){c.abort();return}o?.addEventListener("abort",()=>c.abort(),{once:!0}),l(u=>({abortControllers:{...u.abortControllers,[t]:c}}));const i=async(u,p,g=1,a)=>{if(a?.aborted){r().failUpload(t,u,"Upload cancelled");return}r().startUpload(t,u);try{const U=r().uploadTimeout;await Promise.race([p(d=>{r().setProgress(t,u,d)},a),new Promise((d,F)=>{const y=setTimeout(()=>F(new Error("Upload timed out")),U);a?.addEventListener("abort",()=>{clearTimeout(y),F(new Error("Upload cancelled"))},{once:!0})})]),r().completeUpload(t,u),l(d=>({retryAttempts:{...d.retryAttempts,[t]:{...d.retryAttempts[t]||{},[u]:0}}}))}catch(U){if(a?.aborted){r().failUpload(t,u,"Upload cancelled");return}const d=U instanceof Error?U.message:"Upload failed",F=r().maxRetries;if((r().retryAttempts[t]?.[u]??0)<F){l(h=>({retryAttempts:{...h.retryAttempts,[t]:{...h.retryAttempts[t]||{},[u]:(h.retryAttempts[t]?.[u]??0)+1}}}));const A=r().retryDelay*Math.pow(2,g-1);if(await new Promise(h=>setTimeout(h,A)),a?.aborted){r().failUpload(t,u,"Upload cancelled");return}return i(u,p,g+1,a)}else throw r().failUpload(t,u,d),U}};try{await Promise.all(s.map(async([u,p])=>{await i(u,p,1,c.signal)}))}finally{l(u=>{const{[t]:p,...g}=u.abortControllers;return{abortControllers:g}})}},abortAll:t=>{const o=r().abortControllers[t];o&&o.abort();const n=r().uploads[t];n&&Object.entries(n).forEach(([e,s])=>{s.status==="uploading"&&r().failUpload(t,e,"Upload cancelled")})},hasPendingUploads:t=>{const o=r(),n=o.uploadFunctions[t],e=o.checkPendingFunctions[t];return n?Object.entries(n).some(([s,c])=>{const i=e?.[s];return i?i():!0}):!1},getStatus:(t,o)=>r().uploads[t]?.[o]?.status??"idle",getProgress:(t,o)=>r().uploads[t]?.[o]?.progress??0,getTotalProgress:t=>{const o=r().uploads[t];if(!o)return 100;const n=Object.values(o);if(n.length===0)return 100;const e=n.reduce((s,c)=>s+c.progress,0);return Math.round(e/n.length)},isUploading:t=>{const o=r().uploads[t];return o?Object.values(o).some(n=>n.status==="uploading"):!1},getError:(t,o)=>r().uploads[t]?.[o]?.error??null})}),_=l=>P(r=>{const t=r.uploads[l];if(!t)return 100;const o=Object.values(t);if(o.length===0)return 100;const n=o.reduce((e,s)=>e+s.progress,0);return Math.round(n/o.length)}),w=l=>P(r=>{const t=r.uploads[l];return t?Object.values(t).some(o=>o.status==="uploading"):!1}),x=(l,r)=>P(t=>t.uploads[l]?.[r]?.progress??0),m=(l,r)=>P(t=>t.uploads[l]?.[r]?.status??"idle");export{x as useFieldProgress,m as useFieldUploadStatus,w as useIsUploading,_ as useTotalProgress,P as useUploadStore};
@@ -2,7 +2,7 @@
2
2
  * @fileoverview CRUD Stores
3
3
  * @description Store exports for CRUD feature
4
4
  *
5
- * @version 0.0.1
5
+ * @version 0.1.0
6
6
  * @since 0.0.1
7
7
  * @author AMBROISE PARK Consulting
8
8
  */
@@ -1 +1 @@
1
- import{useFormStore as s,useFormStatus as r,useFormLoading as a,useUploadProgress as o,useFormError as e,useFormIsDirty as u,useHasDirtyForms as t}from"./FormStore";import{useUploadStore as m,useTotalProgress as F,useIsUploading as d,useFieldProgress as i,useFieldUploadStatus as l}from"./UploadStore";export{i as useFieldProgress,l as useFieldUploadStatus,e as useFormError,u as useFormIsDirty,a as useFormLoading,r as useFormStatus,s as useFormStore,t as useHasDirtyForms,d as useIsUploading,F as useTotalProgress,o as useUploadProgress,m as useUploadStore};
1
+ import{useFormStore as o,useFormStatus as e,useFormLoading as u,useUploadProgress as t,useFormError as a,useFormIsDirty as m,useHasDirtyForms as F}from"./FormStore";import{useUploadStore as l,useTotalProgress as i,useIsUploading as p,useFieldProgress as g,useFieldUploadStatus as S}from"./UploadStore";export{g as useFieldProgress,S as useFieldUploadStatus,a as useFormError,m as useFormIsDirty,u as useFormLoading,e as useFormStatus,o as useFormStore,F as useHasDirtyForms,p as useIsUploading,i as useTotalProgress,t as useUploadProgress,l as useUploadStore};
@@ -0,0 +1 @@
1
+ {"FunctionsAdapter":"/**\n * Functions backend adapter\n * Works with any collection dynamically (collection name passed per operation)\n * Assumes Functions are named: `get_${collection}`, `create_${collection}`, etc.\n *\n * All backends go through ICallableProvider. If none configured, falls back to FirebaseCallableProvider.\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare class FunctionsAdapter implements ICrudAdapter {\n readonly serverSideOnly = true;\n /**\n * Resolve ICallableProvider from provider registry.\n * Consumer must configure via configureProviders({ callable: adapter }).\n */\n private getCallable;\n /**\n * Get callable function invoker. Always uses ICallableProvider (configured or Firebase fallback).\n */\n private getCallableFn;\n get<T>(collectionName: string, id: string, schema: dndevSchema<unknown>): Promise<T | null>;\n set<T>(collectionName: string, id: string, data: T, schema: dndevSchema<T>): Promise<void>;\n update<T>(collectionName: string, id: string, data: Partial<T>): Promise<void>;\n delete(collectionName: string, id: string): Promise<void>;\n add<T>(collectionName: string, data: T, schema: dndevSchema<T>): Promise<{\n id: string;\n data: Record<string, unknown>;\n }>;\n query<T>(collectionName: string, options: FunctionsQueryOptions, schema: dndevSchema<unknown>, schemaType?: ListSchemaType): Promise<PaginatedQueryResult<T>>;\n subscribe<T>(): () => void;\n subscribeToCollection<T>(): () => void;\n}","FunctionsQueryOptions":"/**\n * Query options for Functions queries\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport interface FunctionsQueryOptions {\n where?: Array<{\n field: string;\n operator: string;\n value: unknown;\n }>;\n orderBy?: Array<{\n field: string;\n direction?: 'asc' | 'desc';\n }>;\n limit?: number;\n /** Cursor from previous page (QueryOptions uses startAfter; server uses startAfterId) */\n startAfter?: string | null;\n startAfterId?: string;\n}","getCrudService":"/**\n * Get or create CrudService singleton instance\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const getCrudService: () => CrudService;","useCrudStore":"/**\n * CRUD store hook for accessing CRUD state and actions\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const useCrudStore: import(\"zustand\").UseBoundStore<import(\"zustand\").StoreApi<CrudState & CrudActions & import(\"@donotdev/stores\").DoNotDevStore>>;","CrudServiceInterface":"/**\n * CRUD Service Interface\n * Complete interface for CRUD operations with caching and optimistic updates\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport interface CrudServiceInterface {\n /** Initialize the CRUD adapter from the provider registry. Call configureProviders() first. */\n initialize(): Promise<void>;\n setStore(store: CrudStoreApi): void;\n /** Schema accepts unknown since OperationSchemas stores dndevSchema<unknown>. T is for return type. */\n getListQueryOptions<T>(collection: string, queryOptions: QueryOptions, schema: dndevSchema<unknown>, cacheOptions?: CacheOptions, schemaType?: ListSchemaType): {\n queryKey: readonly string[];\n queryFn: () => Promise<PaginatedQueryResult<T>>;\n staleTime: number;\n };\n /** Schema accepts unknown since OperationSchemas stores dndevSchema<unknown>. T is for return type. */\n getDocQueryOptions<T>(collection: string, id: string, schema: dndevSchema<unknown>, cacheOptions?: CacheOptions): {\n queryKey: readonly string[];\n queryFn: () => Promise<T | null>;\n staleTime: number;\n };\n get<T>(collection: string, id: string, schema: dndevSchema<T>, options?: CacheOptions): Promise<T | null>;\n query<T>(collection: string, options: QueryOptions, schema: dndevSchema<T>, cacheOptions?: CacheOptions, schemaType?: ListSchemaType): Promise<PaginatedQueryResult<T>>;\n set<T>(collection: string, id: string, data: T, schema: dndevSchema<T>, options?: MutationOptions): Promise<void>;\n update<T>(collection: string, id: string, data: Partial<T>, schema?: dndevSchema<T>, options?: MutationOptions): Promise<void>;\n delete(collection: string, id: string, options?: MutationOptions): Promise<void>;\n add<T>(collection: string, data: T, schema: dndevSchema<T>, options?: MutationOptions): Promise<string>;\n subscribe<T>(collection: string, id: string, callback: (data: T | null, error?: Error) => void, schema: dndevSchema<T>): () => void;\n subscribeToCollection<T>(collection: string, options: QueryOptions, callback: (data: T[], error?: Error) => void, schema: dndevSchema<T>): () => void;\n /** Add with optimistic update - shows item immediately, confirms/rolls back after server */\n addOptimistic<T extends {\n id?: string;\n }>(collection: string, data: T, schema: dndevSchema<T>, options?: MutationOptions): Promise<T & {\n id: string;\n }>;\n /** Update with optimistic update - shows change immediately, confirms/rolls back after server */\n updateOptimistic<T>(collection: string, id: string, data: Partial<T>, schema: dndevSchema<T>, options?: MutationOptions): Promise<T>;\n /** Delete with optimistic update - hides item immediately, confirms/restores after server */\n deleteOptimistic(collection: string, id: string, options?: MutationOptions): Promise<void>;\n /** Invalidate all cached queries for a collection */\n invalidateCollection(collection: string): Promise<void>;\n /** Get the shared QueryClient instance from @donotdev/core */\n getQueryClient(): QueryClient;\n}","CrudState":"/**\n * CRUD store state interface\n * Note: No data field - TanStack Query owns data, CrudStore only tracks optimistic ops\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport interface CrudState {\n crudService: CrudServiceInterface | null;\n /** Global flag to hide success toasts (set from app config) */\n hideSuccessToasts: boolean;\n collections: Record<string, {\n loading: boolean;\n error: Error | null;\n lastUpdated: number;\n /** Optimistic operation metadata keyed by document id */\n optimistic: Record<string, OptimisticMeta>;\n /** UI state: filters and favorites toggle (persists across navigation) */\n ui: CollectionUIState;\n }>;\n}","CrudActions":"/**\n * CRUD store actions interface\n * Note: No setData/getData - TanStack Query owns data, CrudStore only tracks optimistic ops\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport interface CrudActions {\n setCrudService: (service: CrudServiceInterface) => void;\n /** Set global flag to hide success toasts (called from app bootstrap) */\n setHideSuccessToasts: (hide: boolean) => void;\n setLoading: (collection: string, loading: boolean) => void;\n setError: (collection: string, error: Error | null) => void;\n clearCollection: (collection: string) => void;\n clearError: (collection: string) => void;\n setFilters: (collection: string, filters: FilterState) => void;\n setShowFavoritesOnly: (collection: string, show: boolean) => void;\n setPageSize: (collection: string, pageSize: number) => void;\n getFilters: (collection: string) => FilterState;\n getShowFavoritesOnly: (collection: string) => boolean;\n getPageSize: (collection: string) => number | undefined;\n /** Add item optimistically (before server confirms) */\n addOptimistic: (collection: string, tempId: string, data: unknown) => void;\n /** Confirm optimistic add - replace temp item with real item */\n confirmOptimistic: (collection: string, tempId: string, realId: string, realData: unknown) => void;\n /** Reject optimistic add - remove temp item */\n rejectOptimistic: (collection: string, tempId: string) => void;\n /** Update item optimistically */\n updateOptimistic: (collection: string, id: string, data: unknown, originalData: unknown) => void;\n /** Confirm optimistic update */\n confirmUpdate: (collection: string, id: string) => void;\n /** Reject optimistic update - restore original data */\n rejectUpdate: (collection: string, id: string) => void;\n /** Delete item optimistically (hide but keep for rollback) */\n deleteOptimistic: (collection: string, id: string, originalData: unknown) => void;\n /** Confirm optimistic delete - remove completely */\n confirmDelete: (collection: string, id: string) => void;\n /** Reject optimistic delete - restore item */\n rejectDelete: (collection: string, id: string) => void;\n getLoading: (collection: string) => boolean;\n getError: (collection: string) => Error | null;\n /** Check if item is optimistic (not yet confirmed by server) */\n isOptimistic: (collection: string, id: string) => boolean;\n /** Get optimistic status for an item */\n getOptimisticStatus: (collection: string, id: string) => OptimisticStatus | null;\n /** Get optimistic data for an item (for display during pending state) */\n getOptimisticData: (collection: string, id: string) => unknown | null;\n}","OptimisticStatus":"/** Union of optimistic operation status values: 'pending' | 'confirmed' | 'failed'. */\nexport type OptimisticStatus = (typeof OPTIMISTIC_STATUSES)[keyof typeof OPTIMISTIC_STATUSES];","OptimisticMeta":"/**\n * Optimistic operation metadata\n * Contains both original data (for rollback) and current data (for display)\n */\nexport interface OptimisticMeta {\n tempId: string;\n originalData: unknown | null;\n /** Current optimistic data to display (the new/updated value) */\n optimisticData: unknown;\n status: OptimisticStatus;\n operation: CrudOperation;\n}","CrudOperation":"/** Union of CRUD mutation operation kinds: 'add' | 'update' | 'set' | 'delete'. */\nexport type CrudOperation = (typeof CRUD_OPERATION)[keyof typeof CRUD_OPERATION];","CrudStoreApi":"/**\n * Store API type for CrudService - typed instead of any\n * Used by CrudService to type the store it receives\n */\nexport type CrudStoreApi = {\n getState: () => CrudState & CrudActions;\n}","CacheOptions":"/**\n * Cache options for read operations\n */\nexport interface CacheOptions {\n /** Bypass cache and fetch directly from adapter */\n noCache?: boolean;\n /** Custom stale time in ms (default: Infinity) */\n staleTime?: number;\n}","MutationOptions":"/**\n * Options for mutation operations (add, update, delete, set)\n */\nexport interface MutationOptions {\n /**\n * Override success toast behavior for this operation\n * - true: always show toast\n * - false: never show toast\n * - undefined: use global setting (hideSuccessToasts)\n */\n showSuccessToast?: boolean;\n}","FilterState":"/**\n * Filter state type for list views\n * Persists across navigation within CrudStore\n * - string: single value filter (text, select)\n * - string[]: multi-select filter (multiple values)\n * - { min?: string; max?: string }: range filter (number, date)\n */\nexport type FilterState = Record<string, string | string[] | {\n min?: string;\n max?: string;\n}","CollectionUIState":"/**\n * Collection UI state (filters, favorites toggle)\n * Persists across navigation\n */\nexport interface CollectionUIState {\n filters: FilterState;\n showFavoritesOnly: boolean;\n /** Persisted items-per-page preference (survives navigation) */\n pageSize?: number;\n}","OPTIMISTIC_STATUSES":"/**\n * Optimistic operation status\n */\nexport declare const OPTIMISTIC_STATUSES: {\n readonly PENDING: \"pending\";\n readonly CONFIRMED: \"confirmed\";\n readonly FAILED: \"failed\";\n}","CRUD_OPERATION":"/** Optimistic mutation operation kind */\nexport declare const CRUD_OPERATION: {\n readonly ADD: \"add\";\n readonly UPDATE: \"update\";\n /** Full document replacement (set/upsert) — cache replaces, not merges */\n readonly SET: \"set\";\n readonly DELETE: \"delete\";\n}","loadDeterministicRange":"/**\n * Load a deterministic range of items from a subcollection\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare function loadDeterministicRange<T>(userId: string, config: DeterministicSubcollectionConfig<T>): Promise<T[]>;","upsertDeterministic":"/**\n * Upsert a deterministic range of items in a subcollection\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare function upsertDeterministic<T>(userId: string, config: DeterministicSubcollectionConfig<T>, data: T[]): Promise<void>;","appendToCollection":"/**\n * Append an item to a subcollection\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare function appendToCollection<T>(userId: string, config: AppendSubcollectionConfig<T>, item: T): Promise<string | void>;","getFieldRegistry":"/**\n * Get the field registry singleton.\n * Backed by globalThis to survive Vite pre-bundling chunk splits and HMR.\n */\nexport declare function getFieldRegistry(): FieldRegistry;","registerFieldType":"/**\n * Register a custom field type (form, optional display, optional filter).\n * Schema must be defined in entity.validation.schema\n *\n * @example\n * ```ts\n * import { useController, registerFieldType } from '@donotdev/crud';\n * import type { ControlledFieldProps } from '@donotdev/crud';\n * import * as v from 'valibot';\n *\n * function ControlledRepairOperationsField({\n * fieldConfig,\n * control,\n * errors,\n * t,\n * }: ControlledFieldProps) {\n * const { field, fieldState } = useController({\n * name: fieldConfig.name,\n * control: control,\n * });\n * return (\n * <div>\n * Your custom UI here\n * {fieldState?.error && <span>{fieldState.error.message}</span>}\n * </div>\n * );\n * }\n *\n * registerFieldType({\n * type: 'repairOperations',\n * controlledComponent: ControlledRepairOperationsField,\n * displayFormatter: (value) => (value != null ? String(value) : '—'),\n * filterable: true,\n * filterType: 'text',\n * });\n *\n * const carEntity = defineEntity({\n * fields: {\n * repairs: {\n * type: 'repairOperations',\n * validation: { schema: v.array(v.object({ operation: v.string(), cost: v.number() })) }\n * }\n * }\n * });\n * ```\n */\nexport declare function registerFieldType<FT extends FieldType>(registration: FieldTypeRegistration<FT>): void;","isFieldTypeRegistered":"/**\n * Check if a field type is registered\n */\nexport declare function isFieldTypeRegistered(type: string): boolean;","registerBuiltinFieldType":"/**\n * Register a built-in field type with all metadata.\n * For internal/plugin use — consumers should use registerFieldType() instead.\n */\nexport declare function registerBuiltinFieldType(metadata: FieldTypeMetadata): void;","getFieldTypeMetadata":"export declare function getFieldTypeMetadata(type: string): FieldTypeMetadata | undefined;","getFilterType":"export declare function getFilterType(type: string): FilterType | undefined;","getDisplayFormatter":"export declare function getDisplayFormatter(type: string): DisplayFormatter | undefined;","isFilterable":"export declare function isFilterable(type: string): boolean;","getValueType":"export declare function getValueType(type: string): ValueType | undefined;","clearFieldTypeRegistry":"export declare function clearFieldTypeRegistry(): void;","registerBuiltinFieldTypes":"/**\n * @deprecated No-op. Built-in registration is now automatic (lazy on first access).\n * Kept for API compatibility with consumers that call this at app startup.\n */\nexport declare function registerBuiltinFieldTypes(): void;","useEntityForm":"/**\n * Creates a type-safe form instance from an entity definition.\n *\n * Simple, predictable behavior:\n * - Edit mode: defaultValues (DB object) is used as-is, auto-save to localStorage\n * - Create mode: starts empty, auto-save to localStorage\n * - Draft restored on mount with dismissible toast\n *\n * When formId is provided:\n * - Tracks form status (uploading/validating/submitting)\n * - Orchestrates file uploads before validation\n * - Provides cleanup function for unmount\n *\n * @template E - Entity type from defineEntity()\n * @param entity - Entity definition from defineEntity()\n * @param options - Form configuration options\n * @returns Form instance with React Hook Form API plus entity-aware extensions\n */\nexport declare function useEntityForm<E extends Entity>(entity: E, options?: UseEntityFormOptions<E>): EntityFormReturn<E>;","useEntityField":"/**\n * Granular hook for single field control within an entity form.\n *\n * Useful when you need fine-grained control over field rendering,\n * such as custom components, conditional logic, or complex layouts.\n *\n * Returns `{ field, meta, config, isEditable, isVisible, display }`.\n * - `display(options?)` formats the current value using the registered field type formatter.\n *\n * @template E - Entity type from defineEntity()\n * @template K - Field key from entity\n * @param form - Form instance from useEntityForm\n * @param fieldName - Name of the field to control\n * @returns Field state, config, editability info, and display formatter\n *\n * @example\n * ```tsx\n * // Custom field with display()\n * const { field, display, isEditable } = useEntityField(form, 'price');\n * // display() → \"€42.00\" (uses registered formatter)\n * // display({ compact: true }) → compact format for lists\n * if (!isEditable) return <span>{display()}</span>;\n * ```\n *\n * @example\n * ```tsx\n * // Full custom field\n * function CustomEmailField({ form }) {\n * const { field, meta, config, isEditable } = useEntityField(form, 'email');\n *\n * if (!isEditable) return <span>{field.value}</span>;\n *\n * return (\n * <div>\n * <label>{config.label}</label>\n * <input\n * type=\"email\"\n * value={field.value ?? ''}\n * onChange={field.onChange}\n * onBlur={field.onBlur}\n * />\n * {meta.error && <span className=\"error\">{meta.error}</span>}\n * </div>\n * );\n * }\n * ```\n *\n * @see {@link useEntityForm} for creating the form instance\n * @see {@link EntityFieldReturn} for return type\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare function useEntityField<E extends Entity, K extends keyof InferEntityData<E>>(form: EntityFormReturn<E>, fieldName: K): EntityFieldReturn<E, K>;","useController":"/**\n * Framework-provided useController hook\n *\n * Use this instead of importing useController from react-hook-form directly.\n * This ensures type compatibility with framework's Control types.\n *\n * @template TFieldValues - Form values type\n * @template TName - Field name path\n * @param props - Controller props (name and control)\n * @returns Controller return value (field, fieldState, formState)\n *\n * @example\n * ```tsx\n * import { useController } from '@donotdev/crud';\n * import type { ControlledFieldProps } from '@donotdev/crud';\n *\n * function MyCustomField({ control, fieldConfig }: ControlledFieldProps) {\n * const { field, fieldState } = useController({\n * name: fieldConfig.name,\n * control: control,\n * });\n * // ...\n * }\n * ```\n */\nexport declare function useController<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>(props: UseControllerProps<TFieldValues, TName>): UseControllerReturn<TFieldValues, TName>;","isFieldEditable":"/**\n * Determines if a field is editable by the current viewer.\n *\n * NOTE: Visibility is handled by backend - this function only handles editability (UI concern).\n *\n * @param editable - Field's editable configuration\n * @param viewerRole - Current viewer's role\n * @param operation - Form operation type\n * @returns Whether the field should be rendered as an input (true) or read-only (false)\n *\n * @example\n * ```typescript\n * // Default editable\n * isFieldEditable(undefined, 'user', 'create'); // true\n *\n * // Role-based (uses hierarchy: guest < user < admin < super)\n * isFieldEditable('admin', 'user', 'edit'); // false\n * isFieldEditable('admin', 'admin', 'edit'); // true\n * isFieldEditable('user', 'admin', 'edit'); // true (admin >= user)\n * isFieldEditable('super', 'admin', 'edit'); // false (admin < super)\n *\n * // Create-only field\n * isFieldEditable('create-only', 'user', 'create'); // true\n * isFieldEditable('create-only', 'user', 'edit'); // false\n *\n * // Generated/computed - always false (excluded from forms)\n * isFieldEditable('generated', 'admin', 'create'); // false\n * isFieldEditable('computed', 'admin', 'edit'); // false\n * ```\n *\n * @see {@link Editable} for editable configuration options\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare function isFieldEditable(editable: Editable | undefined, viewerRole: string, operation: 'create' | 'edit'): boolean;","getFieldsForOperation":"/**\n * Filters entity fields based on operation type and viewer role.\n *\n * Pure function, no React dependencies. Use for building custom form layouts.\n *\n * **Create operation:**\n * - Excludes `visibility: 'technical'` fields (auto-added by backend)\n * - Excludes `visibility: 'hidden'` fields (never shown)\n *\n * **Edit operation:**\n * - Excludes `visibility: 'hidden'` fields (never shown)\n * - Technical fields are marked as `editable: false` (read-only)\n * - If `availableFields` provided, only returns fields in that list (backend-filtered)\n *\n * @param entity - Entity definition from defineEntity()\n * @param options - Filtering options\n * @returns Array of renderable fields with computed editability\n *\n * @example\n * ```typescript\n * import { getFieldsForOperation } from '@donotdev/crud/forms';\n * import { productEntity } from './entities/product';\n *\n * // Create form - excludes technical and hidden\n * const createFields = getFieldsForOperation(productEntity, {\n * operation: 'create',\n * viewerRole: 'user'\n * });\n *\n * // Edit form - uses backend-filtered fields\n * const editFields = getFieldsForOperation(productEntity, {\n * operation: 'edit',\n * viewerRole: 'admin',\n * availableFields: Object.keys(existingData)\n * });\n *\n * // Render custom form\n * editFields.map(({ name, config, editable }) => (\n * editable\n * ? <Input key={name} {...config} />\n * : <ReadOnlyDisplay key={name} {...config} />\n * ));\n * ```\n *\n * @see {@link Entity} for entity definition structure\n * @see {@link RenderableField} for return type\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare function getFieldsForOperation(entity: EntityFieldsInput, options: GetFieldsForOperationOptions): RenderableField[];","validateEntity":"/**\n * Validates data against an entity definition.\n *\n * Uses Valibot under the hood with entity-derived schemas.\n * Pure function, no React dependencies.\n *\n * @template E - Entity type from defineEntity()\n * @param entity - Entity definition from defineEntity()\n * @param data - Data to validate\n * @param operation - Validation context ('create', 'draft', 'update', or 'full')\n * @returns Validation result with typed issues\n *\n * @example\n * ```typescript\n * import { validateEntity } from '@donotdev/crud/forms';\n * import { productEntity } from './entities/product';\n *\n * // Validate create data\n * const result = validateEntity(productEntity, formData, 'create');\n *\n * if (result.success) {\n * await saveProduct(result.data);\n * } else {\n * console.error('Validation failed:', result.issues);\n * // [{ path: 'name', message: 'Required' }, ...]\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Use in form submission\n * const onSubmit = async (data: unknown) => {\n * const validation = validateEntity(productEntity, data, 'create');\n *\n * if (!validation.success) {\n * validation.issues?.forEach(issue => {\n * form.setError(issue.path, { message: issue.message });\n * });\n * return;\n * }\n *\n * await api.createProduct(validation.data);\n * };\n * ```\n *\n * @see {@link Entity} for entity definition structure\n * @see {@link ValidationResult} for return type\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare function validateEntity<E extends Entity>(entity: E, data: unknown, operation?: SchemaOperation): ValidationResult<Record<string, unknown>>;","translateFieldLabel":"/**\n * Translates a field label using the provided translation function.\n *\n * Supports multiple label formats:\n * - Namespace syntax: `\"namespace:key\"` → translates `key` in `namespace`\n * - Direct label: `\"label\"` → translates `label` in current namespace\n * - Field name fallback: uses field name if no label in config\n *\n * @param fieldName - Field name (used as fallback)\n * @param config - Field configuration (may contain label)\n * @param t - Translation function from useTranslation hook\n * @returns Translated label string\n *\n * @example\n * ```typescript\n * import { translateFieldLabel } from '@donotdev/crud/forms';\n * import { useTranslation } from '@donotdev/core';\n *\n * const { t } = useTranslation('entity-car');\n * const label = translateFieldLabel('make', carEntity.fields.make, t);\n * // Returns: translated \"make\" from entity-car namespace\n * ```\n *\n * @example\n * ```typescript\n * // With namespace syntax in config.label\n * const label = translateFieldLabel('status', {\n * label: 'common:status',\n * type: 'select'\n * }, t);\n * // Returns: translated \"status\" from \"common\" namespace\n * ```\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare function translateFieldLabel<T extends FieldType = FieldType>(fieldName: string, config: EntityField<T> | undefined, t: (key: string, options?: Record<string, any>) => string): string;","translateLabel":"/**\n * Translates a label string with namespace support.\n * Used for translating option labels, field labels, or any label string.\n *\n * Supports namespace:key syntax (e.g., \"crud:status.draft\")\n *\n * **Translation Fallback Order (for status labels):**\n * 1. Entity namespace (`entity-{name}`) - User overrides take priority\n * 2. CRUD namespace (`crud`) - Framework defaults\n *\n * No dndev fallback - CRUD is optional and shouldn't pollute core framework namespace.\n *\n * @param label - Label string to translate (may include namespace:key syntax)\n * @param t - Translation function from useTranslation hook (should be from multi-namespace hook like [entity.namespace, 'crud'])\n * @returns Translated label string\n *\n * @example\n * ```typescript\n * translateLabel('crud:status.draft', t); // Tries entity namespace first, then crud\n * translateLabel('make', t); // Translates \"make\" in current namespace (entity or crud)\n * ```\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare function translateLabel(label: string, t: (key: string, options?: Record<string, any>) => string): string;","ViewerRole":"/** Viewer role type - used for editability checks */\nexport type ViewerRole = 'public' | 'guest' | 'user' | 'admin' | 'super';","RenderableField":"/** Field with computed editability for rendering */\nexport interface RenderableField<T extends FieldType = FieldType> {\n /** Field name/key */\n name: string;\n /** Field configuration */\n config: EntityField<T>;\n /** Whether field is editable (input vs read-only) */\n editable: boolean;\n}","GetFieldsForOperationOptions":"/** Options for field filtering */\nexport interface GetFieldsForOperationOptions {\n /** Form operation type */\n operation: 'create' | 'edit';\n /** Viewer role for editability checks (defaults to 'guest' if undefined) */\n viewerRole?: string;\n /**\n * Available field names (for edit mode).\n * When provided, only fields in this list are returned.\n * Typically comes from Object.keys(defaultValues) - backend-filtered data.\n */\n availableFields?: string[];\n}","EntityFieldsInput":"/** Entity fields input - supports Entity, Entity['fields'], or plain Record */\nexport type EntityFieldsInput = Entity | Entity['fields'] | Record<string, EntityField<FieldType>>;","SchemaOperation":"/**\n * Validation operation type\n */\nexport type SchemaOperation = 'create' | 'draft' | 'update' | 'full';","ValidationIssue":"/**\n * Validation issue structure\n */\nexport interface ValidationIssue {\n /** Field path (e.g., 'name' or 'address.street') */\n path: string;\n /** Error message */\n message: string;\n}","ValidationResult":"/**\n * Validation result structure\n * @template T - Data type\n */\nexport interface ValidationResult<T> {\n /** Whether validation succeeded */\n success: boolean;\n /** Validated data (if success) */\n data?: T;\n /** Validation issues (if failed) */\n issues?: ValidationIssue[];\n}","InferEntityData":"/**\n * Infers the data type from an entity definition.\n *\n * Maps each field in the entity to its corresponding TypeScript type\n * based on the field's `type` property.\n *\n * @template E - Entity type from defineEntity()\n *\n * @example\n * ```typescript\n * const productEntity = defineEntity({\n * name: 'Product',\n * collection: 'products',\n * fields: {\n * name: { type: 'text', visibility: 'guest' },\n * price: { type: 'number', visibility: 'guest' },\n * active: { type: 'boolean', visibility: 'user' }\n * }\n * });\n *\n * type ProductData = InferEntityData<typeof productEntity>;\n * // { name: string; price: number; active: boolean; id: string; ... }\n * ```\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport type InferEntityData<E extends Entity> = {\n [K in keyof E['fields']]: E['fields'][K] extends {\n type: infer T;\n } ? T extends FieldType ? T extends keyof FieldTypeToValue ? FieldTypeToValue[T] : unknown : unknown : unknown;\n}","InferEntityInput":"/**\n * Infers form input type (values before validation).\n * All fields are optional/partial since form may be incomplete.\n *\n * @template E - Entity type from defineEntity()\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport type InferEntityInput<E extends Entity> = Partial<InferEntityData<E>>;","InferEntityOutput":"/**\n * Infers form output type (values after validation).\n * Represents validated, complete data ready for submission.\n *\n * @template E - Entity type from defineEntity()\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport type InferEntityOutput<E extends Entity> = InferEntityData<E>;","UseEntityFormOptions":"/**\n * Options for useEntityForm hook.\n *\n * @template E - Entity type from defineEntity()\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport interface UseEntityFormOptions<E extends Entity> {\n /**\n * Form ID for tracking form/upload state.\n * Required for deferred file uploads and form status tracking.\n * Generate with useId() in the parent component.\n */\n formId?: string;\n /**\n * Form operation type.\n * - 'create': Excludes technical fields, all other fields editable\n * - 'edit': Shows all fields from defaultValues, technical fields read-only\n * @default 'create' (or 'edit' if defaultValues provided)\n */\n operation?: 'create' | 'edit';\n /**\n * Initial form values.\n * For edit mode, should come from backend (already visibility-filtered).\n */\n defaultValues?: Partial<InferEntityData<E>>;\n /**\n * Viewer role for editability checks.\n * Determines which fields render as inputs vs read-only.\n * If not provided, defaults to 'guest' (most restrictive)\n * @default 'guest'\n */\n viewerRole?: string;\n /**\n * React Hook Form mode.\n * @default 'onSubmit'\n */\n mode?: 'onBlur' | 'onChange' | 'onSubmit' | 'onTouched' | 'all';\n /**\n * Translation function for field labels.\n * If not provided, uses entity labels or generates from field names.\n */\n t?: (key: string, options?: Record<string, unknown>) => string;\n}","EntityFormReturn":"/**\n * Return type for useEntityForm hook.\n *\n * Extends React Hook Form's UseFormReturn with entity-aware additions.\n *\n * @template E - Entity type from defineEntity()\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport interface EntityFormReturn<E extends Entity> extends UseFormReturn<InferEntityData<E>> {\n /**\n * Pre-filtered fields ready for rendering.\n * Already filtered by operation and visibility.\n */\n fields: RenderableField[];\n /**\n * Current operation type.\n */\n operation: 'create' | 'edit';\n /**\n * Original entity definition.\n */\n entity: E;\n /**\n * Translation function for labels.\n */\n t: (key: string, options?: Record<string, unknown>) => string;\n /**\n * Current viewer role.\n * Always has a value (defaults to 'guest' if not provided).\n */\n viewerRole: string;\n /**\n * Form ID for state tracking.\n * Undefined if not provided in options.\n */\n formId: string | undefined;\n /**\n * Current form status from FormStore.\n * Tracks: idle → uploading → validating → submitting → success/error\n */\n formStatus: FormStatus;\n /**\n * Upload progress 0-100 when status is 'uploading'.\n */\n uploadProgress: number;\n /**\n * Cleanup function to call on unmount.\n * Cleans up FormStore and UploadStore state for this form.\n */\n cleanup: () => void;\n /**\n * Cancel in-flight uploads and reset form submission state.\n * Aborts the AbortController, resets FormStore, and releases the submit mutex.\n */\n cancel: () => void;\n /**\n * Whether the form has unsaved changes.\n * True if any field value differs from original/default values.\n */\n isDirty: boolean;\n /**\n * Whether the user has interacted with the form.\n * True if any field has been touched or the form has been submitted.\n * Used to gate navigation blocking so we don't warn on untouched forms.\n */\n hasUserInteracted: boolean;\n /**\n * Reset form to original values and clear any saved draft.\n * Use this for \"Cancel\" button functionality.\n */\n resetForm: () => void;\n /**\n * Original values the form was initialized with.\n * For create mode: schema-based defaults.\n * For edit mode: schema defaults overlaid with the DB record.\n */\n originalValues: Partial<InferEntityData<E>> | undefined;\n}","EntityFieldReturn":"/**\n * Return type for useEntityField hook.\n *\n * @template E - Entity type from defineEntity()\n * @template K - Field key from entity\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport interface EntityFieldReturn<E extends Entity, K extends keyof InferEntityData<E>> {\n /**\n * React Hook Form field props (value, onChange, onBlur, etc.)\n */\n field: ControllerRenderProps<InferEntityData<E>, FieldPath<InferEntityData<E>>>;\n /**\n * Field metadata (error, touched, dirty state).\n */\n meta: {\n error: string | undefined;\n touched: boolean;\n isDirty: boolean;\n };\n /**\n * Normalized field configuration.\n */\n config: EntityField;\n /**\n * Whether field is editable (based on role, operation, config).\n */\n isEditable: boolean;\n /**\n * Whether field is visible (based on filtering).\n */\n isVisible: boolean;\n /**\n * Format the current field value for display using registered formatter.\n * Returns the formatted value as string or ReactElement.\n *\n * @param options - Formatting options\n * @param options.compact - Use compact formatting (smaller images, plain spans for empty)\n * @param options.asString - Prefer string output when possible\n */\n display: (options?: {\n compact?: boolean;\n asString?: boolean;\n }) => string | ReactElement;\n}","UploadProvider":"/**\n * UploadProvider - Provides formId to upload components via context\n * Used by EntityFormRenderer to enable deferred uploads\n */\nexport declare function UploadProvider({ formId, children }","useUploadContext":"/**\n * useUploadContext - Get formId for upload components\n * Returns undefined if not inside an UploadProvider (standalone usage)\n */\nexport declare function useUploadContext(): string | undefined;","UploadProviderProps":"/** Props for the {@link UploadProvider} component. */\nexport interface UploadProviderProps {\n formId: string | undefined;\n children: ReactNode;\n}","useFileUpload":"/**\n * useFileUpload - Unified hook for file uploads\n *\n * Features:\n * - Local preview before upload\n * - Deferred upload on form submit (when inside EntityFormRenderer)\n * - Immediate upload when standalone (no UploadProvider context)\n * - UploadStore integration\n * - File validation\n * - Progress tracking\n * - Works with Image, File, Document field types\n */\nexport declare function useFileUpload({ name, value, onChange, multiple, maxFiles, maxSize, accept, storagePath, uploadFn, }","useUnsavedChangesWarning":"/**\n * Hook to warn users about unsaved changes on browser close/refresh only.\n *\n * Handles:\n * - Browser refresh/close (beforeunload event)\n * - Browser back/forward (beforeunload event)\n *\n * Does NOT block SPA navigation — auto-save handles that.\n *\n * @example\n * ```tsx\n * const { isDirty } = useFormState();\n *\n * useUnsavedChangesWarning({\n * isDirty,\n * message: 'You have unsaved changes. Are you sure you want to leave?',\n * });\n * ```\n */\nexport declare function useUnsavedChangesWarning({ isDirty, enabled, message, }","useEntityFavorites":"/**\n * Hook for managing entity favorites\n *\n * @example\n * ```typescript\n * // In detail page\n * const { isFavorite, toggleFavorite } = useEntityFavorites({ collection: 'cars' });\n *\n * <Button onClick={() => toggleFavorite(carId)}>\n * {isFavorite(carId) ? 'Saved' : 'Save'}\n * </Button>\n * ```\n *\n * @example\n * ```typescript\n * // In list page with filter (EntityCardList from @donotdev/ui)\n * const { favoritesFilter } = useEntityFavorites({ collection: 'cars' });\n * const [showFavoritesOnly, setShowFavoritesOnly] = useState(false);\n *\n * <EntityCardList\n * entity={carEntity}\n * filter={showFavoritesOnly ? favoritesFilter : undefined}\n * />\n * ```\n */\nexport declare function useEntityFavorites(options?: UseEntityFavoritesOptions): UseEntityFavoritesReturn;","useRelatedItems":"/**\n * useRelatedItems - Finds related items based on matching field criteria\n *\n * Matching logic by field type:\n * - String/select fields: exact match\n * - Number fields: within ±tolerance% of current value\n *\n * Items are matched if they satisfy ANY of the specified fields (OR logic).\n * Current item is automatically excluded.\n *\n * @example\n * ```tsx\n * const { items: relatedCars } = useRelatedItems(\n * carEntity,\n * currentCar,\n * allCars,\n * ['make', 'price'],\n * { limit: 3, tolerance: 0.2 }\n * );\n * ```\n */\nexport declare function useRelatedItems<T extends Record<string, unknown>>(entity: Entity, currentItem: T | null | undefined, allItems: T[] | null | undefined, matchFields: string[], options?: UseRelatedItemsOptions): UseRelatedItemsReturn<T>;","useCrudFilters":"export declare function useCrudFilters(options: UseCrudFiltersOptions): UseCrudFiltersReturn;","useCrudPageSize":"/**\n * Hook for managing per-collection page size preference from CrudStore\n *\n * @example\n * ```typescript\n * const { pageSize, setPageSize } = useCrudPageSize({ collection: 'cars' });\n *\n * <DataTable\n * pageSize={pageSize}\n * onPageSizeChange={setPageSize}\n * />\n * ```\n */\nexport declare function useCrudPageSize(options: UseCrudPageSizeOptions): UseCrudPageSizeReturn;","useFieldConditions":"/**\n * Evaluate field conditions against live form values.\n *\n * @param fields - Array of renderable fields (from useEntityForm or getFieldsForOperation)\n * @param control - React Hook Form control object\n * @returns Record mapping field names to their computed condition states.\n * Fields without conditions are not included — treat missing entries as defaults.\n *\n * @example\n * ```tsx\n * function MyForm({ entity }) {\n * const { fields, control } = useEntityForm(entity, { operation: 'create' });\n * const conditions = useFieldConditions(fields, control);\n *\n * return fields.map(({ name, config }) => {\n * const cond = conditions[name];\n * if (cond && !cond.visible) return null;\n * return <FormField key={name} disabled={cond?.disabled} required={cond?.required} />;\n * });\n * }\n * ```\n */\nexport declare function useFieldConditions<TFieldValues extends FieldValues = FieldValues>(fields: readonly RenderableField[], control: Control<TFieldValues>): Record<string, ConditionResult>;","useReferenceResolver":"/**\n * Hook that fetches referenced collections for an entity and builds a lookup map.\n *\n * Supports up to 4 unique referenced collections. Each collection is fetched via useCrudList.\n * Because hooks must be called unconditionally, we always call all 4 useCrudList slots\n * and disable unused ones.\n *\n * @param entity - The entity whose reference fields to resolve\n * @returns ReferenceData lookup map\n */\nexport declare function useReferenceResolver(entity: Entity, enabled?: boolean): ReferenceData;","FileMetadata":"/** Metadata for a file in the upload queue */\nexport interface FileMetadata {\n /** Unique ID for React keys */\n id: string;\n /** Original file object (for new uploads) */\n file: File;\n /** Local preview URL (blob: for new, https: for existing) */\n previewURL: string;\n /** Upload progress 0-100 (null = not started) */\n progress: number | null;\n /** Uploaded result (null = pending) */\n uploaded: Picture | null;\n /** Error message if upload failed */\n error: string | null;\n}","UseFileUploadOptions":"export interface UseFileUploadOptions {\n /** Field name for UploadStore registration */\n name: string;\n /** Current value from form */\n value: Picture | Picture[] | null | undefined;\n /** Change handler to update form */\n onChange: (value: Picture | Picture[] | null) => void;\n /** Allow multiple files */\n multiple?: boolean;\n /** Max number of files (multiple mode) */\n maxFiles?: number;\n /** Max file size in bytes (default: 10MB) */\n maxSize?: number;\n /** Accepted MIME types (e.g., ['image/*'], ['application/pdf']) */\n accept?: string[];\n /** Storage path prefix */\n storagePath?: string;\n /** Upload function - injected to avoid coupling to specific storage */\n uploadFn?: (file: File, onProgress: (progress: number) => void) => Promise<Picture>;\n}","UseEntityFavoritesOptions":"/** Options for the {@link useEntityFavorites} hook. */\nexport interface UseEntityFavoritesOptions {\n /** Storage key (default: 'entity-favorites') */\n storageKey?: string;\n /** Entity collection name (e.g., 'cars', 'products') - used to namespace favorites */\n collection?: string;\n}","UseEntityFavoritesReturn":"/** Return type of the {@link useEntityFavorites} hook. */\nexport interface UseEntityFavoritesReturn {\n /** Array of favorited entity IDs */\n favorites: string[];\n /** Check if an entity is favorited */\n isFavorite: (id: string) => boolean;\n /** Toggle favorite status for an entity */\n toggleFavorite: (id: string) => void;\n /** Add entity to favorites */\n addFavorite: (id: string) => void;\n /** Remove entity from favorites */\n removeFavorite: (id: string) => void;\n /** Clear all favorites */\n clearFavorites: () => void;\n /** Filter function for use with EntityCardList/EntityList (from @donotdev/ui) filter prop */\n favoritesFilter: (item: {\n id: string;\n }) => boolean;\n /** Whether favorites are loaded from localStorage */\n isLoaded: boolean;\n}","UseRelatedItemsOptions":"/** Options for the {@link useRelatedItems} hook. */\nexport interface UseRelatedItemsOptions {\n /** Maximum number of related items to return (default: 3) */\n limit?: number;\n /** Tolerance for numeric field matching as percentage (default: 0.2 = 20%) */\n tolerance?: number;\n}","UseRelatedItemsReturn":"/** Return type of the {@link useRelatedItems} hook. */\nexport interface UseRelatedItemsReturn<T> {\n /** Array of related items */\n items: T[];\n /** Whether any related items were found */\n hasItems: boolean;\n}","UseCrudFiltersOptions":"/** Options for the {@link useCrudFilters} hook. */\nexport interface UseCrudFiltersOptions {\n /** Entity collection name (e.g., 'cars', 'products') */\n collection: string;\n}","UseCrudFiltersReturn":"/** Return type of the {@link useCrudFilters} hook. */\nexport interface UseCrudFiltersReturn {\n /** Current filter state */\n filters: FilterState;\n /** Update filters */\n setFilters: (filters: FilterState) => void;\n /** Whether favorites-only toggle is enabled */\n showFavoritesOnly: boolean;\n /** Toggle favorites-only filter */\n setShowFavoritesOnly: (show: boolean) => void;\n}","UseCrudPageSizeOptions":"/** Options for the {@link useCrudPageSize} hook. */\nexport interface UseCrudPageSizeOptions {\n /** Entity collection name (e.g., 'cars', 'products') */\n collection: string;\n /** Default page size when no preference is stored (default: 12) */\n defaultPageSize?: number;\n}","UseCrudPageSizeReturn":"/** Return type of the {@link useCrudPageSize} hook. */\nexport interface UseCrudPageSizeReturn {\n /** Current page size (from store or default) */\n pageSize: number;\n /** Persist a new page size preference */\n setPageSize: (pageSize: number) => void;\n}","ReferenceData":"/** Lookup map: collection → { id → displayLabel } */\nexport type ReferenceData = Record<string, Record<string, string>>;","isStorageUrl":"/**\n * Check if a URL is a valid storage URL (not a blob URL)\n * @param url - URL to check\n * @returns true if URL is a storage URL (https://), false if blob URL or invalid\n */\nexport declare function isStorageUrl(url: string): boolean;","validatePicture":"/**\n * Validate that a Picture object has valid storage URLs.\n * `thumbUrl` is optional — only validated when present (W9: false positive fix).\n * @param picture - Picture object to validate\n * @returns true if fullUrl is a valid storage URL (and thumbUrl, when present, is also valid)\n */\nexport declare function validatePicture(picture: Picture): boolean;","checkForBlobUrls":"/**\n * Recursively check for blob URLs in form data\n * Returns array of paths where blob URLs were found\n * @param data - Data to check (can be nested object/array)\n * @param path - Current path in the data structure (for error messages)\n * @returns Array of paths where blob URLs were found\n */\nexport declare function checkForBlobUrls(data: unknown, path?: string): string[];","hasBlobUrls":"/**\n * Check if form data contains any blob URLs\n * @param data - Form data to check\n * @returns true if any blob URLs found, false otherwise\n */\nexport declare function hasBlobUrls(data: unknown): boolean;","defineWorkflow":"/**\n * Define a multi-step workflow configuration.\n * Identity function that provides type safety and documentation.\n *\n * @param config - Workflow configuration\n * @returns The same config, typed as WorkflowConfig\n */\nexport declare function defineWorkflow(config: WorkflowConfig): WorkflowConfig;","useEntityWorkflow":"/**\n * Orchestrate a multi-step entity workflow.\n *\n * @param config - Workflow configuration from defineWorkflow()\n * @param options - Workflow options (callbacks, defaults)\n * @returns Workflow state and navigation methods\n */\nexport declare function useEntityWorkflow(config: WorkflowConfig, options?: UseEntityWorkflowOptions): EntityWorkflowReturn;","saveWorkflowState":"/**\n * Save workflow state to localStorage.\n */\nexport declare function saveWorkflowState(workflowId: string, state: PersistedWorkflowState): void;","loadWorkflowState":"/**\n * Load workflow state from localStorage.\n * Returns null if no saved state exists or parsing fails.\n */\nexport declare function loadWorkflowState(workflowId: string): PersistedWorkflowState | null;","clearWorkflowState":"/**\n * Clear persisted workflow state.\n */\nexport declare function clearWorkflowState(workflowId: string): void;","WorkflowConfig":"/** Full workflow configuration */\nexport interface WorkflowConfig {\n /** Unique workflow identifier */\n id: string;\n /** Workflow display name */\n name: string;\n /** Whether to persist progress to localStorage */\n persist?: boolean;\n /** Persistence key prefix (defaults to workflow id) */\n persistKey?: string;\n /** Workflow steps */\n steps: WorkflowStep[];\n /** Callback when all steps are completed */\n onComplete?: (allData: Record<string, unknown>) => void | Promise<void>;\n}","WorkflowStep":"/** Configuration for a single workflow step */\nexport interface WorkflowStep {\n /** Unique step identifier */\n id: string;\n /** Step title displayed in stepper */\n title: string;\n /** Step description (optional) */\n description?: string;\n /** Entity definition to use for this step's form */\n entity?: Entity;\n /** Subset of entity fields to show in this step (if omitted, shows all) */\n fields?: string[];\n /** Whether the user can skip this step */\n allowSkip?: boolean;\n /** Conditions for step visibility (cross-step references use 'stepId.field' notation) */\n conditions?: {\n visible?: ConditionInput;\n };\n /** Field-level condition overrides for this step (e.g., make a field required based on previous step data) */\n fieldConditions?: Record<string, ConditionalBehavior>;\n /** Callback after step is completed */\n after?: (context: WorkflowStepContext) => void | Promise<void>;\n /** Custom render function for non-entity steps (e.g., review/summary) */\n custom?: (allData: Record<string, unknown>) => ReactNode;\n /** Custom validation for the step */\n validation?: {\n validate?: (data: Record<string, unknown>) => boolean | string;\n message?: string;\n };\n}","WorkflowStepContext":"/** Context passed to step callbacks */\nexport interface WorkflowStepContext {\n /** Data collected in the current step */\n data: Record<string, unknown>;\n /** All data collected across all steps */\n allData: Record<string, unknown>;\n /** Helper to prefill next step */\n next: {\n prefill: (values: Record<string, unknown>) => void;\n };\n}","UseEntityWorkflowOptions":"/** Options for useEntityWorkflow */\nexport interface UseEntityWorkflowOptions {\n /** Callback when all steps are completed and data is submitted */\n onComplete?: (allData: Record<string, unknown>) => void | Promise<void>;\n /** Callback when step changes */\n onStepChange?: (fromIndex: number, toIndex: number) => void;\n /** Default values to pre-fill across steps */\n defaultValues?: Record<string, unknown>;\n}","EntityWorkflowReturn":"/** Return type of useEntityWorkflow */\nexport interface EntityWorkflowReturn {\n /** Current step configuration */\n currentStep: WorkflowStep;\n /** Current step index (0-based, relative to visible steps) */\n currentStepIndex: number;\n /** Steps after condition filtering (only visible steps) */\n visibleSteps: WorkflowStep[];\n /** Data per step (keyed by step id) */\n stepData: Record<string, Record<string, unknown>>;\n /** Merged data across all steps */\n allData: Record<string, unknown>;\n /** Navigate to next step (validates current step first) */\n goNext: (currentStepData?: Record<string, unknown>) => Promise<boolean>;\n /** Navigate to previous step */\n goPrevious: () => void;\n /** Skip current step (only if allowSkip is true) */\n skipStep: () => void;\n /** Jump to a specific step by index */\n goToStep: (index: number) => void;\n /** Whether current step is the first visible step */\n isFirst: boolean;\n /** Whether current step is the last visible step */\n isLast: boolean;\n /** Whether the workflow is submitting (final step) */\n isSubmitting: boolean;\n /** Whether the current step can proceed (no validation errors) */\n canGoNext: boolean;\n /** Force save current state to localStorage */\n persistNow: () => void;\n /** Clear all persisted state */\n clearPersisted: () => void;\n /** Prefill data for a specific step */\n prefillStep: (stepId: string, values: Record<string, unknown>) => void;\n}","PersistedWorkflowState":"/** Persisted workflow state */\nexport interface PersistedWorkflowState {\n /** Current step index */\n currentStepIndex: number;\n /** Data per step (keyed by step id) */\n stepData: Record<string, Record<string, unknown>>;\n /** Timestamp of last save */\n savedAt: number;\n}","formatValue":"/**\n * Formats a value for display based on field type\n *\n * @param value - Field value to format\n * @param config - Field configuration\n * @param t - Translation function\n * @param options - Formatting options\n * @param options.compact - Use compact formatting (smaller images, plain spans for empty)\n * @param options.asString - Prefer string output when possible (e.g. for price in text placeholders)\n * @returns Formatted value as string or ReactElement\n */\nexport declare function formatValue(value: any, config: EntityField, t: (key: string, options?: Record<string, any>) => string, options?: DisplayFormatterOptions): string | ReactElement;","buildReferenceLabel":"/**\n * Build a display label for a referenced item.\n *\n * Resolution order:\n * 1. `labelFields` — join multiple fields (e.g. `['first_name', 'last_name']` → \"John Doe\")\n * 2. `displayField` — single field\n * 3. Auto-detect: first match from name/title/label/displayName\n * 4. Fallback: document `id`\n */\nexport declare function buildReferenceLabel(item: Record<string, any>, labelFields?: string[], displayField?: string): string;","matchesFilter":"/**\n * Pure filter matching utility — checks if an item value matches a filter value.\n *\n * Supports all built-in field types: text (contains), number/price (range),\n * date/datetime (range), select (exact), multiselect (contains), address (formatted_address).\n *\n * Null/undefined handling for range filters:\n * - MIN only → exclude null/undefined\n * - MAX only → include null/undefined\n * - MIN + MAX → exclude null/undefined\n *\n * @param itemValue - The item's field value to test\n * @param filterValue - The filter criterion (string, range, date, array)\n * @param fieldType - Entity field type (e.g. 'text', 'number', 'date', 'price')\n * @returns true if item passes the filter\n *\n * @example\n * ```typescript\n * import { matchesFilter } from '@donotdev/crud';\n *\n * matchesFilter('hello world', 'hello', 'text'); // true (contains)\n * matchesFilter(42, { min: '10', max: '50' }, 'number'); // true (in range)\n * matchesFilter(null, { min: '10' }, 'number'); // false (null excluded)\n * ```\n */\nexport declare function matchesFilter(itemValue: any, filterValue: string | {\n min?: string;\n max?: string;\n}","applyFilters":"/**\n * Apply filter state to items using entity field type metadata.\n * Typically called automatically by `useCrudList`/`useCrudCardList` via `processed`.\n * Export available for advanced use cases (e.g. filtering outside React).\n *\n * @param items - Raw items array\n * @param filters - Current filter state from CrudStore\n * @param entity - Entity definition (for field type lookup)\n * @returns Filtered items\n *\n * @example\n * ```typescript\n * import { applyFilters } from '@donotdev/crud';\n * const filtered = applyFilters(items, { status: 'active' }, productEntity);\n * ```\n */\nexport declare function applyFilters<T extends Record<string, any>>(items: T[], filters: FilterState, entity: Entity): T[];","applySearch":"/**\n * Apply search query to items.\n * Searches fields defined by `entity.search.fields` or auto-detected text-like visible fields.\n * Typically called automatically by `useCrudList`/`useCrudCardList` when `searchQuery` option is set.\n *\n * @param items - Items to search\n * @param query - Search query string (case-insensitive contains)\n * @param entity - Entity definition (for field config and search.fields lookup)\n * @returns Filtered items matching search\n *\n * @example\n * ```typescript\n * import { applySearch } from '@donotdev/crud';\n * const results = applySearch(items, 'bmw', carEntity);\n * ```\n */\nexport declare function applySearch<T extends Record<string, any>>(items: T[], query: string, entity: Entity): T[];","applySort":"/**\n * Apply client-side sorting to items.\n * Accepts a field-based config or a custom comparator function.\n * Handles null/undefined values by sorting them last.\n * Supports number, string, Date, and price ({ amount }) comparisons.\n *\n * @param items - Items to sort\n * @param sort - Sort configuration (field + direction) or comparator function\n * @returns Sorted items (new array, original unchanged)\n *\n * @example\n * ```typescript\n * import { applySort } from '@donotdev/crud';\n * // Field-based\n * const sorted = applySort(items, { field: 'createdAt', direction: 'desc' });\n * // Custom comparator\n * const sorted = applySort(items, (a, b) => a.priority - b.priority);\n * ```\n */\nexport declare function applySort<T extends Record<string, any>>(items: T[], sort: ClientSort<T>): T[];","getSearchableFields":"/**\n * Returns the list of searchable field names for an entity.\n * Uses entity.search.fields if defined, otherwise auto-detects text-like visible fields.\n *\n * @param entity - Entity definition\n * @returns Array of field names to search\n */\nexport declare function getSearchableFields(entity: Entity): string[];","ClientSort":"/**\n * Client-side sort: field-based config or custom comparator function.\n *\n * @example\n * ```typescript\n * // Field-based\n * const sort: ClientSort = { field: 'price', direction: 'desc' };\n *\n * // Custom comparator (multi-key, status priority, etc.)\n * const sort: ClientSort<Apartment> = (a, b) =>\n * STATUS_PRIORITY[a.status] - STATUS_PRIORITY[b.status]\n * || a.date.localeCompare(b.date);\n * ```\n */\nexport type ClientSort<T = Record<string, unknown>> = ClientSortConfig | ((a: T, b: T) => number);","ClientSortConfig":"/**\n * Sort configuration for client-side sorting.\n *\n * @example\n * ```typescript\n * const sort: ClientSortConfig = { field: 'price', direction: 'desc' };\n * ```\n */\nexport interface ClientSortConfig {\n field: string;\n direction?: 'asc' | 'desc';\n}","EMPTY_DATA":"export declare const EMPTY_DATA: Record<string, unknown>;","EMPTY_OPTIMISTIC":"export declare const EMPTY_OPTIMISTIC: Record<string, unknown>;","getCrudServiceInstance":"/**\n * Get the current CrudService instance (for use in callbacks)\n */\nexport declare function getCrudServiceInstance(): CrudServiceInterface | null;","UseCrudOptions":"/** Options for the {@link useCrud} hook. */\nexport interface UseCrudOptions<T> {\n schema?: dndevSchema<T>;\n /** Entity definition - auto-generates schema if schema not provided */\n entity?: Entity;\n /** TanStack Query stale time in ms (default: Infinity) */\n staleTime?: number;\n /** Disable caching (bypass TanStack Query) */\n noCache?: boolean;\n}","UseCrudReturn":"/**\n * CRUD API return type - Single Document & Actions\n */\nexport interface UseCrudReturn<T> extends CrudAPI<T> {\n /** @internal Collection name */\n _collection: string;\n /** @internal Generated schemas */\n _schemas: OperationSchemas | undefined;\n /** @internal Cache options */\n _cacheOptions: CacheOptions;\n /** @internal Scope configuration (for multi-tenancy) */\n _scope: ScopeConfig | undefined;\n}","useCrud":"/**\n * React hook for CRUD Actions & Single Documents\n *\n * Use this hook for:\n * - Checking feature status: `const status = useCrud('status');`\n * - Adding, Updating, Deleting items\n * - Fetching a single document\n *\n * @template T - Document type for this collection\n * @param entityOrCollection - Entity definition or collection name\n * @param options - Configuration options\n * @returns CRUD Actions API\n */\nexport declare function useCrud(key: 'status'): FeatureStatus;","UseCrudListOptions":"/** Options for the {@link useCrudList} hook. */\nexport interface UseCrudListOptions<T> extends UseCrudOptions<T> {\n /** Automatically fetch data on mount (default: true) */\n enabled?: boolean;\n /**\n * Pagination mode:\n * - `'auto'` (default) — fetches up to 1000 client-side. If total > 1000, auto-switches to server pagination.\n * - `'client'` — forces client-side (fetches all, paginates in browser).\n * - `'server'` — forces server-side (cursor pagination, one page at a time).\n */\n pagination?: 'auto' | 'client' | 'server';\n /** Page number for server-side pagination (1-indexed, default: 1) */\n page?: number;\n /** Page size for server-side pagination (default: 10) */\n pageSize?: number;\n /** Where/orderBy/limit passed to list query (merged with pagination on server) */\n queryOptions?: QueryOptions;\n /** Client-side search query. Applied after filters. */\n searchQuery?: string;\n /** Client-side sort: field config, comparator function, or null to disable. Defaults to entity.defaultSort. */\n clientSort?: ClientSort<T> | ClientSortConfig | null;\n}","UseCrudListReturn":"/** Return type of the {@link useCrudList} hook. */\nexport interface UseCrudListReturn<T> {\n status: FeatureStatus;\n data: {\n items: T[];\n total?: number;\n } | null;\n /** Convenience: items array (data?.items ?? []) — raw + optimistic, no client processing */\n items: T[];\n /** Items after client-side filters + search + sort — ready to render */\n processed: T[];\n /** Count of items after filters + search (before pagination) */\n filteredTotal: number;\n /** True during initial fetch (show skeletons) */\n loading: boolean;\n /** True during background refetch (show subtle indicator) */\n fetching: boolean;\n error: Error | null;\n /** Manual refresh function */\n mutate: () => Promise<void>;\n /** Alias for mutate (manual refresh) */\n refresh: () => Promise<void>;\n isAvailable: boolean;\n /** Effective pagination mode after auto-detection ('client' or 'server'). */\n effectiveMode: 'client' | 'server';\n}","useCrudList":"/**\n * React hook for fetching and managing a list of entities\n *\n * Use this hook for:\n * - Admin tables\n * - Data grids\n * - Lists of items\n *\n * @template T - Document type\n * @param entityOrCollection - Entity definition or collection name\n * @param options - Configuration options\n * @returns List data and control methods\n *\n * @example\n * ```typescript\n * // Basic usage — processed has filters + search + sort applied\n * const { processed, loading, refresh } = useCrudList(carEntity, {\n * searchQuery: search,\n * });\n *\n * // With explicit sort\n * const { processed } = useCrudList(carEntity, {\n * searchQuery: search,\n * clientSort: { field: 'price', direction: 'asc' },\n * });\n * ```\n */\nexport declare function useCrudList<T extends {\n id: string;\n}","UseCrudCardListOptions":"/** Options for the {@link useCrudCardList} hook. */\nexport interface UseCrudCardListOptions<T> extends UseCrudOptions<T> {\n /** Automatically fetch data on mount (default: true) */\n enabled?: boolean;\n /** Where/orderBy/limit passed to listCard query */\n queryOptions?: QueryOptions;\n /** Client-side search query. Applied after filters. */\n searchQuery?: string;\n /** Client-side sort: field config, comparator function, or null to disable. Defaults to entity.defaultSort. */\n clientSort?: ClientSort<T> | ClientSortConfig | null;\n}","UseCrudCardListReturn":"/** Return type of the {@link useCrudCardList} hook. */\nexport interface UseCrudCardListReturn<T> {\n status: FeatureStatus;\n data: {\n items: T[];\n } | null;\n /** Convenience: items array (data?.items ?? []) — raw + optimistic, no client processing */\n items: T[];\n /** Items after client-side filters + search + sort — ready to render */\n processed: T[];\n /** Count of items after filters + search (before pagination) */\n filteredTotal: number;\n /** True during initial fetch (show skeletons) */\n loading: boolean;\n /** True during background refetch (show subtle indicator) */\n fetching: boolean;\n error: Error | null;\n /** Manual refresh function */\n mutate: () => Promise<void>;\n /** Alias for mutate (manual refresh) */\n refresh: () => Promise<void>;\n isAvailable: boolean;\n}","useCrudCardList":"/**\n * React hook for fetching a list of entities optimized for Card views\n *\n * Use this hook for:\n * - Public-facing grids\n * - Dashboard widgets\n * - Summary lists\n *\n * @template T - Document type\n * @param entityOrCollection - Entity definition or collection name\n * @param options - Configuration options\n * @returns List data and control methods\n *\n * @example\n * ```typescript\n * // processed has filters + search + sort applied\n * const { processed, loading } = useCrudCardList(carEntity, {\n * searchQuery: search,\n * });\n * ```\n */\nexport declare function useCrudCardList<T extends {\n id: string;\n}","CrudButton":"/**\n * Defensive button component for CRUD operations.\n *\n * Features (inherited from ActionButton):\n * - Auto-disables while loading\n * - Shows spinner + loadingText during action\n * - Optional confirmation dialog\n * - aria-busy for accessibility\n *\n * CRUD-specific features:\n * - **Auto-detects CRUD availability** - no manual prop needed\n * - Auto-disables when user not authenticated (if requiresAuth=true)\n *\n * @example\n * ```tsx\n * const { delete: deleteItem } = useCrud(itemEntity);\n * const user = useAuth('user');\n *\n * <CrudButton\n * action={() => deleteItem(itemId)}\n * user={user}\n * loadingText=\"Deleting...\"\n * confirmText=\"Delete this item?\"\n * confirmTitle=\"Delete Item\"\n * onSuccess={() => refetch()}\n * variant=\"destructive\"\n * >\n * Delete\n * </CrudButton>\n * ```\n */\ndeclare function CrudButton<T = unknown>({ requiresAuth, user, disabled, children, ...actionButtonProps }","CrudButtonProps":"/** Props for {@link CrudButton}, an ActionButton variant that auto-checks CRUD availability. */\nexport interface CrudButtonProps<T = unknown> extends Omit<ActionButtonProps<T>, 'disabled'> {\n /**\n * Whether user authentication is required for this action.\n * When true, button is disabled if user is not authenticated.\n * @default true\n */\n requiresAuth?: boolean;\n /**\n * Current user object. Pass from useAuth('user').\n * Required when requiresAuth=true.\n */\n user?: unknown;\n /**\n * Additional disabled condition.\n */\n disabled?: boolean;\n /** Button content */\n children: ReactNode;\n}","FormFieldRenderer":"/**\n * FormFieldRenderer - renders fields via registry lookup\n */\nexport declare function FormFieldRenderer<T extends FieldType, TFieldValues extends FieldValues = FieldValues>({ name, config, t, ...props }","DisplayFieldRenderer":"/**\n * DisplayFieldRenderer - Renders a field value as read-only display\n *\n * Used when:\n * - editable: false (field is never editable)\n * - editable: 'admin' and viewer is not admin\n * - editable: 'create-only' and viewing existing record\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare function DisplayFieldRenderer<T extends FieldType = FieldType>({ name, config, value, t, }","DisplayFieldRendererProps":"/** Props for {@link DisplayFieldRenderer}, renders a field value as read-only text. */\nexport interface DisplayFieldRendererProps<T extends FieldType = FieldType> {\n /** Field identifier */\n name: string;\n /** Field configuration */\n config: EntityField<T>;\n /** Current field value */\n value: any;\n /** Translation function */\n t: (key: string, options?: Record<string, any>) => string;\n}","FormLayout":"/**\n * Enhanced FormLayout with modern UX features\n *\n * Features:\n * - Responsive design\n * - Loading states\n * - ARIA compliance\n * - Multiple variants\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n * - Action buttons\n * - Error handling\n */\ndeclare const FormLayout: <T extends FieldValues>({ title, onSubmit, children, formMethods, loading, submitText, cancelText, showCancel, onCancel, variant, columns, description, }","EntityFilters":"/**\n\n * Entity Filters Component - Auto-generates filter UI based on entity field types\n\n *\n\n * Features:\n\n * - String/Select fields: Combobox with unique values\n\n * - Number fields: Min/Max inputs + Slider (2 rows)\n\n * - Date fields: Min/Max date pickers + shortcuts (2 rows)\n\n * - Filters wrap naturally with flex-wrap\n\n * - Clear individual filters or all filters\n\n */\nexport declare function EntityFilters<T extends Record<string, any> & {\n id: string;\n}","EntityFiltersProps":"/** Props for {@link EntityFilters}, auto-generates filter UI based on entity field types. */\nexport interface EntityFiltersProps<T extends Record<string, any> & {\n id: string;\n}","DisplayThumbnail":"/**\n * DisplayThumbnail - Renders thumbnail of first picture for list cards.\n * Used by CrudCard and any list view that needs a single thumbnail.\n */\nexport declare function DisplayThumbnail({ pictures, alt, aspectRatio, className, style, }","CrudCard":"/**\n * CrudCard — Presentational card from entity + item + field slots.\n * No routing: use onClick for interaction. Parent wraps with Link if needed.\n */\nexport declare function CrudCard({ item, entity, onClick, titleFields: titleFieldsProp, subtitleFields: subtitleFieldsProp, contentFields: contentFieldsProp, footerFields: footerFieldsProp, showDelete, renderActions, renderOverlay, className, }","ControlledFieldProps":"type ControlledFieldProps, type UncontrolledFieldProps, } from './FieldRegistry';","convertValidationRules":"/**\n\n * Convert validation rules to react-hook-form RegisterOptions\n\n */\nexport declare function convertValidationRules(validation: any): RegisterOptions;","convertPatternToRegex":"/**\n\n * Convert pattern string to RegExp\n\n */\nexport declare function convertPatternToRegex(pattern: string | RegExp | undefined): RegExp | undefined;","ControlledCheckboxField":"/**\n\n * ControlledCheckboxField - Explicit controlled component for checkbox inputs\n\n * Uses standard React Hook Form Controller pattern\n\n */\nexport declare function ControlledCheckboxField(props: ControlledFieldProps): ReactElement;","ControlledCurrencyField":"/**\n * ControlledCurrencyField - Explicit controlled component for currency inputs\n * Uses CurrencyFieldComponent with currency code from field options\n */\nexport declare function ControlledCurrencyField(props: ControlledFieldProps): ReactElement;","ControlledNumberField":"/**\n\n * ControlledNumberField - Explicit controlled component for number inputs\n\n * Forwards Controller's ref for focus/validation (simple input)\n\n */\nexport declare function ControlledNumberField(props: ControlledFieldProps): ReactElement;","ControlledPasswordField":"/**\n\n * ControlledPasswordField - Explicit controlled component for password inputs\n\n * Forwards Controller's ref for focus/validation (simple input)\n\n */\nexport declare function ControlledPasswordField(props: ControlledFieldProps): ReactElement;","ControlledPriceField":"/**\n * ControlledPriceField - Controlled component for structured price (amount, currency, VAT, discount %).\n * Value: { amount, currency?, vatIncluded?, discountPercent? }.\n */\nexport declare function ControlledPriceField(props: ControlledFieldProps): ReactElement;","ControlledPhoneField":"/**\n\n * ControlledPhoneField - Explicit controlled component for phone inputs\n\n * Forwards Controller's ref for focus/validation (simple input)\n\n */\nexport declare function ControlledPhoneField(props: ControlledFieldProps): ReactElement;","ControlledRangeField":"/**\n\n * ControlledRangeField - Explicit controlled component for range inputs\n\n * Forwards Controller's ref for focus/validation (simple input)\n\n */\nexport declare function ControlledRangeField(props: ControlledFieldProps): ReactElement;","ControlledRatingField":"/**\n * ControlledRatingField - Controlled component for star rating inputs\n * Wraps RatingFieldComponent with react-hook-form Controller\n */\nexport declare function ControlledRatingField(props: ControlledFieldProps): ReactElement;","ControlledDurationField":"/**\n * ControlledDurationField - Controlled component for duration (minutes) with preset chips + custom slider\n */\nexport declare function ControlledDurationField(props: ControlledFieldProps): ReactElement;","ControlledSwitchField":"/**\n\n * ControlledSwitchField - Switch with custom value mapping\n\n * Supports uncheckedValue/checkedValue for string values like 'Manual'/'Automatic'\n\n */\nexport declare function ControlledSwitchField(props: ControlledFieldProps): ReactElement;","ControlledTextField":"/**\n * ControlledTextField - Text input controlled by react-hook-form\n *\n * Uses Controller to keep value in sync with RHF state.\n * register() is incompatible with TextFieldComponent's controlled\n * `<Input value={value}>` — default values are overwritten on re-render.\n */\nexport declare function ControlledTextField(props: ControlledFieldProps): ReactElement;","ControlledTextareaField":"/**\n\n * ControlledTextareaField - Explicit controlled component for textarea inputs\n\n * Forwards Controller's ref for focus/validation (simple input)\n\n */\nexport declare function ControlledTextareaField(props: ControlledFieldProps): ReactElement;","ControlledGdprConsentField":"/**\n * ControlledGdprConsentField - GDPR-compliant consent checkbox with automatic label generation\n * Uses standard React Hook Form Controller pattern\n */\nexport declare function ControlledGdprConsentField(props: ControlledFieldProps): ReactElement;","ControlledComboboxField":"/**\n\n * ControlledComboboxField - Explicit controlled component for combobox inputs\n\n * Forwards Controller's ref for focus/validation (simple input)\n\n * Handles dynamic options and creatable mode\n\n */\nexport declare function ControlledComboboxField(props: ControlledFieldProps): ReactElement;","ControlledDropdownField":"/**\n * ControlledDropdownField - Explicit controlled component for select/dropdown inputs\n *\n * Forwards Controller's ref for focus/validation (simple input)\n *\n * Handles dynamic options (function-based) and dependsOn logic\n */\nexport declare function ControlledDropdownField(props: ControlledFieldProps): ReactElement;","ControlledMultiDropdownField":"/**\n * ControlledMultiDropdownField - Explicit controlled component for multiselect inputs\n *\n * Forwards Controller's ref for focus/validation (simple input)\n *\n * Handles dynamic options\n */\nexport declare function ControlledMultiDropdownField(props: ControlledFieldProps): ReactElement;","ControlledRadioField":"/**\n * ControlledRadioField - Explicit controlled component for radio inputs\n *\n * Forwards Controller's ref for focus/validation (simple input)\n *\n * Handles dynamic options\n */\nexport declare function ControlledRadioField(props: ControlledFieldProps): ReactElement;","ControlledReferenceField":"/**\n * ControlledReferenceField — Controlled component for `type: 'reference'` fields.\n *\n * Reads `validation.reference` to determine the collection, auto-fetches items\n * via `useCrudList`, and renders the existing `ReferenceFieldComponent` (Combobox).\n */\nexport declare function ControlledReferenceField(props: ControlledFieldProps): ReactElement;","ControlledYearField":"/**\n * ControlledYearField - Year input using Combobox (type or select)\n * Auto-generates year options from validation.min/max or defaults to 1900-2100\n * Stores value as number, displays as string in combobox\n */\nexport declare function ControlledYearField(props: ControlledFieldProps): ReactElement;","ControlledDocumentField":"/**\n\n * ControlledDocumentField - Explicit controlled component for document uploads\n\n * NO ref forwarding - complex component (forwardRef) handles its own refs\n\n */\nexport declare function ControlledDocumentField(props: ControlledFieldProps): ReactElement;","ControlledFileField":"/**\n\n * ControlledFileField - Explicit controlled component for file uploads\n\n * NO ref forwarding - complex component (forwardRef) handles its own refs\n\n */\nexport declare function ControlledFileField(props: ControlledFieldProps): ReactElement;","ControlledImageField":"/**\n\n * ControlledImageField - Explicit controlled component for image uploads\n\n * NO ref forwarding - complex component (forwardRef) handles its own refs\n\n */\nexport declare function ControlledImageField(props: ControlledFieldProps): ReactElement;","ControlledMultiDocumentField":"/**\n\n * ControlledMultiDocumentField - Explicit controlled component for multiple document uploads\n\n * NO ref forwarding - complex component (forwardRef) handles its own refs\n\n */\nexport declare function ControlledMultiDocumentField(props: ControlledFieldProps): ReactElement;","ControlledMultiFileField":"/**\n\n * ControlledMultiFileField - Explicit controlled component for multiple file uploads\n\n * NO ref forwarding - complex component (forwardRef) handles its own refs\n\n */\nexport declare function ControlledMultiFileField(props: ControlledFieldProps): ReactElement;","ControlledMultiImageField":"/**\n\n * ControlledMultiImageField - Explicit controlled component for multiple image uploads\n\n * NO ref forwarding - complex component (forwardRef) handles its own refs\n\n */\nexport declare function ControlledMultiImageField(props: ControlledFieldProps): ReactElement;","ControlledAddressField":"/**\n\n * ControlledAddressField - Explicit controlled component for address inputs\n\n * NO ref forwarding - complex component handles its own refs\n\n */\nexport declare function ControlledAddressField(props: ControlledFieldProps): ReactElement;","ControlledFieldArrayField":"/**\n * ControlledFieldArrayField — nested object array with per-row sub-fields.\n * Each sub-field is rendered via the field type registry so custom types work automatically.\n */\nexport declare function ControlledFieldArrayField(props: ControlledFieldProps): ReactElement;","ControlledDateField":"/**\n\n * ControlledDateField - Explicit controlled component for date inputs\n\n * Forwards Controller's ref for focus/validation (simple input)\n\n */\nexport declare function ControlledDateField(props: ControlledFieldProps): ReactElement;","ControlledGeoPointField":"/**\n\n * ControlledGeoPointField - Explicit controlled component for geographic coordinates\n\n * NO ref forwarding - complex component handles its own refs\n\n */\nexport declare function ControlledGeoPointField(props: ControlledFieldProps): ReactElement;","ControlledMapField":"/**\n\n * ControlledMapField - Explicit controlled component for map data inputs\n\n * NO ref forwarding - complex component handles its own refs\n\n */\nexport declare function ControlledMapField(props: ControlledFieldProps): ReactElement;","ControlledMultiInputField":"/**\n\n * ControlledMultiInputField - Explicit controlled component for array of text inputs\n\n * NO ref forwarding - complex component handles its own refs\n\n */\nexport declare function ControlledMultiInputField(props: ControlledFieldProps): ReactElement;","ControlledRichTextField":"/**\n\n * ControlledRichTextField - Explicit controlled component for rich text editor\n\n * NO ref forwarding - complex component handles its own refs\n\n */\nexport declare function ControlledRichTextField(props: ControlledFieldProps): ReactElement;","ControlledTimestampField":"/**\n\n * ControlledTimestampField - Explicit controlled component for timestamp inputs\n\n * Forwards Controller's ref for focus/validation (simple input)\n\n */\nexport declare function ControlledTimestampField(props: ControlledFieldProps): ReactElement;","AvatarFieldComponent":"/**\n * AvatarFieldComponent - Input field for avatar URLs with preview\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const AvatarFieldComponent: ComponentType<AvatarFieldComponentProps>;","AvatarFieldComponentProps":"export interface AvatarFieldComponentProps extends Omit<ComponentProps<typeof Input>, 'value' | 'onChange'> {\n /** Field configuration */\n config: EntityField<'avatar'>;\n /** Current value */\n value: string;\n /** Change handler */\n onChange: (value: string) => void;\n /** Error state */\n error?: boolean;\n /** Helper text */\n helperText?: string;\n /** Translation function */\n t: (key: string, options?: Record<string, any>) => string;\n}","BadgeFieldComponent":"/**\n * BadgeFieldComponent - Input field for badge text with preview\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const BadgeFieldComponent: ComponentType<BadgeFieldComponentProps>;","BadgeFieldComponentProps":"export interface BadgeFieldComponentProps extends Omit<ComponentProps<typeof Input>, 'value' | 'onChange'> {\n /** Field configuration */\n config: EntityField<'badge'>;\n /** Current value */\n value: string;\n /** Change handler */\n onChange: (value: string) => void;\n /** Error state */\n error?: boolean;\n /** Helper text */\n helperText?: string;\n /** Translation function */\n t: (key: string, options?: Record<string, any>) => string;\n /** Badge variant */\n variant?: 'default' | 'secondary' | 'destructive' | 'outline';\n}","TextFieldComponent":"/**\n * Enhanced TextFieldComponent with modern UX features\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n *\n * Features:\n * - Full ARIA compliance\n * - Loading states with spinner\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n * - Character counting\n * - Error handling\n * - Required field indicators\n * - Responsive design\n *\n * @param props - TextFieldComponentProps\n * @returns JSX.Element\n */\ndeclare function TextFieldComponent({ label, value, onChange, error, helperText, type, loading, maxLength, showCharCount, required, disabled, className, ref, ...props }","TextFieldComponentProps":"export interface TextFieldComponentProps extends Omit<ComponentProps<typeof Input>, 'value' | 'onChange'> {\n /** Field label */\n label: string;\n /** Current value */\n value?: string;\n /** Change handler */\n onChange: (event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;\n /** Error message */\n error?: string;\n /** Helper text to display */\n helperText?: string;\n /** Input type (default: text) */\n type?: string;\n /** Loading state */\n loading?: boolean;\n /** Maximum character count */\n maxLength?: number;\n /** Show character count */\n showCharCount?: boolean;\n /** Required field indicator */\n required?: boolean;\n /** Disabled state */\n disabled?: boolean;\n}","NumberFieldComponent":"/**\n * NumberFieldComponent renders a styled number input with validation.\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n * @param props - NumberFieldComponentProps\n * @returns JSX.Element\n */\ndeclare const NumberFieldComponent: ComponentType<NumberFieldComponentProps>;","NumberFieldComponentProps":"export interface NumberFieldComponentProps {\n /** Label for the field */\n label: string;\n /** Current numeric value */\n value?: number;\n /** Change handler */\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n /** Whether the field is in error state */\n error?: boolean;\n /** Helper text to display */\n helperText?: string;\n /** Minimum allowed value */\n min?: number;\n /** Maximum allowed value */\n max?: number;\n /** Step value for increments/decrements */\n step?: number;\n /** Whether the field is disabled */\n disabled?: boolean;\n /** Whether the field is required */\n required?: boolean;\n /** Optional className */\n className?: string;\n /** Input mask type: 'currency' (commas + 2 decimals), 'mileage' (commas, no decimals), or 'number' (no formatting) */\n mask?: 'currency' | 'mileage' | 'number';\n}","DateFieldComponent":"/**\n * DateFieldComponent renders a date (or related) input field\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\ndeclare const DateFieldComponent: ComponentType<DateFieldComponentProps>;","DateFieldComponentProps":"export interface DateFieldComponentProps {\n /** Field label */\n label: string;\n /** Value as an ISO string or null */\n value?: string | null;\n /** Change handler emitting an ISO string or null */\n onChange: (date: string | null) => void;\n /** Error message (string = message to display, falsy = no error) */\n error?: string;\n /** Helper text to display */\n helperText?: string;\n /**\n * Input mode: \"date\", \"datetime-local\", \"month\", \"time\", or \"week\".\n * This controls both the input type and the formatting of the displayed value.\n */\n mode?: 'date' | 'datetime-local' | 'month' | 'time' | 'week';\n /** Whether the field is required */\n required?: boolean;\n}","CheckboxFieldComponent":"/**\n * CheckboxFieldComponent renders a labeled checkbox.\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n * @param props - CheckboxFieldComponentProps\n * @returns JSX.Element\n */\ndeclare const CheckboxFieldComponent: ComponentType<CheckboxFieldComponentProps>;","CheckboxFieldComponentProps":"export interface CheckboxFieldComponentProps {\n /** The label for the checkbox - can be a string or ReactNode (e.g., with links) */\n label: string | ReactNode;\n /** Whether the checkbox is checked */\n checked?: boolean;\n /** Change handler for the checkbox */\n onChange?: (event: ChangeEvent<HTMLInputElement>) => void;\n /** Whether the field is required */\n required?: boolean;\n}","ComboboxComponent":"/**\n * ComboboxComponent renders a searchable combobox with autocomplete.\n * Input + Dropdown pattern: user types in input, dropdown appears below.\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n * @param props - ComboboxComponentProps\n * @returns JSX.Element\n */\ndeclare const ComboboxComponent: ComponentType<ComboboxComponentProps>;","ComboboxComponentProps":"export interface ComboboxComponentProps {\n /** Field label */\n label: string;\n /** Current value */\n value?: string;\n /** Available options */\n options: {\n value: string;\n label: string;\n }[];\n /** Error state */\n error?: boolean;\n /** Helper text */\n helperText?: string;\n /** Change handler - accepts both event and direct value */\n onChange?: (value: string | ChangeEvent<HTMLSelectElement>) => void;\n /** Blur handler */\n onBlur?: () => void;\n /** Whether the field is required */\n required?: boolean;\n /** Placeholder text */\n placeholder?: string;\n /** Translation namespace for placeholder fallback (default: 'dndev') */\n translationNamespace?: string;\n /** Translation key for placeholder fallback (default: 'actions.select') */\n placeholderKey?: string;\n /** Default placeholder text if translation not found (default: 'Select') */\n placeholderDefault?: string;\n /** Enable creating new values */\n creatable?: boolean;\n /** Label for create option */\n createLabel?: string;\n /** Empty message */\n emptyMessage?: string;\n}","DropdownComponent":"/**\n * DropdownComponent renders a styled select input.\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n * @param props - DropdownComponentProps\n * @returns JSX.Element\n */\ndeclare const DropdownComponent: ComponentType<DropdownComponentProps>;","DropdownComponentProps":"export interface DropdownComponentProps {\n /** Field label */\n label: string;\n /** Current value */\n value?: string | number | boolean;\n /** Available options */\n options: {\n value: string | number | boolean;\n label: string;\n }[];\n /** Error state */\n error?: boolean;\n /** Helper text */\n helperText?: string;\n /** Change handler - accepts both event and direct value */\n onChange?: (value: string | ChangeEvent<HTMLSelectElement>) => void;\n /** Blur handler */\n onBlur?: () => void;\n /** Whether the field is required */\n required?: boolean;\n}","MultiDropdownComponent":"/**\n * MultiDropdownComponent renders a multi-select dropdown field using Radix UI's Select.\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n * @param props - MultiDropdownComponentProps\n * @returns JSX.Element\n */\ndeclare const MultiDropdownComponent: ComponentType<MultiDropdownComponentProps>;","MultiDropdownComponentProps":"export interface MultiDropdownComponentProps {\n /** Label for the dropdown */\n label: string;\n /** Current selected values */\n value?: string[];\n /** Options for selection */\n options: {\n value: string | number | boolean;\n label: string;\n }[];\n /** Whether an error exists */\n error?: boolean;\n /** Helper text for the field */\n helperText?: string;\n /** Change handler - accepts both event and direct value */\n onChange: (value: string[] | ChangeEvent<HTMLSelectElement>) => void;\n /** Blur handler */\n onBlur?: () => void;\n /** Whether the field is required */\n required?: boolean;\n /** Additional CSS classes */\n className?: string;\n}","FileFieldComponent":"/**\n * FileFieldComponent - Generic file upload with Firebase Storage\n * Features: Deferred upload, progress indicator, multiple files, drag-and-drop\n */\ndeclare const FileFieldComponent: import(\"react\").ForwardRefExoticComponent<FileFieldComponentProps & import(\"react\").RefAttributes<FileFieldComponentRef>>;","FileFieldComponentProps":"export interface FileFieldComponentProps {\n /** Field name (for upload registration) */\n name?: string;\n /** Field label */\n label: string;\n /** Current value - FileAsset for single, FileAsset[] for multiple */\n value?: FileAsset | FileAsset[] | null;\n /** Change handler */\n onChange: (value: FileAsset | FileAsset[] | null) => void;\n /** Error state */\n error?: boolean;\n /** Helper text */\n helperText?: string;\n /** Accept attribute for file input (MIME types or extensions) */\n accept?: string;\n /** Multiple files mode */\n multiple?: boolean;\n /** Maximum number of files (multiple mode only) */\n maxFiles?: number;\n /** Maximum file size in bytes (default: 50MB) */\n maxSize?: number;\n /** Firebase Storage path (default: 'uploads/files') */\n storagePath?: string;\n /** Whether the field is required */\n required?: boolean;\n}","ImageFieldComponent":"/**\n * ImageFieldComponent - Image upload with viewer dialog for crop/rotate and drag-to-reorder\n */\ndeclare const ImageFieldComponent: import(\"react\").ForwardRefExoticComponent<ImageFieldComponentProps & import(\"react\").RefAttributes<ImageFieldComponentRef>>;","ImageFieldComponentProps":"export interface ImageFieldComponentProps {\n /** Field name (for upload registration) */\n name?: string;\n /** Field label */\n label: string;\n /** Current value - Picture for single, Picture[] for multiple */\n value?: Picture | Picture[] | null;\n /** Change handler */\n onChange: (value: Picture | Picture[] | null) => void;\n /** Error state */\n error?: boolean;\n /** Helper text */\n helperText?: string;\n /** Multiple images mode */\n multiple?: boolean;\n /** Maximum number of images (multiple mode only) */\n maxFiles?: number;\n /** Maximum file size in bytes (default: 10MB) */\n maxSize?: number;\n /** Firebase Storage path (default: 'uploads/images') */\n storagePath?: string;\n /** Whether the field is required */\n required?: boolean;\n /** Camera capture mode: 'environment' (back), 'user' (front), or undefined (browser decides) */\n capture?: 'environment' | 'user';\n}","DocumentFieldComponent":"/**\n * DocumentFieldComponent - Document-specific upload with Firebase Storage\n * Features: Restricted to document types, PDF preview, deferred upload\n */\ndeclare const DocumentFieldComponent: import(\"react\").ForwardRefExoticComponent<DocumentFieldComponentProps & import(\"react\").RefAttributes<DocumentFieldComponentRef>>;","DocumentFieldComponentProps":"export interface DocumentFieldComponentProps {\n /** Field name (for upload registration) */\n name?: string;\n /** Field label */\n label: string;\n /** Current value - FileAsset for single, FileAsset[] for multiple */\n value?: FileAsset | FileAsset[] | null;\n /** Change handler */\n onChange: (value: FileAsset | FileAsset[] | null) => void;\n /** Error state */\n error?: boolean;\n /** Helper text */\n helperText?: string;\n /** Multiple files mode */\n multiple?: boolean;\n /** Maximum number of files (multiple mode only) */\n maxFiles?: number;\n /** Maximum file size in bytes (default: 25MB for documents) */\n maxSize?: number;\n /** Firebase Storage path (default: 'uploads/documents') */\n storagePath?: string;\n /** Whether the field is required */\n required?: boolean;\n /** Enable PDF preview */\n enablePreview?: boolean;\n}","TextAreaComponent":"/**\n * Enhanced TextAreaComponent with modern UX features\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n *\n * Features:\n * - Full ARIA compliance\n * - Auto-resize functionality\n * - Loading states with spinner\n * - Character counting\n * - Error handling\n * - Required field indicators\n * - Responsive design\n *\n * @param props - TextAreaComponentProps\n * @returns JSX.Element\n */\ndeclare const TextAreaComponent: ComponentType<TextAreaComponentProps>;","TextAreaComponentProps":"export interface TextAreaComponentProps extends Omit<ComponentProps<typeof Textarea>, 'value' | 'onChange'> {\n /** Field label */\n label: string;\n /** Current value */\n value?: string;\n /** Change handler */\n onChange: (event: ChangeEvent<HTMLTextAreaElement>) => void;\n /** Error message */\n error?: string;\n /** Helper text to display */\n helperText?: string;\n /** Number of rows (default: 3) */\n rows?: number;\n /** Loading state */\n loading?: boolean;\n /** Maximum character count */\n maxLength?: number;\n /** Show character count */\n showCharCount?: boolean;\n /** Auto-resize based on content */\n autoResize?: boolean;\n /** Required field indicator */\n required?: boolean;\n /** Disabled state */\n disabled?: boolean;\n}","SwitchFieldComponent":"/**\n * SwitchFieldComponent renders a switch field for CRUD forms.\n * Displays field label, delegates switch rendering to Switch component.\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n * @param props - SwitchFieldComponentProps\n * @returns JSX.Element\n */\ndeclare const SwitchFieldComponent: ComponentType<SwitchFieldComponentProps>;","SwitchFieldComponentProps":"export interface SwitchFieldComponentProps {\n /** Field label */\n label: string;\n /** Whether the toggle is checked */\n checked?: boolean;\n /** Change handler */\n onChange?: (event: ChangeEvent<HTMLInputElement>) => void;\n /** Label for unchecked state (e.g., \"Manual\") */\n uncheckedLabel?: string;\n /** Label for checked state (e.g., \"Automatic\") */\n checkedLabel?: string;\n /** Helper text */\n helperText?: string;\n}","RadioFieldComponent":"declare const RadioFieldComponent: ComponentType<RadioFieldComponentProps>;","RadioFieldComponentProps":"export interface RadioFieldComponentProps {\n /** Field label */\n label: string;\n /** Selected value */\n value?: string;\n /** Change handler - accepts both event and direct value */\n onChange: (value: string | ChangeEvent<HTMLInputElement>) => void;\n /** Available radio options */\n options: RadioOption[];\n /** Error state */\n error?: boolean;\n /** Helper text */\n helperText?: string;\n /** Whether the field is required */\n required?: boolean;\n}","RangeFieldComponent":"/**\n * RangeFieldComponent renders a slider input with optional value display\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n * @param props - RangeFieldComponentProps\n * @returns JSX.Element\n */\ndeclare const RangeFieldComponent: ComponentType<RangeFieldComponentProps>;","RangeFieldComponentProps":"export interface RangeFieldComponentProps {\n /** Label for the field */\n label: string;\n /** Current numeric value */\n value?: number;\n /** Change handler - accepts both event and direct value */\n onChange: (value: number | ChangeEvent<HTMLInputElement>) => void;\n /** Whether the field is in error state */\n error?: boolean;\n /** Helper text to display */\n helperText?: string;\n /** Minimum allowed value */\n min?: number;\n /** Maximum allowed value */\n max?: number;\n /** Step value for increments */\n step?: number;\n /** Whether the field is disabled */\n disabled?: boolean;\n /** Whether the field is required */\n required?: boolean;\n /** Show value label */\n showValue?: boolean;\n}","RatingFieldComponent":"/**\n * RatingFieldComponent renders a star rating input\n *\n * Used by the built-in entity field type `rating`. Supports whole-number input\n * (1–max), optional fractional display, and optional numeric value display.\n *\n * @see Entity field type: `rating` (registered in registerBuiltinFieldTypes)\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\ndeclare const RatingFieldComponent: ComponentType<RatingFieldComponentProps>;","RatingFieldComponentProps":"export interface RatingFieldComponentProps {\n /** Label for the field */\n label: string;\n /** Current rating value (1-5) */\n value?: number;\n /** Change handler */\n onChange: (value: number) => void;\n /** Whether the field is in error state */\n error?: boolean;\n /** Helper text to display */\n helperText?: string;\n /** Maximum rating value */\n max?: number;\n /** Whether the field is disabled */\n disabled?: boolean;\n /** Whether the field is required */\n required?: boolean;\n /** Read-only mode (display only) */\n readonly?: boolean;\n /** Show numeric value next to stars */\n showValue?: boolean;\n}","DurationFieldComponent":"/**\n * DurationFieldComponent - Preset chips + Custom slider for duration (minutes)\n *\n * Used by the built-in entity field type `duration`.\n *\n * @see Entity field type: `duration` (registered in registerBuiltinFieldTypes)\n */\ndeclare const DurationFieldComponent: ComponentType<DurationFieldComponentProps>;","DurationFieldComponentProps":"export interface DurationFieldComponentProps {\n /** Label for the field */\n label: string;\n /** Current value in minutes */\n value?: number;\n /** Change handler (minutes) */\n onChange: (value: number) => void;\n /** Whether the field is in error state */\n error?: boolean;\n /** Helper text */\n helperText?: string;\n /** Whether the field is disabled */\n disabled?: boolean;\n /** Whether the field is required */\n required?: boolean;\n /** Read-only mode (display only) */\n readonly?: boolean;\n /** Min minutes for custom slider (default 0) */\n min?: number;\n /** Max minutes for custom slider (default 480 = 8h) */\n max?: number;\n /** Step for custom slider (default 5) */\n step?: number;\n /**\n * Translation function for preset labels (e.g. t('crud:duration.30m')).\n * Receives i18n key; return value is the chip label.\n */\n t?: (key: string, options?: Record<string, unknown>) => string;\n}","DURATION_PRESETS":"/** Preset durations in minutes */\nexport declare const DURATION_PRESETS: readonly [15, 30, 45, 60, 90, 120, 150, 180];","PhoneNumberComponent":"/**\n * PhoneNumberComponent renders a single phone number input with country code selector.\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\ndeclare const PhoneNumberComponent: ComponentType<PhoneNumberComponentProps>;","PhoneNumberComponentProps":"export interface PhoneNumberComponentProps {\n /** Field label */\n label: string;\n /** Current phone number value (full number with country code) */\n value?: string;\n /** Change handler */\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n /** Error message */\n error?: string;\n /** Helper text */\n helperText?: string;\n /** Required field indicator */\n required?: boolean;\n /** Disabled state */\n disabled?: boolean;\n /** Default country code (e.g., 'FR' for +33) */\n defaultCountry?: string;\n /** Whether to show country flags */\n showFlags?: boolean;\n /** Preferred country codes to show at the top (e.g., ['FR', 'US', 'GB']) */\n preferredCountries?: string[];\n /** Custom list of country codes to show (if provided, only these countries are shown) */\n countries?: string[];\n}","GeoPointFieldComponent":"/**\n * GeoPointFieldComponent renders latitude and longitude input fields\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\ndeclare const GeoPointFieldComponent: ComponentType<GeoPointFieldComponentProps>;","GeoPointFieldComponentProps":"export interface GeoPointFieldComponentProps {\n /** Field label */\n label: string;\n /** Current coordinates */\n value?: GeoPoint;\n /** Change handler - accepts both event and direct value */\n onChange: (point: GeoPoint | ChangeEvent<HTMLInputElement>) => void;\n /** Error state */\n error?: boolean;\n /** Helper text */\n helperText?: string;\n /** Whether the field is disabled */\n disabled?: boolean;\n /** Whether the field is required */\n required?: boolean;\n}","GeoPoint":"export interface GeoPoint {\n lat: number;\n lng: number;\n}","MapFieldComponent":"declare const MapFieldComponent: ComponentType<MapFieldComponentProps>;","MapFieldComponentProps":"export interface MapFieldComponentProps {\n /** Field label */\n label: string;\n /** Map data as an object */\n value?: Record<string, any>;\n /** Change handler - accepts both event and direct value */\n onChange: (value: Record<string, any> | ChangeEvent<HTMLInputElement>) => void;\n /** Error state */\n error?: boolean;\n /** Helper text */\n helperText?: string;\n /** Whether the field is required */\n required?: boolean;\n}","TimestampFieldComponent":"declare const TimestampFieldComponent: ComponentType<TimestampFieldComponentProps>;","TimestampFieldComponentProps":"export interface TimestampFieldComponentProps {\n /** Field label */\n label: string;\n /** Current Date value or null */\n value?: Date | null;\n /** Change handler - accepts both event and direct value */\n onChange: (date: Date | null | ChangeEvent<HTMLInputElement>) => void;\n /** Error message */\n error?: string;\n /** Helper text */\n helperText?: string;\n /** Mode for underlying date field (defaults to \"datetime-local\") */\n mode?: 'datetime-local' | 'date';\n /** Whether the field is required */\n required?: boolean;\n}","MultiInputTextFieldComponent":"declare const MultiInputTextFieldComponent: ComponentType<MultiInputTextFieldComponentProps>;","MultiInputTextFieldComponentProps":"export interface MultiInputTextFieldComponentProps {\n /** Label for the input field */\n label: string;\n /** Array of current text entries */\n value: string[];\n /** Handler for value changes - accepts both event and direct value */\n onChange: (value: string[] | ChangeEvent<HTMLInputElement>) => void;\n /** Optional classname for styling */\n className?: string;\n /** Whether the field is required */\n required?: boolean;\n}","ButtonFieldComponent":"declare const ButtonFieldComponent: ComponentType<ButtonFieldComponentProps>;","ButtonFieldComponentProps":"export interface ButtonFieldComponentProps {\n /** The button label */\n label: string;\n /** The button type: submit, reset, or button */\n type: 'submit' | 'reset' | 'button';\n /** Optional click handler */\n onClick?: () => void;\n /** Button variant */\n variant?: ButtonVariant;\n /** Disabled state */\n disabled?: boolean;\n}","HiddenFieldComponent":"declare const HiddenFieldComponent: ComponentType<HiddenFieldComponentProps>;","HiddenFieldComponentProps":"export interface HiddenFieldComponentProps {\n name: string;\n value: string;\n}","PasswordFieldComponent":"/**\n * PasswordFieldComponent renders a styled password input.\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n * @param props - PasswordFieldComponentProps\n * @returns JSX.Element\n */\ndeclare const PasswordFieldComponent: ComponentType<PasswordFieldComponentProps>;","PasswordFieldComponentProps":"export interface PasswordFieldComponentProps extends Omit<ComponentProps<typeof PasswordInput>, 'value' | 'onChange'> {\n /** Field label */\n label: string;\n /** Current value */\n value?: string;\n /** Change handler */\n onChange: (event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;\n /** Error state */\n error?: boolean;\n /** Helper text to display */\n helperText?: string;\n}","AddressFieldComponent":"/**\n * Address field component with Google Maps autocomplete\n * Integrates with Google Places API for address selection\n *\n * Environment variables required for Google Maps:\n * - Vite: VITE_GOOGLE_MAPS_API_KEY\n * - Next.js: NEXT_PUBLIC_GOOGLE_MAPS_API_KEY\n *\n * @component\n * @param {AddressFieldComponentProps} props - Component props\n * @returns {JSX.Element} Address input field with autocomplete\n */\ndeclare const AddressFieldComponent: ({ label, value, onChange, enableGoogleMaps, extractDistrictCode, error, helperText, required, }","AddressFieldComponentProps":"/**\n * Address field component props\n */\nexport interface AddressFieldComponentProps {\n /** Field label */\n label: string;\n /** Address value with formatted address and coordinates */\n value?: {\n formatted_address: string;\n latitude?: number;\n longitude?: number;\n [key: string]: any;\n };\n /** Change handler */\n onChange: (value: any) => void;\n /**\n * Whether to enable Google Maps autocomplete (default: false)\n * Requires env var: VITE_GOOGLE_MAPS_API_KEY (Vite) or NEXT_PUBLIC_GOOGLE_MAPS_API_KEY (Next.js)\n */\n enableGoogleMaps?: boolean;\n /** Whether to extract district code for Paris addresses */\n extractDistrictCode?: boolean;\n /** Error state */\n error?: boolean;\n /** Helper text */\n helperText?: string;\n /** Whether the field is required */\n required?: boolean;\n}","CurrencyFieldComponent":"/**\n * Currency field with locale-aware formatting\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\ndeclare const CurrencyFieldComponent: ComponentType<CurrencyFieldComponentProps>;","CurrencyFieldComponentProps":"export interface CurrencyFieldComponentProps {\n /** Field label */\n label: string;\n /** Current value (number in cents/smallest unit) */\n value?: number;\n /** Change handler */\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n /** Currency code (e.g., 'EUR', 'USD') */\n currency?: string;\n /** Locale for formatting (e.g., 'fr-FR', 'en-US') */\n locale?: string;\n /** Error state */\n error?: boolean;\n /** Helper text */\n helperText?: string;\n /** Required field */\n required?: boolean;\n /** Disabled state */\n disabled?: boolean;\n /** Placeholder */\n placeholder?: string;\n}","PriceFieldComponent":"declare const PriceFieldComponent: ComponentType<PriceFieldComponentProps>;","PriceFieldComponentProps":"export interface PriceFieldComponentProps {\n /** Field label (for amount) */\n label: string;\n /** Current value */\n value?: PriceValue | null;\n /** Change handler */\n onChange: (value: PriceValue) => void;\n /** Error state */\n error?: boolean;\n /** Helper text */\n helperText?: string;\n /** Required */\n required?: boolean;\n /** Disabled */\n disabled?: boolean;\n /** Placeholder for amount */\n placeholder?: string;\n /** Default currency when value.currency is unset */\n defaultCurrency?: string;\n /** Label for collapsible section */\n optionsTitle?: string;\n /** Allowed currencies in the select; when set, only these are shown (e.g. ['EUR'] for single-currency) */\n currencies?: string[];\n}","PriceValue":"export interface PriceValue {\n amount: number;\n currency?: string;\n vatIncluded?: boolean;\n discountPercent?: number;\n}","RichTextComponent":"/**\n * RichTextComponent - WYSIWYG editor with Tiptap\n * Falls back to textarea if Tiptap is not available\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\ndeclare const RichTextComponent: ComponentType<RichTextComponentProps>;","RichTextComponentProps":"/**\n * Rich Text Field Component Props\n */\nexport interface RichTextComponentProps {\n /** Field label */\n label: string;\n /** Current HTML value */\n value?: string;\n /** Change handler */\n onChange: (event: ChangeEvent<HTMLTextAreaElement>) => void;\n /** Error state */\n error?: string;\n /** Helper text */\n helperText?: string;\n /** Required field */\n required?: boolean;\n /** Disabled state */\n disabled?: boolean;\n /** Placeholder */\n placeholder?: string;\n /** Optional className */\n className?: string;\n}","GdprConsentFieldComponent":"/**\n * GDPR Consent Field Component - Renders a consent checkbox with automatic label generation.\n * Opens privacy policy and terms in Sheet with iframe when links are clicked.\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n * @param props - GdprConsentFieldComponentProps\n * @returns JSX.Element\n */\ndeclare const GdprConsentFieldComponent: ComponentType<GdprConsentFieldComponentProps>;","GdprConsentFieldComponentProps":"export interface GdprConsentFieldComponentProps {\n /** Whether the checkbox is checked */\n checked?: boolean;\n /** Change handler for the checkbox */\n onChange?: (event: ChangeEvent<HTMLInputElement>) => void;\n /** Whether the field is required */\n required?: boolean;\n /** Path to privacy policy page (default: '/legal/privacy') */\n privacyPolicyPath?: string;\n /** Path to terms of use page (default: '/legal/terms') */\n termsPath?: string;\n}","TextFieldDisplay":"/**\n * Enhanced TextFieldDisplay with modern UX features\n *\n * Features:\n * - Smart formatting based on field type\n * - Copy to clipboard functionality\n * - Truncation with tooltips\n * - Badge display option\n * - Loading states\n * - Responsive design\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const TextFieldDisplay: ComponentType<TextFieldDisplayProps>;","BadgeFieldDisplay":"/**\n * BadgeFieldDisplay - Displays boolean/select values as badges\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const BadgeFieldDisplay: React.ComponentType<BadgeFieldDisplayProps>;","AvatarFieldDisplay":"/**\n * AvatarFieldDisplay - Displays image values as avatars\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const AvatarFieldDisplay: React.ComponentType<AvatarFieldDisplayProps>;","LinkFieldDisplay":"/**\n * LinkFieldDisplay - Displays URL/email/tel values as clickable links\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const LinkFieldDisplay: ComponentType<LinkFieldDisplayProps>;","DateFieldDisplay":"/**\n * DateFieldDisplay - Displays date values in read-only mode\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const DateFieldDisplay: ComponentType<DateFieldDisplayProps>;","NumberFieldDisplay":"/**\n * NumberFieldDisplay - Displays number values in read-only mode\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const NumberFieldDisplay: ComponentType<NumberFieldDisplayProps>;","PhoneNumberDisplay":"/**\n * PhoneNumberDisplay - Displays phone number values as clickable links\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const PhoneNumberDisplay: ComponentType<PhoneNumberDisplayProps>;","TextAreaDisplay":"/**\n * TextAreaDisplay - Displays textarea values in read-only mode\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const TextAreaDisplay: ComponentType<TextAreaDisplayProps>;","RichTextDisplay":"/**\n * RichTextDisplay - Displays rich text/HTML content in read-only mode\n *\n * Renders HTML with styling that matches Tiptap editor output.\n * Safe to use with HTML from Tiptap (sanitized by Tiptap).\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const RichTextDisplay: ComponentType<RichTextDisplayProps>;","CheckboxFieldDisplay":"/**\n * CheckboxFieldDisplay - Displays checkbox/boolean values as badges\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const CheckboxFieldDisplay: React.ComponentType<CheckboxFieldDisplayProps>;","DropdownDisplay":"/**\n * DropdownDisplay - Displays select values as badges\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const DropdownDisplay: React.ComponentType<DropdownDisplayProps>;","MultiDropdownDisplay":"/**\n * MultiDropdownDisplay - Displays multiselect values as multiple badges\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const MultiDropdownDisplay: ComponentType<MultiDropdownDisplayProps>;","MultiInputTextFieldDisplay":"/**\n * MultiInputTextFieldDisplay - Displays array values as multiple badges\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const MultiInputTextFieldDisplay: ComponentType<MultiInputTextFieldDisplayProps>;","RadioFieldDisplay":"/**\n * RadioFieldDisplay - Displays radio values as badges\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const RadioFieldDisplay: ComponentType<RadioFieldDisplayProps>;","RangeFieldDisplay":"/**\n * RangeFieldDisplay - Displays range values in read-only mode\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const RangeFieldDisplay: ComponentType<RangeFieldDisplayProps>;","FileFieldDisplay":"/**\n * FileFieldDisplay - Displays file values in read-only mode\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const FileFieldDisplay: React.ComponentType<FileFieldDisplayProps>;","ImageFieldDisplay":"/**\n * ImageFieldDisplay - Displays image values as avatars\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const ImageFieldDisplay: ComponentType<ImageFieldDisplayProps>;","GeoPointFieldDisplay":"/**\n * GeoPointFieldDisplay - Displays geopoint values in read-only mode\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const GeoPointFieldDisplay: ComponentType<GeoPointFieldDisplayProps>;","MapFieldDisplay":"/**\n * MapFieldDisplay - Displays map values in read-only mode\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const MapFieldDisplay: ComponentType<MapFieldDisplayProps>;","ReferenceFieldDisplay":"/**\n * ReferenceFieldDisplay - Displays reference values as badges\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const ReferenceFieldDisplay: ComponentType<ReferenceFieldDisplayProps>;","TimestampFieldDisplay":"/**\n * TimestampFieldDisplay - Displays timestamp values in read-only mode\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const TimestampFieldDisplay: ComponentType<TimestampFieldDisplayProps>;","HiddenFieldDisplay":"/**\n * HiddenFieldDisplay - Hidden fields are not displayed\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const HiddenFieldDisplay: ComponentType<HiddenFieldDisplayProps>;","ButtonFieldDisplay":"/**\n * ButtonFieldDisplay - Button fields are not displayed in read-only mode\n *\n * @version 0.1.0\n * @since 0.0.1\n * @author AMBROISE PARK Consulting\n */\nexport declare const ButtonFieldDisplay: React.ComponentType<ButtonFieldDisplayProps>;","useFormStore":"/**\n * Form store for managing form submission states\n *\n * @example\n * ```tsx\n * const formId = useId();\n * const isLoading = useFormStore((s) => s.isLoading(formId));\n * const status = useFormStore((s) => s.getStatus(formId));\n * ```\n */\nexport declare const useFormStore: import(\"zustand\").UseBoundStore<import(\"zustand\").StoreApi<FormStoreState & FormStoreActions & import(\"@donotdev/stores\").DoNotDevStore>>;","useFormStatus":"/**\n * Hook to get form status\n */\nexport declare const useFormStatus: (formId: string) => FormStatus;","useFormLoading":"/**\n * Hook to check if form is loading\n */\nexport declare const useFormLoading: (formId: string) => boolean;","useUploadProgress":"/**\n * Hook to get upload progress\n */\nexport declare const useUploadProgress: (formId: string) => number;","useFormError":"/**\n * Hook to get form error\n */\nexport declare const useFormError: (formId: string) => string | null;","useFormIsDirty":"/**\n * Hook to check if form is dirty\n */\nexport declare const useFormIsDirty: (formId: string) => boolean;","useHasDirtyForms":"/**\n * Hook to check if any form is dirty\n */\nexport declare const useHasDirtyForms: () => boolean;","useUploadStore":"/**\n * Upload store for managing file upload progress\n *\n * @example\n * ```tsx\n * const formId = useId();\n * const totalProgress = useUploadStore((s) => s.getTotalProgress(formId));\n * const isUploading = useUploadStore((s) => s.isUploading(formId));\n * ```\n */\nexport declare const useUploadStore: import(\"zustand\").UseBoundStore<import(\"zustand\").StoreApi<UploadStoreState & UploadStoreActions & import(\"@donotdev/stores\").DoNotDevStore>>;","useTotalProgress":"/**\n * Hook to get total upload progress for a form\n */\nexport declare const useTotalProgress: (formId: string) => number;","useIsUploading":"/**\n * Hook to check if any field is currently uploading\n */\nexport declare const useIsUploading: (formId: string) => boolean;","useFieldProgress":"/**\n * Hook to get upload progress for a specific field\n */\nexport declare const useFieldProgress: (formId: string, fieldName: string) => number;","useFieldUploadStatus":"/**\n * Hook to get upload status for a specific field\n */\nexport declare const useFieldUploadStatus: (formId: string, fieldName: string) => UploadStatus;"}