@donotdev/crud 0.0.4 → 0.0.6

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 (150) hide show
  1. package/dist/CrudService.d.ts +7 -3
  2. package/dist/CrudService.d.ts.map +1 -1
  3. package/dist/CrudService.js +1 -1
  4. package/dist/CrudStore.d.ts +6 -1
  5. package/dist/CrudStore.d.ts.map +1 -1
  6. package/dist/CrudStore.js +1 -1
  7. package/dist/FieldRegistry.d.ts +126 -0
  8. package/dist/FieldRegistry.d.ts.map +1 -0
  9. package/dist/FieldRegistry.js +1 -0
  10. package/dist/adapters/FirestoreAdapter.d.ts.map +1 -1
  11. package/dist/adapters/FirestoreAdapter.js +1 -1
  12. package/dist/builtinFieldTypes.d.ts +5 -0
  13. package/dist/builtinFieldTypes.d.ts.map +1 -0
  14. package/dist/builtinFieldTypes.js +1 -0
  15. package/dist/components/ControlledFields.d.ts +42 -24
  16. package/dist/components/ControlledFields.d.ts.map +1 -1
  17. package/dist/components/ControlledFields.js +1 -1
  18. package/dist/components/DisplayFieldRenderer.d.ts +36 -0
  19. package/dist/components/DisplayFieldRenderer.d.ts.map +1 -0
  20. package/dist/components/DisplayFieldRenderer.js +1 -0
  21. package/dist/components/EntityFormRenderer.d.ts +36 -8
  22. package/dist/components/EntityFormRenderer.d.ts.map +1 -1
  23. package/dist/components/EntityFormRenderer.js +5 -1
  24. package/dist/components/FormFieldRenderer.d.ts +3 -16
  25. package/dist/components/FormFieldRenderer.d.ts.map +1 -1
  26. package/dist/components/FormFieldRenderer.js +1 -1
  27. package/dist/components/form/fields/AddressFieldComponent.d.ts +3 -1
  28. package/dist/components/form/fields/AddressFieldComponent.d.ts.map +1 -1
  29. package/dist/components/form/fields/AddressFieldComponent.js +1 -1
  30. package/dist/components/form/fields/CheckboxFieldComponent.d.ts +2 -0
  31. package/dist/components/form/fields/CheckboxFieldComponent.d.ts.map +1 -1
  32. package/dist/components/form/fields/CheckboxFieldComponent.js +1 -1
  33. package/dist/components/form/fields/ComboboxComponent.d.ts +43 -0
  34. package/dist/components/form/fields/ComboboxComponent.d.ts.map +1 -0
  35. package/dist/components/form/fields/ComboboxComponent.js +1 -0
  36. package/dist/components/form/fields/CurrencyFieldComponent.d.ts +41 -0
  37. package/dist/components/form/fields/CurrencyFieldComponent.d.ts.map +1 -0
  38. package/dist/components/form/fields/CurrencyFieldComponent.js +1 -0
  39. package/dist/components/form/fields/DateFieldComponent.d.ts +2 -0
  40. package/dist/components/form/fields/DateFieldComponent.d.ts.map +1 -1
  41. package/dist/components/form/fields/DateFieldComponent.js +1 -1
  42. package/dist/components/form/fields/DropdownComponent.d.ts.map +1 -1
  43. package/dist/components/form/fields/DropdownComponent.js +1 -1
  44. package/dist/components/form/fields/FileFieldComponent.d.ts +2 -0
  45. package/dist/components/form/fields/FileFieldComponent.d.ts.map +1 -1
  46. package/dist/components/form/fields/FileFieldComponent.js +1 -1
  47. package/dist/components/form/fields/GeoPointFieldComponent.d.ts +2 -0
  48. package/dist/components/form/fields/GeoPointFieldComponent.d.ts.map +1 -1
  49. package/dist/components/form/fields/GeoPointFieldComponent.js +1 -1
  50. package/dist/components/form/fields/ImageFieldComponent.d.ts +32 -17
  51. package/dist/components/form/fields/ImageFieldComponent.d.ts.map +1 -1
  52. package/dist/components/form/fields/ImageFieldComponent.js +1 -1
  53. package/dist/components/form/fields/MapFieldComponent.d.ts +2 -0
  54. package/dist/components/form/fields/MapFieldComponent.d.ts.map +1 -1
  55. package/dist/components/form/fields/MapFieldComponent.js +1 -1
  56. package/dist/components/form/fields/MultiDropdownComponent.d.ts +2 -2
  57. package/dist/components/form/fields/MultiDropdownComponent.d.ts.map +1 -1
  58. package/dist/components/form/fields/MultiDropdownComponent.js +1 -1
  59. package/dist/components/form/fields/MultiInputTextFieldComponent.d.ts +2 -0
  60. package/dist/components/form/fields/MultiInputTextFieldComponent.d.ts.map +1 -1
  61. package/dist/components/form/fields/MultiInputTextFieldComponent.js +1 -1
  62. package/dist/components/form/fields/NumberFieldComponent.d.ts.map +1 -1
  63. package/dist/components/form/fields/NumberFieldComponent.js +1 -1
  64. package/dist/components/form/fields/PasswordFieldComponent.d.ts.map +1 -1
  65. package/dist/components/form/fields/PasswordFieldComponent.js +1 -1
  66. package/dist/components/form/fields/PhoneNumberComponent.d.ts +31 -17
  67. package/dist/components/form/fields/PhoneNumberComponent.d.ts.map +1 -1
  68. package/dist/components/form/fields/PhoneNumberComponent.js +1 -1
  69. package/dist/components/form/fields/RadioFieldComponent.d.ts.map +1 -1
  70. package/dist/components/form/fields/RadioFieldComponent.js +1 -1
  71. package/dist/components/form/fields/RangeFieldComponent.d.ts.map +1 -1
  72. package/dist/components/form/fields/RangeFieldComponent.js +1 -1
  73. package/dist/components/form/fields/ReferenceFieldComponent.d.ts +7 -2
  74. package/dist/components/form/fields/ReferenceFieldComponent.d.ts.map +1 -1
  75. package/dist/components/form/fields/ReferenceFieldComponent.js +1 -1
  76. package/dist/components/form/fields/SwitchFieldComponent.d.ts +28 -0
  77. package/dist/components/form/fields/SwitchFieldComponent.d.ts.map +1 -0
  78. package/dist/components/form/fields/SwitchFieldComponent.js +1 -0
  79. package/dist/components/form/fields/TextAreaComponent.d.ts.map +1 -1
  80. package/dist/components/form/fields/TextAreaComponent.js +1 -1
  81. package/dist/components/form/fields/TextFieldComponent.d.ts.map +1 -1
  82. package/dist/components/form/fields/TextFieldComponent.js +1 -1
  83. package/dist/components/form/fields/TimestampFieldComponent.d.ts +2 -0
  84. package/dist/components/form/fields/TimestampFieldComponent.d.ts.map +1 -1
  85. package/dist/components/form/fields/TimestampFieldComponent.js +1 -1
  86. package/dist/components/form/fields/index.d.ts +7 -1
  87. package/dist/components/form/fields/index.d.ts.map +1 -1
  88. package/dist/components/form/fields/index.js +1 -1
  89. package/dist/components/form/internal/ImageViewerDialog.d.ts +25 -0
  90. package/dist/components/form/internal/ImageViewerDialog.d.ts.map +1 -0
  91. package/dist/components/form/internal/ImageViewerDialog.js +1 -0
  92. package/dist/components/index.d.ts +2 -0
  93. package/dist/components/index.d.ts.map +1 -1
  94. package/dist/components/index.js +1 -1
  95. package/dist/context/FormUploadContext.d.ts +36 -0
  96. package/dist/context/FormUploadContext.d.ts.map +1 -0
  97. package/dist/context/FormUploadContext.js +1 -0
  98. package/dist/context/index.d.ts +2 -0
  99. package/dist/context/index.d.ts.map +1 -0
  100. package/dist/context/index.js +1 -0
  101. package/dist/forms/hooks/index.d.ts +11 -0
  102. package/dist/forms/hooks/index.d.ts.map +1 -0
  103. package/dist/forms/hooks/index.js +1 -0
  104. package/dist/forms/hooks/useEntityField.d.ts +67 -0
  105. package/dist/forms/hooks/useEntityField.d.ts.map +1 -0
  106. package/dist/forms/hooks/useEntityField.js +1 -0
  107. package/dist/forms/hooks/useEntityForm.d.ts +89 -0
  108. package/dist/forms/hooks/useEntityForm.d.ts.map +1 -0
  109. package/dist/forms/hooks/useEntityForm.js +1 -0
  110. package/dist/forms/index.d.ts +37 -0
  111. package/dist/forms/index.d.ts.map +1 -0
  112. package/dist/forms/index.js +1 -0
  113. package/dist/forms/types.d.ts +185 -0
  114. package/dist/forms/types.d.ts.map +1 -0
  115. package/dist/forms/types.js +0 -0
  116. package/dist/forms/utils/createEntitySchema.d.ts +53 -0
  117. package/dist/forms/utils/createEntitySchema.d.ts.map +1 -0
  118. package/dist/forms/utils/createEntitySchema.js +1 -0
  119. package/dist/forms/utils/getFieldsForOperation.d.ts +87 -0
  120. package/dist/forms/utils/getFieldsForOperation.d.ts.map +1 -0
  121. package/dist/forms/utils/getFieldsForOperation.js +1 -0
  122. package/dist/forms/utils/index.d.ts +14 -0
  123. package/dist/forms/utils/index.d.ts.map +1 -0
  124. package/dist/forms/utils/index.js +1 -0
  125. package/dist/forms/utils/isFieldEditable.d.ts +43 -0
  126. package/dist/forms/utils/isFieldEditable.d.ts.map +1 -0
  127. package/dist/forms/utils/isFieldEditable.js +1 -0
  128. package/dist/forms/utils/normalizeToFieldConfig.d.ts +47 -0
  129. package/dist/forms/utils/normalizeToFieldConfig.d.ts.map +1 -0
  130. package/dist/forms/utils/normalizeToFieldConfig.js +1 -0
  131. package/dist/forms/utils/validateEntity.d.ts +77 -0
  132. package/dist/forms/utils/validateEntity.d.ts.map +1 -0
  133. package/dist/forms/utils/validateEntity.js +1 -0
  134. package/dist/index.d.ts +4 -1
  135. package/dist/index.d.ts.map +1 -1
  136. package/dist/index.js +1 -1
  137. package/dist/tsconfig.tsbuildinfo +1 -1
  138. package/dist/useCrud.d.ts +67 -15
  139. package/dist/useCrud.d.ts.map +1 -1
  140. package/dist/useCrud.js +1 -1
  141. package/dist/utils/imageProcessing.d.ts +49 -0
  142. package/dist/utils/imageProcessing.d.ts.map +1 -0
  143. package/dist/utils/imageProcessing.js +1 -0
  144. package/dist/utils/imageStorage.d.ts +35 -0
  145. package/dist/utils/imageStorage.d.ts.map +1 -0
  146. package/dist/utils/imageStorage.js +1 -0
  147. package/dist/utils/imageUtils.d.ts +86 -0
  148. package/dist/utils/imageUtils.d.ts.map +1 -0
  149. package/dist/utils/imageUtils.js +1 -0
  150. package/package.json +10 -7
@@ -1,11 +1,12 @@
1
- import type { FieldConfig } from '@donotdev/core';
2
- interface EntityFormRendererProps<T extends Record<string, any> = any> {
3
- /** Entity definition with field configs */
4
- entity: Record<string, FieldConfig>;
1
+ import type { Entity } from '@donotdev/core';
2
+ import type { ViewerRole } from '../forms/utils';
3
+ interface EntityFormRendererProps<T extends Record<string, unknown> = Record<string, unknown>> {
4
+ /** Entity definition - pass the full entity from defineEntity() */
5
+ entity: Entity;
5
6
  /** Form submission handler */
6
7
  onSubmit: (data: T) => void | Promise<void>;
7
8
  /** Translation function */
8
- t?: (key: string, options?: Record<string, any>) => string;
9
+ t?: (key: string, options?: Record<string, unknown>) => string;
9
10
  /** Additional CSS classes */
10
11
  className?: string;
11
12
  /** Submit button text */
@@ -22,21 +23,48 @@ interface EntityFormRendererProps<T extends Record<string, any> = any> {
22
23
  secondaryButtonVariant?: 'primary' | 'destructive' | 'outline' | 'ghost' | 'link';
23
24
  /** Secondary button submission handler */
24
25
  onSecondarySubmit?: (data: T) => void | Promise<void>;
26
+ /**
27
+ * Current viewer's role for editability checks
28
+ * Used to determine if fields with editable:'admin' should be inputs or read-only
29
+ * If not provided, auto-detected from current user's auth state
30
+ * Falls back to 'admin' if auth unavailable (assumes admin context for forms)
31
+ * NOTE: Visibility is handled by backend, not this prop
32
+ */
33
+ viewerRole?: ViewerRole;
34
+ /**
35
+ * Form operation type
36
+ * - 'create': Excludes technical and hidden fields
37
+ * - 'edit': Shows all fields from defaultValues, technical fields are read-only
38
+ * @default 'create'
39
+ */
40
+ operation?: 'create' | 'edit';
41
+ /**
42
+ * Enable auto-save to localStorage for crash recovery.
43
+ * Saves form state every 3 seconds (debounced) with multi-tab sync.
44
+ * Only works for create mode.
45
+ * @default true (auto-enabled for create forms)
46
+ */
47
+ autoSave?: boolean;
25
48
  }
26
49
  /**
27
50
  * EntityFormRenderer - High-level component that renders a complete form from an entity definition
28
51
  *
52
+ * Security model:
53
+ * - VISIBILITY is handled by BACKEND (filterVisibleFields) - frontend trusts what it receives
54
+ * - EDITABILITY is handled by FRONTEND - determines input vs read-only display
55
+ *
29
56
  * Features:
30
57
  * - Automatic form setup with react-hook-form
31
- * - Loops through entity fields and renders each with FormFieldRenderer
58
+ * - Respects editability rules (input vs read-only display based on role)
32
59
  * - Built-in submit button with loading states
33
60
  * - Automatic validation from field configs
61
+ * - Deferred file uploads (images uploaded on form submit)
34
62
  * - Full i18n support
35
63
  *
36
- * @version 0.0.1
64
+ * @version 0.0.4
37
65
  * @since 0.0.1
38
66
  * @author AMBROISE PARK Consulting
39
67
  */
40
- export declare function EntityFormRenderer<T extends Record<string, any> = any>({ entity, onSubmit, t, className, submitText, isLoading, defaultValues, submitVariant, secondaryButtonText, secondaryButtonVariant, onSecondarySubmit, }: EntityFormRendererProps<T>): import("react/jsx-runtime").JSX.Element;
68
+ export declare function EntityFormRenderer<T extends Record<string, any> = any>(props: EntityFormRendererProps<T>): import("react/jsx-runtime").JSX.Element;
41
69
  export default EntityFormRenderer;
42
70
  //# sourceMappingURL=EntityFormRenderer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"EntityFormRenderer.d.ts","sourceRoot":"","sources":["../../src/components/EntityFormRenderer.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAIlD,UAAU,uBAAuB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG;IACnE,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACpC,8BAA8B;IAC9B,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,2BAA2B;IAC3B,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC;IAC3D,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,0BAA0B;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3B,4BAA4B;IAC5B,aAAa,CAAC,EAAE,SAAS,GAAG,aAAa,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;IACzE,4BAA4B;IAC5B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,+BAA+B;IAC/B,sBAAsB,CAAC,EACnB,SAAS,GACT,aAAa,GACb,SAAS,GACT,OAAO,GACP,MAAM,CAAC;IACX,0CAA0C;IAC1C,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,EACtE,MAAM,EACN,QAAQ,EACR,CAAC,EACD,SAAc,EACd,UAAU,EACV,SAAiB,EACjB,aAAa,EACb,aAAyB,EACzB,mBAAmB,EACnB,sBAAkC,EAClC,iBAAiB,GAClB,EAAE,uBAAuB,CAAC,CAAC,CAAC,2CAiH5B;AACD,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"EntityFormRenderer.d.ts","sourceRoot":"","sources":["../../src/components/EntityFormRenderer.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAS7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGjD,UAAU,uBAAuB,CAC/B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAE3D,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,8BAA8B;IAC9B,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,2BAA2B;IAC3B,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC;IAC/D,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,0BAA0B;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3B,4BAA4B;IAC5B,aAAa,CAAC,EAAE,SAAS,GAAG,aAAa,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;IACzE,4BAA4B;IAC5B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,+BAA+B;IAC/B,sBAAsB,CAAC,EACrB,SAAS,GACT,aAAa,GACb,SAAS,GACT,OAAO,GACP,MAAM,CAAC;IACT,0CAA0C;IAC1C,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAsRD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EACpE,KAAK,EAAE,uBAAuB,CAAC,CAAC,CAAC,2CAOlC;AACD,eAAe,kBAAkB,CAAC"}
@@ -1 +1,5 @@
1
- "use client";import{jsx as o,jsxs as g}from"react/jsx-runtime";import{useForm as k}from"react-hook-form";import{Button as d,Stack as v}from"@donotdev/components";import{useTranslation as R}from"@donotdev/core";import{FormFieldRenderer as z}from"./FormFieldRenderer";function A({entity:b,onSubmit:p,t:r,className:h="",submitText:i,isLoading:e=!1,defaultValues:S,submitVariant:l="primary",secondaryButtonText:u,secondaryButtonVariant:y="outline",onSecondarySubmit:c}){const{t:F}=R("dndev"),w=r||F,{control:j,handleSubmit:m,formState:{errors:s,isSubmitting:a},setError:f}=k({defaultValues:S}),x=async t=>{try{await p(t)}catch(n){f("root",{message:n.message||"An error occurred"})}},V=async t=>{if(c)try{await c(t)}catch(n){f("root",{message:n.message||"An error occurred"})}},N=Object.entries(b);return o("form",{onSubmit:m(x),className:h,children:g(v,{gap:"medium",children:[s.root&&o("div",{className:"dndev-surface","data-variant":"destructive",style:{padding:"var(--gap-sm)",fontSize:"var(--font-size-sm)",border:"1px solid var(--destructive)",borderRadius:"var(--radius-lg)",backgroundColor:"var(--muted)",color:"var(--destructive-foreground)"},children:s.root.message}),N.map(([t,n])=>o(z,{name:t,config:n,control:j,errors:s,t:w},t)),u?g(v,{direction:"row",gap:"tight",children:[o(d,{type:"submit",disabled:a||e,variant:l,className:"dndev-w-full",children:a||e?r?r("loading",{defaultValue:"Loading..."}):"Loading...":i||(r?r("submit",{defaultValue:"Submit"}):"Submit")}),o(d,{type:"button",onClick:m(V),disabled:a||e,variant:y,className:"dndev-w-full",children:a||e?r?r("loading",{defaultValue:"Loading..."}):"Loading...":u})]}):o(d,{type:"submit",disabled:a||e,variant:l,className:"dndev-w-full",children:a||e?r?r("loading",{defaultValue:"Loading..."}):"Loading...":i||(r?r("submit",{defaultValue:"Submit"}):"Submit")})]})})}var B=A;export{A as EntityFormRenderer,B as default};
1
+ "use client";import{jsx as i,jsxs as O}from"react/jsx-runtime";import{FormProvider as z}from"react-hook-form";import{Button as y,Stack as L,Alert as G}from"@donotdev/components";import{TECHNICAL_FIELD_NAMES as M,useTranslation as J}from"@donotdev/core";import{FormFieldRenderer as K}from"./FormFieldRenderer";import{DisplayFieldRenderer as Q}from"./DisplayFieldRenderer";import{useEntityForm as W}from"../forms/hooks/useEntityForm";import{FormUploadProvider as X,useFormUpload as Y}from"../context/FormUploadContext";function Z({entity:m,onSubmit:N,t:n,className:x="",submitText:b,isLoading:o=!1,defaultValues:d,submitVariant:h="primary",secondaryButtonText:j,secondaryButtonVariant:$="outline",onSecondarySubmit:v,viewerRole:A,operation:f=d?"edit":"create",autoSave:I=f==="create"}){const F=Y(),u=W(m,{operation:f,defaultValues:d,viewerRole:A,t:n,autoSave:I}),{control:P,handleSubmit:k,formState:{errors:a,isSubmitting:l},setError:g}=u,S=u.fields,D=t=>f!=="create"?t:Object.fromEntries(Object.entries(t).filter(([e])=>!M.includes(e))),U=t=>{if(typeof t=="string")return t.trim()||void 0;if(t&&typeof t=="object"){const e=t;if(e.message&&typeof e.message=="string"){const r=e.message.trim();if(r&&!r.includes("[object Object]"))return r}if(e.types&&e.type){const r=e.types[e.type]?.message;if(typeof r=="string"){const s=r.trim();if(s&&!s.includes("[object Object]"))return s}}if(e.types&&typeof e.types=="object"){const r=Object.keys(e.types)[0];if(r){const s=e.types[r]?.message;if(typeof s=="string"){const c=s.trim();if(c&&!c.includes("[object Object]"))return c}}}}},V=t=>{const e=Object.entries(t).filter(([s])=>!M.includes(s)).map(([s,c])=>{const B=S.find(q=>q.name===s)?.config?.label||s,p=U(c);return!p||p==="Invalid value"?null:{field:B,message:p}}).filter(s=>s!==null),r=e.length===0?"Please check the form for errors. Some fields may be missing or invalid.":e.length===1?`${e[0].field}: ${e[0].message}`:`Please fix the following errors:
2
+ ${e.map(s=>`\u2022 ${s.field}: ${s.message}`).join(`
3
+ `)}`;g("root",{message:r})},E=async()=>{if(!F)return!0;try{return await F.uploadAll(),!0}catch(t){const e=t instanceof Error?t.message:"Upload failed";return g("root",{message:e}),!1}},w=t=>k(async e=>{try{const r=D(e);await t(r)}catch(r){const s=r instanceof Error?r.message:"An error occurred";g("root",{message:s})}},V),_=async t=>{t.preventDefault(),await E()&&w(N)()},R=async()=>{v&&await E()&&w(v)()},H=`entity-${m.name.toLowerCase()}`,{t:T}=J(H),C=n||T;return i(z,{...u,children:O("form",{onSubmit:_,noValidate:!0,className:x,style:{width:"100%",gridColumn:"1 / -1",display:"contents"},children:[a.root?.message&&i(G,{variant:"error",description:typeof a.root.message=="string"&&a.root.message.includes(`
4
+ `)?i(L,{as:"ul",gap:"tight",style:{listStyle:"disc",listStylePosition:"inside",margin:0,paddingLeft:"1em"},children:a.root.message.split(`
5
+ `).filter(t=>t.trim()).map((t,e)=>i("li",{children:t.replace(/^•\s*/,"")},e))}):a.root.message,style:{marginBottom:"var(--gap-md)",gridColumn:"1 / -1"}}),S.map(({name:t,config:e,editable:r})=>r?i(K,{name:t,config:e,control:P,errors:a,t:C},t):i(Q,{name:t,config:e,value:d?.[t],t:C},t)),j?O(L,{direction:"row",gap:"tight",style:{gridColumn:"1 / -1"},children:[i(y,{type:"submit",disabled:l||o,variant:h,className:"dndev-w-full",children:l||o?n?n("loading",{defaultValue:"Loading..."}):"Loading...":b||(n?n("submit",{defaultValue:"Submit"}):"Submit")}),i(y,{type:"button",onClick:R,disabled:l||o,variant:$,className:"dndev-w-full",children:l||o?n?n("loading",{defaultValue:"Loading..."}):"Loading...":j})]}):i(y,{type:"submit",disabled:l||o,variant:h,className:"dndev-w-full",style:{gridColumn:"1 / -1"},children:l||o?n?n("loading",{defaultValue:"Loading..."}):"Loading...":b||(n?n("submit",{defaultValue:"Submit"}):"Submit")})]})})}function ee(m){return i(X,{children:i(Z,{...m})})}var me=ee;export{ee as EntityFormRenderer,me as default};
@@ -1,36 +1,28 @@
1
1
  /**
2
2
  * @fileoverview FormFieldRenderer component
3
- * @description Renders form fields based on field configuration
3
+ * @description Renders form fields using FieldRegistry - no switch statement
4
4
  *
5
5
  * @version 0.0.1
6
6
  * @since 0.0.1
7
7
  * @author AMBROISE PARK Consulting
8
8
  */
9
9
  import type { ReactElement } from 'react';
10
- import type { FieldConfig, FieldType, ValueTypeForField } from '@donotdev/core';
11
10
  import type { Control, FieldValues } from 'react-hook-form';
11
+ import type { FieldConfig, FieldType, ValueTypeForField } from '@donotdev/core';
12
12
  interface FormFieldRendererBaseProps<T extends FieldType = FieldType> {
13
- /** Field identifier */
14
13
  name: string;
15
- /** Field configuration */
16
14
  config: FieldConfig<T>;
17
- /** Translation function */
18
15
  t: (key: string, options?: Record<string, any>) => string;
19
16
  }
20
17
  interface UncontrolledProps<T extends FieldType> extends FormFieldRendererBaseProps<T> {
21
- /** Current field value */
22
18
  value: ValueTypeForField<T>;
23
- /** Change handler */
24
19
  onChange: (value: ValueTypeForField<T>) => void;
25
- /** Error message if validation fails */
26
20
  error?: string;
27
21
  control?: never;
28
22
  errors?: never;
29
23
  }
30
24
  interface ControlledProps<T extends FieldType, TFieldValues extends FieldValues = FieldValues> extends FormFieldRendererBaseProps<T> {
31
- /** react-hook-form control object */
32
25
  control: Control<TFieldValues>;
33
- /** Form errors object */
34
26
  errors: Record<string, any>;
35
27
  value?: never;
36
28
  onChange?: never;
@@ -38,12 +30,7 @@ interface ControlledProps<T extends FieldType, TFieldValues extends FieldValues
38
30
  }
39
31
  export type FormFieldRendererProps<T extends FieldType, TFieldValues extends FieldValues = FieldValues> = UncontrolledProps<T> | ControlledProps<T, TFieldValues>;
40
32
  /**
41
- * FormFieldRenderer selects and renders the appropriate field component
42
- * based on the field type and whether it's controlled by react-hook-form.
43
- *
44
- * @version 0.0.1
45
- * @since 0.0.1
46
- * @author AMBROISE PARK Consulting
33
+ * FormFieldRenderer - renders fields via registry lookup
47
34
  */
48
35
  export declare function FormFieldRenderer<T extends FieldType, TFieldValues extends FieldValues = FieldValues>({ name, config, t, ...props }: FormFieldRendererProps<T, TFieldValues>): ReactElement;
49
36
  export default FormFieldRenderer;
@@ -1 +1 @@
1
- {"version":3,"file":"FormFieldRenderer.d.ts","sourceRoot":"","sources":["../../src/components/FormFieldRenderer.tsx"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE1C,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAoChF,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG5D,UAAU,0BAA0B,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS;IAClE,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACvB,2BAA2B;IAC3B,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC;CAC3D;AAGD,UAAU,iBAAiB,CACzB,CAAC,SAAS,SAAS,CACnB,SAAQ,0BAA0B,CAAC,CAAC,CAAC;IACrC,0BAA0B;IAC1B,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAC5B,qBAAqB;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IAChD,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,KAAK,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,CAAC;CAChB;AAGD,UAAU,eAAe,CACvB,CAAC,SAAS,SAAS,EACnB,YAAY,SAAS,WAAW,GAAG,WAAW,CAC9C,SAAQ,0BAA0B,CAAC,CAAC,CAAC;IACrC,qCAAqC;IACrC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAC/B,yBAAyB;IACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,QAAQ,CAAC,EAAE,KAAK,CAAC;IACjB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAGD,MAAM,MAAM,sBAAsB,CAChC,CAAC,SAAS,SAAS,EACnB,YAAY,SAAS,WAAW,GAAG,WAAW,IAC5C,iBAAiB,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;AAE5D;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,CAAC,SAAS,SAAS,EACnB,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,EACA,IAAI,EACJ,MAAM,EACN,CAAC,EACD,GAAG,KAAK,EACT,EAAE,sBAAsB,CAAC,CAAC,EAAE,YAAY,CAAC,GAAG,YAAY,CA6PxD;AAED,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"FormFieldRenderer.d.ts","sourceRoot":"","sources":["../../src/components/FormFieldRenderer.tsx"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE1C,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAQ,MAAM,iBAAiB,CAAC;AAElE,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAoBhF,UAAU,0BAA0B,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACvB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC;CAC3D;AAED,UAAU,iBAAiB,CACzB,CAAC,SAAS,SAAS,CACnB,SAAQ,0BAA0B,CAAC,CAAC,CAAC;IACrC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAC5B,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,KAAK,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,CAAC;CAChB;AAED,UAAU,eAAe,CACvB,CAAC,SAAS,SAAS,EACnB,YAAY,SAAS,WAAW,GAAG,WAAW,CAC9C,SAAQ,0BAA0B,CAAC,CAAC,CAAC;IACrC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,QAAQ,CAAC,EAAE,KAAK,CAAC;IACjB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,MAAM,MAAM,sBAAsB,CAChC,CAAC,SAAS,SAAS,EACnB,YAAY,SAAS,WAAW,GAAG,WAAW,IAC5C,iBAAiB,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;AAE5D;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,CAAC,SAAS,SAAS,EACnB,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,EACA,IAAI,EACJ,MAAM,EACN,CAAC,EACD,GAAG,KAAK,EACT,EAAE,sBAAsB,CAAC,CAAC,EAAE,YAAY,CAAC,GAAG,YAAY,CAwFxD;AAED,eAAe,iBAAiB,CAAC"}
@@ -1 +1 @@
1
- "use client";import{jsx as e}from"react/jsx-runtime";import{handleError as m}from"@donotdev/core";import{ControlledCheckboxField as f,ControlledDateField as v,ControlledDropdownField as T,ControlledFileField as w,ControlledGeoPointField as M,ControlledImageField as k,ControlledMapField as P,ControlledMultiDropdownField as R,ControlledMultiInputField as A,ControlledNumberField as D,ControlledPasswordField as E,ControlledPhoneField as H,ControlledRangeField as N,ControlledRadioField as S,ControlledReferenceField as g,ControlledTextField as h,ControlledTimestampField as j,ControlledAddressField as B}from"./ControlledFields";import{AvatarFieldComponent as I,BadgeFieldComponent as $,ButtonFieldComponent as y,HiddenFieldComponent as b,TextAreaComponent as G,TextFieldComponent as U}from"./form/fields";function _({name:n,config:r,t:s,...d}){const c=u=>p=>{try{u(p)}catch(t){m(t,{userMessage:`Error updating field ${r.label||n}`,context:{fieldName:n,fieldType:r.type},severity:"warning"})}};if(r.hidden)return e(b,{name:n,value:"value"in d?d.value:""});if("control"in d&&d.control){const{control:u,errors:p}=d,t={control:u,errors:p,fieldConfig:{...r,label:r.label||n},t:s,onChange:c(F=>{})},l=F=>F;switch(r.type){case"array":return e(A,{...l(t)});case"boolean":case"checkbox":return e(f,{...l(t)});case"date":case"datetime-local":return e(v,{...l(t)});case"file":return e(w,{...l(t)});case"geopoint":return e(M,{...l(t)});case"image":return e(k,{...l(t)});case"map":return e(P,{...l(t)});case"multiselect":return e(R,{...l(t)});case"number":return e(D,{...l(t)});case"radio":return e(S,{...l(t)});case"range":return e(N,{...l(t)});case"reference":return e(g,{...l(t)});case"select":return e(T,{...l(t)});case"tel":return e(H,{...l(t)});case"timestamp":return e(j,{...l(t)});case"password":return e(E,{...l(t)});case"address":return e(B,{...l(t)});case"text":case"email":case"url":case"color":return e(h,{...l(t)});default:return m(new Error(`Unsupported field type: ${r.type}`),{userMessage:s("errors.unsupportedFieldType",{type:r.type}),context:{fieldName:n,fieldType:r.type},severity:"warning"}),e(h,{...l({...t,fieldConfig:{...r,type:"text"}})})}}const{value:i,onChange:x,error:o}=d,a=c(x),C=(()=>{switch(r.type){case"avatar":return e(I,{config:r,value:i,onChange:a,error:!!o,helperText:o||void 0,t:s,...r.options});case"badge":return e($,{config:r,value:i,onChange:a,error:!!o,helperText:o||void 0,t:s,...r.options});case"submit":return e(y,{label:r.label||n,type:"submit",onClick:()=>a(void 0),...r.options});case"reset":return e(y,{label:r.label||n,type:"reset",onClick:()=>a(void 0),...r.options});case"hidden":return e(b,{name:n,value:i});case"textarea":return e(G,{label:r.label||n,value:i,onChange:a,error:o||void 0,helperText:void 0,...r.options});default:return null}})();return C||e(U,{label:r.label||n,value:i,onChange:a,error:o||void 0,helperText:void 0,...r.options})}var Q=_;export{_ as FormFieldRenderer,Q as default};
1
+ "use client";import{jsx as l}from"react/jsx-runtime";import{useController as b}from"react-hook-form";import{handleError as f}from"@donotdev/core";import{getFieldRegistry as g}from"../FieldRegistry";import{registerBuiltinFieldTypes as F}from"../builtinFieldTypes";F();import{TextFieldComponent as T}from"./form/fields";import{ControlledTextField as v}from"./ControlledFields";const c=g();function w({name:r,config:e,t:n,...t}){const s=o=>i=>{try{o(i)}catch(d){f(d,{userMessage:`Error updating field ${e.label||r}`,context:{fieldName:r,fieldType:e.type},severity:"warning"})}};if("control"in t&&t.control){const{control:o,errors:i}=t,{field:d,fieldState:h}=b({name:r,control:o}),C={control:o,errors:i,fieldConfig:{...e,label:e.label||r},t:n,onChange:s(()=>{}),field:d,fieldState:h},m=c.getControlledComponent(e.type);return m?l(m,{...C}):(f(new Error(`Unregistered field type: ${e.type}`),{userMessage:n("errors.unsupportedFieldType",{type:e.type}),context:{fieldName:r,fieldType:e.type},severity:"warning"}),l(v,{...C,fieldConfig:{...e,type:"text"}}))}const{value:a,onChange:x,error:p}=t,u=s(x),y=c.getUncontrolledComponent(e.type);return y?l(y,{name:r,label:e.label||r,value:a,onChange:u,error:p,t:n,config:e,...e.options}):l(T,{label:e.label||r,value:a,onChange:u,error:p||void 0,...e.options})}var $=w;export{w as FormFieldRenderer,$ as default};
@@ -24,6 +24,8 @@ export interface AddressFieldComponentProps {
24
24
  error?: boolean;
25
25
  /** Helper text */
26
26
  helperText?: string;
27
+ /** Whether the field is required */
28
+ required?: boolean;
27
29
  }
28
30
  /**
29
31
  * Address field component with Google Maps autocomplete
@@ -37,6 +39,6 @@ export interface AddressFieldComponentProps {
37
39
  * @param {AddressFieldComponentProps} props - Component props
38
40
  * @returns {JSX.Element} Address input field with autocomplete
39
41
  */
40
- declare const AddressFieldComponent: ({ label, value, onChange, enableGoogleMaps, extractDistrictCode, error, helperText, }: AddressFieldComponentProps) => import("react/jsx-runtime").JSX.Element;
42
+ declare const AddressFieldComponent: ({ label, value, onChange, enableGoogleMaps, extractDistrictCode, error, helperText, required, }: AddressFieldComponentProps) => import("react/jsx-runtime").JSX.Element;
41
43
  export default AddressFieldComponent;
42
44
  //# sourceMappingURL=AddressFieldComponent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AddressFieldComponent.d.ts","sourceRoot":"","sources":["../../../../src/components/form/fields/AddressFieldComponent.tsx"],"names":[],"mappings":"AAsBA;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,KAAK,CAAC,EAAE;QACN,iBAAiB,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC;IACF,qBAAqB;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,2DAA2D;IAC3D,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,kBAAkB;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;GAWG;AACH,QAAA,MAAM,qBAAqB,GAAI,uFAQ5B,0BAA0B,4CAsQ5B,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"AddressFieldComponent.d.ts","sourceRoot":"","sources":["../../../../src/components/form/fields/AddressFieldComponent.tsx"],"names":[],"mappings":"AAgBA;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,KAAK,CAAC,EAAE;QACN,iBAAiB,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC;IACF,qBAAqB;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,2DAA2D;IAC3D,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,kBAAkB;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;GAWG;AACH,QAAA,MAAM,qBAAqB,GAAI,iGAS5B,0BAA0B,4CAiS5B,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
@@ -1 +1 @@
1
- import{jsx as n,jsxs as y}from"react/jsx-runtime";import{useState as v,useEffect as C,useRef as P}from"react";import{Input as M,Popover as x,Command as q,Stack as j}from"@donotdev/components";import{useTranslation as D,getPlatformEnvVar as W}from"@donotdev/core";import{MapPin as Y}from"lucide-react";const $=({label:b,value:l,onChange:E,enableGoogleMaps:A=!1,extractDistrictCode:T,error:p,helperText:m})=>{const{t:r}=D(),[u,a]=v(!1),[c,g]=v(l?.formatted_address||""),[G,h]=v([]),[I,f]=v(!1),_=P(null),w=P(null),i=P(null),S=W("GOOGLE_MAPS_API_KEY")||"",d=A&&!!S,K=e=>{w.current&&(f(!0),w.current.getDetails({placeId:e,fields:["formatted_address","geometry","address_components"]},(t,o)=>{if(f(!1),o===window.google?.maps?.places?.PlacesServiceStatus.OK&&t){const s=t.formatted_address||"",k=t.geometry?.location?.lat(),L=t.geometry?.location?.lng(),O={formatted_address:s,latitude:k,longitude:L};if(T&&t.address_components){const z=t.address_components.find(F=>F.types.includes("postal_code"))?.long_name||"",V=z.startsWith("92")?92:parseInt(z.slice(-2),10)||null;O.district_code=V}g(s),E(O),a(!1)}}))};C(()=>{l?.formatted_address&&g(l.formatted_address)},[l]),C(()=>{if(!d)return;const e=()=>{if(window.google?.maps?.places){t();return}if(document.querySelector("#google-maps-script")){const s=setInterval(()=>{window.google?.maps?.places&&(clearInterval(s),t())},100);return}const o=document.createElement("script");o.id="google-maps-script",o.src=`https://maps.googleapis.com/maps/api/js?key=${S}&libraries=places`,o.async=!0,o.defer=!0,o.onload=()=>t(),document.head.appendChild(o)},t=()=>{window.google?.maps?.places&&(_.current=new window.google.maps.places.AutocompleteService,w.current=new window.google.maps.places.PlacesService(document.createElement("div")))};e()},[d,S]),C(()=>{if(!d||!c||!_.current||!u){h([]);return}return i.current&&clearTimeout(i.current),i.current=setTimeout(()=>{f(!0),_.current.getPlacePredictions({input:c,types:["geocode","establishment"]},(e,t)=>{if(f(!1),t===window.google?.maps?.places?.PlacesServiceStatus.OK&&e){const o=e.map(s=>({label:s.description,value:s.place_id,description:s.structured_formatting?.secondary_text,icon:n(Y,{style:{width:"var(--size-icon-sm)",height:"var(--size-icon-sm)"}}),onSelect:()=>K(s.place_id)}));h(o)}else h([])})},300),()=>{i.current&&clearTimeout(i.current)}},[d,c,u]);const R=e=>{g(e),E({formatted_address:e})};return d?y(j,{gap:"tight",children:[y(x,{open:u,onOpenChange:a,children:[n(x.Trigger,{asChild:!0,children:n(M,{type:"text",label:b,value:c,onChange:e=>{g(e.target.value),u||a(!0)},onFocus:()=>a(!0),placeholder:r("common.address_placeholder"),"data-variant":p?"destructive":void 0,disabled:I})}),n(x.Content,{style:{width:"var(--radix-popover-trigger-width)",padding:0},children:n(q,{placeholder:r("common.search_placeholder"),emptyMessage:r(I?"common.loading":"common.no_results"),items:G,onClose:()=>a(!1)})})]}),m&&n("p",{style:{fontSize:"var(--font-size-xs)",color:p?"var(--destructive-foreground)":"var(--muted-foreground)",marginTop:"var(--gap-sm)"},children:m})]}):y(j,{gap:"tight",children:[n(M,{type:"text",label:b,value:c,onChange:e=>R(e.target.value),placeholder:r("common.address_placeholder"),"data-variant":p?"destructive":void 0}),m&&n("p",{style:{fontSize:"var(--font-size-xs)",color:p?"var(--destructive-foreground)":"var(--muted-foreground)",marginTop:"var(--gap-sm)"},children:m})]})};var X=$;export{X as default};
1
+ import{jsx as r,jsxs as f}from"react/jsx-runtime";import{useState as S,useEffect as w,useRef as b,useMemo as D}from"react";import{Combobox as M,Stack as L}from"@donotdev/components";import{useTranslation as F,getPlatformEnvVar as W}from"@donotdev/core";import{MapPin as Y}from"lucide-react";const $=({label:C,value:d,onChange:P,enableGoogleMaps:j=!1,extractDistrictCode:O,error:l,helperText:u,required:x})=>{const{t:n}=F("dndev"),[c,m]=S(d?.formatted_address||""),[g,v]=S([]),[I,p]=S(!1),h=b(null),_=b(null),i=b(null),y=W("GOOGLE_MAPS_API_KEY")||"",s=j&&!!y,V=D(()=>g.map(e=>({value:e.place_id,label:e.description,description:e.structured_formatting?.secondary_text,content:f("div",{style:{display:"flex",alignItems:"center",gap:"var(--gap-sm)"},children:[r(Y,{style:{width:"var(--size-icon-sm)",height:"var(--size-icon-sm)"}}),f("div",{children:[r("div",{children:e.description}),e.structured_formatting?.secondary_text&&r("div",{style:{fontSize:"var(--font-size-xs)",color:"var(--muted-foreground)"},children:e.structured_formatting.secondary_text})]})]})})),[g]),G=e=>{_.current&&(p(!0),_.current.getDetails({placeId:e,fields:["formatted_address","geometry","address_components"]},(t,o)=>{if(p(!1),o===window.google?.maps?.places?.PlacesServiceStatus.OK&&t){const a=t.formatted_address||"",k=t.geometry?.location?.lat(),q=t.geometry?.location?.lng(),A={formatted_address:a,latitude:k,longitude:q};if(O&&t.address_components){const E=t.address_components.find(U=>U.types.includes("postal_code"))?.long_name||"",T=E.startsWith("92")?92:parseInt(E.slice(-2),10)||null;A.district_code=T}m(a),P(A)}}))};w(()=>{d?.formatted_address&&m(d.formatted_address)},[d]),w(()=>{if(!s)return;const e=()=>{if(window.google?.maps?.places){t();return}if(document.querySelector("#google-maps-script")){const a=setInterval(()=>{window.google?.maps?.places&&(clearInterval(a),t())},100);return}const o=document.createElement("script");o.id="google-maps-script",o.src=`https://maps.googleapis.com/maps/api/js?key=${y}&libraries=places`,o.async=!0,o.defer=!0,o.onload=()=>t(),document.head.appendChild(o)},t=()=>{window.google?.maps?.places&&(h.current=new window.google.maps.places.AutocompleteService,_.current=new window.google.maps.places.PlacesService(document.createElement("div")))};e()},[s,y]),w(()=>{if(!s||!c||!h.current){v([]);return}return i.current&&clearTimeout(i.current),i.current=setTimeout(()=>{p(!0),h.current.getPlacePredictions({input:c,types:["geocode","establishment"]},(e,t)=>{p(!1),t===window.google?.maps?.places?.PlacesServiceStatus.OK&&e?v(e):v([])})},300),()=>{i.current&&clearTimeout(i.current)}},[s,c]);const K=e=>{m(e),P({formatted_address:e})},z=e=>{const t=Array.isArray(e)?e[0]||"":e;if(!s){K(t);return}g.some(a=>a.place_id===t)&&G(t)},R=e=>{s&&m(e)};return s?f(L,{gap:"tight",children:[r(M,{label:C,value:c,onValueChange:z,onSearchChange:R,placeholder:n("common.address_placeholder"),emptyMessage:n(I?"common.loading":"common.no_results"),options:V,required:x,variant:l?"destructive":void 0,isLoading:I,creatable:!0,createLabel:n("actions.use","Use")}),u&&r("p",{style:{fontSize:"var(--font-size-xs)",color:l?"var(--destructive-foreground)":"var(--muted-foreground)"},children:u})]}):f(L,{gap:"tight",children:[r(M,{label:C,value:c,onValueChange:z,placeholder:n("common.address_placeholder"),options:[],required:x,variant:l?"destructive":void 0,creatable:!0,createLabel:n("actions.use","Use")}),u&&r("p",{style:{fontSize:"var(--font-size-xs)",color:l?"var(--destructive-foreground)":"var(--muted-foreground)"},children:u})]})};var Z=$;export{Z as default};
@@ -6,6 +6,8 @@ export interface CheckboxFieldComponentProps {
6
6
  checked?: boolean;
7
7
  /** Change handler for the checkbox */
8
8
  onChange?: (event: ChangeEvent<HTMLInputElement>) => void;
9
+ /** Whether the field is required */
10
+ required?: boolean;
9
11
  }
10
12
  /**
11
13
  * CheckboxFieldComponent renders a labeled checkbox.
@@ -1 +1 @@
1
- {"version":3,"file":"CheckboxFieldComponent.d.ts","sourceRoot":"","sources":["../../../../src/components/form/fields/CheckboxFieldComponent.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAExD,MAAM,WAAW,2BAA2B;IAC1C,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;CAC3D;AAED;;;;;;;;GAQG;AACH,QAAA,MAAM,sBAAsB,EAAE,aAAa,CAAC,2BAA2B,CAoBtE,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
1
+ {"version":3,"file":"CheckboxFieldComponent.d.ts","sourceRoot":"","sources":["../../../../src/components/form/fields/CheckboxFieldComponent.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAExD,MAAM,WAAW,2BAA2B;IAC1C,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IAC1D,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,QAAA,MAAM,sBAAsB,EAAE,aAAa,CAAC,2BAA2B,CAqBtE,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
@@ -1 +1 @@
1
- import{jsx as t,jsxs as r}from"react/jsx-runtime";import{Checkbox as c,Label as h,Stack as s}from"@donotdev/components";const i=({label:n,checked:a=!1,onChange:e})=>r(s,{direction:"row",align:"center",gap:"tight",children:[t(c,{checked:a,onCheckedChange:o=>{e&&e({target:{checked:o}})}}),t(h,{children:n})]});var g=i;export{g as default};
1
+ import{jsx as r,jsxs as c}from"react/jsx-runtime";import{Checkbox as h,Label as i,Stack as s}from"@donotdev/components";const d=({label:t,checked:n=!1,onChange:e,required:a})=>c(s,{direction:"row",align:"center",gap:"tight",children:[r(h,{checked:n,onCheckedChange:o=>{e&&e({target:{checked:o}})}}),r(i,{required:a,children:t})]});var C=d;export{C as default};
@@ -0,0 +1,43 @@
1
+ import type { ChangeEvent, ComponentType } from 'react';
2
+ export interface ComboboxComponentProps {
3
+ /** Field label */
4
+ label: string;
5
+ /** Current value */
6
+ value?: string;
7
+ /** Available options */
8
+ options: {
9
+ value: string;
10
+ label: string;
11
+ }[];
12
+ /** Error state */
13
+ error?: boolean;
14
+ /** Helper text */
15
+ helperText?: string;
16
+ /** Change handler - accepts both event and direct value */
17
+ onChange?: (value: string | ChangeEvent<HTMLSelectElement>) => void;
18
+ /** Blur handler */
19
+ onBlur?: () => void;
20
+ /** Whether the field is required */
21
+ required?: boolean;
22
+ /** Placeholder text */
23
+ placeholder?: string;
24
+ /** Enable creating new values */
25
+ creatable?: boolean;
26
+ /** Label for create option */
27
+ createLabel?: string;
28
+ /** Empty message */
29
+ emptyMessage?: string;
30
+ }
31
+ /**
32
+ * ComboboxComponent renders a searchable combobox with autocomplete.
33
+ * Input + Dropdown pattern: user types in input, dropdown appears below.
34
+ *
35
+ * @version 0.0.1
36
+ * @since 0.0.1
37
+ * @author AMBROISE PARK Consulting
38
+ * @param props - ComboboxComponentProps
39
+ * @returns JSX.Element
40
+ */
41
+ declare const ComboboxComponent: ComponentType<ComboboxComponentProps>;
42
+ export default ComboboxComponent;
43
+ //# sourceMappingURL=ComboboxComponent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ComboboxComponent.d.ts","sourceRoot":"","sources":["../../../../src/components/form/fields/ComboboxComponent.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAExD,MAAM,WAAW,sBAAsB;IACrC,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,oBAAoB;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5C,kBAAkB;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IACpE,mBAAmB;IACnB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iCAAiC;IACjC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,8BAA8B;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oBAAoB;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,QAAA,MAAM,iBAAiB,EAAE,aAAa,CAAC,sBAAsB,CA6F5D,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1 @@
1
+ import{jsx as a,jsxs as c}from"react/jsx-runtime";import{useMemo as A,useId as I}from"react";import{Combobox as O,Stack as d}from"@donotdev/components";import{useTranslation as E}from"@donotdev/core";const M=({label:u,value:n,options:s,error:f,helperText:o,onChange:l,onBlur:m,required:p,placeholder:g,creatable:h=!1,createLabel:b,emptyMessage:v})=>{const{t:r}=E("dndev"),i=I(),x=A(()=>s.map(e=>({value:String(e.value),label:e.label})),[s]),C=e=>{if(l){const z={target:{value:Array.isArray(e)?e[0]||"":e}};l(z)}},y=e=>{e||m?.()},t=!!f,S=`${i}-error`,j=`${i}-helper`;return c(d,{gap:"tight",children:[a(O,{label:u,value:n||"",onValueChange:C,onOpenChange:y,placeholder:g||r("actions.select","Select"),emptyMessage:v||r("messages.noResults","No results found"),creatable:h,createLabel:b||r("actions.create","Create"),options:x,required:p,variant:t?"destructive":void 0,clearable:!!n}),t&&c(d,{id:S,direction:"row",align:"center",gap:"tight",style:{fontSize:"var(--font-size-xs)",color:"var(--destructive-foreground)"},role:"alert",children:[a("span",{children:"\u26A0"}),o]}),o&&!t&&a("p",{id:j,style:{fontSize:"var(--font-size-xs)",color:"var(--muted-foreground)"},children:o})]})};var N=M;export{N as default};
@@ -0,0 +1,41 @@
1
+ /**
2
+ * @fileoverview Currency Field Component
3
+ * @description Currency input with locale-aware formatting and currency symbol
4
+ *
5
+ * @version 0.0.1
6
+ * @since 0.0.1
7
+ * @author AMBROISE PARK Consulting
8
+ */
9
+ import { type ChangeEvent, type ComponentType } from 'react';
10
+ export interface CurrencyFieldComponentProps {
11
+ /** Field label */
12
+ label: string;
13
+ /** Current value (number in cents/smallest unit) */
14
+ value?: number;
15
+ /** Change handler */
16
+ onChange: (event: ChangeEvent<HTMLInputElement>) => void;
17
+ /** Currency code (e.g., 'EUR', 'USD') */
18
+ currency?: string;
19
+ /** Locale for formatting (e.g., 'fr-FR', 'en-US') */
20
+ locale?: string;
21
+ /** Error state */
22
+ error?: boolean;
23
+ /** Helper text */
24
+ helperText?: string;
25
+ /** Required field */
26
+ required?: boolean;
27
+ /** Disabled state */
28
+ disabled?: boolean;
29
+ /** Placeholder */
30
+ placeholder?: string;
31
+ }
32
+ /**
33
+ * Currency field with locale-aware formatting
34
+ *
35
+ * @version 0.0.1
36
+ * @since 0.0.1
37
+ * @author AMBROISE PARK Consulting
38
+ */
39
+ declare const CurrencyFieldComponent: ComponentType<CurrencyFieldComponentProps>;
40
+ export default CurrencyFieldComponent;
41
+ //# sourceMappingURL=CurrencyFieldComponent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CurrencyFieldComponent.d.ts","sourceRoot":"","sources":["../../../../src/components/form/fields/CurrencyFieldComponent.tsx"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,aAAa,EACnB,MAAM,OAAO,CAAC;AAGf,MAAM,WAAW,2BAA2B;IAC1C,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IACzD,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,kBAAkB;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,QAAA,MAAM,sBAAsB,EAAE,aAAa,CAAC,2BAA2B,CAuHtE,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
@@ -0,0 +1 @@
1
+ import{jsx as n,jsxs as s}from"react/jsx-runtime";import{useState as N,useEffect as V,useId as j}from"react";import{Input as E,FloatingLabel as I,Stack as z}from"@donotdev/components";const L=({label:m,value:r,onChange:g,currency:a="EUR",locale:y,error:l,helperText:i,required:v=!1,disabled:c=!1,placeholder:h})=>{const d=j(),b=y||(typeof navigator<"u"?navigator.language:"en-US"),u=e=>e==null||isNaN(e)?"":(e/100).toFixed(2),x=e=>{if(!e||e.trim()==="")return null;const t=e.replace(/[^\d.,\-]/g,"").replace(",","."),o=parseFloat(t);return isNaN(o)?null:Math.round(o*100)},[S,p]=N(u(r));V(()=>{p(u(r))},[r]);const C=e=>{const t=e.target.value;p(t);const F={target:{value:x(t)}};g(F)},f=(()=>{try{return new Intl.NumberFormat(b,{style:"currency",currency:a,currencyDisplay:"symbol"}).formatToParts(0).find(e=>e.type==="currency")?.value||a}catch{return a}})();return s(z,{gap:"tight",children:[s("div",{className:"dndev-relative",children:[n(I,{htmlFor:d,disabled:c,required:v,children:m}),s("div",{style:{position:"relative"},children:[n("span",{style:{position:"absolute",left:"var(--gap-md)",top:"50%",transform:"translateY(-50%)",color:"var(--muted-foreground)",pointerEvents:"none",zIndex:1},children:f}),n(E,{id:d,type:"text",inputMode:"decimal",value:S,onChange:C,disabled:c,placeholder:h||"0.00","data-variant":l?"destructive":void 0,style:{paddingLeft:`calc(var(--gap-md) + ${f.length*.6}em + var(--gap-sm))`}})]})]}),i&&n("p",{style:{fontSize:"var(--font-size-xs)",color:l?"var(--destructive-foreground)":"var(--muted-foreground)",marginTop:"var(--gap-sm)"},children:i})]})};var k=L;export{k as default};
@@ -15,6 +15,8 @@ export interface DateFieldComponentProps {
15
15
  * This controls both the input type and the formatting of the displayed value.
16
16
  */
17
17
  mode?: 'date' | 'datetime-local' | 'month' | 'time' | 'week';
18
+ /** Whether the field is required */
19
+ required?: boolean;
18
20
  }
19
21
  /**
20
22
  * DateFieldComponent renders a date (or related) input field
@@ -1 +1 @@
1
- {"version":3,"file":"DateFieldComponent.d.ts","sourceRoot":"","sources":["../../../../src/components/form/fields/DateFieldComponent.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAe,aAAa,EAAE,MAAM,OAAO,CAAC;AAExD,MAAM,WAAW,uBAAuB;IACtC,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,oDAAoD;IACpD,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACxC,0CAA0C;IAC1C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,6BAA6B;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,gBAAgB,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;CAC9D;AAED;;;;;;GAMG;AACH,QAAA,MAAM,kBAAkB,EAAE,aAAa,CAAC,uBAAuB,CAsE9D,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"DateFieldComponent.d.ts","sourceRoot":"","sources":["../../../../src/components/form/fields/DateFieldComponent.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAe,aAAa,EAAE,MAAM,OAAO,CAAC;AAExD,MAAM,WAAW,uBAAuB;IACtC,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,oDAAoD;IACpD,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACxC,0CAA0C;IAC1C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,6BAA6B;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,gBAAgB,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IAC7D,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;GAMG;AACH,QAAA,MAAM,kBAAkB,EAAE,aAAa,CAAC,uBAAuB,CAwE9D,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -1 +1 @@
1
- import{jsx as n,jsxs as S}from"react/jsx-runtime";import{Input as d,Label as p,Stack as u}from"@donotdev/components";const h=({label:s,value:a,onChange:r,error:o,helperText:l,mode:e="date",...c})=>{const f=t=>{const g=t.target.value?new Date(t.target.value).toISOString():null;r(g)};let i="";if(a){const t=new Date(a);e==="date"?i=t.toISOString().split("T")[0]||"":e==="datetime-local"?i=t.toISOString().slice(0,16)||"":e==="month"?i=t.toISOString().slice(0,7):e==="time"?i=t.toISOString().slice(11,16):e==="week"&&(i=t.toISOString().split("T")[0]||"")}return S(u,{gap:"tight",children:[n(p,{style:{display:"block",fontSize:"var(--font-size-sm)",fontWeight:500},children:s}),n(d,{type:e,value:i,onChange:f,className:"dndev-w-full",...c}),l&&n("p",{style:{fontSize:"var(--font-size-xs)",color:o?"var(--destructive-foreground)":"var(--muted-foreground)",marginTop:"var(--gap-sm)"},children:l})]})};var O=h;export{O as default};
1
+ import{jsx as n,jsxs as d}from"react/jsx-runtime";import{Input as u,Label as p,Stack as h}from"@donotdev/components";const m=({label:s,value:a,onChange:r,error:o,helperText:l,mode:e="date",required:c,...f})=>{const g=t=>{const S=t.target.value?new Date(t.target.value).toISOString():null;r(S)};let i="";if(a){const t=new Date(a);e==="date"?i=t.toISOString().split("T")[0]||"":e==="datetime-local"?i=t.toISOString().slice(0,16)||"":e==="month"?i=t.toISOString().slice(0,7):e==="time"?i=t.toISOString().slice(11,16):e==="week"&&(i=t.toISOString().split("T")[0]||"")}return d(h,{gap:"tight",children:[n(p,{required:c,style:{display:"block",fontSize:"var(--font-size-sm)",fontWeight:500},children:s}),n(u,{type:e,value:i,onChange:g,className:"dndev-w-full",...f}),l&&n("p",{style:{fontSize:"var(--font-size-xs)",color:o?"var(--destructive-foreground)":"var(--muted-foreground)",marginTop:"var(--gap-sm)"},children:l})]})};var w=m;export{w as default};
@@ -1 +1 @@
1
- {"version":3,"file":"DropdownComponent.d.ts","sourceRoot":"","sources":["../../../../src/components/form/fields/DropdownComponent.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAExD,MAAM,WAAW,sBAAsB;IACrC,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,oBAAoB;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAClC,wBAAwB;IACxB,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC/D,kBAAkB;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IACpE,mBAAmB;IACnB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,QAAA,MAAM,iBAAiB,EAAE,aAAa,CAAC,sBAAsB,CAuE5D,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"DropdownComponent.d.ts","sourceRoot":"","sources":["../../../../src/components/form/fields/DropdownComponent.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAExD,MAAM,WAAW,sBAAsB;IACrC,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,oBAAoB;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAClC,wBAAwB;IACxB,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC/D,kBAAkB;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IACpE,mBAAmB;IACnB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,QAAA,MAAM,iBAAiB,EAAE,aAAa,CAAC,sBAAsB,CAqD5D,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -1 +1 @@
1
- import{jsx as n,jsxs as s}from"react/jsx-runtime";import{Select as v,Label as f,Stack as m}from"@donotdev/components";import{useTranslation as h}from"@donotdev/core";const S=({label:l,value:r,options:i,error:c,helperText:a,onChange:o,onBlur:d,required:p})=>{const{t}=h("dndev"),g=r!==void 0?String(r):"",u=e=>{o&&o({target:{value:e}})};return s(m,{gap:"tight",children:[s(f,{style:{display:"block",fontSize:"var(--font-size-sm)",fontWeight:500},children:[t(l),p&&n("span",{style:{color:"var(--destructive-foreground)",marginInlineStart:"var(--gap-sm)"},children:"*"})]}),n(v,{value:g,onValueChange:u,onOpenChange:e=>!e&&d?.(),placeholder:t("actions.select","Select"),options:i.map(e=>({value:String(e.value),label:t(e.label)}))}),a&&n("p",{style:{fontSize:"var(--font-size-xs)",color:c?"var(--destructive-foreground)":"var(--muted-foreground)",marginTop:"var(--gap-sm)"},children:a})]})};var C=S;export{C as default};
1
+ import{jsx as o,jsxs as p}from"react/jsx-runtime";import{Select as g,Stack as m}from"@donotdev/components";import{useTranslation as v}from"@donotdev/core";const f=({label:r,value:t,options:s,error:l,helperText:n,onChange:a,onBlur:i,required:c})=>{const{t:d}=v("dndev"),u=t!==void 0?String(t):"";return p(m,{gap:"tight",children:[o(g,{label:r,value:u,onValueChange:e=>{a&&a({target:{value:e}})},onOpenChange:e=>!e&&i?.(),placeholder:d("actions.select","Select"),required:c,options:s.map(e=>({value:String(e.value),label:e.label}))}),n&&o("p",{style:{fontSize:"var(--font-size-xs)",color:l?"var(--destructive-foreground)":"var(--muted-foreground)",marginTop:"var(--gap-sm)"},children:n})]})};var C=f;export{C as default};
@@ -16,6 +16,8 @@ export interface FileFieldComponentProps {
16
16
  maxSize?: number;
17
17
  /** Whether multiple files are allowed */
18
18
  multiple?: boolean;
19
+ /** Whether the field is required */
20
+ required?: boolean;
19
21
  }
20
22
  /**
21
23
  * FileFieldComponent renders a file upload field with drag & drop support
@@ -1 +1 @@
1
- {"version":3,"file":"FileFieldComponent.d.ts","sourceRoot":"","sources":["../../../../src/components/form/fields/FileFieldComponent.tsx"],"names":[],"mappings":"AAaA,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,aAAa,EACnB,MAAM,OAAO,CAAC;AAWf,MAAM,WAAW,uBAAuB;IACtC,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,yBAAyB;IACzB,KAAK,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACpB,2DAA2D;IAC3D,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IACtE,kBAAkB;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;GAMG;AACH,QAAA,MAAM,kBAAkB,EAAE,aAAa,CAAC,uBAAuB,CAgK9D,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"FileFieldComponent.d.ts","sourceRoot":"","sources":["../../../../src/components/form/fields/FileFieldComponent.tsx"],"names":[],"mappings":"AAaA,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,aAAa,EACnB,MAAM,OAAO,CAAC;AAWf,MAAM,WAAW,uBAAuB;IACtC,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,yBAAyB;IACzB,KAAK,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACpB,2DAA2D;IAC3D,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IACtE,kBAAkB;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;GAMG;AACH,QAAA,MAAM,kBAAkB,EAAE,aAAa,CAAC,uBAAuB,CAkK9D,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -1 +1 @@
1
- "use client";import{jsx as r,jsxs as a}from"react/jsx-runtime";import{Upload as y,X as b}from"lucide-react";import{useCallback as p,useState as z}from"react";import{Button as k,BUTTON_VARIANT as x,Input as D,Label as N,Stack as l}from"@donotdev/components";const w=({label:f,value:c,onChange:t,error:n,helperText:u,accept:m,maxSize:s,multiple:g=!1})=>{const[v,o]=z(!1),i=p(e=>{if(!e){t({target:{value:"",files:null}});return}if(s&&e.size>s)return;const d={target:{value:e.name,files:[e]}};t(d)},[s,t]),h=p(e=>{e.preventDefault(),o(!1);const d=e.dataTransfer?.files[0]||null;i(d)},[i]);return a(l,{gap:"tight",children:[r(N,{style:{display:"block",fontSize:"var(--font-size-sm)",fontWeight:500},children:f}),a("div",{className:"dndev-relative dndev-surface","data-variant":n?"destructive":"default",style:{border:"2px dashed",borderColor:v?"var(--primary)":n?"var(--destructive)":"var(--border)",borderRadius:"var(--radius-lg)",padding:"var(--gap-lg)",backgroundColor:v?"color-mix(in oklab, var(--primary) 5%, transparent)":void 0,transition:"border-color 0.2s, background-color 0.2s"},onDragOver:e=>{e.preventDefault(),o(!0)},onDragLeave:()=>o(!1),onDrop:h,children:[r(D,{type:"file",accept:m,multiple:g,className:"dndev-absolute dndev-inset-0 dndev-pointer-events-auto",style:{width:"100%",height:"100%",opacity:0,cursor:"pointer"},onChange:e=>i(e.target.files?.[0]||null)}),a(l,{align:"center",justify:"center",gap:"medium",children:[r(y,{className:"dndev-size-touch",style:{color:"var(--muted-foreground)"}}),r("p",{style:{fontSize:"var(--font-size-sm)",color:"var(--muted-foreground)"},children:"Drag & drop or click to upload"})]}),c&&a(l,{direction:"row",align:"center",justify:"between",className:"dndev-surface","data-variant":"muted",style:{marginTop:"var(--gap-md)",padding:"var(--gap-md)",borderRadius:"var(--radius-lg)"},children:[r("span",{style:{fontSize:"var(--font-size-sm)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:c.name}),r(k,{variant:x.GHOST,onClick:()=>t(null),className:"dndev-size-touch",children:r(b,{className:"dndev-size-md"})})]})]}),u&&r("p",{style:{fontSize:"var(--font-size-xs)",color:n?"var(--destructive-foreground)":"var(--muted-foreground)",marginTop:"var(--gap-sm)"},children:u})]})};var C=w;export{C as default};
1
+ "use client";import{jsx as r,jsxs as a}from"react/jsx-runtime";import{Upload as b,X as z}from"lucide-react";import{useCallback as p,useState as k}from"react";import{Button as x,BUTTON_VARIANT as D,Input as N,Label as w,Stack as l}from"@donotdev/components";const S=({label:f,value:c,onChange:t,error:n,helperText:u,accept:m,maxSize:s,multiple:g=!1,required:h})=>{const[v,o]=k(!1),i=p(e=>{if(!e){t({target:{value:"",files:null}});return}if(s&&e.size>s)return;const d={target:{value:e.name,files:[e]}};t(d)},[s,t]),y=p(e=>{e.preventDefault(),o(!1);const d=e.dataTransfer?.files[0]||null;i(d)},[i]);return a(l,{gap:"tight",children:[r(w,{required:h,style:{display:"block",fontSize:"var(--font-size-sm)",fontWeight:500},children:f}),a("div",{className:"dndev-relative dndev-surface","data-variant":n?"destructive":"default",style:{border:"2px dashed",borderColor:v?"var(--primary)":n?"var(--destructive)":"var(--border)",borderRadius:"var(--radius-lg)",padding:"var(--gap-lg)",backgroundColor:v?"color-mix(in oklab, var(--primary) 5%, transparent)":void 0,transition:"border-color 0.2s, background-color 0.2s"},onDragOver:e=>{e.preventDefault(),o(!0)},onDragLeave:()=>o(!1),onDrop:y,children:[r(N,{type:"file",accept:m,multiple:g,className:"dndev-absolute dndev-inset-0 dndev-pointer-events-auto",style:{width:"100%",height:"100%",opacity:0,cursor:"pointer"},onChange:e=>i(e.target.files?.[0]||null)}),a(l,{align:"center",justify:"center",gap:"medium",children:[r(b,{className:"dndev-size-touch",style:{color:"var(--muted-foreground)"}}),r("p",{style:{fontSize:"var(--font-size-sm)",color:"var(--muted-foreground)"},children:"Drag & drop or click to upload"})]}),c&&a(l,{direction:"row",align:"center",justify:"between",className:"dndev-surface","data-variant":"muted",style:{marginTop:"var(--gap-md)",padding:"var(--gap-md)",borderRadius:"var(--radius-lg)"},children:[r("span",{style:{fontSize:"var(--font-size-sm)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:c.name}),r(x,{variant:D.GHOST,onClick:()=>t(null),className:"dndev-size-touch",children:r(z,{className:"dndev-size-md"})})]})]}),u&&r("p",{style:{fontSize:"var(--font-size-xs)",color:n?"var(--destructive-foreground)":"var(--muted-foreground)",marginTop:"var(--gap-sm)"},children:u})]})};var E=S;export{E as default};
@@ -16,6 +16,8 @@ export interface GeoPointFieldComponentProps {
16
16
  helperText?: string;
17
17
  /** Whether the field is disabled */
18
18
  disabled?: boolean;
19
+ /** Whether the field is required */
20
+ required?: boolean;
19
21
  }
20
22
  /**
21
23
  * GeoPointFieldComponent renders latitude and longitude input fields
@@ -1 +1 @@
1
- {"version":3,"file":"GeoPointFieldComponent.d.ts","sourceRoot":"","sources":["../../../../src/components/form/fields/GeoPointFieldComponent.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAExD,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,2BAA2B;IAC1C,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,2DAA2D;IAC3D,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,GAAG,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IACpE,kBAAkB;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;GAMG;AACH,QAAA,MAAM,sBAAsB,EAAE,aAAa,CAAC,2BAA2B,CAoGtE,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
1
+ {"version":3,"file":"GeoPointFieldComponent.d.ts","sourceRoot":"","sources":["../../../../src/components/form/fields/GeoPointFieldComponent.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAExD,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,2BAA2B;IAC1C,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,2DAA2D;IAC3D,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,GAAG,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IACpE,kBAAkB;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;GAMG;AACH,QAAA,MAAM,sBAAsB,EAAE,aAAa,CAAC,2BAA2B,CAsGtE,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
@@ -1 +1 @@
1
- import{jsx as e,jsxs as a}from"react/jsx-runtime";import{Label as l,Input as f,Stack as i}from"@donotdev/components";const p=({label:m,value:n={lat:0,lng:0},onChange:c,error:o,helperText:g,disabled:u})=>{const v=s=>{const t=parseFloat(s.target.value)||0;if(t>=-90&&t<=90){const r={...n,lat:t},d={target:{value:JSON.stringify(r)}};c(d)}},h=s=>{const t=parseFloat(s.target.value)||0;if(t>=-180&&t<=180){const r={...n,lng:t},d={target:{value:JSON.stringify(r)}};c(d)}};return a(i,{gap:"tight",children:[e(l,{style:{display:"block",fontSize:"var(--font-size-sm)",fontWeight:500},children:m}),a(i,{direction:"row",gap:"medium",children:[a(i,{gap:"tight",className:"dndev-w-full",children:[e(l,{style:{fontSize:"var(--font-size-xs)",color:"var(--muted-foreground)"},children:"Latitude"}),e(f,{type:"number",value:n.lat,onChange:v,min:"-90",max:"90",step:"0.000001",disabled:u,"data-variant":o?"destructive":void 0})]}),a(i,{gap:"tight",className:"dndev-w-full",children:[e(l,{style:{fontSize:"var(--font-size-xs)",color:"var(--muted-foreground)"},children:"Longitude"}),e(f,{type:"number",value:n.lng,onChange:h,min:"-180",max:"180",step:"0.000001",disabled:u,"data-variant":o?"destructive":void 0})]})]}),g&&e("p",{style:{fontSize:"var(--font-size-xs)",color:o?"var(--destructive-foreground)":"var(--muted-foreground)",marginTop:"var(--gap-sm)"},children:g})]})};var S=p;export{S as default};
1
+ import{jsx as e,jsxs as a}from"react/jsx-runtime";import{Label as l,Input as f,Stack as i}from"@donotdev/components";const y=({label:m,value:n={lat:0,lng:0},onChange:c,error:o,helperText:g,disabled:u,required:v})=>{const h=r=>{const t=parseFloat(r.target.value)||0;if(t>=-90&&t<=90){const s={...n,lat:t},d={target:{value:JSON.stringify(s)}};c(d)}},p=r=>{const t=parseFloat(r.target.value)||0;if(t>=-180&&t<=180){const s={...n,lng:t},d={target:{value:JSON.stringify(s)}};c(d)}};return a(i,{gap:"tight",children:[e(l,{required:v,style:{display:"block",fontSize:"var(--font-size-sm)",fontWeight:500},children:m}),a(i,{direction:"row",gap:"medium",children:[a(i,{gap:"tight",className:"dndev-w-full",children:[e(l,{style:{fontSize:"var(--font-size-xs)",color:"var(--muted-foreground)"},children:"Latitude"}),e(f,{type:"number",value:n.lat,onChange:h,min:"-90",max:"90",step:"0.000001",disabled:u,"data-variant":o?"destructive":void 0})]}),a(i,{gap:"tight",className:"dndev-w-full",children:[e(l,{style:{fontSize:"var(--font-size-xs)",color:"var(--muted-foreground)"},children:"Longitude"}),e(f,{type:"number",value:n.lng,onChange:p,min:"-180",max:"180",step:"0.000001",disabled:u,"data-variant":o?"destructive":void 0})]})]}),g&&e("p",{style:{fontSize:"var(--font-size-xs)",color:o?"var(--destructive-foreground)":"var(--muted-foreground)",marginTop:"var(--gap-sm)"},children:g})]})};var b=y;export{b as default};
@@ -1,27 +1,42 @@
1
- import { type ChangeEvent, type ComponentType } from 'react';
1
+ import { type ComponentType } from 'react';
2
+ import type { Picture } from '@donotdev/types';
3
+ import { type ImageMetadata } from '../../../utils/imageUtils';
2
4
  export interface ImageFieldComponentProps {
5
+ /** Field name (for upload registration) */
6
+ name?: string;
3
7
  /** Field label */
4
8
  label: string;
5
- /** Current image value */
6
- value?: File | null;
7
- /** Change handler - accepts both event and direct value */
8
- onChange: (file: File | null | ChangeEvent<HTMLInputElement>) => void;
9
+ /** Current value - Picture for single, Picture[] for multiple */
10
+ value?: Picture | Picture[] | null;
11
+ /** Change handler */
12
+ onChange: (value: Picture | Picture[] | null) => void;
9
13
  /** Error state */
10
14
  error?: boolean;
11
15
  /** Helper text */
12
16
  helperText?: string;
13
- /** Maximum file size in bytes */
14
- maxSize?: number;
15
- /** Whether multiple images are allowed */
17
+ /** Multiple images mode */
16
18
  multiple?: boolean;
19
+ /** Maximum number of images (multiple mode only) */
20
+ maxFiles?: number;
21
+ /** Maximum file size in bytes before processing (default: 10MB) */
22
+ maxSize?: number;
23
+ /** Firebase Storage path (default: 'uploads/images') */
24
+ storagePath?: string;
25
+ /** Entity ID for hash deduplication scope (same entity only) */
26
+ entityId?: string;
27
+ /** Whether the field is required */
28
+ required?: boolean;
29
+ /** Translation function */
30
+ t?: (key: string, options?: Record<string, any>) => string;
31
+ }
32
+ export interface ImageFieldComponentRef {
33
+ /** Trigger upload of all pending images */
34
+ upload: () => Promise<void>;
35
+ /** Get current images metadata */
36
+ getImages: () => ImageMetadata[];
17
37
  }
18
- /**
19
- * ImageFieldComponent renders an image upload field with preview
20
- *
21
- * @version 0.0.1
22
- * @since 0.0.1
23
- * @author AMBROISE PARK Consulting
24
- */
25
- declare const ImageFieldComponent: ComponentType<ImageFieldComponentProps>;
26
- export default ImageFieldComponent;
38
+ declare const _default: ComponentType<ImageFieldComponentProps & {
39
+ ref?: React.Ref<ImageFieldComponentRef>;
40
+ }>;
41
+ export default _default;
27
42
  //# sourceMappingURL=ImageFieldComponent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ImageFieldComponent.d.ts","sourceRoot":"","sources":["../../../../src/components/form/fields/ImageFieldComponent.tsx"],"names":[],"mappings":"AAaA,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,aAAa,EACnB,MAAM,OAAO,CAAC;AAWf,MAAM,WAAW,wBAAwB;IACvC,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,KAAK,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACpB,2DAA2D;IAC3D,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IACtE,kBAAkB;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;GAMG;AACH,QAAA,MAAM,mBAAmB,EAAE,aAAa,CAAC,wBAAwB,CAgKhE,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"ImageFieldComponent.d.ts","sourceRoot":"","sources":["../../../../src/components/form/fields/ImageFieldComponent.tsx"],"names":[],"mappings":"AAwBA,OAAO,EAQL,KAAK,aAAa,EAGnB,MAAM,OAAO,CAAC;AAkBf,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAKL,KAAK,aAAa,EAInB,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,wBAAwB;IACvC,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,EAAE,GAAG,IAAI,CAAC;IACnC,qBAAqB;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,EAAE,GAAG,IAAI,KAAK,IAAI,CAAC;IACtD,kBAAkB;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2BAA2B;IAC3B,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC;CAC5D;AAED,MAAM,WAAW,sBAAsB;IACrC,2CAA2C;IAC3C,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,kCAAkC;IAClC,SAAS,EAAE,MAAM,aAAa,EAAE,CAAC;CAClC;wBA+8BqC,aAAa,CACjD,wBAAwB,GAAG;IAAE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAA;CAAE,CACvE;AAFD,wBAEE"}