@donotdev/crud 0.0.9 → 0.0.11

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 (194) hide show
  1. package/dist/CrudService.d.ts +26 -8
  2. package/dist/CrudService.d.ts.map +1 -1
  3. package/dist/CrudService.js +1 -1
  4. package/dist/CrudStore.d.ts.map +1 -1
  5. package/dist/CrudStore.js +1 -1
  6. package/dist/adapters/FirestoreAdapter.d.ts +1 -1
  7. package/dist/adapters/FirestoreAdapter.d.ts.map +1 -1
  8. package/dist/adapters/FirestoreAdapter.js +1 -1
  9. package/dist/adapters/FunctionsAdapter.d.ts +1 -1
  10. package/dist/adapters/FunctionsAdapter.d.ts.map +1 -1
  11. package/dist/adapters/FunctionsAdapter.js +1 -1
  12. package/dist/builtinFieldTypes.d.ts +17 -4
  13. package/dist/builtinFieldTypes.d.ts.map +1 -1
  14. package/dist/builtinFieldTypes.js +1 -1
  15. package/dist/components/DisplayFieldRenderer.d.ts +2 -0
  16. package/dist/components/DisplayFieldRenderer.d.ts.map +1 -1
  17. package/dist/components/DisplayFieldRenderer.js +1 -1
  18. package/dist/components/EntityDisplayRenderer.d.ts +2 -2
  19. package/dist/components/EntityDisplayRenderer.d.ts.map +1 -1
  20. package/dist/components/EntityDisplayRenderer.js +1 -1
  21. package/dist/components/EntityFilters.d.ts +19 -1
  22. package/dist/components/EntityFilters.d.ts.map +1 -1
  23. package/dist/components/EntityFilters.js +1 -1
  24. package/dist/components/FormFieldRenderer.d.ts.map +1 -1
  25. package/dist/components/FormFieldRenderer.js +1 -1
  26. package/dist/components/controlled/input/ControlledCurrencyField.d.ts +8 -0
  27. package/dist/components/controlled/input/ControlledCurrencyField.d.ts.map +1 -0
  28. package/dist/components/controlled/input/ControlledCurrencyField.js +1 -0
  29. package/dist/components/controlled/input/ControlledDurationField.d.ts +7 -0
  30. package/dist/components/controlled/input/ControlledDurationField.d.ts.map +1 -0
  31. package/dist/components/controlled/input/ControlledDurationField.js +1 -0
  32. package/dist/components/controlled/input/ControlledGdprConsentField.d.ts.map +1 -1
  33. package/dist/components/controlled/input/ControlledGdprConsentField.js +1 -1
  34. package/dist/components/controlled/input/ControlledPriceField.d.ts +8 -0
  35. package/dist/components/controlled/input/ControlledPriceField.d.ts.map +1 -0
  36. package/dist/components/controlled/input/ControlledPriceField.js +1 -0
  37. package/dist/components/controlled/input/ControlledRatingField.d.ts +8 -0
  38. package/dist/components/controlled/input/ControlledRatingField.d.ts.map +1 -0
  39. package/dist/components/controlled/input/ControlledRatingField.js +1 -0
  40. package/dist/components/controlled/input/index.d.ts +4 -0
  41. package/dist/components/controlled/input/index.d.ts.map +1 -1
  42. package/dist/components/controlled/input/index.js +1 -1
  43. package/dist/components/controlled/select/ControlledYearField.js +1 -1
  44. package/dist/components/fields/display/AvatarFieldDisplay.d.ts +23 -0
  45. package/dist/components/fields/display/AvatarFieldDisplay.d.ts.map +1 -0
  46. package/dist/components/fields/display/AvatarFieldDisplay.js +1 -0
  47. package/dist/components/fields/display/BadgeFieldDisplay.d.ts +21 -0
  48. package/dist/components/fields/display/BadgeFieldDisplay.d.ts.map +1 -0
  49. package/dist/components/fields/display/BadgeFieldDisplay.js +1 -0
  50. package/dist/components/fields/display/ButtonFieldDisplay.d.ts +29 -0
  51. package/dist/components/fields/display/ButtonFieldDisplay.d.ts.map +1 -0
  52. package/dist/components/fields/display/ButtonFieldDisplay.js +1 -0
  53. package/dist/components/fields/display/CheckboxFieldDisplay.d.ts +21 -0
  54. package/dist/components/fields/display/CheckboxFieldDisplay.d.ts.map +1 -0
  55. package/dist/components/fields/display/CheckboxFieldDisplay.js +1 -0
  56. package/dist/components/fields/display/DateFieldDisplay.d.ts +24 -0
  57. package/dist/components/fields/display/DateFieldDisplay.d.ts.map +1 -0
  58. package/dist/components/fields/display/DateFieldDisplay.js +1 -0
  59. package/dist/components/fields/display/DropdownDisplay.d.ts +21 -0
  60. package/dist/components/fields/display/DropdownDisplay.d.ts.map +1 -0
  61. package/dist/components/fields/display/DropdownDisplay.js +1 -0
  62. package/dist/components/fields/display/FileFieldDisplay.d.ts +21 -0
  63. package/dist/components/fields/display/FileFieldDisplay.d.ts.map +1 -0
  64. package/dist/components/fields/display/FileFieldDisplay.js +1 -0
  65. package/dist/components/fields/display/GeoPointFieldDisplay.d.ts +25 -0
  66. package/dist/components/fields/display/GeoPointFieldDisplay.d.ts.map +1 -0
  67. package/dist/components/fields/display/GeoPointFieldDisplay.js +1 -0
  68. package/dist/components/fields/display/HiddenFieldDisplay.d.ts +30 -0
  69. package/dist/components/fields/display/HiddenFieldDisplay.d.ts.map +1 -0
  70. package/dist/components/fields/display/HiddenFieldDisplay.js +1 -0
  71. package/dist/components/fields/display/ImageFieldDisplay.d.ts +24 -0
  72. package/dist/components/fields/display/ImageFieldDisplay.d.ts.map +1 -0
  73. package/dist/components/fields/display/ImageFieldDisplay.js +1 -0
  74. package/dist/components/fields/display/LinkFieldDisplay.d.ts +22 -0
  75. package/dist/components/fields/display/LinkFieldDisplay.d.ts.map +1 -0
  76. package/dist/components/fields/display/LinkFieldDisplay.js +1 -0
  77. package/dist/components/fields/display/MapFieldDisplay.d.ts +25 -0
  78. package/dist/components/fields/display/MapFieldDisplay.d.ts.map +1 -0
  79. package/dist/components/fields/display/MapFieldDisplay.js +1 -0
  80. package/dist/components/fields/display/MultiDropdownDisplay.d.ts +22 -0
  81. package/dist/components/fields/display/MultiDropdownDisplay.d.ts.map +1 -0
  82. package/dist/components/fields/display/MultiDropdownDisplay.js +1 -0
  83. package/dist/components/fields/display/MultiInputTextFieldDisplay.d.ts +22 -0
  84. package/dist/components/fields/display/MultiInputTextFieldDisplay.d.ts.map +1 -0
  85. package/dist/components/fields/display/MultiInputTextFieldDisplay.js +1 -0
  86. package/dist/components/fields/display/NumberFieldDisplay.d.ts +24 -0
  87. package/dist/components/fields/display/NumberFieldDisplay.d.ts.map +1 -0
  88. package/dist/components/fields/display/NumberFieldDisplay.js +1 -0
  89. package/dist/components/fields/display/PasswordFieldDisplay.d.ts +24 -0
  90. package/dist/components/fields/display/PasswordFieldDisplay.d.ts.map +1 -0
  91. package/dist/components/fields/display/PasswordFieldDisplay.js +1 -0
  92. package/dist/components/fields/display/PhoneNumberDisplay.d.ts +22 -0
  93. package/dist/components/fields/display/PhoneNumberDisplay.d.ts.map +1 -0
  94. package/dist/components/fields/display/PhoneNumberDisplay.js +1 -0
  95. package/dist/components/fields/display/RadioFieldDisplay.d.ts +22 -0
  96. package/dist/components/fields/display/RadioFieldDisplay.d.ts.map +1 -0
  97. package/dist/components/fields/display/RadioFieldDisplay.js +1 -0
  98. package/dist/components/fields/display/RangeFieldDisplay.d.ts +22 -0
  99. package/dist/components/fields/display/RangeFieldDisplay.d.ts.map +1 -0
  100. package/dist/components/fields/display/RangeFieldDisplay.js +1 -0
  101. package/dist/components/fields/display/ReferenceFieldDisplay.d.ts +22 -0
  102. package/dist/components/fields/display/ReferenceFieldDisplay.d.ts.map +1 -0
  103. package/dist/components/fields/display/ReferenceFieldDisplay.js +1 -0
  104. package/dist/components/fields/display/RichTextDisplay.d.ts +25 -0
  105. package/dist/components/fields/display/RichTextDisplay.d.ts.map +1 -0
  106. package/dist/components/fields/display/RichTextDisplay.js +61 -0
  107. package/dist/components/fields/display/TextAreaDisplay.d.ts +22 -0
  108. package/dist/components/fields/display/TextAreaDisplay.d.ts.map +1 -0
  109. package/dist/components/fields/display/TextAreaDisplay.js +1 -0
  110. package/dist/components/fields/display/TextFieldDisplay.d.ts +42 -0
  111. package/dist/components/fields/display/TextFieldDisplay.d.ts.map +1 -0
  112. package/dist/components/fields/display/TextFieldDisplay.js +1 -0
  113. package/dist/components/fields/display/TimestampFieldDisplay.d.ts +22 -0
  114. package/dist/components/fields/display/TimestampFieldDisplay.d.ts.map +1 -0
  115. package/dist/components/fields/display/TimestampFieldDisplay.js +1 -0
  116. package/dist/components/fields/display/index.d.ts +32 -0
  117. package/dist/components/fields/display/index.d.ts.map +1 -0
  118. package/dist/components/fields/display/index.js +1 -0
  119. package/dist/components/form/fields/ComboboxComponent.d.ts +6 -0
  120. package/dist/components/form/fields/ComboboxComponent.d.ts.map +1 -1
  121. package/dist/components/form/fields/ComboboxComponent.js +1 -1
  122. package/dist/components/form/fields/DurationFieldComponent.d.ts +42 -0
  123. package/dist/components/form/fields/DurationFieldComponent.d.ts.map +1 -0
  124. package/dist/components/form/fields/DurationFieldComponent.js +1 -0
  125. package/dist/components/form/fields/GdprConsentFieldComponent.d.ts +2 -2
  126. package/dist/components/form/fields/GdprConsentFieldComponent.d.ts.map +1 -1
  127. package/dist/components/form/fields/GdprConsentFieldComponent.js +1 -1
  128. package/dist/components/form/fields/PriceFieldComponent.d.ts +34 -0
  129. package/dist/components/form/fields/PriceFieldComponent.d.ts.map +1 -0
  130. package/dist/components/form/fields/PriceFieldComponent.js +1 -0
  131. package/dist/components/form/fields/RatingFieldComponent.d.ts +37 -0
  132. package/dist/components/form/fields/RatingFieldComponent.d.ts.map +1 -0
  133. package/dist/components/form/fields/RatingFieldComponent.js +1 -0
  134. package/dist/components/form/fields/index.d.ts +7 -0
  135. package/dist/components/form/fields/index.d.ts.map +1 -1
  136. package/dist/components/form/fields/index.js +1 -1
  137. package/dist/components/index.d.ts +3 -9
  138. package/dist/components/index.d.ts.map +1 -1
  139. package/dist/components/index.js +1 -1
  140. package/dist/fieldTypeRegistry.d.ts +92 -0
  141. package/dist/fieldTypeRegistry.d.ts.map +1 -0
  142. package/dist/fieldTypeRegistry.js +1 -0
  143. package/dist/forms/hooks/useEntityForm.d.ts.map +1 -1
  144. package/dist/forms/hooks/useEntityForm.js +1 -1
  145. package/dist/forms/types.d.ts +5 -3
  146. package/dist/forms/types.d.ts.map +1 -1
  147. package/dist/forms/utils/getFieldsForOperation.d.ts +2 -3
  148. package/dist/forms/utils/getFieldsForOperation.d.ts.map +1 -1
  149. package/dist/forms/utils/getFieldsForOperation.js +1 -1
  150. package/dist/forms/utils/isFieldEditable.d.ts +1 -1
  151. package/dist/forms/utils/isFieldEditable.d.ts.map +1 -1
  152. package/dist/hooks/index.d.ts +5 -0
  153. package/dist/hooks/index.d.ts.map +1 -1
  154. package/dist/hooks/index.js +1 -1
  155. package/dist/hooks/useEntityFavorites.d.ts +53 -0
  156. package/dist/hooks/useEntityFavorites.d.ts.map +1 -0
  157. package/dist/hooks/useEntityFavorites.js +1 -0
  158. package/dist/hooks/useRelatedItems.d.ts +37 -0
  159. package/dist/hooks/useRelatedItems.d.ts.map +1 -0
  160. package/dist/hooks/useRelatedItems.js +1 -0
  161. package/dist/index.d.ts +4 -3
  162. package/dist/index.d.ts.map +1 -1
  163. package/dist/index.js +1 -1
  164. package/dist/registerBuiltinFieldTypes.d.ts +6 -0
  165. package/dist/registerBuiltinFieldTypes.d.ts.map +1 -0
  166. package/dist/registerBuiltinFieldTypes.js +1 -0
  167. package/dist/tsconfig.tsbuildinfo +1 -1
  168. package/dist/types.d.ts +60 -25
  169. package/dist/types.d.ts.map +1 -1
  170. package/dist/useBaseCrudList.d.ts +53 -0
  171. package/dist/useBaseCrudList.d.ts.map +1 -0
  172. package/dist/useBaseCrudList.js +1 -0
  173. package/dist/useCrud.d.ts +3 -6
  174. package/dist/useCrud.d.ts.map +1 -1
  175. package/dist/useCrud.js +1 -1
  176. package/dist/useCrudCardList.d.ts +10 -4
  177. package/dist/useCrudCardList.d.ts.map +1 -1
  178. package/dist/useCrudCardList.js +1 -1
  179. package/dist/useCrudList.d.ts +12 -5
  180. package/dist/useCrudList.d.ts.map +1 -1
  181. package/dist/useCrudList.js +1 -1
  182. package/dist/utils/mergeWithOptimistic.d.ts +4 -5
  183. package/dist/utils/mergeWithOptimistic.d.ts.map +1 -1
  184. package/dist/utils/mergeWithOptimistic.js +1 -1
  185. package/dist/utils/scopeUtils.d.ts +38 -0
  186. package/dist/utils/scopeUtils.d.ts.map +1 -0
  187. package/dist/utils/scopeUtils.js +1 -0
  188. package/package.json +15 -14
  189. package/dist/components/EntityCardList.d.ts +0 -29
  190. package/dist/components/EntityCardList.d.ts.map +0 -1
  191. package/dist/components/EntityCardList.js +0 -1
  192. package/dist/components/EntityList.d.ts +0 -30
  193. package/dist/components/EntityList.d.ts.map +0 -1
  194. package/dist/components/EntityList.js +0 -1
@@ -1,5 +1,5 @@
1
1
  import type { dndevSchema, QueryClient } from '@donotdev/core';
2
- import type { BackendType, CrudStoreApi, CrudServiceInterface, CacheOptions } from './types';
2
+ import type { BackendType, CrudStoreApi, CrudServiceInterface, CacheOptions, MutationOptions } from './types';
3
3
  import type { QueryOptions } from './adapters/FirestoreAdapter';
4
4
  import type { PaginatedQueryResult } from './adapters/FunctionsAdapter';
5
5
  export type { QueryOptions, CacheOptions };
@@ -14,6 +14,13 @@ declare class CrudService implements CrudServiceInterface {
14
14
  private adapter;
15
15
  private backend;
16
16
  private store;
17
+ /**
18
+ * Determine if success toast should be shown based on per-call options and global setting
19
+ * - options.showSuccessToast=true → always show
20
+ * - options.showSuccessToast=false → never show
21
+ * - options.showSuccessToast=undefined → use global !hideSuccessToasts
22
+ */
23
+ private _shouldShowSuccessToast;
17
24
  setStore(store: CrudStoreApi): void;
18
25
  initialize(backend: BackendType): Promise<void>;
19
26
  /**
@@ -51,6 +58,11 @@ declare class CrudService implements CrudServiceInterface {
51
58
  * Automatically syncs both list and document caches for consistency.
52
59
  */
53
60
  private _updateListCaches;
61
+ /**
62
+ * Get an item from any list cache for this collection.
63
+ * Used to get previous data for optimistic operations when individual GET cache is empty.
64
+ */
65
+ private _getItemFromListCache;
54
66
  /**
55
67
  * Invalidate all cached queries for a collection
56
68
  */
@@ -61,19 +73,25 @@ declare class CrudService implements CrudServiceInterface {
61
73
  query<T>(collection: string, options: QueryOptions, schema: dndevSchema<T>, cacheOptions?: CacheOptions, schemaType?: 'list' | 'listCard'): Promise<PaginatedQueryResult<T>>;
62
74
  /** Internal: query from adapter with store updates */
63
75
  private _queryFromAdapter;
64
- set<T>(collection: string, id: string, data: T, schema: dndevSchema<T>): Promise<void>;
65
- update<T>(collection: string, id: string, data: Partial<T>): Promise<void>;
66
- delete(collection: string, id: string): Promise<void>;
67
- add<T>(collection: string, data: T, schema: dndevSchema<T>): Promise<string>;
76
+ /**
77
+ * Helper to get translated entity name from collection
78
+ * Tries entity-{collection}:name and entity-{singular}:name patterns
79
+ * Falls back to collection name if translation not found
80
+ */
81
+ private _getEntityName;
82
+ set<T>(collection: string, id: string, data: T, schema: dndevSchema<T>, options?: MutationOptions): Promise<void>;
83
+ update<T>(collection: string, id: string, data: Partial<T>, options?: MutationOptions): Promise<void>;
84
+ delete(collection: string, id: string, options?: MutationOptions): Promise<void>;
85
+ add<T>(collection: string, data: T, schema: dndevSchema<T>, options?: MutationOptions): Promise<string>;
68
86
  subscribe<T>(collection: string, id: string, callback: (data: T | null, error?: Error) => void, schema: dndevSchema<T>): () => void;
69
87
  subscribeToCollection<T>(collection: string, options: QueryOptions, callback: (data: T[], error?: Error) => void, schema: dndevSchema<T>): () => void;
70
88
  addOptimistic<T extends {
71
89
  id?: string;
72
- }>(collection: string, data: T, schema: dndevSchema<T>): Promise<T & {
90
+ }>(collection: string, data: T, schema: dndevSchema<T>, options?: MutationOptions): Promise<T & {
73
91
  id: string;
74
92
  }>;
75
- updateOptimistic<T>(collection: string, id: string, data: Partial<T>, schema: dndevSchema<T>): Promise<T>;
76
- deleteOptimistic(collection: string, id: string): Promise<void>;
93
+ updateOptimistic<T>(collection: string, id: string, data: Partial<T>, schema: dndevSchema<T>, options?: MutationOptions): Promise<T>;
94
+ deleteOptimistic(collection: string, id: string, options?: MutationOptions): Promise<void>;
77
95
  }
78
96
  /**
79
97
  * Get or create CrudService singleton instance
@@ -1 +1 @@
1
- {"version":3,"file":"CrudService.d.ts","sourceRoot":"","sources":["../src/CrudService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CrudService.d.ts","sourceRoot":"","sources":["../src/CrudService.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- import{toast as f}from"@donotdev/components";import{createSingleton as g,handleError as o,getQueryClient as y}from"@donotdev/core";import{FirestoreAdapter as w}from"./adapters/FirestoreAdapter";import{FunctionsAdapter as S}from"./adapters/FunctionsAdapter";const n=1/0,A=1e3*60*30;class m{adapter=null;backend=null;store=null;setStore(t){this.store=t}async initialize(t){if(!(this.backend===t&&this.adapter)){if(this.backend=t,t==="functions")this.adapter=new S;else if(t==="firestore")this.adapter=new w;else throw new Error(`Unknown backend: ${t}`);this.store&&(this.store.getState().setBackend(t),this.store.getState().setCrudService(this))}}getQueryClient(){return y()}getListQueryOptions(t,e,s,i,r="list"){const a=this.adapter,h=()=>this.initialize("firestore");return{queryKey:["crud",t,"query",r,JSON.stringify(e)],queryFn:async()=>{if(a||await h(),!this.adapter)throw new Error("Adapter not initialized");return this.adapter.query(t,e,s)},staleTime:i?.staleTime??n}}getDocQueryOptions(t,e,s,i){const r=this.adapter,a=()=>this.initialize("firestore");return{queryKey:["crud",t,"get",e],queryFn:async()=>{if(r||await a(),!this.adapter)throw new Error("Adapter not initialized");return this.adapter.get(t,e,s)},staleTime:i?.staleTime??n}}_updateGetCache(t,e,s,i){const r=this.getQueryClient(),a=["crud",t,"get",e];i==="delete"?r.removeQueries({queryKey:a}):(i==="update"||i==="add")&&s&&r.setQueryData(a,h=>h?{...h,...s}:s)}_updateListCaches(t,e,s,i){const r=this.getQueryClient();this._updateGetCache(t,e,s,i),r.setQueriesData({queryKey:["crud",t]},a=>Array.isArray(a)?i==="delete"?a.filter(h=>h.id!==e):i==="add"&&s?[...a,{...s,id:e}]:i==="update"&&s&&a.some(u=>u.id===e)?a.map(u=>u.id===e?{...u,...s}:u):a:a)}async invalidateCollection(t){await this.getQueryClient().invalidateQueries({queryKey:["crud",t]})}async get(t,e,s,i){if(this.adapter||await this.initialize("firestore"),i?.noCache)return this._getFromAdapter(t,e,s);this.store&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));try{return await this.getQueryClient().fetchQuery({queryKey:["crud",t,"get",e],queryFn:()=>this._getFromAdapter(t,e,s,!1),staleTime:i?.staleTime??n})}catch(r){const a=o(r,{userMessage:`Failed to fetch ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,a),a}finally{this.store&&this.store.getState().setLoading(t,!1)}}async _getFromAdapter(t,e,s,i=!0){this.store&&i&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));try{if(!this.adapter)throw new Error("Adapter not initialized");const r=await this.adapter.get(t,e,s);return this.store&&r&&this.store.getState().setData(t,e,r),r}catch(r){const a=o(r,{userMessage:`Failed to fetch ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,a),a}finally{this.store&&i&&this.store.getState().setLoading(t,!1)}}async query(t,e,s,i,r="list"){if(this.adapter||await this.initialize("firestore"),i?.noCache)return this._queryFromAdapter(t,e,s);this.store&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));try{const h=await this.getQueryClient().fetchQuery({queryKey:["crud",t,"query",r,JSON.stringify(e)],queryFn:()=>this._queryFromAdapter(t,e,s,!1),staleTime:i?.staleTime??n});if(this.store&&h.items){const u=[];for(const d of h.items){const p=d;p.id&&u.push({id:p.id,data:d})}u.length>0&&this.store.getState().setDataBatch(t,u)}return h}catch(a){const h=o(a,{userMessage:`Failed to query ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,h),h}finally{this.store&&this.store.getState().setLoading(t,!1)}}async _queryFromAdapter(t,e,s,i=!0){this.store&&i&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));try{if(!this.adapter)throw new Error("Adapter not initialized");return await this.adapter.query(t,e,s)}catch(r){const a=o(r,{userMessage:`Failed to query ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,a),a}finally{this.store&&i&&this.store.getState().setLoading(t,!1)}}async set(t,e,s,i){this.adapter||await this.initialize("firestore"),this.store&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));const r=this.store?.getState().getData(t,e);this.store&&this.store.getState().updateOptimistic(t,e,s,r);try{if(!this.adapter)throw new Error("Adapter not initialized");await this.adapter.set(t,e,s,i),this.store&&(this.store.getState().confirmUpdate(t,e),this.store.getState().setData(t,e,s)),this._updateListCaches(t,e,s,"update"),f("success",`${t} saved successfully`)}catch(a){this.store&&this.store.getState().rejectUpdate(t,e);const h=o(a,{userMessage:`Failed to save ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,h),h}finally{this.store&&this.store.getState().setLoading(t,!1)}}async update(t,e,s){this.adapter||await this.initialize("firestore"),this.store&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));let i=null;this.store&&(i=this.store.getState().getData(t,e));const r=i?{...i,...s}:{...s,id:e};this.store&&i&&this.store.getState().updateOptimistic(t,e,r,i);try{if(!this.adapter)throw new Error("Adapter not initialized");await this.adapter.update(t,e,s),this.store&&(this.store.getState().confirmUpdate(t,e),this.store.getState().setData(t,e,r)),this._updateListCaches(t,e,r,"update"),f("success",`${t} updated successfully`)}catch(a){this.store&&this.store.getState().rejectUpdate(t,e);const h=o(a,{userMessage:`Failed to update ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,h),h}finally{this.store&&this.store.getState().setLoading(t,!1)}}async delete(t,e){this.adapter||await this.initialize("firestore"),this.store&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));const s=this.store?.getState().getData(t,e);this.store&&s&&this.store.getState().deleteOptimistic(t,e,s);try{if(!this.adapter)throw new Error("Adapter not initialized");await this.adapter.delete(t,e),this.store&&this.store.getState().confirmDelete(t,e),this._updateListCaches(t,e,null,"delete"),f("success",`${t} deleted successfully`)}catch(i){this.store&&this.store.getState().rejectDelete(t,e);const r=o(i,{userMessage:`Failed to delete ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,r),r}finally{this.store&&this.store.getState().setLoading(t,!1)}}async add(t,e,s){this.adapter||await this.initialize("firestore"),this.store&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));const i=`temp_${crypto.randomUUID()}`;this.store&&this.store.getState().addOptimistic(t,i,{...e,id:i});try{if(!this.adapter)throw new Error("Adapter not initialized");const r=await this.adapter.add(t,e,s);return this.store&&this.store.getState().confirmOptimistic(t,i,r,{...e,id:r}),this._updateListCaches(t,r,{...e,id:r},"add"),f("success",`${t} created successfully`),r}catch(r){this.store&&this.store.getState().rejectOptimistic(t,i);const a=o(r,{userMessage:`Failed to create ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,a),a}finally{this.store&&this.store.getState().setLoading(t,!1)}}subscribe(t,e,s,i){this.adapter||this.initialize("firestore").catch(()=>{});try{return this.adapter?this.adapter.subscribe(t,e,(r,a)=>{r&&this.store&&this.store.getState().setData(t,e,r),r&&this.getQueryClient().setQueryData(["crud",t,"get",e],r),s(r,a)},i):(s(null,new Error("Adapter not initialized")),()=>{})}catch(r){return s(null,o(r)),()=>{}}}subscribeToCollection(t,e,s,i){this.adapter||this.initialize("firestore").catch(()=>{});try{return this.adapter?this.adapter.subscribeToCollection(t,e,(r,a)=>{if(r&&this.store){const h=[];for(const u of r){const d=u;d.id&&h.push({id:d.id,data:u})}h.length>0&&this.store.getState().setDataBatch(t,h)}r&&this.getQueryClient().setQueryData(["crud",t,"query",JSON.stringify(e)],r),s(r,a)},i):(s([],new Error("Adapter not initialized")),()=>{})}catch(r){return s([],o(r)),()=>{}}}async addOptimistic(t,e,s){this.adapter||await this.initialize("firestore");const i=`temp_${crypto.randomUUID()}`,r={...e,id:i,_optimistic:!0};this.store&&this.store.getState().addOptimistic(t,i,r);try{if(!this.adapter)throw new Error("Adapter not initialized");const a=await this.adapter.add(t,e,s),h={...e,id:a};return this.store&&this.store.getState().confirmOptimistic(t,i,a,h),this._updateListCaches(t,a,h,"add"),f("success",`${t} created successfully`),h}catch(a){throw this.store&&this.store.getState().rejectOptimistic(t,i),o(a,{userMessage:`Failed to create ${t}`,showNotification:!0})}}async updateOptimistic(t,e,s,i){this.adapter||await this.initialize("firestore");let r=null;this.store&&(r=this.store.getState().getData(t,e));const a=r?{...r,...s,_optimistic:!0}:{...s,id:e,_optimistic:!0};this.store&&r&&this.store.getState().updateOptimistic(t,e,a,r);try{if(!this.adapter)throw new Error("Adapter not initialized");return await this.adapter.update(t,e,s),this.store&&(this.store.getState().confirmUpdate(t,e),this.store.getState().setData(t,e,{...a,_optimistic:void 0})),this._updateListCaches(t,e,a,"update"),f("success",`${t} updated successfully`),a}catch(h){throw this.store&&this.store.getState().rejectUpdate(t,e),o(h,{userMessage:`Failed to update ${t}`,showNotification:!0})}}async deleteOptimistic(t,e){this.adapter||await this.initialize("firestore");let s=null;this.store&&(s=this.store.getState().getData(t,e)),this.store&&s&&this.store.getState().deleteOptimistic(t,e,s);try{if(!this.adapter)throw new Error("Adapter not initialized");await this.adapter.delete(t,e),this.store&&this.store.getState().confirmDelete(t,e),this._updateListCaches(t,e,null,"delete"),f("success",`${t} deleted successfully`)}catch(i){throw this.store&&this.store.getState().rejectDelete(t,e),o(i,{userMessage:`Failed to delete ${t}`,showNotification:!0})}}}const F=g(()=>new m);export{F as getCrudService};
1
+ import{toast as p}from"@donotdev/components";import{createSingleton as m,handleError as d,getQueryClient as w,getI18nInstance as f}from"@donotdev/core";import{FirestoreAdapter as S}from"./adapters/FirestoreAdapter";import{FunctionsAdapter as C}from"./adapters/FunctionsAdapter";const g=1/0,Q=1e3*60*30;class c{adapter=null;backend=null;store=null;_shouldShowSuccessToast(t){return t?.showSuccessToast===!0?!0:t?.showSuccessToast===!1?!1:!this.store?.getState().hideSuccessToasts}setStore(t){this.store=t}async initialize(t){if(!(this.backend===t&&this.adapter)){if(this.backend=t,t==="functions")this.adapter=new C;else if(t==="firestore")this.adapter=new S;else throw new Error(`Unknown backend: ${t}`);this.store&&(this.store.getState().setBackend(t),this.store.getState().setCrudService(this))}}getQueryClient(){return w()}getListQueryOptions(t,e,i,h,s="list"){const r=this.adapter,a=()=>this.initialize("firestore");return{queryKey:["crud",t,"query",s,JSON.stringify(e)],queryFn:async()=>{if(r||await a(),!this.adapter)throw new Error("Adapter not initialized");return this.adapter.query(t,e,i,s)},staleTime:h?.staleTime??g}}getDocQueryOptions(t,e,i,h){const s=this.adapter,r=()=>this.initialize("firestore");return{queryKey:["crud",t,"get",e],queryFn:async()=>{if(s||await r(),!this.adapter)throw new Error("Adapter not initialized");return this.adapter.get(t,e,i)},staleTime:h?.staleTime??g}}_updateGetCache(t,e,i,h){const s=this.getQueryClient(),r=["crud",t,"get",e];h==="delete"?s.removeQueries({queryKey:r}):(h==="update"||h==="add")&&i&&s.setQueryData(r,a=>a?{...a,...i}:i)}_updateListCaches(t,e,i,h){const s=this.getQueryClient();this._updateGetCache(t,e,i,h),s.setQueriesData({queryKey:["crud",t]},r=>{if(r&&typeof r=="object"&&"items"in r){const a=r;let u=a.items;return h==="delete"?(u=a.items.filter(n=>n.id!==e),{...a,items:u,total:(a.total??u.length)-1}):h==="add"&&i?(u=[...a.items,{...i,id:e}],{...a,items:u,total:(a.total??a.items.length)+1}):h==="update"&&i&&a.items.some(o=>o.id===e)?(u=a.items.map(o=>o.id===e?{...o,...i}:o),{...a,items:u}):r}if(Array.isArray(r)){if(h==="delete")return r.filter(a=>a.id!==e);if(h==="add"&&i)return[...r,{...i,id:e}];if(h==="update"&&i)return r.some(u=>u.id===e)?r.map(u=>u.id===e?{...u,...i}:u):r}return r})}_getItemFromListCache(t,e){const h=this.getQueryClient().getQueriesData({queryKey:["crud",t]});for(const[,s]of h)if(s?.items){const r=s.items.find(a=>a.id===e);if(r)return r}return null}async invalidateCollection(t){await this.getQueryClient().invalidateQueries({queryKey:["crud",t]})}async get(t,e,i,h){if(this.adapter||await this.initialize("firestore"),h?.noCache)return this._getFromAdapter(t,e,i);this.store&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));try{return await this.getQueryClient().fetchQuery({queryKey:["crud",t,"get",e],queryFn:()=>this._getFromAdapter(t,e,i,!1),staleTime:h?.staleTime??g})}catch(s){const r=d(s,{userMessage:`Failed to fetch ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,r),r}finally{this.store&&this.store.getState().setLoading(t,!1)}}async _getFromAdapter(t,e,i,h=!0){this.store&&h&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));try{if(!this.adapter)throw new Error("Adapter not initialized");return await this.adapter.get(t,e,i)}catch(s){const r=d(s,{userMessage:`Failed to fetch ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,r),r}finally{this.store&&h&&this.store.getState().setLoading(t,!1)}}async query(t,e,i,h,s="list"){if(this.adapter||await this.initialize("firestore"),h?.noCache)return this._queryFromAdapter(t,e,i,!0,s);this.store&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));try{return await this.getQueryClient().fetchQuery({queryKey:["crud",t,"query",s,JSON.stringify(e)],queryFn:()=>this._queryFromAdapter(t,e,i,!1,s),staleTime:h?.staleTime??g})}catch(r){const a=d(r,{userMessage:`Failed to query ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,a),a}finally{this.store&&this.store.getState().setLoading(t,!1)}}async _queryFromAdapter(t,e,i,h=!0,s="list"){this.store&&h&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));try{if(!this.adapter)throw new Error("Adapter not initialized");return await this.adapter.query(t,e,i,s)}catch(r){const a=d(r,{userMessage:`Failed to query ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,a),a}finally{this.store&&h&&this.store.getState().setLoading(t,!1)}}_getEntityName(t){const e=f();let i=`entity-${t}`,h=e.t("name",{ns:i,defaultValue:null});return h&&h!=="name"&&h!==`${i}:name`||t.endsWith("s")&&t.length>1&&(i=`entity-${t.slice(0,-1)}`,h=e.t("name",{ns:i,defaultValue:null}),h&&h!=="name"&&h!==`${i}:name`)?h:t}async set(t,e,i,h,s){this.adapter||await this.initialize("firestore"),this.store&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));const a=this.getQueryClient().getQueryData(["crud",t,"get",e])??null;this.store&&this.store.getState().updateOptimistic(t,e,i,a);try{if(!this.adapter)throw new Error("Adapter not initialized");if(await this.adapter.set(t,e,i,h),this._updateListCaches(t,e,i,"update"),this.store&&this.store.getState().confirmUpdate(t,e),this._shouldShowSuccessToast(s)){const u=f(),n=this._getEntityName(t);p("success",u.t("messages.updateSuccess",{ns:"crud",entity:n}))}}catch(u){a&&this._updateListCaches(t,e,a,"update"),this.store&&this.store.getState().rejectUpdate(t,e);const n=d(u,{userMessage:`Failed to save ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,n),n}finally{this.store&&this.store.getState().setLoading(t,!1)}}async update(t,e,i,h){this.adapter||await this.initialize("firestore"),this.store&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));const r=this.getQueryClient().getQueryData(["crud",t,"get",e])??this._getItemFromListCache(t,e),a=r?{...r,...i}:{...i,id:e};this.store&&r&&this.store.getState().updateOptimistic(t,e,a,r);try{if(!this.adapter)throw new Error("Adapter not initialized");if(await this.adapter.update(t,e,i),this._updateListCaches(t,e,a,"update"),this.store&&this.store.getState().confirmUpdate(t,e),this._shouldShowSuccessToast(h)){const u=f(),n=this._getEntityName(t);p("success",u.t("messages.updateSuccess",{ns:"crud",entity:n}))}}catch(u){r&&this._updateListCaches(t,e,r,"update"),this.store&&this.store.getState().rejectUpdate(t,e);const n=d(u,{userMessage:`Failed to update ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,n),n}finally{this.store&&this.store.getState().setLoading(t,!1)}}async delete(t,e,i){this.adapter||await this.initialize("firestore"),this.store&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));const s=this.getQueryClient().getQueryData(["crud",t,"get",e])??this._getItemFromListCache(t,e);this.store&&s&&this.store.getState().deleteOptimistic(t,e,s);try{if(!this.adapter)throw new Error("Adapter not initialized");if(await this.adapter.delete(t,e),this._updateListCaches(t,e,null,"delete"),this.store&&this.store.getState().confirmDelete(t,e),this._shouldShowSuccessToast(i)){const r=f(),a=this._getEntityName(t);p("success",r.t("messages.deleteSuccess",{ns:"crud",entity:a}))}}catch(r){s&&this._updateListCaches(t,e,s,"add"),this.store&&this.store.getState().rejectDelete(t,e);const a=d(r,{userMessage:`Failed to delete ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,a),a}finally{this.store&&this.store.getState().setLoading(t,!1)}}async add(t,e,i,h){this.adapter||await this.initialize("firestore"),this.store&&(this.store.getState().setLoading(t,!0),this.store.getState().setError(t,null));const s=`temp_${crypto.randomUUID()}`;this.store&&this.store.getState().addOptimistic(t,s,{...e,id:s});try{if(!this.adapter)throw new Error("Adapter not initialized");const r=await this.adapter.add(t,e,i);if(this._updateListCaches(t,s,null,"delete"),this._updateListCaches(t,r,{...e,id:r},"add"),this.store&&this.store.getState().confirmOptimistic(t,s,r,{...e,id:r}),this._shouldShowSuccessToast(h)){const a=f(),u=this._getEntityName(t);p("success",a.t("messages.createSuccess",{ns:"crud",entity:u}))}return r}catch(r){this._updateListCaches(t,s,null,"delete"),this.store&&this.store.getState().rejectOptimistic(t,s);const a=d(r,{userMessage:`Failed to create ${t}`,showNotification:!0});throw this.store&&this.store.getState().setError(t,a),a}finally{this.store&&this.store.getState().setLoading(t,!1)}}subscribe(t,e,i,h){this.adapter||this.initialize("firestore").catch(()=>{});try{return this.adapter?this.adapter.subscribe(t,e,(s,r)=>{s&&this.getQueryClient().setQueryData(["crud",t,"get",e],s),i(s,r)},h):(i(null,new Error("Adapter not initialized")),()=>{})}catch(s){return i(null,d(s)),()=>{}}}subscribeToCollection(t,e,i,h){this.adapter||this.initialize("firestore").catch(()=>{});try{return this.adapter?this.adapter.subscribeToCollection(t,e,(s,r)=>{s&&this.getQueryClient().setQueryData(["crud",t,"query",JSON.stringify(e)],{items:s}),i(s,r)},h):(i([],new Error("Adapter not initialized")),()=>{})}catch(s){return i([],d(s)),()=>{}}}async addOptimistic(t,e,i,h){this.adapter||await this.initialize("firestore");const s=`temp_${crypto.randomUUID()}`,r={...e,id:s,_optimistic:!0};this.store&&this.store.getState().addOptimistic(t,s,r);try{if(!this.adapter)throw new Error("Adapter not initialized");const a=await this.adapter.add(t,e,i),u={...e,id:a};if(this._updateListCaches(t,s,null,"delete"),this._updateListCaches(t,a,u,"add"),this.store&&this.store.getState().confirmOptimistic(t,s,a,u),this._shouldShowSuccessToast(h)){const n=f(),o=this._getEntityName(t);p("success",n.t("messages.createSuccess",{ns:"crud",entity:o}))}return u}catch(a){throw this._updateListCaches(t,s,null,"delete"),this.store&&this.store.getState().rejectOptimistic(t,s),d(a,{userMessage:`Failed to create ${t}`,showNotification:!0})}}async updateOptimistic(t,e,i,h,s){this.adapter||await this.initialize("firestore");const a=this.getQueryClient().getQueryData(["crud",t,"get",e])??this._getItemFromListCache(t,e),u=a?{...a,...i,_optimistic:!0}:{...i,id:e,_optimistic:!0};this.store&&a&&this.store.getState().updateOptimistic(t,e,u,a);try{if(!this.adapter)throw new Error("Adapter not initialized");await this.adapter.update(t,e,i);const n={...u,_optimistic:void 0};if(this._updateListCaches(t,e,n,"update"),this.store&&this.store.getState().confirmUpdate(t,e),this._shouldShowSuccessToast(s)){const o=f(),y=this._getEntityName(t);p("success",o.t("messages.updateSuccess",{ns:"crud",entity:y}))}return n}catch(n){throw a&&this._updateListCaches(t,e,a,"update"),this.store&&this.store.getState().rejectUpdate(t,e),d(n,{userMessage:`Failed to update ${t}`,showNotification:!0})}}async deleteOptimistic(t,e,i){this.adapter||await this.initialize("firestore");const s=this.getQueryClient().getQueryData(["crud",t,"get",e])??this._getItemFromListCache(t,e);this.store&&s&&this.store.getState().deleteOptimistic(t,e,s);try{if(!this.adapter)throw new Error("Adapter not initialized");if(await this.adapter.delete(t,e),this._updateListCaches(t,e,null,"delete"),this.store&&this.store.getState().confirmDelete(t,e),this._shouldShowSuccessToast(i)){const r=f(),a=this._getEntityName(t);p("success",r.t("messages.deleteSuccess",{ns:"crud",entity:a}))}}catch(r){throw s&&this._updateListCaches(t,e,s,"add"),this.store&&this.store.getState().rejectDelete(t,e),d(r,{userMessage:`Failed to delete ${t}`,showNotification:!0})}}}const N=m(()=>new c);export{N as getCrudService};
@@ -1 +1 @@
1
- {"version":3,"file":"CrudStore.d.ts","sourceRoot":"","sources":["../src/CrudStore.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAIV,SAAS,EACT,WAAW,EAEZ,MAAM,SAAS,CAAC;AAQjB;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,iIAoevB,CAAC"}
1
+ {"version":3,"file":"CrudStore.d.ts","sourceRoot":"","sources":["../src/CrudStore.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAGV,SAAS,EACT,WAAW,EAIZ,MAAM,SAAS,CAAC;AA0BjB;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,iIAqZvB,CAAC"}
package/dist/CrudStore.js CHANGED
@@ -1 +1 @@
1
- import{createDoNotDevStore as d}from"@donotdev/core";const m={backend:null,crudService:null,collections:{}},D=d({name:"crud-store",createStore:(l,r)=>({...m,setCrudService:t=>{l({crudService:t})},setBackend:t=>{l({backend:t})},setLoading:(t,i)=>{l(c=>{const o=c.collections[t]||{loading:!1,error:null,data:{},lastUpdated:0,optimistic:{}};return{collections:{...c.collections,[t]:{...o,loading:i}}}})},setError:(t,i)=>{l(c=>{const o=c.collections[t]||{loading:!1,error:null,data:{},lastUpdated:0,optimistic:{}};return{collections:{...c.collections,[t]:{...o,error:i,loading:!1}}}})},setData:(t,i,c)=>{l(o=>{const n=o.collections[t]||{loading:!1,error:null,data:{},lastUpdated:0,optimistic:{}};return{collections:{...o.collections,[t]:{...n,data:{...n.data,[i]:c},lastUpdated:Date.now(),error:null}}}})},setDataBatch:(t,i)=>{i.length!==0&&l(c=>{const o=c.collections[t]||{loading:!1,error:null,data:{},lastUpdated:0,optimistic:{}},n={...o.data};for(const{id:e,data:a}of i)n[e]=a;return{collections:{...c.collections,[t]:{...o,data:n,lastUpdated:Date.now(),error:null}}}})},removeData:(t,i)=>{l(c=>{const o=c.collections[t];if(!o)return c;const{[i]:n,...e}=o.data;return{collections:{...c.collections,[t]:{...o,data:e,lastUpdated:Date.now()}}}})},clearCollection:t=>{l(i=>{const{[t]:c,...o}=i.collections;return{collections:o}})},clearError:t=>{l(i=>{const c=i.collections[t];return c?{collections:{...i.collections,[t]:{...c,error:null}}}:i})},addOptimistic:(t,i,c)=>{l(o=>{const n=o.collections[t]||{loading:!1,error:null,data:{},lastUpdated:0,optimistic:{}};return{collections:{...o.collections,[t]:{...n,data:{...n.data,[i]:c},optimistic:{...n.optimistic,[i]:{tempId:i,originalData:null,status:"pending",operation:"add"}},lastUpdated:Date.now()}}}})},confirmOptimistic:(t,i,c,o)=>{l(n=>{const e=n.collections[t];if(!e)return n;const{[i]:a,...s}=e.data,{[i]:u,...p}=e.optimistic;return{collections:{...n.collections,[t]:{...e,data:{...s,[c]:o},optimistic:p,lastUpdated:Date.now()}}}})},rejectOptimistic:(t,i)=>{l(c=>{const o=c.collections[t];if(!o)return c;const{[i]:n,...e}=o.data,{[i]:a,...s}=o.optimistic;return{collections:{...c.collections,[t]:{...o,data:e,optimistic:s,lastUpdated:Date.now()}}}})},updateOptimistic:(t,i,c,o)=>{l(n=>{const e=n.collections[t]||{loading:!1,error:null,data:{},lastUpdated:0,optimistic:{}};return{collections:{...n.collections,[t]:{...e,data:{...e.data,[i]:c},optimistic:{...e.optimistic,[i]:{tempId:i,originalData:o,status:"pending",operation:"update"}},lastUpdated:Date.now()}}}})},confirmUpdate:(t,i)=>{l(c=>{const o=c.collections[t];if(!o)return c;const{[i]:n,...e}=o.optimistic;return{collections:{...c.collections,[t]:{...o,optimistic:e}}}})},rejectUpdate:(t,i)=>{l(c=>{const o=c.collections[t];if(!o)return c;const n=o.optimistic[i];if(!n||n.operation!=="update")return c;const{[i]:e,...a}=o.optimistic;return{collections:{...c.collections,[t]:{...o,data:{...o.data,[i]:n.originalData},optimistic:a,lastUpdated:Date.now()}}}})},deleteOptimistic:(t,i,c)=>{l(o=>{const n=o.collections[t];if(!n)return o;const{[i]:e,...a}=n.data;return{collections:{...o.collections,[t]:{...n,data:a,optimistic:{...n.optimistic,[i]:{tempId:i,originalData:c,status:"pending",operation:"delete"}},lastUpdated:Date.now()}}}})},confirmDelete:(t,i)=>{l(c=>{const o=c.collections[t];if(!o)return c;const{[i]:n,...e}=o.optimistic;return{collections:{...c.collections,[t]:{...o,optimistic:e}}}})},rejectDelete:(t,i)=>{l(c=>{const o=c.collections[t];if(!o)return c;const n=o.optimistic[i];if(!n||n.operation!=="delete")return c;const{[i]:e,...a}=o.optimistic;return{collections:{...c.collections,[t]:{...o,data:{...o.data,[i]:n.originalData},optimistic:a,lastUpdated:Date.now()}}}})},getLoading:t=>r().collections[t]?.loading||!1,getError:t=>r().collections[t]?.error||null,getData:(t,i)=>r().collections[t]?.data[i]||null,isOptimistic:(t,i)=>r().collections[t]?.optimistic[i]?.status==="pending",getOptimisticStatus:(t,i)=>r().collections[t]?.optimistic[i]?.status??null,getCollectionData:t=>{const i=r().collections[t];return i?Object.entries(i.data).map(([c,o])=>({id:c,data:o,isOptimistic:i.optimistic[c]?.status==="pending"})):[]}})});export{D as useCrudStore};
1
+ import{createDoNotDevStore as m}from"@donotdev/core";const u={filters:{},showFavoritesOnly:!1};function r(){return{loading:!1,error:null,lastUpdated:0,optimistic:{},ui:{...u}}}const d={backend:null,crudService:null,hideSuccessToasts:!1,collections:{}},f=m({name:"crud-store",createStore:(n,s)=>({...d,setCrudService:t=>{n({crudService:t})},setBackend:t=>{n({backend:t})},setHideSuccessToasts:t=>{n({hideSuccessToasts:t})},setLoading:(t,c)=>{n(i=>{const o=i.collections[t]||r();return{collections:{...i.collections,[t]:{...o,loading:c}}}})},setError:(t,c)=>{n(i=>{const o=i.collections[t]||r();return{collections:{...i.collections,[t]:{...o,error:c,loading:!1}}}})},setFilters:(t,c)=>{n(i=>{const o=i.collections[t]||r();return{collections:{...i.collections,[t]:{...o,ui:{...o.ui,filters:c}}}}})},setShowFavoritesOnly:(t,c)=>{n(i=>{const o=i.collections[t]||r();return{collections:{...i.collections,[t]:{...o,ui:{...o.ui,showFavoritesOnly:c}}}}})},getFilters:t=>s().collections[t]?.ui?.filters||{},getShowFavoritesOnly:t=>s().collections[t]?.ui?.showFavoritesOnly||!1,clearCollection:t=>{n(c=>{const{[t]:i,...o}=c.collections;return{collections:o}})},clearError:t=>{n(c=>{const i=c.collections[t];return i?{collections:{...c.collections,[t]:{...i,error:null}}}:c})},addOptimistic:(t,c,i)=>{n(o=>{const e=o.collections[t]||r();return{collections:{...o.collections,[t]:{...e,optimistic:{...e.optimistic,[c]:{tempId:c,originalData:null,optimisticData:i,status:"pending",operation:"add"}},lastUpdated:Date.now()}}}})},confirmOptimistic:(t,c,i,o)=>{n(e=>{const l=e.collections[t];if(!l)return e;const{[c]:a,...p}=l.optimistic;return{collections:{...e.collections,[t]:{...l,optimistic:p,lastUpdated:Date.now()}}}})},rejectOptimistic:(t,c)=>{n(i=>{const o=i.collections[t];if(!o)return i;const{[c]:e,...l}=o.optimistic;return{collections:{...i.collections,[t]:{...o,optimistic:l,lastUpdated:Date.now()}}}})},updateOptimistic:(t,c,i,o)=>{n(e=>{const l=e.collections[t]||r();return{collections:{...e.collections,[t]:{...l,optimistic:{...l.optimistic,[c]:{tempId:c,originalData:o,optimisticData:i,status:"pending",operation:"update"}},lastUpdated:Date.now()}}}})},confirmUpdate:(t,c)=>{n(i=>{const o=i.collections[t];if(!o)return i;const{[c]:e,...l}=o.optimistic;return{collections:{...i.collections,[t]:{...o,optimistic:l}}}})},rejectUpdate:(t,c)=>{n(i=>{const o=i.collections[t];if(!o)return i;const e=o.optimistic[c];if(!e||e.operation!=="update")return i;const{[c]:l,...a}=o.optimistic;return{collections:{...i.collections,[t]:{...o,optimistic:a,lastUpdated:Date.now()}}}})},deleteOptimistic:(t,c,i)=>{n(o=>{const e=o.collections[t];return e?{collections:{...o.collections,[t]:{...e,optimistic:{...e.optimistic,[c]:{tempId:c,originalData:i,optimisticData:null,status:"pending",operation:"delete"}},lastUpdated:Date.now()}}}:o})},confirmDelete:(t,c)=>{n(i=>{const o=i.collections[t];if(!o)return i;const{[c]:e,...l}=o.optimistic;return{collections:{...i.collections,[t]:{...o,optimistic:l}}}})},rejectDelete:(t,c)=>{n(i=>{const o=i.collections[t];if(!o)return i;const e=o.optimistic[c];if(!e||e.operation!=="delete")return i;const{[c]:l,...a}=o.optimistic;return{collections:{...i.collections,[t]:{...o,optimistic:a,lastUpdated:Date.now()}}}})},getLoading:t=>s().collections[t]?.loading||!1,getError:t=>s().collections[t]?.error||null,isOptimistic:(t,c)=>s().collections[t]?.optimistic[c]?.status==="pending",getOptimisticStatus:(t,c)=>s().collections[t]?.optimistic[c]?.status??null,getOptimisticData:(t,c)=>s().collections[t]?.optimistic[c]?.optimisticData??null})});export{f as useCrudStore};
@@ -58,7 +58,7 @@ export declare class FirestoreAdapter {
58
58
  update<T>(collectionName: string, id: string, data: Partial<T>): Promise<void>;
59
59
  delete(collectionName: string, id: string): Promise<void>;
60
60
  add<T>(collectionName: string, data: T, schema: dndevSchema<T>): Promise<string>;
61
- query<T>(collectionName: string, options: QueryOptions, schema: dndevSchema<unknown>): Promise<PaginatedQueryResult<T>>;
61
+ query<T>(collectionName: string, options: QueryOptions, schema: dndevSchema<unknown>, _schemaType?: 'list' | 'listCard'): Promise<PaginatedQueryResult<T>>;
62
62
  subscribe<T>(collectionName: string, id: string, callback: SubscriptionCallback<T>, schema: dndevSchema<unknown>): Unsubscribe;
63
63
  subscribeToCollection<T>(collectionName: string, options: QueryOptions, callback: CollectionSubscriptionCallback<T>, schema: dndevSchema<unknown>): Unsubscribe;
64
64
  }
@@ -1 +1 @@
1
- {"version":3,"file":"FirestoreAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/FirestoreAdapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FirestoreAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/FirestoreAdapter.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- import*as u from"valibot";import{handleError as F}from"@donotdev/core";import{getFirestore as B,getFirebaseSDK as C,doc as h,getDoc as w,getDocs as E,setDoc as v,updateDoc as V,deleteDoc as z,addDoc as M,collection as L,query as A,where as D,orderBy as R,limit as I,startAfter as S,onSnapshot as q}from"@donotdev/firebase";import{transformFirestoreData as y,prepareForFirestore as m}from"@donotdev/firebase";class U{firestore;ensureFirestore(){if(this.firestore)return!0;try{return this.firestore=B(),!0}catch{return!1}}getCollectionRef(o){return!this.ensureFirestore()||!this.firestore?null:L(this.firestore,o)}async get(o,e,t){if(!this.ensureFirestore()||!this.firestore)return null;try{const i=h(this.firestore,o,e),r=await w(i);if(!r.exists())return null;let s=r.data();return s=y(s),{...u.parse(t,s),id:e}}catch(i){return F(i,{context:{operation:"FirestoreAdapter.get",collection:o,docId:e},severity:"warning"}),null}}async set(o,e,t,i){if(!(!this.ensureFirestore()||!this.firestore))try{u.parse(i,t);const r=h(this.firestore,o,e),s=m(t);await v(r,s)}catch(r){throw r}}async update(o,e,t){if(!(!this.ensureFirestore()||!this.firestore))try{const i=h(this.firestore,o,e),r=m(t);await V(i,r)}catch(i){throw i}}async delete(o,e){if(!(!this.ensureFirestore()||!this.firestore))try{const t=h(this.firestore,o,e);await z(t)}catch(t){throw t}}async add(o,e,t){if(!this.ensureFirestore())return"";try{u.parse(t,e);const i=this.getCollectionRef(o);if(!i)return"";const r=new Date().toISOString(),s=C().getCurrentUser()?.uid||"anonymous",c={...e,createdAt:r,updatedAt:r,createdById:s,updatedById:s},a=m(c);return(await M(i,a)).id}catch(i){throw i}}async query(o,e,t){if(!this.ensureFirestore())return{items:[]};const i=this.getCollectionRef(o);if(!i)return{items:[]};try{const r=[];if(e.where)for(const n of e.where)r.push(D(n.field,n.operator,n.value));if(e.orderBy)for(const n of e.orderBy)r.push(R(n.field,n.direction||"asc"));if(e.startAfterId){const n=await w(h(i,e.startAfterId));n.exists()&&r.push(S(n))}const s=e.limit?e.limit+1:void 0;s&&r.push(I(s));const c=A(i,...r),a=await E(c),d=[];let p=null;a.forEach(n=>{try{let l=n.data();if(!l)return;l=y(l);const x=u.parse(t,l);d.push({...x,id:n.id}),p=n.id}catch(l){F(l,{context:{operation:"FirestoreAdapter.query.parse",docId:n.id,collection:o},showNotification:!1})}});const f=s?d.length>(e.limit||0):!1;return{items:f?d.slice(0,e.limit):d,hasMore:f,lastVisible:p,total:void 0}}catch(r){throw F(r,{context:{operation:"FirestoreAdapter.query",collection:o,options:e}}),r}}subscribe(o,e,t,i){if(!this.ensureFirestore()||!this.firestore)return()=>{};const r=h(this.firestore,o,e);return q(r,s=>{try{if(!s.exists()){t(null);return}let c=s.data();c=y(c);const a=u.parse(i,c);t({...a,id:e})}catch(c){t(null,c)}},s=>{t(null,s)})}subscribeToCollection(o,e,t,i){if(!this.ensureFirestore())return()=>{};const r=this.getCollectionRef(o);if(!r)return()=>{};try{const s=[];if(e.where)for(const a of e.where)s.push(D(a.field,a.operator,a.value));if(e.orderBy)for(const a of e.orderBy)s.push(R(a.field,a.direction||"asc"));e.limit&&s.push(I(e.limit));const c=A(r,...s);return q(c,a=>{try{const d=[];a.forEach(p=>{let f=p.data();f=y(f);const g=u.parse(i,f);d.push({...g,id:p.id})}),t(d)}catch(d){t([],d)}},a=>{t([],a)})}catch(s){return t([],s),()=>{}}}}export{U as FirestoreAdapter};
1
+ import*as h from"valibot";import{handleError as m}from"@donotdev/core";import{getFirestore as B,getFirebaseSDK as C,doc as p,getDoc as w,getDocs as E,setDoc as v,updateDoc as V,deleteDoc as z,addDoc as M,collection as L,query as A,where as D,orderBy as R,limit as I,startAfter as S,onSnapshot as q}from"@donotdev/firebase";import{transformFirestoreData as F,prepareForFirestore as g}from"@donotdev/firebase";class W{firestore;ensureFirestore(){if(this.firestore)return!0;try{return this.firestore=B(),!0}catch{return!1}}getCollectionRef(s){return!this.ensureFirestore()||!this.firestore?null:L(this.firestore,s)}async get(s,e,t){if(!this.ensureFirestore()||!this.firestore)return null;try{const o=p(this.firestore,s,e),i=await w(o);if(!i.exists())return null;let r=i.data();return r=F(r),{...h.parse(t,r),id:e}}catch(o){return m(o,{context:{operation:"FirestoreAdapter.get",collection:s,docId:e},severity:"warning"}),null}}async set(s,e,t,o){if(!(!this.ensureFirestore()||!this.firestore))try{h.parse(o,t);const i=p(this.firestore,s,e),r=g(t);await v(i,r)}catch(i){throw i}}async update(s,e,t){if(!(!this.ensureFirestore()||!this.firestore))try{const o=p(this.firestore,s,e),i=g(t);await V(o,i)}catch(o){throw o}}async delete(s,e){if(!(!this.ensureFirestore()||!this.firestore))try{const t=p(this.firestore,s,e);await z(t)}catch(t){throw t}}async add(s,e,t){if(!this.ensureFirestore())return"";try{h.parse(t,e);const o=this.getCollectionRef(s);if(!o)return"";const i=new Date().toISOString(),r=C().getCurrentUser()?.uid||"anonymous",n={...e,createdAt:i,updatedAt:i,createdById:r,updatedById:r},a=g(n);return(await M(o,a)).id}catch(o){throw o}}async query(s,e,t,o="list"){if(!this.ensureFirestore())return{items:[]};const i=this.getCollectionRef(s);if(!i)return{items:[]};try{const r=[];if(e.where)for(const c of e.where)r.push(D(c.field,c.operator,c.value));if(e.orderBy)for(const c of e.orderBy)r.push(R(c.field,c.direction||"asc"));if(e.startAfterId){const c=await w(p(i,e.startAfterId));c.exists()&&r.push(S(c))}const n=e.limit?e.limit+1:void 0;n&&r.push(I(n));const a=A(i,...r),d=await E(a),f=[];let l=null;d.forEach(c=>{try{let u=c.data();if(!u)return;u=F(u);const x=h.parse(t,u);f.push({...x,id:c.id}),l=c.id}catch(u){m(u,{context:{operation:"FirestoreAdapter.query.parse",docId:c.id,collection:s},showNotification:!1})}});const y=n?f.length>(e.limit||0):!1;return{items:y?f.slice(0,e.limit):f,hasMore:y,lastVisible:l,total:void 0}}catch(r){throw m(r,{context:{operation:"FirestoreAdapter.query",collection:s,options:e}}),r}}subscribe(s,e,t,o){if(!this.ensureFirestore()||!this.firestore)return()=>{};const i=p(this.firestore,s,e);return q(i,r=>{try{if(!r.exists()){t(null);return}let n=r.data();n=F(n);const a=h.parse(o,n);t({...a,id:e})}catch(n){t(null,n)}},r=>{t(null,r)})}subscribeToCollection(s,e,t,o){if(!this.ensureFirestore())return()=>{};const i=this.getCollectionRef(s);if(!i)return()=>{};try{const r=[];if(e.where)for(const a of e.where)r.push(D(a.field,a.operator,a.value));if(e.orderBy)for(const a of e.orderBy)r.push(R(a.field,a.direction||"asc"));e.limit&&r.push(I(e.limit));const n=A(i,...r);return q(n,a=>{try{const d=[];a.forEach(f=>{let l=f.data();l=F(l);const y=h.parse(o,l);d.push({...y,id:f.id})}),t(d)}catch(d){t([],d)}},a=>{t([],a)})}catch(r){return t([],r),()=>{}}}}export{W as FirestoreAdapter};
@@ -44,7 +44,7 @@ export declare class FunctionsAdapter {
44
44
  update<T>(collectionName: string, id: string, data: Partial<T>): Promise<void>;
45
45
  delete(collectionName: string, id: string): Promise<void>;
46
46
  add<T>(collectionName: string, data: T, schema: dndevSchema<T>): Promise<string>;
47
- query<T>(collectionName: string, options: FunctionsQueryOptions, schema: dndevSchema<unknown>): Promise<PaginatedQueryResult<T>>;
47
+ query<T>(collectionName: string, options: FunctionsQueryOptions, schema: dndevSchema<unknown>, schemaType?: 'list' | 'listCard'): Promise<PaginatedQueryResult<T>>;
48
48
  listCard<T>(collectionName: string, options: FunctionsQueryOptions, schema: dndevSchema<T>): Promise<T[]>;
49
49
  subscribe<T>(): () => void;
50
50
  subscribeToCollection<T>(): () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"FunctionsAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/FunctionsAdapter.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGlD;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,GAAG,CAAC;QAAC,KAAK,EAAE,GAAG,CAAA;KAAE,CAAC,CAAC;IAC5D,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB,CAAC,CAAC;IACrC,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED;;;;;;;;GAQG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,MAAM,CAAS;;YAOT,eAAe;IAUvB,GAAG,CAAC,CAAC,EACT,cAAc,EAAE,MAAM,EACtB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,GAC3B,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAed,GAAG,CAAC,CAAC,EACT,cAAc,EAAE,MAAM,EACtB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,CAAC,EACP,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GACrB,OAAO,CAAC,IAAI,CAAC;IAeV,MAAM,CAAC,CAAC,EACZ,cAAc,EAAE,MAAM,EACtB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GACf,OAAO,CAAC,IAAI,CAAC;IAcV,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAczD,GAAG,CAAC,CAAC,EACT,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,CAAC,EACP,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GACrB,OAAO,CAAC,MAAM,CAAC;IAgBZ,KAAK,CAAC,CAAC,EACX,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,qBAAqB,EAC9B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,GAC3B,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC;IAwD7B,QAAQ,CAAC,CAAC,EACd,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,qBAAqB,EAC9B,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GACrB,OAAO,CAAC,CAAC,EAAE,CAAC;IAgDf,SAAS,CAAC,CAAC,KAAK,MAAM,IAAI;IAM1B,qBAAqB,CAAC,CAAC,KAAK,MAAM,IAAI;CAKvC"}
1
+ {"version":3,"file":"FunctionsAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/FunctionsAdapter.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGlD;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,GAAG,CAAC;QAAC,KAAK,EAAE,GAAG,CAAA;KAAE,CAAC,CAAC;IAC5D,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB,CAAC,CAAC;IACrC,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED;;;;;;;;GAQG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,MAAM,CAAS;;YAOT,eAAe;IAUvB,GAAG,CAAC,CAAC,EACT,cAAc,EAAE,MAAM,EACtB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,GAC3B,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAed,GAAG,CAAC,CAAC,EACT,cAAc,EAAE,MAAM,EACtB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,CAAC,EACP,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GACrB,OAAO,CAAC,IAAI,CAAC;IAeV,MAAM,CAAC,CAAC,EACZ,cAAc,EAAE,MAAM,EACtB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GACf,OAAO,CAAC,IAAI,CAAC;IAcV,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAczD,GAAG,CAAC,CAAC,EACT,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,CAAC,EACP,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GACrB,OAAO,CAAC,MAAM,CAAC;IAgBZ,KAAK,CAAC,CAAC,EACX,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,qBAAqB,EAC9B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,EAC5B,UAAU,GAAE,MAAM,GAAG,UAAmB,GACvC,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC;IA2D7B,QAAQ,CAAC,CAAC,EACd,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,qBAAqB,EAC9B,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GACrB,OAAO,CAAC,CAAC,EAAE,CAAC;IAgDf,SAAS,CAAC,CAAC,KAAK,MAAM,IAAI;IAM1B,qBAAqB,CAAC,CAAC,KAAK,MAAM,IAAI;CAKvC"}
@@ -1 +1 @@
1
- import{httpsCallable as i}from"firebase/functions";import*as u from"valibot";import{getPlatformEnvVar as l}from"@donotdev/core";import{getFirebaseFunctions as f}from"@donotdev/firebase";class F{functions;region;constructor(){this.region=l("FIREBASE_FUNCTIONS_REGION")||"europe-west1"}async ensureFunctions(){if(this.functions)return!0;try{return this.functions=await f(this.region),!0}catch{return!1}}async get(a,t,n){if(!await this.ensureFunctions())return null;try{const r=`get_${a}`;return(await i(this.functions,r)({id:t})).data}catch(r){throw r}}async set(a,t,n,r){if(await this.ensureFunctions())try{u.parse(r,n);const e=`update_${a}`;await i(this.functions,e)({id:t,payload:n})}catch(e){throw e}}async update(a,t,n){if(await this.ensureFunctions())try{const r=`update_${a}`;await i(this.functions,r)({id:t,payload:n})}catch(r){throw r}}async delete(a,t){if(await this.ensureFunctions())try{const n=`delete_${a}`;await i(this.functions,n)({id:t})}catch(n){throw n}}async add(a,t,n){if(!await this.ensureFunctions())return"";try{u.parse(n,t);const r=`create_${a}`;return(await i(this.functions,r)({payload:t})).data.id}catch(r){throw r}}async query(a,t,n){if(!await this.ensureFunctions())return{items:[]};try{const r=`list_${a}`,e={};t.where&&(e.where=t.where.map(s=>[s.field,s.operator,s.value])),t.orderBy&&(e.orderBy=t.orderBy.map(s=>[s.field,s.direction||"asc"])),t.limit&&(e.limit=t.limit),t.startAfterId&&(e.startAfterId=t.startAfterId);const c=await i(this.functions,r)(e);return{items:c.data.items,total:c.data.count,hasMore:c.data.hasMore,lastVisible:c.data.lastVisible}}catch(r){throw r}}async listCard(a,t,n){if(!await this.ensureFunctions())return[];try{const r=`listCard_${a}`,e={};return t.where&&(e.where=t.where.map(s=>[s.field,s.operator,s.value])),t.orderBy&&(e.orderBy=t.orderBy.map(s=>[s.field,s.direction||"asc"])),t.limit&&(e.limit=t.limit),(await i(this.functions,r)(e)).data.items}catch(r){throw r}}subscribe(){throw new Error("Subscriptions are not supported with Functions backend. Use Firestore backend for real-time features.")}subscribeToCollection(){throw new Error("Subscriptions are not supported with Functions backend. Use Firestore backend for real-time features.")}}export{F as FunctionsAdapter};
1
+ import{httpsCallable as c}from"firebase/functions";import*as u from"valibot";import{getPlatformEnvVar as d}from"@donotdev/core";import{getFirebaseFunctions as f}from"@donotdev/firebase";class y{functions;region;constructor(){this.region=d("FIREBASE_FUNCTIONS_REGION")||"europe-west1"}async ensureFunctions(){if(this.functions)return!0;try{return this.functions=await f(this.region),!0}catch{return!1}}async get(e,t,s){if(!await this.ensureFunctions())return null;try{const r=`get_${e}`;return(await c(this.functions,r)({id:t})).data}catch(r){throw r}}async set(e,t,s,r){if(await this.ensureFunctions())try{u.parse(r,s);const a=`update_${e}`;await c(this.functions,a)({id:t,payload:s})}catch(a){throw a}}async update(e,t,s){if(await this.ensureFunctions())try{const r=`update_${e}`;await c(this.functions,r)({id:t,payload:s})}catch(r){throw r}}async delete(e,t){if(await this.ensureFunctions())try{const s=`delete_${e}`;await c(this.functions,s)({id:t})}catch(s){throw s}}async add(e,t,s){if(!await this.ensureFunctions())return"";try{u.parse(s,t);const r=`create_${e}`;return(await c(this.functions,r)({payload:t})).data.id}catch(r){throw r}}async query(e,t,s,r="list"){if(!await this.ensureFunctions())return{items:[]};try{const a=r==="listCard"?`listCard_${e}`:`list_${e}`,i={};t.where&&(i.where=t.where.map(o=>[o.field,o.operator,o.value])),t.orderBy&&(i.orderBy=t.orderBy.map(o=>[o.field,o.direction||"asc"])),t.limit&&(i.limit=t.limit),t.startAfterId&&(i.startAfterId=t.startAfterId);const n=await c(this.functions,a)(i);return{items:n.data.items,total:n.data.count,hasMore:n.data.hasMore,lastVisible:n.data.lastVisible}}catch(a){throw a}}async listCard(e,t,s){if(!await this.ensureFunctions())return[];try{const r=`listCard_${e}`,a={};return t.where&&(a.where=t.where.map(n=>[n.field,n.operator,n.value])),t.orderBy&&(a.orderBy=t.orderBy.map(n=>[n.field,n.direction||"asc"])),t.limit&&(a.limit=t.limit),(await c(this.functions,r)(a)).data.items}catch(r){throw r}}subscribe(){throw new Error("Subscriptions are not supported with Functions backend. Use Firestore backend for real-time features.")}subscribeToCollection(){throw new Error("Subscriptions are not supported with Functions backend. Use Firestore backend for real-time features.")}}export{y as FunctionsAdapter};
@@ -1,9 +1,22 @@
1
1
  /**
2
- * Register built-in field types (UI components only)
2
+ * @fileoverview Built-in Field Type Registrations
3
+ * @description Legacy wrapper - now delegates to unified registry.
3
4
  *
4
- * **Note for Consumers:**
5
- * This function demonstrates the registration pattern. For your own custom field types,
6
- * use `registerFieldType()` from `@donotdev/crud` instead. See SETUP_CRUD.md for examples.
5
+ * **For Framework Consumers:**
6
+ * This file is kept for backward compatibility. The actual registration happens
7
+ * in registerBuiltinFieldTypes.ts via the unified field type registry.
8
+ *
9
+ * For your own custom field types, use `registerFieldType()` from `@donotdev/crud`.
10
+ * See SETUP_CRUD.md for examples.
11
+ *
12
+ * @version 0.0.2
13
+ * @since 0.0.1
14
+ * @author AMBROISE PARK Consulting
15
+ */
16
+ import './registerBuiltinFieldTypes';
17
+ /**
18
+ * @deprecated Registration now handled by unified registry
19
+ * Kept for backward compatibility
7
20
  */
8
21
  export declare function registerBuiltinFieldTypes(): void;
9
22
  //# sourceMappingURL=builtinFieldTypes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"builtinFieldTypes.d.ts","sourceRoot":"","sources":["../src/builtinFieldTypes.tsx"],"names":[],"mappings":"AA2KA;;;;;;GAMG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CA6GhD"}
1
+ {"version":3,"file":"builtinFieldTypes.d.ts","sourceRoot":"","sources":["../src/builtinFieldTypes.tsx"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,6BAA6B,CAAC;AAErC;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CAGhD"}
@@ -1 +1 @@
1
- "use client";import{jsx as s}from"react/jsx-runtime";import{ControlledCheckboxField as g,ControlledComboboxField as F,ControlledDateField as C,ControlledDropdownField as f,ControlledFileField as h,ControlledMultiFileField as b,ControlledDocumentField as x,ControlledMultiDocumentField as v,ControlledGeoPointField as T,ControlledImageField as U,ControlledMapField as w,ControlledMultiDropdownField as y,ControlledMultiInputField as R,ControlledNumberField as p,ControlledPasswordField as M,ControlledPhoneField as k,ControlledRangeField as D,ControlledRadioField as A,ControlledTextField as d,ControlledTextareaField as B,ControlledRichTextField as I,ControlledTimestampField as P,ControlledAddressField as j,ControlledSwitchField as G,ControlledMultiImageField as H,ControlledGdprConsentField as S}from"./components/controlled";import{AvatarFieldComponent as N,BadgeFieldComponent as Y,ButtonFieldComponent as c,HiddenFieldComponent as _,TextAreaComponent as q,RichTextComponent as z,TextFieldComponent as E}from"./components/form/fields";import{getFieldRegistry as J}from"./FieldRegistry";const K=e=>{const{name:t,value:o,onChange:r,error:n,t:i,config:l,...a}=e;return s(N,{config:l,value:o,onChange:r,error:!!n,helperText:n||void 0,t:i,...l.options,...a})},L=e=>{const{name:t,value:o,onChange:r,error:n,t:i,config:l,...a}=e;return s(Y,{config:l,value:o,onChange:r,error:!!n,helperText:n||void 0,t:i,...l.options,...a})},O=e=>{const{name:t,label:o,onChange:r,config:n}=e;return s(c,{label:o||t,type:"submit",onClick:()=>r(void 0),...n.options})},Q=e=>{const{name:t,label:o,onChange:r,config:n}=e;return s(c,{label:o||t,type:"reset",onClick:()=>r(void 0),...n.options})},V=e=>{const{name:t,value:o}=e;return s(_,{name:t,value:o})},W=e=>{const{name:t,label:o,value:r,onChange:n,error:i,config:l}=e;return s(q,{label:o||t,value:r,onChange:n,error:i||void 0,...l.options})},X=e=>{const{name:t,label:o,value:r,onChange:n,error:i,config:l}=e;return s(z,{label:o||t,value:r,onChange:n,error:i||void 0,...l.options})},m=e=>{const{name:t,label:o,value:r,onChange:n,error:i,config:l}=e;return s(E,{label:o||t,value:r,onChange:n,error:i||void 0,...l.options})};let u=!1;function Z(){if(u)return;u=!0;const e=J();e.registerComponent("text",d,m),e.registerComponent("email",d,m),e.registerComponent("url",d,m),e.registerComponent("color",d,m),e.registerComponent("textarea",B,W),e.registerComponent("richtext",I,X),e.registerComponent("password",M),e.registerComponent("number",p),e.registerComponent("range",D),e.registerComponent("year",p),e.registerComponent("boolean",g),e.registerComponent("checkbox",g),e.registerComponent("gdprConsent",S),e.registerComponent("switch",G),e.registerComponent("date",C),e.registerComponent("datetime-local",C),e.registerComponent("time",C),e.registerComponent("week",C),e.registerComponent("month",C),e.registerComponent("timestamp",P),e.registerComponent("file",h),e.registerComponent("files",b),e.registerComponent("document",x),e.registerComponent("documents",v),e.registerComponent("image",U),e.registerComponent("images",H),e.registerComponent("geopoint",T),e.registerComponent("address",j),e.registerComponent("map",w),e.registerComponent("array",R),e.registerComponent("select",f),e.registerComponent("combobox",F),e.registerComponent("multiselect",y),e.registerComponent("radio",A),e.registerComponent("tel",k),e.registerComponent("avatar",d,K),e.registerComponent("badge",d,L),e.registerComponent("hidden",d,V),e.registerComponent("submit",d,O),e.registerComponent("reset",d,Q)}Z();export{Z as registerBuiltinFieldTypes};
1
+ "use client";import"./registerBuiltinFieldTypes";function i(){}export{i as registerBuiltinFieldTypes};
@@ -18,10 +18,12 @@ export interface DisplayFieldRendererProps<T extends FieldType = FieldType> {
18
18
  * @param t - Translation function
19
19
  * @param options - Formatting options
20
20
  * @param options.compact - Use compact formatting (smaller images, plain spans for empty)
21
+ * @param options.asString - Prefer string output when possible (e.g. for price in text placeholders)
21
22
  * @returns Formatted value as string or ReactElement
22
23
  */
23
24
  export declare function formatValue(value: any, config: EntityField, t: (key: string, options?: Record<string, any>) => string, options?: {
24
25
  compact?: boolean;
26
+ asString?: boolean;
25
27
  }): string | ReactElement;
26
28
  /**
27
29
  * DisplayFieldRenderer - Renders a field value as read-only display
@@ -1 +1 @@
1
- {"version":3,"file":"DisplayFieldRenderer.d.ts","sourceRoot":"","sources":["../../src/components/DisplayFieldRenderer.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAI7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE1C,MAAM,WAAW,yBAAyB,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS;IACxE,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACvB,0BAA0B;IAC1B,KAAK,EAAE,GAAG,CAAC;IACX,2BAA2B;IAC3B,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC;CAC3D;AAED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,GAAG,EACV,MAAM,EAAE,WAAW,EACnB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,MAAM,EACzD,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAC9B,MAAM,GAAG,YAAY,CAoYvB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EAAE,EACpE,IAAI,EACJ,MAAM,EACN,KAAK,EACL,CAAC,GACF,EAAE,yBAAyB,CAAC,CAAC,CAAC,GAAG,YAAY,CAyC7C;AAED,eAAe,oBAAoB,CAAC"}
1
+ {"version":3,"file":"DisplayFieldRenderer.d.ts","sourceRoot":"","sources":["../../src/components/DisplayFieldRenderer.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAK7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE1C,MAAM,WAAW,yBAAyB,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS;IACxE,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACvB,0BAA0B;IAC1B,KAAK,EAAE,GAAG,CAAC;IACX,2BAA2B;IAC3B,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC;CAC3D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,GAAG,EACV,MAAM,EAAE,WAAW,EACnB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,MAAM,EACzD,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GAClD,MAAM,GAAG,YAAY,CA0DvB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EAAE,EACpE,IAAI,EACJ,MAAM,EACN,KAAK,EACL,CAAC,GACF,EAAE,yBAAyB,CAAC,CAAC,CAAC,GAAG,YAAY,CAyC7C;AAED,eAAe,oBAAoB,CAAC"}
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as o}from"react/jsx-runtime";import{Text as i,Stack as d}from"@donotdev/components";import{translateFieldLabel as y,translateLabel as g}from"../forms/utils";function b(r,c,l,m){const n=m?.compact??!1;if(r==null||r==="")return n?e("span",{style:{color:"var(--muted-foreground)"},children:"\u2014"}):e(i,{variant:"muted",children:"\u2014"});switch(c.type){case"timestamp":case"date":case"datetime-local":try{const t=r instanceof Date?r:new Date(r);return c.type==="date"?t.toLocaleDateString():t.toLocaleString()}catch{return String(r)}case"boolean":case"checkbox":return r?"Yes":"No";case"number":case"range":return typeof r=="number"?r.toLocaleString():String(r);case"select":case"radio":const p=c.validation?.options;if(Array.isArray(p)){const a=p.find(s=>s.value===r)?.label;return a?g(a,l):String(r)}return String(r);case"multiselect":if(Array.isArray(r)){const t=c.validation?.options;if(Array.isArray(t))return r.map(s=>{const h=t.find(u=>u.value===s)?.label;return h?g(h,l):s}).join(", ")}return String(r);case"image":case"images":if(typeof r=="string")return e("img",{src:r,alt:c.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)"}});if(Array.isArray(r)&&r.length>0){const t=r[0],a=typeof t=="object"&&t.thumbUrl?t.thumbUrl:t;return n?o("div",{style:{display:"flex",alignItems:"center",gap:"var(--gap-xs)"},children:[e("img",{src:a,alt:"",style:{width:"40px",height:"40px",objectFit:"cover",borderRadius:"var(--radius-sm)"}}),r.length>1&&o("span",{style:{fontSize:"var(--font-size-xs)",color:"var(--muted-foreground)"},children:["+",r.length-1]})]}):o(d,{direction:"row",gap:"tight",style:{flexWrap:"wrap"},children:[r.slice(0,4).map((s,f)=>{const h=typeof s=="object"&&s.thumbUrl?s.thumbUrl:s;return e("img",{src:h,alt:`${c.label} ${f+1}`,style:{width:"60px",height:"60px",objectFit:"cover",borderRadius:"var(--radius-sm)"}},f)}),r.length>4&&o(i,{variant:"muted",children:["+",r.length-4," more"]})]})}return n?e("span",{style:{color:"var(--muted-foreground)"},children:"\u2014"}):e(i,{variant:"muted",children:"\u2014"});case"files":case"documents":return Array.isArray(r)?r.length===0?n?e("span",{style:{color:"var(--muted-foreground)"},children:"\u2014"}):e(i,{variant:"muted",children:"\u2014"}):e(d,{gap:"tight",children:r.map((t,a)=>o("a",{href:t.url||t,target:"_blank",rel:"noopener noreferrer",style:{color:"var(--primary)",textDecoration:"none",display:"flex",alignItems:"center",fontSize:"var(--font-size-sm)"},children:[t.filename||`File ${a+1}`,t.size&&o(i,{level:"caption",variant:"muted",style:{marginLeft:"var(--gap-sm)"},children:["(",Math.round(t.size/1024)," KB)"]})]},a))}):n?e("span",{style:{color:"var(--muted-foreground)"},children:"\u2014"}):e(i,{variant:"muted",children:"\u2014"});case"file":case"document":if(r){const t=typeof r=="string"?r:r.url,a=typeof r=="string"?"View file":r.filename||"View file";return o("a",{href:t,target:"_blank",rel:"noopener noreferrer",style:{color:"var(--primary)",textDecoration:"none"},children:[a,typeof r=="object"&&r.size&&o("span",{style:{color:"var(--muted-foreground)",marginLeft:"var(--gap-sm)"},children:["(",Math.round(r.size/1024)," KB)"]})]})}return n?e("span",{style:{color:"var(--muted-foreground)"},children:"\u2014"}):e(i,{variant:"muted",children:"\u2014"});case"reference":return String(r);case"geopoint":return r&&typeof r=="object"&&"lat"in r&&"lng"in r?`${r.lat.toFixed(6)}, ${r.lng.toFixed(6)}`:n?e("span",{style:{color:"var(--muted-foreground)"},children:"\u2014"}):e(i,{variant:"muted",children:"\u2014"});case"address":return r&&typeof r=="object"&&"formatted_address"in r?r.formatted_address:String(r);case"map":if(r&&typeof r=="object"){const t=Object.entries(r);return t.length===0?n?e("span",{style:{color:"var(--muted-foreground)"},children:"\u2014"}):e(i,{variant:"muted",children:"\u2014"}):o(d,{direction:"column",gap:"tight",children:[t.slice(0,5).map(([a,s])=>o(i,{style:{fontSize:"var(--font-size-sm)"},children:[o("strong",{children:[a,":"]})," ",String(s)]},a)),t.length>5&&o(i,{variant:"muted",children:["+",t.length-5," more"]})]})}return n?e("span",{style:{color:"var(--muted-foreground)"},children:"\u2014"}):e(i,{variant:"muted",children:"\u2014"});case"array":return Array.isArray(r)?r.length===0?n?e("span",{style:{color:"var(--muted-foreground)"},children:"\u2014"}):e(i,{variant:"muted",children:"\u2014"}):r.join(", "):n?e("span",{style:{color:"var(--muted-foreground)"},children:"\u2014"}):e(i,{variant:"muted",children:"\u2014"});case"password":return"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";case"email":return e("a",{href:`mailto:${r}`,style:{color:"var(--primary)"},onClick:t=>t.stopPropagation(),children:r});case"tel":return e("a",{href:`tel:${r}`,style:{color:"var(--primary)"},onClick:t=>t.stopPropagation(),children:r});case"url":return e("a",{href:r,target:"_blank",rel:"noopener noreferrer",style:{color:"var(--primary)"},children:r});case"color":return o(d,{direction:"row",gap:"tight",align:"center",children:[e("div",{style:{width:"20px",height:"20px",backgroundColor:r,borderRadius:"var(--radius-sm)",border:"1px solid var(--border)"}}),e(i,{children:r})]});case"textarea":case"text":return String(r);case"richtext":return r&&typeof r=="string"?n?r.replace(/<[^>]*>/g,"").trim()||e("span",{style:{color:"var(--muted-foreground)"},children:"\u2014"}):e("div",{dangerouslySetInnerHTML:{__html:r},style:{padding:"var(--gap-sm)",fontSize:"var(--font-size-sm)",lineHeight:"1.6"}}):n?e("span",{style:{color:"var(--muted-foreground)"},children:"\u2014"}):e(i,{variant:"muted",children:"\u2014"});default:return String(r)}}function x({name:r,config:c,value:l,t:m}){const n=b(l,c,m,{compact:!1}),p=y(r,c,m);return o(d,{direction:"row",align:"baseline",style:{marginBottom:"var(--gap-sm)",padding:"var(--gap-sm)",minHeight:"38px",alignItems:"center"},children:[o(i,{variant:"muted",style:{fontSize:"var(--font-size-sm)",fontWeight:500,minWidth:"fit-content",flexShrink:0},children:[p,":"]}),e("div",{style:{flex:1,display:"flex",alignItems:"center"},children:typeof n=="string"?e(i,{children:n}):n})]})}var w=x;export{x as DisplayFieldRenderer,w as default,b as formatValue};
1
+ "use client";import{jsx as t,jsxs as s}from"react/jsx-runtime";import{Text as a,Stack as p}from"@donotdev/components";import{handleError as d}from"@donotdev/core";import{translateFieldLabel as f}from"../forms/utils";import{getDisplayFormatter as y}from"../fieldTypeRegistry";function c(r,e,o,n){const i=n?.compact??!1;if(r==null||r==="")return i?t("span",{style:{color:"var(--muted-foreground)"},children:"\u2014"}):t(a,{variant:"muted",children:"\u2014"});const l=y(e.type);if(l)try{return l(r,e,o,n)}catch(m){return d(m,{userMessage:`Error formatting field "${e.label||e.name}"`,context:{fieldType:e.type,fieldName:e.label||"unknown",operation:"display_format"},severity:"warning"}),i?t("span",{style:{color:"var(--muted-foreground)"},children:String(r)}):t(a,{variant:"muted",children:String(r)})}return d(new Error(`Display formatter not registered for field type: ${e.type}`),{userMessage:`Field type "${e.type}" is missing display formatter`,context:{fieldType:e.type,fieldName:e.label||"unknown",operation:"display_format",fix:"Add displayFormatter to registerBuiltinFieldType() in registerBuiltinFieldTypes.tsx"},severity:"warning"}),i?t("span",{style:{color:"var(--muted-foreground)"},children:String(r)}):t(a,{variant:"muted",children:String(r)})}function u({name:r,config:e,value:o,t:n}){const i=c(o,e,n,{compact:!1}),l=f(r,e,n);return s(p,{direction:"row",align:"baseline",style:{marginBottom:"var(--gap-sm)",padding:"var(--gap-sm)",minHeight:"38px",alignItems:"center"},children:[s(a,{variant:"muted",style:{fontSize:"var(--font-size-sm)",fontWeight:500,minWidth:"fit-content",flexShrink:0},children:[l,":"]}),t("div",{style:{flex:1,display:"flex",alignItems:"center"},children:typeof i=="string"?t(a,{children:i}):i})]})}var b=u;export{u as DisplayFieldRenderer,b as default,c as formatValue};
@@ -1,4 +1,4 @@
1
- import type { Entity, UserRole } from '@donotdev/core';
1
+ import type { Entity } from '@donotdev/core';
2
2
  export interface EntityDisplayRendererProps<T extends Record<string, unknown> = Record<string, unknown>> {
3
3
  /** Entity definition - pass the full entity from defineEntity() */
4
4
  entity: Entity;
@@ -20,7 +20,7 @@ export interface EntityDisplayRendererProps<T extends Record<string, unknown> =
20
20
  * If not provided, defaults to 'guest' (most restrictive - shows only public fields)
21
21
  * @default 'guest'
22
22
  */
23
- viewerRole?: UserRole;
23
+ viewerRole?: string;
24
24
  }
25
25
  /**
26
26
  * EntityDisplayRenderer - Automatically fetches and displays entity data
@@ -1 +1 @@
1
- {"version":3,"file":"EntityDisplayRenderer.d.ts","sourceRoot":"","sources":["../../src/components/EntityDisplayRenderer.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAKvD,MAAM,WAAW,0BAA0B,CACzC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAE3D,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,uEAAuE;IACvE,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,qBAAqB;IACrB,OAAO,CAAC,EAAE,WAAW,GAAG,WAAW,CAAC;IACpC,6BAA6B;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+BAA+B;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,QAAQ,CAAC;CACvB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACnC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3D,EACA,MAAM,EACN,EAAE,EACF,CAAC,EACD,SAAc,EACd,OAAqB,EACrB,cAAc,EACd,eAAe,EACf,UAAoB,GACrB,EAAE,0BAA0B,CAAC,CAAC,CAAC,2CAgM/B;AAED,eAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"EntityDisplayRenderer.d.ts","sourceRoot":"","sources":["../../src/components/EntityDisplayRenderer.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAK7C,MAAM,WAAW,0BAA0B,CACzC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAE3D,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,uEAAuE;IACvE,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,qBAAqB;IACrB,OAAO,CAAC,EAAE,WAAW,GAAG,WAAW,CAAC;IACpC,6BAA6B;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+BAA+B;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACnC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3D,EACA,MAAM,EACN,EAAE,EACF,CAAC,EACD,SAAc,EACd,OAAqB,EACrB,cAAc,EACd,eAAe,EACf,UAAoB,GACrB,EAAE,0BAA0B,CAAC,CAAC,CAAC,2CAgM/B;AAED,eAAe,qBAAqB,CAAC"}
@@ -1 +1 @@
1
- "use client";import{jsx as n,jsxs as O}from"react/jsx-runtime";import{useEffect as _,useState as m,useMemo as I}from"react";import{Stack as p,Spinner as M}from"@donotdev/components";import{useTranslation as v,isFieldVisible as R}from"@donotdev/core";import{DisplayFieldRenderer as T}from"./DisplayFieldRenderer";import{useCrud as $}from"../useCrud";function q({entity:i,id:o,t:E,className:f="",backend:b="functions",loadingMessage:j,notFoundMessage:x,viewerRole:g="guest"}){const{get:d,loading:F,data:A,error:S,isAvailable:y}=$(i,{backend:b}),[D,u]=m(!1),[V,s]=m(null),[k,c]=m(null),{t:w}=v(i.namespace),{t:h}=v("crud"),z=E||w;_(()=>{if(!o){c(null),s(null),u(!1);return}if(!y||!d)return;let t=!1;return u(!0),s(null),d(o).then(r=>{t||(u(!1),r?(c(r),s(null)):(c(null),s(new Error("Entity not found"))))}).catch(r=>{t||(u(!1),s(r instanceof Error?r:new Error(String(r))),c(null))}),()=>{t=!0}},[o,d,y]);const l=A||k,a=S||V,C=F||D||!o,L=I(()=>l?Object.entries(i.fields).filter(([t,r])=>{if(!R(r.visibility,g)||r.visibility==="hidden")return!1;const e=l[t];return!(e==null||typeof e=="string"&&e.trim()===""||Array.isArray(e)&&e.length===0||typeof e=="object"&&!Array.isArray(e)&&e!==null&&Object.keys(e).length===0)}):[],[i.fields,g,l]);return C?n("div",{style:{position:"relative",width:"100%",gridColumn:"1 / -1",display:"contents"},className:f,children:n(M,{overlay:!0,"aria-label":j||h("form.loading",{defaultValue:"Loading..."})})}):a||!l?n(p,{align:"center",justify:"center",gap:"medium",style:{padding:"var(--gap-3xl)",textAlign:"center"},className:f,children:O(p,{direction:"column",gap:"tight",children:[n("h3",{style:{color:"var(--muted-foreground)"},children:x||h("errors.notFound",{defaultValue:`${i.name} not found`})}),a&&n("p",{style:{color:"var(--destructive)",fontSize:"var(--font-size-sm)"},children:a instanceof Error?a.message:String(a)})]})}):n(p,{direction:"column",gap:"medium",className:f,children:L.map(([t,r])=>n(T,{name:t,config:r,value:l[t],t:z},t))})}var Q=q;export{q as EntityDisplayRenderer,Q as default};
1
+ "use client";import{jsx as n,jsxs as O}from"react/jsx-runtime";import{useEffect as _,useState as m,useMemo as I}from"react";import{Stack as p,Spinner as M}from"@donotdev/components";import{useTranslation as v,isFieldVisible as R}from"@donotdev/core";import{DisplayFieldRenderer as T}from"./DisplayFieldRenderer";import{useCrud as $}from"../useCrud";function q({entity:i,id:o,t:E,className:f="",backend:b="functions",loadingMessage:j,notFoundMessage:x,viewerRole:g="guest"}){const{get:d,loading:F,data:A,error:S,isAvailable:y}=$(i,{backend:b}),[D,u]=m(!1),[V,s]=m(null),[k,c]=m(null),{t:w}=v([i.namespace,"crud"]),{t:h}=v("crud"),z=E||w;_(()=>{if(!o){c(null),s(null),u(!1);return}if(!y||!d)return;let t=!1;return u(!0),s(null),d(o).then(r=>{t||(u(!1),r?(c(r),s(null)):(c(null),s(new Error("Entity not found"))))}).catch(r=>{t||(u(!1),s(r instanceof Error?r:new Error(String(r))),c(null))}),()=>{t=!0}},[o,d,y]);const l=A||k,a=S||V,C=F||D||!o,L=I(()=>l?Object.entries(i.fields).filter(([t,r])=>{if(!R(r.visibility,g)||r.visibility==="hidden")return!1;const e=l[t];return!(e==null||typeof e=="string"&&e.trim()===""||Array.isArray(e)&&e.length===0||typeof e=="object"&&!Array.isArray(e)&&e!==null&&Object.keys(e).length===0)}):[],[i.fields,g,l]);return C?n("div",{style:{position:"relative",width:"100%",gridColumn:"1 / -1",display:"contents"},className:f,children:n(M,{overlay:!0,"aria-label":j||h("form.loading",{defaultValue:"Loading..."})})}):a||!l?n(p,{align:"center",justify:"center",gap:"medium",style:{padding:"var(--gap-3xl)",textAlign:"center"},className:f,children:O(p,{direction:"column",gap:"tight",children:[n("h3",{style:{color:"var(--muted-foreground)"},children:x||h("errors.notFound",{defaultValue:`${i.name} not found`})}),a&&n("p",{style:{color:"var(--destructive)",fontSize:"var(--font-size-sm)"},children:a instanceof Error?a.message:String(a)})]})}):n(p,{direction:"column",gap:"medium",className:f,children:L.map(([t,r])=>n(T,{name:t,config:r,value:l[t],t:z},t))})}var Q=q;export{q as EntityDisplayRenderer,Q as default};
@@ -1,11 +1,18 @@
1
1
  import type { Entity } from '@donotdev/core';
2
2
  /**
3
+
3
4
  * Shared filter utility - checks if an item matches a filter value
5
+
4
6
  *
7
+
5
8
  * Pattern for null/undefined handling:
9
+
6
10
  * - MIN / undefined → Only show items with defined values >= MIN (exclude null/undefined)
11
+
7
12
  * - undefined / MAX → Show items with value <= MAX OR null/undefined (include null/undefined)
13
+
8
14
  * - MIN / MAX → Show items with MIN <= value <= MAX (exclude null/undefined)
15
+
9
16
  */
10
17
  export declare function matchesFilter(itemValue: any, filterValue: string | {
11
18
  min?: string;
@@ -28,16 +35,27 @@ export interface EntityFiltersProps<T = any> {
28
35
  }>) => void;
29
36
  /** Optional: Specific fields to show filters for (defaults to all entity fields) */
30
37
  fieldsToFilter?: string[];
38
+ /** Layout variant: 'inline' (multi-column grid) or 'sidebar' (single column stack) */
39
+ variant?: 'inline' | 'sidebar';
31
40
  }
32
41
  /**
42
+
33
43
  * Entity Filters Component - Auto-generates filter UI based on entity field types
44
+
34
45
  *
46
+
35
47
  * Features:
48
+
36
49
  * - String/Select fields: Combobox with unique values
50
+
37
51
  * - Number fields: Min/Max inputs + Slider (2 rows)
52
+
38
53
  * - Date fields: Min/Max date pickers + shortcuts (2 rows)
54
+
39
55
  * - Filters wrap naturally with flex-wrap
56
+
40
57
  * - Clear individual filters or all filters
58
+
41
59
  */
42
- export declare function EntityFilters<T extends Record<string, any> = Record<string, any>>({ entity, data, filters, onFiltersChange, fieldsToFilter, }: EntityFiltersProps<T>): import("react/jsx-runtime").JSX.Element | null;
60
+ export declare function EntityFilters<T extends Record<string, any> = Record<string, any>>({ entity, data, filters, onFiltersChange, fieldsToFilter, variant, }: EntityFiltersProps<T>): import("react/jsx-runtime").JSX.Element | null;
43
61
  //# sourceMappingURL=EntityFilters.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"EntityFilters.d.ts","sourceRoot":"","sources":["../../src/components/EntityFilters.tsx"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAI7C;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,GAAG,EACd,WAAW,EAAE,MAAM,GAAG;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,EACpD,SAAS,EAAE,MAAM,GAChB,OAAO,CA8FT;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,GAAG;IACzC,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjE,mCAAmC;IACnC,eAAe,EAAE,CACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,KAC7D,IAAI,CAAC;IACV,oFAAoF;IACpF,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACnD,EACA,MAAM,EACN,IAAI,EACJ,OAAO,EACP,eAAe,EACf,cAAc,GACf,EAAE,kBAAkB,CAAC,CAAC,CAAC,kDA8evB"}
1
+ {"version":3,"file":"EntityFilters.d.ts","sourceRoot":"","sources":["../../src/components/EntityFilters.tsx"],"names":[],"mappings":"AAuDA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAM7C;;;;;;;;;;;;;;GAcG;AAEH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,GAAG,EAEd,WAAW,EAAE,MAAM,GAAG;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,EAEpD,SAAS,EAAE,MAAM,GAChB,OAAO,CA8MT;AAoOD,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,GAAG;IACzC,4BAA4B;IAE5B,MAAM,EAAE,MAAM,CAAC;IAEf,2DAA2D;IAE3D,IAAI,EAAE,CAAC,EAAE,CAAC;IAEV,4BAA4B;IAE5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAEjE,mCAAmC;IAEnC,eAAe,EAAE,CACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,KAC7D,IAAI,CAAC;IAEV,oFAAoF;IAEpF,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAE1B,sFAAsF;IAEtF,OAAO,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AAEH,wBAAgB,aAAa,CAC3B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACnD,EACA,MAAM,EAEN,IAAI,EAEJ,OAAO,EAEP,eAAe,EAEf,cAAc,EAEd,OAAkB,GACnB,EAAE,kBAAkB,CAAC,CAAC,CAAC,kDAwjBvB"}
@@ -1 +1 @@
1
- "use client";import{jsx as x,jsxs as E}from"react/jsx-runtime";import{useMemo as j}from"react";import{Button as k,Stack as A,Combobox as B,Slider as K,Grid as Q,RangeInput as W}from"@donotdev/components";import{useTranslation as _}from"@donotdev/core";import{translateFieldLabel as U,translateLabel as G}from"../forms/utils";function X(n,a,p){if(!a)return!0;if(typeof a=="object"&&"min"in a){const C=p==="date"||p==="datetime-local"||p==="timestamp";if(p==="number"||p==="range"){const c=a.min&&a.min!=="",g=a.max&&a.max!=="";if(c&&!g){if(n==null)return!1;const i=typeof n=="number"?n:Number(n);return isNaN(i)?!1:i>=Number(a.min)}if(!c&&g){if(n==null)return!0;const i=typeof n=="number"?n:Number(n);return isNaN(i)?!1:i<=Number(a.max)}if(c&&g){if(n==null)return!1;const i=typeof n=="number"?n:Number(n);return isNaN(i)?!1:i>=Number(a.min)&&i<=Number(a.max)}return!0}if(C){const c=a.min&&a.min!=="",g=a.max&&a.max!=="";if(c&&!g){if(n==null)return!1;const i=n instanceof Date?n:new Date(n);return isNaN(i.getTime())?!1:i>=new Date(a.min)}if(!c&&g){if(n==null)return!0;const i=n instanceof Date?n:new Date(n);return isNaN(i.getTime())?!1:i<=new Date(a.max)}if(c&&g){if(n==null)return!1;const i=n instanceof Date?n:new Date(n);return isNaN(i.getTime())?!1:i>=new Date(a.min)&&i<=new Date(a.max)}return!0}}return n==null?!1:String(n).toLowerCase().includes(String(a).toLowerCase())}function rn({entity:n,data:a,filters:p,onFiltersChange:C,fieldsToFilter:M}){const{t:c}=_("crud"),{t:g}=_(n.namespace),i=j(()=>M&&M.length>0?M:n.listFields||Object.keys(n.fields),[M,n.listFields,n.fields]),I=j(()=>{const t={};return i.forEach(e=>{const d=Object.fromEntries(Object.entries(p).filter(([l])=>l!==e));if(Object.keys(d).length===0){t[e]=a;return}t[e]=a.filter(l=>Object.entries(d).every(([w,F])=>{const b=l[w],h=n.fields[w]?.type||"text";return X(b,F,h)}))}),t},[a,p,n.fields,i]),P=j(()=>{const t={};return i.forEach(e=>{const d=n.fields[e];if(!d)return;const l=d.type||"text",w=l==="date"||l==="datetime-local"||l==="timestamp";if(l==="number"||l==="range"){const b=a.map(s=>s[e]).filter(s=>s!=null&&s!=="").map(s=>typeof s=="number"?s:Number(s)).filter(s=>!isNaN(s));b.length>0&&(t[e]={min:Math.min(...b),max:Math.max(...b)})}else if(w){const b=a.map(s=>s[e]).filter(s=>s!=null&&s!=="").map(s=>s instanceof Date?s:new Date(s)).filter(s=>!isNaN(s.getTime()));if(b.length>0){const s=new Date(Math.min(...b.map(O=>O.getTime()))),h=new Date(Math.max(...b.map(O=>O.getTime()))),Y=s.toISOString().split("T")[0],y=h.toISOString().split("T")[0];t[e]={min:Y||"",max:y||""}}}}),t},[a,n.fields,i]),D=(t,e)=>{const d={...p};if(!e||e==="")delete d[t];else if(typeof e=="object"&&"min"in e){const l=e.min&&e.min!=="",w=e.max&&e.max!=="";!l&&!w?delete d[t]:d[t]=e}else d[t]=e;C(d)},N=()=>{C({})},v=j(()=>i.length===0?null:i.map(t=>{const e=n.fields[t];if(!e)return null;const d=U(t,e,g),l=e.type||"text",w=l==="date"||l==="datetime-local"||l==="timestamp",F=l==="number"||l==="range",b=l==="year",s=l==="select"||l==="radio"||l==="combobox",h=p[t],y=typeof h=="object"&&h!==null&&"min"in h?h:{min:"",max:""};if(b){const u=e.validation?.min??1900,m=e.validation?.max??new Date().getFullYear()+10,o=[];for(let r=m;r>=u;r--)o.push({value:String(r),label:String(r)});return x("div",{style:{gridColumn:"span 2",gridRow:"span 1"},children:x(B,{label:d,value:typeof h=="string"?h:void 0,onValueChange:r=>{D(t,r==="all"||!r?"":String(r))},options:o,placeholder:c("filter.placeholder",{defaultValue:"Filter..."}),clearable:!0,creatable:!0})},t)}if(F){const u=P[t],m=u?.min??0,o=u?.max??100,r=y.min?Number(y.min):m,f=y.max?Number(y.max):o;return E(A,{gap:"tight",style:{gridColumn:"span 2",gridRow:"span 2"},children:[x(W,{type:"number",label:d,minPlaceholder:c("filter.min",{defaultValue:"Min"}),maxPlaceholder:c("filter.max",{defaultValue:"Max"}),minValue:y.min||"",maxValue:y.max||"",actualMin:m,actualMax:o,onChange:(S,J)=>{D(t,{min:S,max:J})},onClear:()=>D(t,void 0)}),x(K,{value:[r,f],min:m,max:o,step:1,onValueChange:S=>{D(t,{min:String(S[0]),max:String(S[1])})}})]},t)}if(w){const u=P[t],m=u?.min||"",o=u?.max||"";return E(A,{gap:"tight",style:{gridColumn:"span 2",gridRow:"span 2"},children:[x(W,{type:"date",label:d,minPlaceholder:c("filter.from",{defaultValue:"From"}),maxPlaceholder:c("filter.to",{defaultValue:"To"}),minValue:y.min||"",maxValue:y.max||"",actualMin:m,actualMax:o,min:m,max:o,onChange:(r,f)=>{D(t,{min:r,max:f})},onClear:()=>D(t,void 0)}),E(A,{direction:"row",gap:"tight",children:[x(k,{variant:"outline",display:"compact",onClick:()=>{const r=new Date().toISOString().split("T")[0];D(t,{min:r,max:r})},children:c("filter.today",{defaultValue:"Today"})}),x(k,{variant:"outline",display:"compact",onClick:()=>{const r=new Date,f=new Date(r);f.setDate(r.getDate()-r.getDay());const S=new Date(f);S.setDate(f.getDate()+6),D(t,{min:f.toISOString().split("T")[0],max:S.toISOString().split("T")[0]})},children:c("filter.thisWeek",{defaultValue:"This Week"})}),x(k,{variant:"outline",display:"compact",onClick:()=>{const r=new Date,f=new Date(r.getFullYear(),r.getMonth(),1),S=new Date(r.getFullYear(),r.getMonth()+1,0);D(t,{min:f.toISOString().split("T")[0],max:S.toISOString().split("T")[0]})},children:c("filter.thisMonth",{defaultValue:"This Month"})})]})]},t)}const L=s&&e.validation&&"options"in e.validation&&e.validation?Array.isArray(e.validation.options)?e.validation.options:typeof e.validation.options=="function"?e.validation.options():[]:[],H=I[t]||a,R=new Set;H.forEach(u=>{const m=u[t];m!=null&&R.add(String(m))});const T=[{value:"all",label:c("filter.selectPlaceholder",{defaultValue:"All"})}];if(L.length>0){const u=[],m=[];L.forEach(o=>{const r=typeof o=="string"?o:o.value,f=typeof o=="string"?o:o.label;R.has(r)?u.push({value:r,label:f}):m.push({value:r,label:f})}),u.sort((o,r)=>o.label.localeCompare(r.label)),m.sort((o,r)=>o.label.localeCompare(r.label)),u.forEach(o=>{T.push({value:o.value,label:G(o.label,g),disabled:!1})}),m.forEach(o=>{T.push({value:o.value,label:G(o.label,g),disabled:!0})})}else Array.from(R).sort().slice(0,100).forEach(u=>{T.push({value:u,label:u})});return x("div",{style:{gridColumn:"span 2",gridRow:"span 1"},children:x(B,{label:d,value:typeof h=="string"?h:void 0,onValueChange:u=>{D(t,u==="all"||!u?"":String(u))},options:T,placeholder:c("filter.placeholder",{defaultValue:"Filter..."}),clearable:!0})},t)}),[i,n.fields,a,p,g,c,I]);if(!v||v.length===0)return null;const q=v.filter(Boolean),z=Object.keys(p).length>0;return E(Q,{cols:[2,4,6,8],gap:"medium",style:{gridAutoRows:"min-content"},children:[q,x(k,{variant:"outline",onClick:N,disabled:!z,style:{gridColumn:"1 / -1",gridRow:"span 1"},children:c("filter.clear",{defaultValue:"Clear Filters"})})]})}export{rn as EntityFilters,X as matchesFilter};
1
+ "use client";import{jsx as g,jsxs as R}from"react/jsx-runtime";import{useMemo as B,useState as Q}from"react";import{FilterX as U}from"lucide-react";import{Button as j,Calendar as Z,Combobox as V,Grid as ee,Popover as te,RangeInput as ne,Slider as re,Stack as z,Text as X}from"@donotdev/components";import{useTranslation as q,handleError as N}from"@donotdev/core";import{translateFieldLabel as ie,translateLabel as H}from"../forms/utils";import{getFilterType as W,isFilterable as se}from"../fieldTypeRegistry";function oe(e,t,s){if(!t)return!0;if(typeof t=="object"&&"min"in t){const l=W(s);if(!l)throw N(new Error(`Field type "${s}" not registered in field type registry`),{userMessage:`Field type "${s}" is missing from registry`,context:{fieldType:s,operation:"filter_matching",fix:"Add to registerBuiltinFieldTypes.ts or registerFieldType()"}});const C=l==="range"&&(s==="date"||s==="datetime-local"||s==="timestamp"),F=l==="range"&&!C,S=s==="price",u=S&&e!=null&&typeof e=="object"?Number(e.amount):F&&e!=null?typeof e=="number"?e:Number(e):NaN;if(F||S){const d=t.min&&t.min!=="",y=t.max&&t.max!=="";return d&&!y?e==null||isNaN(u)?!1:u>=Number(t.min):!d&&y?e==null?!0:isNaN(u)?!1:u<=Number(t.max):d&&y?e==null||isNaN(u)?!1:u>=Number(t.min)&&u<=Number(t.max):!0}if(C){const d=t.min&&t.min!=="",y=t.max&&t.max!=="";if(d&&!y){if(e==null)return!1;const x=e instanceof Date?e:new Date(e);return isNaN(x.getTime())?!1:x>=new Date(t.min)}if(!d&&y){if(e==null)return!0;const x=e instanceof Date?e:new Date(e);return isNaN(x.getTime())?!1:x<=new Date(t.max)}if(d&&y){if(e==null)return!1;const x=e instanceof Date?e:new Date(e);return isNaN(x.getTime())?!1:x>=new Date(t.min)&&x<=new Date(t.max)}return!0}}const h=W(s);if(!h)throw N(new Error(`Field type "${s}" not registered in field type registry`),{userMessage:`Field type "${s}" is missing from registry`,context:{fieldType:s,operation:"filter_matching",fix:"Add to registerBuiltinFieldTypes.ts or registerFieldType()"}});if(h==="address")return e==null?!1:typeof e=="object"&&"formatted_address"in e?String(e.formatted_address).toLowerCase().includes(String(t).toLowerCase()):!1;if(h==="multiselect"){if(!Array.isArray(e)||e.length===0)return!1;const l=String(t).toLowerCase();return e.some(C=>String(C).toLowerCase().includes(l))}return e==null?!1:String(e).toLowerCase().includes(String(t).toLowerCase())}function ae(e,t,s){if(!e&&!t)return s??"From \u2013 To";const h=e?new Date(e+"T00:00:00").toLocaleDateString(void 0,{day:"numeric",month:"short",year:"numeric"}):"",l=t?new Date(t+"T00:00:00").toLocaleDateString(void 0,{day:"numeric",month:"short",year:"numeric"}):"";return h&&l?`${h} \u2013 ${l}`:h?`${h} \u2013 \u2026`:l?`\u2026 \u2013 ${l}`:s??"From \u2013 To"}function le({label:e,rangeFilter:t,onRangeChange:s,onClear:h,tCrud:l}){const[C,F]=Q(!1),S=!!(t.min||t.max),u=t.min||t.max?{from:t.min?new Date(t.min+"T00:00:00"):void 0,to:t.max?new Date(t.max+"T00:00:00"):void 0}:void 0,d=a=>{if(!a){h();return}const b=a.from?a.from.toISOString().split("T")[0]:"",O=a.to?a.to.toISOString().split("T")[0]:"";s(b,O),a.from&&a.to&&F(!1)},y=(a,b)=>{s(a,b),F(!1)},x=()=>{h(),F(!1)},E=ae(t.min,t.max,l("filter.fromTo",{defaultValue:"From \u2013 To"}));return g(te,{open:C,onOpenChange:F,trigger:g(j,{variant:"outline",display:"compact",className:"dndev-w-full dndev-justify-between","aria-haspopup":"dialog","aria-expanded":C,"aria-label":e,children:R(X,{as:"span",level:"small",variant:S?void 0:"muted",children:[e,": ",E]})}),children:R(z,{gap:"medium",style:{padding:"var(--gap-md)"},children:[g(X,{as:"span",level:"small",variant:"muted",children:e}),R(z,{direction:"row",gap:"tight",children:[g(j,{variant:"outline",display:"compact",onClick:()=>{const a=new Date().toISOString().split("T")[0];y(a,a)},children:l("filter.today",{defaultValue:"Today"})}),g(j,{variant:"outline",display:"compact",onClick:()=>{const a=new Date,b=new Date(a);b.setDate(a.getDate()-a.getDay());const O=new Date(b);O.setDate(b.getDate()+6),y(b.toISOString().split("T")[0],O.toISOString().split("T")[0])},children:l("filter.thisWeek",{defaultValue:"This Week"})}),g(j,{variant:"outline",display:"compact",onClick:()=>{const a=new Date,b=new Date(a.getFullYear(),a.getMonth(),1),O=new Date(a.getFullYear(),a.getMonth()+1,0);y(b.toISOString().split("T")[0],O.toISOString().split("T")[0])},children:l("filter.thisMonth",{defaultValue:"This Month"})})]}),g(Z,{mode:"range",selected:u,onSelect:d,defaultMonth:u?.from??u?.to??new Date}),g(j,{variant:"ghost",display:"compact",onClick:x,children:l("filter.clearDate",{defaultValue:"Clear"})})]})})}function he({entity:e,data:t,filters:s,onFiltersChange:h,fieldsToFilter:l,variant:C="inline"}){const F=C==="sidebar",{t:S}=q("crud"),{t:u}=q(e.namespace),d=B(()=>(l&&l.length>0?l:e.listFields||Object.keys(e.fields)).filter(n=>{const o=e.fields[n]?.type||"text";return se(o)}),[l,e.listFields,e.fields]),y=B(()=>{const r={};return d.forEach(n=>{const m=Object.fromEntries(Object.entries(s).filter(([o])=>o!==n));if(Object.keys(m).length===0){r[n]=t;return}r[n]=t.filter(o=>Object.entries(m).every(([w,v])=>{const A=o[w],p=e.fields[w]?.type||"text";return oe(A,v,p)}))}),r},[t,s,e.fields,d]),x=B(()=>{const r={};return d.forEach(n=>{const m=e.fields[n];if(!m)return;const o=m.type||"text",w=W(o);if(!w){N(new Error(`Field type "${o}" not registered in field type registry`),{userMessage:`Field type "${o}" is missing from registry`,context:{fieldType:o,fieldName:n,operation:"minmax_computation",fix:"Add to registerBuiltinFieldTypes.ts or registerFieldType()"},severity:"warning"});return}const v=w==="range"&&(o==="date"||o==="datetime-local"||o==="timestamp"),A=w==="range"&&!v,k=o==="price";if(A||k){const p=t.map(i=>i[n]).filter(i=>i!=null&&i!=="").map(i=>k&&typeof i=="object"&&i!==null?Number(i.amount):typeof i=="number"?i:Number(i)).filter(i=>!isNaN(i));p.length>0&&(r[n]={min:Math.min(...p),max:Math.max(...p)})}else if(v){const p=t.map(i=>i[n]).filter(i=>i!=null&&i!=="").map(i=>i instanceof Date?i:new Date(i)).filter(i=>!isNaN(i.getTime()));if(p.length>0){const i=new Date(Math.min(...p.map(L=>L.getTime()))),T=new Date(Math.max(...p.map(L=>L.getTime()))),G=i.toISOString().split("T")[0],I=T.toISOString().split("T")[0];r[n]={min:G||"",max:I||""}}}}),r},[t,e.fields,d]),E=(r,n)=>{const m={...s};if(!n||n==="")delete m[r];else if(typeof n=="object"&&"min"in n){const o=n.min&&n.min!=="",w=n.max&&n.max!=="";!o&&!w?delete m[r]:m[r]=n}else m[r]=n;h(m)},a=()=>{h({})},b=B(()=>d.length===0?null:d.map(r=>{const n=e.fields[r];if(!n)return null;const m=ie(r,n,u),o=n.type||"text",w=W(o);if(!w)return N(new Error(`Field type "${o}" not registered in field type registry`),{userMessage:`Field type "${o}" is missing from registry`,context:{fieldType:o,fieldName:r,operation:"filter_ui_render",fix:"Add to registerBuiltinFieldTypes.ts or registerFieldType()"},severity:"warning"}),null;const v=w==="range"&&(o==="date"||o==="datetime-local"||o==="timestamp"),A=w==="range"&&!v,k=w==="select",p=s[r],T=typeof p=="object"&&p!==null&&"min"in p?p:{min:"",max:""};if(A){const f=x[r],D=f?.min??0,c=f?.max??100,M=T.min?Number(T.min):D,_=T.max?Number(T.max):c;return R(z,{gap:"tight",style:{gridColumn:"span 2",gridRow:F?void 0:"span 2"},children:[g(ne,{type:"number",label:m,minPlaceholder:S("filter.min",{defaultValue:"Min"}),maxPlaceholder:S("filter.max",{defaultValue:"Max"}),minValue:T.min||"",maxValue:T.max||"",actualMin:D,actualMax:c,onChange:($,K)=>{E(r,{min:$,max:K})},onClear:()=>E(r,void 0)}),g(re,{value:[M,_],min:D,max:c,step:1,onValueChange:$=>{E(r,{min:String($[0]),max:String($[1])})}})]},r)}if(v)return g("div",{style:{gridColumn:"span 2",gridRow:F?void 0:"span 1"},children:g(le,{label:m,rangeFilter:T,onRangeChange:(f,D)=>E(r,{min:f,max:D}),onClear:()=>E(r,void 0),tCrud:S})},r);const I=k&&n.validation&&"options"in n.validation&&n.validation?Array.isArray(n.validation.options)?n.validation.options:typeof n.validation.options=="function"?n.validation.options():[]:[],L=y[r]||t,Y=new Set;L.forEach(f=>{const D=f[r];D!=null&&Y.add(String(D))});const P=[{value:"all",label:S("filter.selectPlaceholder",{defaultValue:"All"})}];if(I.length>0){const f=[],D=[];I.forEach(c=>{const M=typeof c=="string"?c:c.value,_=typeof c=="string"?c:c.label;Y.has(M)?f.push({value:M,label:_}):D.push({value:M,label:_})}),f.sort((c,M)=>c.label.localeCompare(M.label)),D.sort((c,M)=>c.label.localeCompare(M.label)),f.forEach(c=>{P.push({value:c.value,label:H(c.label,u),disabled:!1})}),D.forEach(c=>{P.push({value:c.value,label:H(c.label,u),disabled:!0})})}else Array.from(Y).sort().slice(0,100).forEach(f=>{P.push({value:f,label:f})});return g("div",{style:{gridColumn:"span 2",gridRow:"span 1"},children:g(V,{label:m,value:typeof p=="string"?p:void 0,onValueChange:f=>{E(r,f==="all"||!f?"":String(f))},options:P,placeholder:S("filter.placeholder",{defaultValue:"Filter..."}),clearable:!0})},r)}),[d,e.fields,t,s,u,S,y]);if(!b||b.length===0)return null;const O=b.filter(Boolean),J=Object.keys(s).length>0;return R(ee,{cols:C==="sidebar"?2:[2,4,6,8],gap:"medium",style:{gridAutoRows:"min-content"},children:[O,g(j,{variant:"outline",icon:g(U,{size:18}),onClick:a,disabled:!J,style:{gridColumn:"1 / -1",gridRow:"span 1"},children:S("filter.clear",{defaultValue:"Clear Filters"})})]})}export{he as EntityFilters,oe as matchesFilter};
@@ -1 +1 @@
1
- {"version":3,"file":"FormFieldRenderer.d.ts","sourceRoot":"","sources":["../../src/components/FormFieldRenderer.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAKhF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAM5D,OAAO,sBAAsB,CAAC;AAM9B,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,CAmGxD;AAED,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"FormFieldRenderer.d.ts","sourceRoot":"","sources":["../../src/components/FormFieldRenderer.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAKhF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAM5D,OAAO,sBAAsB,CAAC;AAM9B,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,CA0GxD;AAED,eAAe,iBAAiB,CAAC"}
@@ -1 +1 @@
1
- "use client";import{jsx as l}from"react/jsx-runtime";import{handleError as f}from"@donotdev/core";import{getFieldRegistry as v}from"../FieldRegistry";import{ControlledTextField as F}from"./controlled";import{TextFieldComponent as T}from"./form/fields";import"../builtinFieldTypes";const h=v();function g({name:r,config:e,t,...o}){const a=s=>d=>{try{s(d)}catch(n){f(n,{userMessage:`Error updating field ${e.label||r}`,context:{fieldName:r,fieldType:e.type},severity:"warning"})}},i="control"in o&&o.control,p=e.type==="submit"||e.type==="reset";if(i&&!p){const{control:s,errors:d}=o,n={control:s,errors:d,fieldConfig:{...e,label:e.label||r},t,onChange:a(()=>{})},c=h.getControlledComponent(e.type);return c?l(c,{...n}):(f(new Error(`Unregistered field type: ${e.type}`),{userMessage:t("errors.unsupportedFieldType",{type:e.type}),context:{fieldName:r,fieldType:e.type},severity:"warning"}),l(F,{...n,fieldConfig:{...e,type:"text"}}))}const x=i&&p?{name:r,config:e,t,value:void 0,onChange:()=>{},error:void 0}:o,{value:u,onChange:b,error:y}=x,C=a(b),m=h.getUncontrolledComponent(e.type);return m?l(m,{name:r,label:e.label||r,value:u,onChange:C,error:y,t,config:e,...e.options}):l(T,{label:e.label||r,value:u,onChange:C,error:y||void 0,...e.options})}var P=g;export{g as FormFieldRenderer,P as default};
1
+ "use client";import{jsx as l}from"react/jsx-runtime";import{handleError as h}from"@donotdev/core";import{getFieldRegistry as T}from"../FieldRegistry";import{ControlledTextField as S}from"./controlled";import{TextFieldComponent as g}from"./form/fields";import"../builtinFieldTypes";const x=T();function w({name:r,config:e,t,...o}){const s=n=>d=>{try{n(d)}catch(C){h(C,{userMessage:`Error updating field ${e.label||r}`,context:{fieldName:r,fieldType:e.type},severity:"warning"})}},i="control"in o&&o.control,p=e.type==="submit"||e.type==="reset";if(i&&!p){const{control:n,errors:d}=o,F=e.options?.fieldSpecific?.placeholder,f={control:n,errors:d,fieldConfig:{...e,label:e.label||r},t,placeholder:F,onChange:s(()=>{})},m=x.getControlledComponent(e.type);return m?l(m,{...f}):(h(new Error(`Unregistered field type: ${e.type}`),{userMessage:t("errors.unsupportedFieldType",{type:e.type}),context:{fieldName:r,fieldType:e.type},severity:"warning"}),l(S,{...f,fieldConfig:{...e,type:"text"}}))}const b=i&&p?{name:r,config:e,t,value:void 0,onChange:()=>{},error:void 0}:o,{value:a,onChange:v,error:u}=b,y=s(v),c=x.getUncontrolledComponent(e.type);return c?l(c,{name:r,label:e.label||r,value:a,onChange:y,error:u,t,config:e,...e.options}):l(g,{label:e.label||r,value:a,onChange:y,error:u||void 0,...e.options})}var R=w;export{w as FormFieldRenderer,R as default};
@@ -0,0 +1,8 @@
1
+ import { type ControlledFieldProps } from '../types';
2
+ import type { ReactElement } from 'react';
3
+ /**
4
+ * ControlledCurrencyField - Explicit controlled component for currency inputs
5
+ * Uses CurrencyFieldComponent with currency code from field options
6
+ */
7
+ export declare function ControlledCurrencyField(props: ControlledFieldProps): ReactElement;
8
+ //# sourceMappingURL=ControlledCurrencyField.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ControlledCurrencyField.d.ts","sourceRoot":"","sources":["../../../../src/components/controlled/input/ControlledCurrencyField.tsx"],"names":[],"mappings":"AAOA,OAAO,EAA0B,KAAK,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAI7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE1C;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,oBAAoB,GAC1B,YAAY,CA4Dd"}