@donotdev/crud 0.0.16 → 0.0.18

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 (201) hide show
  1. package/dist/CrudService.d.ts.map +1 -1
  2. package/dist/CrudService.js +2 -2
  3. package/dist/CrudStore.d.ts.map +1 -1
  4. package/dist/CrudStore.js +1 -1
  5. package/dist/FieldRegistry.d.ts.map +1 -1
  6. package/dist/FieldRegistry.js +1 -1
  7. package/dist/adapters/FunctionsAdapter.d.ts.map +1 -1
  8. package/dist/adapters/FunctionsAdapter.js +1 -1
  9. package/dist/components/CrudButton.js +1 -1
  10. package/dist/components/CrudCard.d.ts.map +1 -1
  11. package/dist/components/CrudCard.js +1 -1
  12. package/dist/components/DateFilter.js +1 -1
  13. package/dist/components/DisplayFieldRenderer.js +1 -1
  14. package/dist/components/DisplayThumbnail.js +1 -1
  15. package/dist/components/EntityFilters.d.ts +1 -34
  16. package/dist/components/EntityFilters.d.ts.map +1 -1
  17. package/dist/components/EntityFilters.js +1 -1
  18. package/dist/components/FormFieldRenderer.js +1 -1
  19. package/dist/components/FormLayout.js +1 -1
  20. package/dist/components/controlled/complex/ControlledAddressField.js +1 -1
  21. package/dist/components/controlled/complex/ControlledDateField.js +1 -1
  22. package/dist/components/controlled/complex/ControlledFieldArrayField.d.ts +18 -0
  23. package/dist/components/controlled/complex/ControlledFieldArrayField.d.ts.map +1 -0
  24. package/dist/components/controlled/complex/ControlledFieldArrayField.js +1 -0
  25. package/dist/components/controlled/complex/ControlledGeoPointField.js +1 -1
  26. package/dist/components/controlled/complex/ControlledMapField.js +1 -1
  27. package/dist/components/controlled/complex/ControlledMultiInputField.js +1 -1
  28. package/dist/components/controlled/complex/ControlledRichTextField.js +1 -1
  29. package/dist/components/controlled/complex/ControlledTimestampField.js +1 -1
  30. package/dist/components/controlled/complex/index.d.ts +1 -0
  31. package/dist/components/controlled/complex/index.d.ts.map +1 -1
  32. package/dist/components/controlled/complex/index.js +1 -1
  33. package/dist/components/controlled/file/ControlledDocumentField.js +1 -1
  34. package/dist/components/controlled/file/ControlledFileField.js +1 -1
  35. package/dist/components/controlled/file/ControlledImageField.js +1 -1
  36. package/dist/components/controlled/file/ControlledMultiDocumentField.js +1 -1
  37. package/dist/components/controlled/file/ControlledMultiFileField.js +1 -1
  38. package/dist/components/controlled/file/ControlledMultiImageField.js +1 -1
  39. package/dist/components/controlled/file/index.js +1 -1
  40. package/dist/components/controlled/index.js +1 -1
  41. package/dist/components/controlled/input/ControlledCheckboxField.js +1 -1
  42. package/dist/components/controlled/input/ControlledCurrencyField.js +1 -1
  43. package/dist/components/controlled/input/ControlledDurationField.js +1 -1
  44. package/dist/components/controlled/input/ControlledGdprConsentField.js +1 -1
  45. package/dist/components/controlled/input/ControlledNumberField.js +1 -1
  46. package/dist/components/controlled/input/ControlledPasswordField.js +1 -1
  47. package/dist/components/controlled/input/ControlledPhoneField.js +1 -1
  48. package/dist/components/controlled/input/ControlledPriceField.js +1 -1
  49. package/dist/components/controlled/input/ControlledRangeField.js +1 -1
  50. package/dist/components/controlled/input/ControlledRatingField.js +1 -1
  51. package/dist/components/controlled/input/ControlledSwitchField.js +1 -1
  52. package/dist/components/controlled/input/ControlledTextField.js +1 -1
  53. package/dist/components/controlled/input/ControlledTextareaField.js +1 -1
  54. package/dist/components/controlled/input/index.js +1 -1
  55. package/dist/components/controlled/select/ControlledComboboxField.js +1 -1
  56. package/dist/components/controlled/select/ControlledDropdownField.js +1 -1
  57. package/dist/components/controlled/select/ControlledMultiDropdownField.js +1 -1
  58. package/dist/components/controlled/select/ControlledRadioField.js +1 -1
  59. package/dist/components/controlled/select/ControlledYearField.js +1 -1
  60. package/dist/components/controlled/select/index.js +1 -1
  61. package/dist/components/controlled/types.js +1 -1
  62. package/dist/components/fields/display/AvatarFieldDisplay.js +1 -1
  63. package/dist/components/fields/display/BadgeFieldDisplay.js +1 -1
  64. package/dist/components/fields/display/ButtonFieldDisplay.js +1 -1
  65. package/dist/components/fields/display/CheckboxFieldDisplay.js +1 -1
  66. package/dist/components/fields/display/DateFieldDisplay.js +1 -1
  67. package/dist/components/fields/display/DropdownDisplay.js +1 -1
  68. package/dist/components/fields/display/FileFieldDisplay.js +1 -1
  69. package/dist/components/fields/display/GeoPointFieldDisplay.js +1 -1
  70. package/dist/components/fields/display/HiddenFieldDisplay.js +1 -1
  71. package/dist/components/fields/display/ImageFieldDisplay.js +1 -1
  72. package/dist/components/fields/display/LinkFieldDisplay.js +1 -1
  73. package/dist/components/fields/display/MapFieldDisplay.js +1 -1
  74. package/dist/components/fields/display/MultiDropdownDisplay.js +1 -1
  75. package/dist/components/fields/display/MultiInputTextFieldDisplay.js +1 -1
  76. package/dist/components/fields/display/NumberFieldDisplay.js +1 -1
  77. package/dist/components/fields/display/PasswordFieldDisplay.js +1 -1
  78. package/dist/components/fields/display/PhoneNumberDisplay.js +1 -1
  79. package/dist/components/fields/display/RadioFieldDisplay.js +1 -1
  80. package/dist/components/fields/display/RangeFieldDisplay.js +1 -1
  81. package/dist/components/fields/display/ReferenceFieldDisplay.js +1 -1
  82. package/dist/components/fields/display/RichTextDisplay.js +2 -2
  83. package/dist/components/fields/display/TextAreaDisplay.js +1 -1
  84. package/dist/components/fields/display/TextFieldDisplay.js +1 -1
  85. package/dist/components/fields/display/TimestampFieldDisplay.js +1 -1
  86. package/dist/components/fields/display/index.js +1 -1
  87. package/dist/components/form/fields/AddressFieldComponent.js +1 -1
  88. package/dist/components/form/fields/AvatarFieldComponent.js +1 -1
  89. package/dist/components/form/fields/BadgeFieldComponent.js +1 -1
  90. package/dist/components/form/fields/ButtonFieldComponent.js +1 -1
  91. package/dist/components/form/fields/CheckboxFieldComponent.js +1 -1
  92. package/dist/components/form/fields/ComboboxComponent.js +1 -1
  93. package/dist/components/form/fields/CurrencyFieldComponent.js +1 -1
  94. package/dist/components/form/fields/DateFieldComponent.js +1 -1
  95. package/dist/components/form/fields/DocumentFieldComponent.d.ts.map +1 -1
  96. package/dist/components/form/fields/DocumentFieldComponent.js +1 -1
  97. package/dist/components/form/fields/DropdownComponent.js +1 -1
  98. package/dist/components/form/fields/DurationFieldComponent.js +1 -1
  99. package/dist/components/form/fields/FileFieldComponent.d.ts.map +1 -1
  100. package/dist/components/form/fields/FileFieldComponent.js +1 -1
  101. package/dist/components/form/fields/GdprConsentFieldComponent.js +1 -1
  102. package/dist/components/form/fields/GeoPointFieldComponent.js +1 -1
  103. package/dist/components/form/fields/HiddenFieldComponent.js +1 -1
  104. package/dist/components/form/fields/ImageFieldComponent.js +1 -1
  105. package/dist/components/form/fields/MapFieldComponent.js +1 -1
  106. package/dist/components/form/fields/MultiDropdownComponent.js +1 -1
  107. package/dist/components/form/fields/MultiInputTextFieldComponent.js +1 -1
  108. package/dist/components/form/fields/NumberFieldComponent.js +1 -1
  109. package/dist/components/form/fields/PasswordFieldComponent.js +1 -1
  110. package/dist/components/form/fields/PhoneNumberComponent.js +1 -1
  111. package/dist/components/form/fields/PriceFieldComponent.js +1 -1
  112. package/dist/components/form/fields/RadioFieldComponent.js +1 -1
  113. package/dist/components/form/fields/RangeFieldComponent.js +1 -1
  114. package/dist/components/form/fields/RatingFieldComponent.js +1 -1
  115. package/dist/components/form/fields/ReferenceFieldComponent.js +1 -1
  116. package/dist/components/form/fields/RichTextComponent.js +1 -1
  117. package/dist/components/form/fields/SwitchFieldComponent.js +1 -1
  118. package/dist/components/form/fields/TextAreaComponent.js +1 -1
  119. package/dist/components/form/fields/TextFieldComponent.js +1 -1
  120. package/dist/components/form/fields/TimestampFieldComponent.js +1 -1
  121. package/dist/components/form/fields/index.js +1 -1
  122. package/dist/components/form/fields/internal/TiptapEditor.d.ts.map +1 -1
  123. package/dist/components/form/fields/internal/TiptapEditor.js +2 -2
  124. package/dist/components/form/internal/ImageViewerDialog.js +1 -1
  125. package/dist/components/index.d.ts +2 -1
  126. package/dist/components/index.d.ts.map +1 -1
  127. package/dist/components/index.js +1 -1
  128. package/dist/contexts/UploadContext.js +1 -1
  129. package/dist/contexts/index.js +1 -1
  130. package/dist/fieldTypeRegistry.js +1 -1
  131. package/dist/forms/hooks/index.js +1 -1
  132. package/dist/forms/hooks/useController.js +1 -1
  133. package/dist/forms/hooks/useEntityField.d.ts +15 -24
  134. package/dist/forms/hooks/useEntityField.d.ts.map +1 -1
  135. package/dist/forms/hooks/useEntityField.js +1 -1
  136. package/dist/forms/hooks/useEntityForm.d.ts.map +1 -1
  137. package/dist/forms/hooks/useEntityForm.js +1 -1
  138. package/dist/forms/index.js +1 -1
  139. package/dist/forms/types.d.ts +13 -0
  140. package/dist/forms/types.d.ts.map +1 -1
  141. package/dist/forms/utils/buildInitialValues.d.ts.map +1 -1
  142. package/dist/forms/utils/buildInitialValues.js +1 -1
  143. package/dist/forms/utils/getFieldsForOperation.js +1 -1
  144. package/dist/forms/utils/index.js +1 -1
  145. package/dist/forms/utils/isFieldEditable.js +1 -1
  146. package/dist/forms/utils/translateFieldLabel.js +1 -1
  147. package/dist/forms/utils/validateEntity.js +1 -1
  148. package/dist/hooks/useCrudFilters.js +1 -1
  149. package/dist/hooks/useEntityFavorites.js +1 -1
  150. package/dist/hooks/useFileUpload.d.ts.map +1 -1
  151. package/dist/hooks/useFileUpload.js +1 -1
  152. package/dist/hooks/useRelatedItems.js +1 -1
  153. package/dist/index.d.ts +4 -0
  154. package/dist/index.d.ts.map +1 -1
  155. package/dist/index.js +1 -1
  156. package/dist/registerBuiltinFieldTypes.d.ts.map +1 -1
  157. package/dist/registerBuiltinFieldTypes.js +1 -1
  158. package/dist/stores/FormStore.js +1 -1
  159. package/dist/stores/UploadStore.d.ts.map +1 -1
  160. package/dist/stores/UploadStore.js +1 -1
  161. package/dist/stores/index.js +1 -1
  162. package/dist/tsconfig.tsbuildinfo +1 -1
  163. package/dist/types.js +1 -1
  164. package/dist/useBaseCrudList.d.ts.map +1 -1
  165. package/dist/useBaseCrudList.js +1 -1
  166. package/dist/useCrud.js +1 -1
  167. package/dist/useCrudCardList.d.ts +14 -19
  168. package/dist/useCrudCardList.d.ts.map +1 -1
  169. package/dist/useCrudCardList.js +1 -1
  170. package/dist/useCrudList.d.ts +19 -18
  171. package/dist/useCrudList.d.ts.map +1 -1
  172. package/dist/useCrudList.js +1 -1
  173. package/dist/utils/clientListProcessing.d.ts +82 -0
  174. package/dist/utils/clientListProcessing.d.ts.map +1 -0
  175. package/dist/utils/clientListProcessing.js +1 -0
  176. package/dist/utils/collections.js +1 -1
  177. package/dist/utils/fileStorage.d.ts.map +1 -1
  178. package/dist/utils/fileStorage.js +1 -1
  179. package/dist/utils/imageProcessing.js +1 -1
  180. package/dist/utils/imageStorage.d.ts.map +1 -1
  181. package/dist/utils/imageStorage.js +1 -1
  182. package/dist/utils/imageUtils.js +1 -1
  183. package/dist/utils/matchesFilter.d.ts +45 -0
  184. package/dist/utils/matchesFilter.d.ts.map +1 -0
  185. package/dist/utils/matchesFilter.js +1 -0
  186. package/dist/utils/mergeWithOptimistic.d.ts.map +1 -1
  187. package/dist/utils/mergeWithOptimistic.js +1 -1
  188. package/dist/utils/sanitizeHtml.js +1 -1
  189. package/dist/utils/scopeUtils.js +1 -1
  190. package/dist/utils/uploadValidation.d.ts.map +1 -1
  191. package/dist/utils/uploadValidation.js +1 -1
  192. package/package.json +8 -5
  193. package/dist/components/__tests__/EntityFilters.test.d.ts +0 -2
  194. package/dist/components/__tests__/EntityFilters.test.d.ts.map +0 -1
  195. package/dist/components/__tests__/EntityFilters.test.js +0 -1
  196. package/dist/components/__tests__/FormFieldRenderer.test.d.ts +0 -2
  197. package/dist/components/__tests__/FormFieldRenderer.test.d.ts.map +0 -1
  198. package/dist/components/__tests__/FormFieldRenderer.test.js +0 -1
  199. package/dist/hooks/useFormNavigationGuard.d.ts +0 -34
  200. package/dist/hooks/useFormNavigationGuard.d.ts.map +0 -1
  201. package/dist/hooks/useFormNavigationGuard.js +0 -1
package/dist/types.js CHANGED
@@ -1 +1 @@
1
- const E={PENDING:"pending",CONFIRMED:"confirmed",FAILED:"failed"},e={ADD:"add",UPDATE:"update",SET:"set",DELETE:"delete"};export{e as CRUD_OPERATION,E as OPTIMISTIC_STATUSES};
1
+ const e={PENDING:"pending",CONFIRMED:"confirmed",FAILED:"failed"},E={ADD:"add",UPDATE:"update",SET:"set",DELETE:"delete"};export{E as CRUD_OPERATION,e as OPTIMISTIC_STATUSES};
@@ -1 +1 @@
1
- {"version":3,"file":"useBaseCrudList.d.ts","sourceRoot":"","sources":["../src/useBaseCrudList.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,cAAc,EAAe,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAQvG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAKhD,+BAA+B;AAC/B,MAAM,WAAW,gBAAgB;IAC/B,uEAAuE;IACvE,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,kCAAkC;AAClC,MAAM,WAAW,sBAAsB,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;IAClE,wDAAwD;IACxD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,sCAAsC;AACtC,MAAM,WAAW,qBAAqB,CAAC,CAAC;IACtC,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,EAAE;QAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5C,mDAAmD;IACnD,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,iDAAiD;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,6DAA6D;IAC7D,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,8BAA8B;IAC9B,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,wCAAwC;IACxC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACvE,kBAAkB,EAAE,MAAM,GAAG,MAAM,EACnC,UAAU,EAAE,cAAc,EAC1B,UAAU,EAAE,gBAAgB,GAAG,IAAI,EACnC,OAAO,GAAE,sBAAsB,CAAC,CAAC,CAAM,GACtC,qBAAqB,CAAC,CAAC,CAAC,CAwO1B"}
1
+ {"version":3,"file":"useBaseCrudList.d.ts","sourceRoot":"","sources":["../src/useBaseCrudList.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,MAAM,EACN,aAAa,EACb,cAAc,EAEd,YAAY,EACb,MAAM,gBAAgB,CAAC;AAQxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAKhD,+BAA+B;AAC/B,MAAM,WAAW,gBAAgB;IAC/B,uEAAuE;IACvE,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,kCAAkC;AAClC,MAAM,WAAW,sBAAsB,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;IAClE,wDAAwD;IACxD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,sCAAsC;AACtC,MAAM,WAAW,qBAAqB,CAAC,CAAC;IACtC,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,EAAE;QAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5C,mDAAmD;IACnD,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,iDAAiD;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,6DAA6D;IAC7D,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,8BAA8B;IAC9B,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,wCAAwC;IACxC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACvE,kBAAkB,EAAE,MAAM,GAAG,MAAM,EACnC,UAAU,EAAE,cAAc,EAC1B,UAAU,EAAE,gBAAgB,GAAG,IAAI,EACnC,OAAO,GAAE,sBAAsB,CAAC,CAAC,CAAM,GACtC,qBAAqB,CAAC,CAAC,CAAC,CA2O1B"}
@@ -1 +1 @@
1
- import{useMemo as D,useCallback as G,useRef as F}from"react";import{useQuery as H}from"@donotdev/core";import{useCrudStore as J}from"./CrudStore";import{useCrud as P,getCrudServiceInstance as X,EMPTY_OPTIMISTIC as Z}from"./useCrud";import{mergeWithOptimistic as $}from"./utils/mergeWithOptimistic";import{injectScopeFilter as ee,getCurrentScopeValue as te}from"./utils/scopeUtils";import{CRUD_OPERATION as Q}from"./types";function se(V,p,t,g={}){const j=g.enabled??!0,C=P("status"),a=C==="ready",x=P(V,g),{error:q,invalidate:_,_collection:m,_schemas:f,_cacheOptions:O,_scope:b}=x,M=J(e=>e.collections[m]?.optimistic||Z),T=F(new Map([[1,null]])),h=F(0),K=te(b),y=D(()=>{if(!a||!f)return null;const e=X();if(!e)return null;const v=p==="listCard"?f.listCard:f.list,d=ee(g.queryOptions,b);if(!t||t.mode==="client")return e.getListQueryOptions(m,d,v,O,p);const o=T.current,n=h.current,{page:l,pageSize:s}=t;let i,r;if(o.has(l))i=o.get(l)??void 0,r=s;else if(l>n&&o.has(n)){const u=l-n;i=o.get(n)??void 0,r=u*s}else i=void 0,r=l*s;return e.getListQueryOptions(m,{...d,limit:r,startAfter:i},v,O,p)},[a,m,O,f?"hasSchema":"noSchema",p,t?.mode,t?.page,t?.pageSize,g.queryOptions,b?.provider,K]),{data:c,isLoading:R,isFetching:k,error:B,refetch:w}=H({queryKey:y?.queryKey??["crud",m,"disabled"],queryFn:y?.queryFn??(()=>Promise.resolve({items:[]})),staleTime:y?.staleTime,enabled:j&&!!y}),A=D(()=>{if(!c||!a)return{items:[],total:void 0};let e=c.items;if(t?.mode==="server"&&e.length>0){const s=T.current,i=h.current,{page:r,pageSize:u}=t,U=e.length;if(Math.ceil(U/u)>1||r>i){const L=s.has(r)?r:i+1;for(let S=L;S<=r;S++){const z=(S-L+1)*u-1;if(z<e.length){const Y=e[z];s.set(S+1,Y.id)}}}c.lastVisible&&s.set(r+1,c.lastVisible),h.current=Math.max(i,r);const I=s.has(r)?0:(r-i-1)*u,W=I+u;e=e.slice(I,W)}const v=$(e,M),d=new Set(e.map(s=>s.id));let o=0,n=0;for(const[s,i]of Object.entries(M))i.operation===Q.ADD&&!d.has(s)?o++:i.operation===Q.DELETE&&d.has(s)&&n++;const l=(c.total??e.length)+o-n;return{items:v,total:t?l:void 0}},[c,M,a,t?.mode,t?.page,t?.pageSize]),E=G(async()=>{a&&(t?.mode==="server"&&(T.current=new Map([[1,null]]),h.current=0),await _(),await w())},[_,w,a,t?.mode]);if(!a){const e=async()=>{};return{status:C,data:{items:[],total:void 0},items:[],loading:!1,fetching:!1,error:q,mutate:e,refresh:e,isAvailable:!1}}const N=A?.items??[];return{status:C,data:A,items:N,loading:R,fetching:k,error:B??q,mutate:E,refresh:E,isAvailable:!0}}export{se as useBaseCrudList};
1
+ import{useMemo as w,useCallback as H,useRef as x}from"react";import{useQuery as J}from"@donotdev/core";import{useCrudStore as X}from"./CrudStore";import{useCrud as Q,getCrudServiceInstance as Z,EMPTY_OPTIMISTIC as $}from"./useCrud";import{mergeWithOptimistic as ee}from"./utils/mergeWithOptimistic";import{injectScopeFilter as te,getCurrentScopeValue as se}from"./utils/scopeUtils";import{CRUD_OPERATION as R}from"./types";function de(z,m,t,p={}){const V=p.enabled??!0,I=Q("status"),c=I==="ready",j=Q(z,p),{error:P,invalidate:D,_collection:a,_schemas:g,_cacheOptions:y,_scope:S}=j,q=X(e=>e.collections[a]?.optimistic||$),v=x(new Map([[1,null]])),O=x(0),K=se(S),b=w(()=>{if(!c||!g)return null;const e=Z();if(!e)return null;const f=m==="listCard"?g.listCard:g.list,u=te(p.queryOptions,S);if(!t||t.mode==="client")return e.getListQueryOptions(a,u,f,y,m);const i=v.current,n=O.current,{page:d,pageSize:h}=t;let s,r;if(i.has(d))s=i.get(d)??void 0,r=h;else if(d>n&&i.has(n)){const o=d-n;s=i.get(n)??void 0,r=o*h}else s=void 0,r=d*h;return e.getListQueryOptions(a,{...u,limit:r,startAfter:s},f,y,m)},[c,a,y,g?"hasSchema":"noSchema",m,t?.mode,t?.page,t?.pageSize,p.queryOptions,S?.provider,K]),{data:l,isLoading:k,isFetching:B,error:N,refetch:T}=J({queryKey:b?.queryKey??["crud",a,"disabled"],queryFn:b?.queryFn??(()=>Promise.resolve({items:[]})),staleTime:b?.staleTime,enabled:V&&!!b}),A=w(()=>{if(!l||!c)return{items:[],total:void 0};let e=l.items;if(t?.mode==="server"&&e.length>0){const s=v.current,r=O.current,{page:o,pageSize:C}=t,W=e.length;if(Math.ceil(W/C)>1||o>r){const M=s.has(o)?o:r+1;for(let F=M;F<=o;F++){const _=(F-M+1)*C-1;if(_<e.length){const G=e[_];s.set(F+1,G.id)}}}l.lastVisible&&s.set(o+1,l.lastVisible),O.current=Math.max(r,o);const L=s.has(o)?0:(o-r-1)*C,Y=L+C;e=e.slice(L,Y)}const f=ee(e,q),u=new Set(e.map(s=>s.id));let i=0,n=0;for(const[s,r]of Object.entries(q))r.operation===R.ADD&&!u.has(s)?i++:r.operation===R.DELETE&&u.has(s)&&n++;const h=(l.total??e.length)+i-n;return{items:f,total:t?h:void 0}},[l,q,c,t?.mode,t?.page,t?.pageSize]),E=H(async()=>{c&&(t?.mode==="server"&&(v.current=new Map([[1,null]]),O.current=0),await D(),await T())},[D,T,c,t?.mode]);if(!c){const e=async()=>{};return{status:I,data:{items:[],total:void 0},items:[],loading:!1,fetching:!1,error:P,mutate:e,refresh:e,isAvailable:!1}}const U=A?.items??[];return{status:I,data:A,items:U,loading:k,fetching:B,error:N??P,mutate:E,refresh:E,isAvailable:!0}}export{de as useBaseCrudList};
package/dist/useCrud.js CHANGED
@@ -1 +1 @@
1
- "use client";import{useEffect as K,useMemo as F,useCallback as n}from"react";import{useFeatureConsent as L,FRAMEWORK_FEATURES as W,FEATURE_STATUS as m,handleError as Z,isClient as B,createSchemas as H,DEGRADED_CRUD_API as J}from"@donotdev/core";import{getCrudService as Q}from"./CrudService";import{useCrudStore as u}from"./CrudStore";import{injectScope as M,injectScopeFilter as V}from"./utils/scopeUtils";const X={},$={};let _=null,E=null,b=!1;function r(){return _}function ee(l,d={}){const f=L(W.CRUD),U=u(e=>e.crudService),g=f&&!U,y=f?g?m.INITIALIZING:m.READY:m.DEGRADED,S=l==="status",p=!S&&typeof l=="object"?l:d.entity,a=S?"__status__":typeof l=="string"?l:l.collection,o=p?.scope,v=d.noCache??!1,T=d.staleTime,h=F(()=>({noCache:v,staleTime:T}),[v,T]),t=F(()=>{if(!S){if(d.schema){const e=d.schema;return{create:e,draft:e,update:e,get:e,list:e,listCard:e,delete:e}}if(p)return H(p)}},[S,d.schema,p?.name,a]),Y=u(e=>e.collections[a]?.loading||!1),A=u(e=>e.collections[a]?.error||null),O=null;K(()=>{if(!B()||!f||!t)return;const{crudService:e}=u.getState();e||_||E||(E=(async()=>{try{if(_||u.getState().crudService)return;const s=Q();_=s,s.setStore(u),await s.initialize(),b=!1,u.getState().setCrudService(s)}catch(s){b||(Z(s,{userMessage:"Failed to initialize CRUD service.",context:{collection:a},severity:"error"}),b=!0)}finally{E=null}})())},[f,a,t?"hasSchema":"noSchema"]);const D=g||Y,P=y===m.READY,j=n(async e=>{const s=r();return!s||!t?null:s.get(a,e,t.get,h)},[a,t?"hasSchema":"noSchema",h]),G=n(async(e,s,c)=>{const i=r();if(!i||!t)return;const C=M(s,o),k=C?.status==="draft"?t.draft:t.create;await i.set(a,e,C,k,c)},[a,t?"hasSchema":"noSchema",o?.provider]),q=n(async(e,s,c)=>{const i=r();i&&await i.update(a,e,s,t?.update,c)},[a,t]),x=n(async(e,s)=>{const c=r();c&&await c.delete(a,e,s)},[a]),z=n(async(e,s)=>{const c=r();if(!c||!t)return"";const i=M(e,o),C=i?.status==="draft"?t.draft:t.create;return c.add(a,i,C,s)},[a,t?"hasSchema":"noSchema",o?.provider]),N=n(async e=>{const s=r();if(!s||!t)return[];const c=V(e,o);return(await s.query(a,c,t.list,h)).items},[a,t?"hasSchema":"noSchema",h,o?.provider]),R=n((e,s)=>{const c=r();return!c||!t?()=>{}:c.subscribe(a,e,s,t.get)},[a,t?"hasSchema":"noSchema"]),I=n((e,s)=>{const c=r();return!c||!t?()=>{}:c.subscribeToCollection(a,e,s,t.list)},[a,t?"hasSchema":"noSchema"]),w=n(async()=>{const e=r();e&&await e.invalidateCollection(a)},[a]);return S?y:P?{status:m.READY,data:O,loading:D,error:A,get:j,set:G,update:q,delete:x,add:z,query:N,subscribe:R,subscribeToCollection:I,invalidate:w,isAvailable:!0,_collection:a,_schemas:t,_cacheOptions:h,_scope:o}:{...J,status:y,loading:D,error:A,subscribe:R,subscribeToCollection:I,invalidate:w,_collection:a,_schemas:t,_cacheOptions:h,_scope:o}}export{X as EMPTY_DATA,$ as EMPTY_OPTIMISTIC,r as getCrudServiceInstance,ee as useCrud};
1
+ "use client";import{useEffect as V,useMemo as F,useCallback as a}from"react";import{useFeatureConsent as W,FRAMEWORK_FEATURES as Z,FEATURE_STATUS as h,handleError as $,isClient as B,createSchemas as H,DEGRADED_CRUD_API as J}from"@donotdev/core";import{getCrudService as X}from"./CrudService";import{useCrudStore as u}from"./CrudStore";import{injectScope as P,injectScopeFilter as O}from"./utils/scopeUtils";const re={},ne={};let v=null,_=null,g=!1;function i(){return v}function ae(l,d={}){const S=W(Z.CRUD),x=u(e=>e.crudService),C=S&&!x,D=S?C?h.INITIALIZING:h.READY:h.DEGRADED,m=l==="status",p=!m&&typeof l=="object"?l:d.entity,s=m?"__status__":typeof l=="string"?l:l.collection,o=p?.scope,T=d.noCache??!1,A=d.staleTime,f=F(()=>({noCache:T,staleTime:A}),[T,A]),t=F(()=>{if(!m){if(d.schema){const e=d.schema;return{create:e,draft:e,update:e,get:e,list:e,listCard:e,delete:e}}if(p)return H(p)}},[m,d.schema,p?.name,s]),M=u(e=>e.collections[s]?.loading||!1),b=u(e=>e.collections[s]?.error||null),N=null;V(()=>{if(!B()||!S||!t)return;const{crudService:e}=u.getState();e||v||_||(_=(async()=>{try{if(v||u.getState().crudService)return;const c=X();v=c,c.setStore(u),await c.initialize(),g=!1,u.getState().setCrudService(c)}catch(c){g||($(c,{userMessage:"Failed to initialize CRUD service.",context:{collection:s},severity:"error"}),g=!0)}finally{_=null}})())},[S,s,t?"hasSchema":"noSchema"]);const I=C||M,z=D===h.READY,Y=a(async e=>{const c=i();return!c||!t?null:c.get(s,e,t.get,f)},[s,t?"hasSchema":"noSchema",f]),j=a(async(e,c,r)=>{const n=i();if(!n||!t)return;const E=P(c,o),Q=E?.status==="draft"?t.draft:t.create;await n.set(s,e,E,Q,r)},[s,t?"hasSchema":"noSchema",o?.provider]),k=a(async(e,c,r)=>{const n=i();n&&await n.update(s,e,c,t?.update,r)},[s,t]),q=a(async(e,c)=>{const r=i();r&&await r.delete(s,e,c)},[s]),G=a(async(e,c)=>{const r=i();if(!r||!t)return"";const n=P(e,o),w=n?.status==="draft"?t.draft:t.create;return r.add(s,n,w,c)},[s,t?"hasSchema":"noSchema",o?.provider]),L=a(async e=>{const c=i();if(!c||!t)return[];const r=O(e,o);return(await c.query(s,r,t.list,f)).items},[s,t?"hasSchema":"noSchema",f,o?.provider]),R=a((e,c)=>{const r=i();return!r||!t?()=>{}:r.subscribe(s,e,c,t.get)},[s,t?"hasSchema":"noSchema"]),y=a((e,c)=>{const r=i();return!r||!t?()=>{}:r.subscribeToCollection(s,e,c,t.list)},[s,t?"hasSchema":"noSchema"]),U=a(async()=>{const e=i();e&&await e.invalidateCollection(s)},[s]);return m?D:z?{status:h.READY,data:N,loading:I,error:b,get:Y,set:j,update:k,delete:q,add:G,query:L,subscribe:R,subscribeToCollection:y,invalidate:U,isAvailable:!0,_collection:s,_schemas:t,_cacheOptions:f,_scope:o}:{...J,status:D,loading:I,error:b,subscribe:R,subscribeToCollection:y,invalidate:U,_collection:s,_schemas:t,_cacheOptions:f,_scope:o}}export{re as EMPTY_DATA,ne as EMPTY_OPTIMISTIC,i as getCrudServiceInstance,ae as useCrud};
@@ -1,27 +1,27 @@
1
- /**
2
- * @fileoverview useCrudCardList Hook - Optimized Card List Management
3
- * @description Specialized hook for fetching lists of entities optimized for card views.
4
- * Fetches only the fields defined in `listCardFields` (or `listFields`) to reduce payload size.
5
- *
6
- * @version 0.0.10
7
- * @since 0.0.1
8
- * @author AMBROISE PARK Consulting
9
- */
10
1
  import type { Entity, FeatureStatus, QueryOptions } from '@donotdev/core';
11
2
  import type { UseCrudOptions } from './useCrud';
3
+ import type { ClientSortConfig } from './utils/clientListProcessing';
12
4
  export interface UseCrudCardListOptions<T> extends UseCrudOptions<T> {
13
5
  /** Automatically fetch data on mount (default: true) */
14
6
  enabled?: boolean;
15
7
  /** Where/orderBy/limit passed to listCard query */
16
8
  queryOptions?: QueryOptions;
9
+ /** Client-side search query. Applied after filters. */
10
+ searchQuery?: string;
11
+ /** Client-side sort config. Defaults to entity.defaultSort. Pass null to disable. */
12
+ clientSort?: ClientSortConfig | null;
17
13
  }
18
14
  export interface UseCrudCardListReturn<T> {
19
15
  status: FeatureStatus;
20
16
  data: {
21
17
  items: T[];
22
18
  } | null;
23
- /** Convenience: items array (data?.items ?? []) */
19
+ /** Convenience: items array (data?.items ?? []) — raw + optimistic, no client processing */
24
20
  items: T[];
21
+ /** Items after client-side filters + search + sort — ready to render */
22
+ processed: T[];
23
+ /** Count of items after filters + search (before pagination) */
24
+ filteredTotal: number;
25
25
  /** True during initial fetch (show skeletons) */
26
26
  loading: boolean;
27
27
  /** True during background refetch (show subtle indicator) */
@@ -48,15 +48,10 @@ export interface UseCrudCardListReturn<T> {
48
48
  *
49
49
  * @example
50
50
  * ```typescript
51
- * const { items, loading, refresh } = useCrudCardList(carEntity);
52
- *
53
- * if (loading) return <Skeletons />;
54
- *
55
- * return (
56
- * <Grid>
57
- * {items.map(car => <Card key={car.id} title={car.make} />)}
58
- * </Grid>
59
- * );
51
+ * // processed has filters + search + sort applied
52
+ * const { processed, loading } = useCrudCardList(carEntity, {
53
+ * searchQuery: search,
54
+ * });
60
55
  * ```
61
56
  */
62
57
  export declare function useCrudCardList<T extends {
@@ -1 +1 @@
1
- {"version":3,"file":"useCrudCardList.d.ts","sourceRoot":"","sources":["../src/useCrudCardList.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAM1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,MAAM,WAAW,sBAAsB,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;IAClE,wDAAwD;IACxD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,mDAAmD;IACnD,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,MAAM,WAAW,qBAAqB,CAAC,CAAC;IACtC,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,EAAE;QAAE,KAAK,EAAE,CAAC,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5B,mDAAmD;IACnD,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,iDAAiD;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,6DAA6D;IAC7D,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,8BAA8B;IAC9B,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,wCAAwC;IACxC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACvE,kBAAkB,EAAE,MAAM,GAAG,MAAM,EACnC,OAAO,GAAE,sBAAsB,CAAC,CAAC,CAAM,GACtC,qBAAqB,CAAC,CAAC,CAAC,CA+B1B"}
1
+ {"version":3,"file":"useCrudCardList.d.ts","sourceRoot":"","sources":["../src/useCrudCardList.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAM1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAQhD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,MAAM,WAAW,sBAAsB,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;IAClE,wDAAwD;IACxD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,mDAAmD;IACnD,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qFAAqF;IACrF,UAAU,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,qBAAqB,CAAC,CAAC;IACtC,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,EAAE;QAAE,KAAK,EAAE,CAAC,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5B,4FAA4F;IAC5F,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,wEAAwE;IACxE,SAAS,EAAE,CAAC,EAAE,CAAC;IACf,gEAAgE;IAChE,aAAa,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,6DAA6D;IAC7D,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,8BAA8B;IAC9B,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,wCAAwC;IACxC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACvE,kBAAkB,EAAE,MAAM,GAAG,MAAM,EACnC,OAAO,GAAE,sBAAsB,CAAC,CAAC,CAAM,GACtC,qBAAqB,CAAC,CAAC,CAAC,CAuE1B"}
@@ -1 +1 @@
1
- import{useBaseCrudList as i}from"./useBaseCrudList";function r(s,t={}){const a={enabled:t.enabled,queryOptions:t.queryOptions,schema:t.schema,entity:t.entity,staleTime:t.staleTime,noCache:t.noCache},e=i(s,"listCard",null,a);return{status:e.status,data:e.data?{items:e.data.items}:null,items:e.items,loading:e.loading,fetching:e.fetching,error:e.error,mutate:e.mutate,refresh:e.refresh,isAvailable:e.isAvailable}}export{r as useCrudCardList};
1
+ import{useMemo as o}from"react";import{useBaseCrudList as f}from"./useBaseCrudList";import{useCrudFilters as h}from"./hooks/useCrudFilters";import{applyFilters as y,applySearch as g,applySort as p}from"./utils/clientListProcessing";function v(l,t={}){const u={enabled:t.enabled,queryOptions:t.queryOptions,schema:t.schema,entity:t.entity,staleTime:t.staleTime,noCache:t.noCache},e=f(l,"listCard",null,u),s=typeof l=="string"?null:l,c=s?.collection??l,{filters:a}=h({collection:c}),i=t.clientSort===null?null:t.clientSort??s?.defaultSort??null,{processed:n,filteredTotal:m}=o(()=>{let r=e.items;s&&Object.keys(a).length>0&&(r=y(r,a,s)),s&&t.searchQuery&&(r=g(r,t.searchQuery,s));const d=r.length;return i&&(r=p(r,i)),{processed:r,filteredTotal:d}},[e.items,a,t.searchQuery,i,s]);return{status:e.status,data:e.data?{items:e.data.items}:null,items:e.items,processed:n,filteredTotal:m,loading:e.loading,fetching:e.fetching,error:e.error,mutate:e.mutate,refresh:e.refresh,isAvailable:e.isAvailable}}export{v as useCrudCardList};
@@ -1,15 +1,7 @@
1
- /**
2
- * @fileoverview useCrudList Hook - Collection Management with Pagination
3
- * @description Specialized hook for fetching and managing lists of entities.
4
- * Supports both client-side and server-side pagination.
5
- *
6
- * @version 0.0.10
7
- * @since 0.0.1
8
- * @author AMBROISE PARK Consulting
9
- */
10
1
  import type { Entity, FeatureStatus } from '@donotdev/core';
11
2
  import type { QueryOptions } from '@donotdev/core';
12
3
  import type { UseCrudOptions } from './useCrud';
4
+ import type { ClientSortConfig } from './utils/clientListProcessing';
13
5
  export interface UseCrudListOptions<T> extends UseCrudOptions<T> {
14
6
  /** Automatically fetch data on mount (default: true) */
15
7
  enabled?: boolean;
@@ -21,6 +13,10 @@ export interface UseCrudListOptions<T> extends UseCrudOptions<T> {
21
13
  pageSize?: number;
22
14
  /** Where/orderBy/limit passed to list query (merged with pagination on server) */
23
15
  queryOptions?: QueryOptions;
16
+ /** Client-side search query. Applied after filters. */
17
+ searchQuery?: string;
18
+ /** Client-side sort config. Defaults to entity.defaultSort. Pass null to disable. */
19
+ clientSort?: ClientSortConfig | null;
24
20
  }
25
21
  export interface UseCrudListReturn<T> {
26
22
  status: FeatureStatus;
@@ -28,8 +24,12 @@ export interface UseCrudListReturn<T> {
28
24
  items: T[];
29
25
  total?: number;
30
26
  } | null;
31
- /** Convenience: items array (data?.items ?? []) */
27
+ /** Convenience: items array (data?.items ?? []) — raw + optimistic, no client processing */
32
28
  items: T[];
29
+ /** Items after client-side filters + search + sort — ready to render */
30
+ processed: T[];
31
+ /** Count of items after filters + search (before pagination) */
32
+ filteredTotal: number;
33
33
  /** True during initial fetch (show skeletons) */
34
34
  loading: boolean;
35
35
  /** True during background refetch (show subtle indicator) */
@@ -56,15 +56,16 @@ export interface UseCrudListReturn<T> {
56
56
  *
57
57
  * @example
58
58
  * ```typescript
59
- * const { items, loading, refresh } = useCrudList(carEntity);
60
- *
61
- * if (loading) return <Loader />;
59
+ * // Basic usage processed has filters + search + sort applied
60
+ * const { processed, loading, refresh } = useCrudList(carEntity, {
61
+ * searchQuery: search,
62
+ * });
62
63
  *
63
- * return (
64
- * <ul>
65
- * {items.map(car => <li key={car.id}>{car.make}</li>)}
66
- * </ul>
67
- * );
64
+ * // With explicit sort
65
+ * const { processed } = useCrudList(carEntity, {
66
+ * searchQuery: search,
67
+ * clientSort: { field: 'price', direction: 'asc' },
68
+ * });
68
69
  * ```
69
70
  */
70
71
  export declare function useCrudList<T extends {
@@ -1 +1 @@
1
- {"version":3,"file":"useCrudList.d.ts","sourceRoot":"","sources":["../src/useCrudList.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAO5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,MAAM,WAAW,kBAAkB,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;IAC9D,wDAAwD;IACxD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iFAAiF;IACjF,UAAU,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IACjC,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kFAAkF;IAClF,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,EAAE;QAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5C,mDAAmD;IACnD,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,iDAAiD;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,6DAA6D;IAC7D,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,8BAA8B;IAC9B,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,wCAAwC;IACxC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACnE,kBAAkB,EAAE,MAAM,GAAG,MAAM,EACnC,OAAO,GAAE,kBAAkB,CAAC,CAAC,CAAM,GAClC,iBAAiB,CAAC,CAAC,CAAC,CA4BtB"}
1
+ {"version":3,"file":"useCrudList.d.ts","sourceRoot":"","sources":["../src/useCrudList.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAO5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAQhD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,MAAM,WAAW,kBAAkB,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;IAC9D,wDAAwD;IACxD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iFAAiF;IACjF,UAAU,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IACjC,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kFAAkF;IAClF,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qFAAqF;IACrF,UAAU,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,EAAE;QAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5C,4FAA4F;IAC5F,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,wEAAwE;IACxE,SAAS,EAAE,CAAC,EAAE,CAAC;IACf,gEAAgE;IAChE,aAAa,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,6DAA6D;IAC7D,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,8BAA8B;IAC9B,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,wCAAwC;IACxC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACnE,kBAAkB,EAAE,MAAM,GAAG,MAAM,EACnC,OAAO,GAAE,kBAAkB,CAAC,CAAC,CAAM,GAClC,iBAAiB,CAAC,CAAC,CAAC,CAwEtB"}
@@ -1 +1 @@
1
- import{useBaseCrudList as p}from"./useBaseCrudList";function r(a,e={}){const t=e.pagination??"client",i=e.page??1,n=e.pageSize??10,s={mode:t,page:i,pageSize:n},o={enabled:e.enabled,queryOptions:e.queryOptions,schema:e.schema,entity:e.entity,staleTime:e.staleTime,noCache:e.noCache};return p(a,"list",s,o)}export{r as useCrudList};
1
+ import{useMemo as h}from"react";import{useBaseCrudList as y}from"./useBaseCrudList";import{useCrudFilters as S}from"./hooks/useCrudFilters";import{applyFilters as b,applySearch as T,applySort as Q}from"./utils/clientListProcessing";function L(s,e={}){const n=e.pagination??"client",u=e.page??1,i=e.pageSize??10,o={mode:n,page:u,pageSize:i},m={enabled:e.enabled,queryOptions:e.queryOptions,schema:e.schema,entity:e.entity,staleTime:e.staleTime,noCache:e.noCache},a=y(s,"list",o,m),r=typeof s=="string"?null:s,d=r?.collection??s,{filters:l}=S({collection:d}),c=e.clientSort===null?null:e.clientSort??r?.defaultSort??null,{processed:f,filteredTotal:p}=h(()=>{let t=a.items;r&&Object.keys(l).length>0&&(t=b(t,l,r)),r&&e.searchQuery&&(t=T(t,e.searchQuery,r));const g=t.length;return c&&(t=Q(t,c)),{processed:t,filteredTotal:g}},[a.items,l,e.searchQuery,c,r]);return{...a,processed:f,filteredTotal:p}}export{L as useCrudList};
@@ -0,0 +1,82 @@
1
+ /**
2
+ * @fileoverview Client-side list processing utilities
3
+ * @description Pure functions for filtering, searching, and sorting entity items.
4
+ * Used by useCrudList/useCrudCardList hooks and UI components.
5
+ *
6
+ * @version 0.0.1
7
+ * @since 0.0.1
8
+ * @author AMBROISE PARK Consulting
9
+ */
10
+ import type { Entity } from '@donotdev/core';
11
+ import type { FilterState } from '../types';
12
+ /**
13
+ * Sort configuration for client-side sorting.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const sort: ClientSortConfig = { field: 'price', direction: 'desc' };
18
+ * ```
19
+ */
20
+ export interface ClientSortConfig {
21
+ field: string;
22
+ direction?: 'asc' | 'desc';
23
+ }
24
+ /**
25
+ * Apply filter state to items using entity field type metadata.
26
+ * Typically called automatically by `useCrudList`/`useCrudCardList` via `processed`.
27
+ * Export available for advanced use cases (e.g. filtering outside React).
28
+ *
29
+ * @param items - Raw items array
30
+ * @param filters - Current filter state from CrudStore
31
+ * @param entity - Entity definition (for field type lookup)
32
+ * @returns Filtered items
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * import { applyFilters } from '@donotdev/crud';
37
+ * const filtered = applyFilters(items, { status: 'active' }, productEntity);
38
+ * ```
39
+ */
40
+ export declare function applyFilters<T extends Record<string, any>>(items: T[], filters: FilterState, entity: Entity): T[];
41
+ /**
42
+ * Returns the list of searchable field names for an entity.
43
+ * Uses entity.search.fields if defined, otherwise auto-detects text-like visible fields.
44
+ *
45
+ * @param entity - Entity definition
46
+ * @returns Array of field names to search
47
+ */
48
+ export declare function getSearchableFields(entity: Entity): string[];
49
+ /**
50
+ * Apply search query to items.
51
+ * Searches fields defined by `entity.search.fields` or auto-detected text-like visible fields.
52
+ * Typically called automatically by `useCrudList`/`useCrudCardList` when `searchQuery` option is set.
53
+ *
54
+ * @param items - Items to search
55
+ * @param query - Search query string (case-insensitive contains)
56
+ * @param entity - Entity definition (for field config and search.fields lookup)
57
+ * @returns Filtered items matching search
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * import { applySearch } from '@donotdev/crud';
62
+ * const results = applySearch(items, 'bmw', carEntity);
63
+ * ```
64
+ */
65
+ export declare function applySearch<T extends Record<string, any>>(items: T[], query: string, entity: Entity): T[];
66
+ /**
67
+ * Apply client-side sorting to items.
68
+ * Handles null/undefined values by sorting them last.
69
+ * Supports number, string, Date, and price ({ amount }) comparisons.
70
+ *
71
+ * @param items - Items to sort
72
+ * @param sort - Sort configuration (field + direction)
73
+ * @returns Sorted items (new array, original unchanged)
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * import { applySort } from '@donotdev/crud';
78
+ * const sorted = applySort(items, { field: 'createdAt', direction: 'desc' });
79
+ * ```
80
+ */
81
+ export declare function applySort<T extends Record<string, any>>(items: T[], sort: ClientSortConfig): T[];
82
+ //# sourceMappingURL=clientListProcessing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clientListProcessing.d.ts","sourceRoot":"","sources":["../../src/utils/clientListProcessing.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAI7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACxD,KAAK,EAAE,CAAC,EAAE,EACV,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,GACb,CAAC,EAAE,CAWL;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAyB5D;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACvD,KAAK,EAAE,CAAC,EAAE,EACV,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,CAAC,EAAE,CA+BL;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACrD,KAAK,EAAE,CAAC,EAAE,EACV,IAAI,EAAE,gBAAgB,GACrB,CAAC,EAAE,CAoCL"}
@@ -0,0 +1 @@
1
+ import{matchesFilter as u}from"./matchesFilter";import{getValueType as c}from"../fieldTypeRegistry";function g(t,l,s){const o=Object.entries(l);return o.length===0?t:t.filter(r=>o.every(([i,f])=>{const n=s.fields[i]?.type||"text";return u(r[i],f,n)}))}function a(t){if(t.search?.fields&&t.search.fields.length>0)return t.search.fields;const l=new Set(["string"]),s=[];for(const[o,r]of Object.entries(t.fields)){if(r.visibility==="hidden"||r.visibility==="technical")continue;const i=c(r.type);i&&l.has(i)&&s.push(o)}return s}function h(t,l,s){if(!l||l.trim()==="")return t;const o=l.toLowerCase(),r=a(s);return r.length===0?t.filter(i=>Object.values(i).some(f=>f==null?!1:String(f).toLowerCase().includes(o))):t.filter(i=>r.some(f=>{const e=i[f];return e==null?!1:typeof e=="object"&&"formatted_address"in e?String(e.formatted_address).toLowerCase().includes(o):String(e).toLowerCase().includes(o)}))}function b(t,l){const{field:s,direction:o="asc"}=l,r=o==="desc"?-1:1;return[...t].sort((i,f)=>{const e=i[s],n=f[s];return e==null&&n==null?0:e==null?1:n==null?-1:typeof e=="number"&&typeof n=="number"?(e-n)*r:typeof e=="object"&&"amount"in e&&typeof n=="object"&&"amount"in n?(e.amount-n.amount)*r:e instanceof Date&&n instanceof Date?(e.getTime()-n.getTime())*r:String(e).localeCompare(String(n))*r})}export{g as applyFilters,h as applySearch,b as applySort,a as getSearchableFields};
@@ -1 +1 @@
1
- import{getCrudService as i}from"../CrudService";async function p(a,t){const e=i(),s=[],o=t.range?.start??1,c=t.range?.end??28;for(let r=o;r<=c;r++){const m=String(r),n=await e.get(t.path(a),m,t.schema);n&&s.push(n)}return s}async function d(a,t,e){const s=i();for(const o of e){const c=t.idOf(o);await s.set(t.path(a),c,o,t.schema)}}async function h(a,t,e){const s=i();if(t.idFrom){const o=t.idFrom(e);return s.set(t.path(a),o,e,t.schema)}return s.add(t.path(a),e,t.schema)}export{h as appendToCollection,p as loadDeterministicRange,d as upsertDeterministic};
1
+ import{getCrudService as o}from"../CrudService";async function u(s,t){const e=o(),r=[],a=t.range?.start??1,n=t.range?.end??28;for(let c=a;c<=n;c++){const i=String(c),d=await e.get(t.path(s),i,t.schema);d&&r.push(d)}return r}async function m(s,t,e){const r=o();for(const a of e){const n=t.idOf(a);await r.set(t.path(s),n,a,t.schema)}}async function h(s,t,e){const r=o();if(t.idFrom){const a=t.idFrom(e);return r.set(t.path(s),a,e,t.schema)}return r.add(t.path(s),e,t.schema)}export{h as appendToCollection,u as loadDeterministicRange,m as upsertDeterministic};
@@ -1 +1 @@
1
- {"version":3,"file":"fileStorage.d.ts","sourceRoot":"","sources":["../../src/utils/fileStorage.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,iGAAiG;AACjG,KAAK,sBAAsB,GAAG,CAAC,QAAQ,EAAE;IACvC,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB,KAAK,IAAI,CAAC;AAEX,YAAY,EAAE,SAAS,EAAE,CAAC;AAE1B,MAAM,WAAW,cAAc;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,UAAU,CAAC,EAAE,sBAAsB,CAAC;CACrC;AAYD;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,IAAI,EACV,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,SAAS,CAAC,CAkDpB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,IAAI,EAAE,EACb,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,SAAS,EAAE,CAAC,CA4BtB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBhE;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CA4CxE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMpD;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB,UAY/B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,UAY/B,CAAC;AAEF;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD"}
1
+ {"version":3,"file":"fileStorage.d.ts","sourceRoot":"","sources":["../../src/utils/fileStorage.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,iGAAiG;AACjG,KAAK,sBAAsB,GAAG,CAAC,QAAQ,EAAE;IACvC,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB,KAAK,IAAI,CAAC;AAEX,YAAY,EAAE,SAAS,EAAE,CAAC;AAE1B,MAAM,WAAW,cAAc;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,UAAU,CAAC,EAAE,sBAAsB,CAAC;CACrC;AAYD;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,IAAI,EACV,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,SAAS,CAAC,CAmDpB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,IAAI,EAAE,EACb,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,SAAS,EAAE,CAAC,CA4BtB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBhE;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CA4CxE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMpD;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB,UAY/B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,UAY/B,CAAC;AAEF;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD"}
@@ -1 +1 @@
1
- "use client";import{handleError as d,hasProvider as u,getProvider as f}from"@donotdev/core";function y(e){return e.replace(/[^a-zA-Z0-9.-]/g,"_").replace(/_{2,}/g,"_").toLowerCase()}async function m(e,t={}){const{storagePath:r="uploads/files",filename:s,onProgress:o}=t,n=Date.now(),i=y(e.name),l=s||`${n}_${i}`,c=`${r}/${l}`;try{let a;if(u("storage"))a=(await f("storage").upload(e,{storagePath:r,filename:l,onProgress:o?p=>o({bytesTransferred:0,totalBytes:0,progress:p}):void 0})).url;else{const{uploadFileResumable:p}=await import("@donotdev/firebase"),{promise:w}=p(e,{basePath:r,filename:l,onProgress:o,metadata:{contentType:e.type}});a=(await w).url}return{url:a,filename:e.name,size:e.size,mimeType:e.type,uploadedAt:new Date().toISOString()}}catch(a){throw d(a,{userMessage:"Failed to upload file",severity:"error",context:{filename:e.name,fileSize:e.size}})}}async function v(e,t={}){const r=[],s=e.reduce((n,i)=>n+i.size,0);let o=0;for(const n of e){const i=t.onProgress?c=>{const a=c.bytesTransferred/c.totalBytes*n.size;t.onProgress({bytesTransferred:o+a,totalBytes:s,progress:(o+a)/s*100})}:void 0,l=await m(n,{...t,onProgress:i});r.push(l),o+=n.size}return r}async function F(e){try{if(u("storage"))await f("storage").delete(e.url);else{const{deleteFileByUrl:t}=await import("@donotdev/firebase");await t(e.url)}}catch(t){throw d(t,{userMessage:"Failed to delete file",severity:"error",context:{url:e.url,filename:e.filename}}),t}}function M(){return`${Date.now()}-${Math.random().toString(36).slice(2,9)}`}function g(e){const t=e.split(".");return t.length>1?t.pop().toLowerCase():""}function P(e,t){const r=t?g(t):"";if(e){if(e.startsWith("image/"))return"image";if(e.startsWith("video/"))return"video";if(e.startsWith("audio/"))return"audio";if(e==="application/pdf")return"pdf";if(e.includes("word")||e.includes("document"))return"doc";if(e.includes("excel")||e.includes("spreadsheet"))return"xls";if(e.includes("powerpoint")||e.includes("presentation"))return"ppt"}switch(r){case"pdf":return"pdf";case"doc":case"docx":return"doc";case"xls":case"xlsx":case"csv":return"xls";case"ppt":case"pptx":return"ppt";case"md":case"txt":return"text";case"html":case"htm":return"html";case"zip":case"rar":case"7z":return"archive";default:return"file"}}function z(e){if(e===0)return"0 B";const t=1024,r=["B","KB","MB","GB"],s=Math.floor(Math.log(e)/Math.log(t));return`${parseFloat((e/Math.pow(t,s)).toFixed(1))} ${r[s]}`}const h=["application/pdf","application/msword","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","application/vnd.ms-powerpoint","application/vnd.openxmlformats-officedocument.presentationml.presentation","text/plain","text/markdown","text/html","text/csv"],x=[".pdf",".doc",".docx",".xls",".xlsx",".ppt",".pptx",".txt",".md",".html",".csv"];function B(){return[...h,...x].join(",")}export{x as DOCUMENT_EXTENSIONS,h as DOCUMENT_MIME_TYPES,F as deleteFile,z as formatFileSize,M as generateFileId,B as getDocumentAcceptString,g as getFileExtension,P as getFileIcon,m as uploadFile,v as uploadFiles};
1
+ "use client";import{handleError as d,hasProvider as f,getProvider as x}from"@donotdev/core";function m(e){return e.replace(/[^a-zA-Z0-9.-]/g,"_").replace(/_{2,}/g,"_").toLowerCase()}async function g(e,t={}){const{storagePath:r="uploads/files",filename:n,onProgress:s}=t,a=Date.now(),i=m(e.name),c=n||`${a}_${i}`,l=`${r}/${c}`;try{let o;if(f("storage"))o=(await x("storage").upload(e,{storagePath:r,filename:c,onProgress:s?u=>s({bytesTransferred:0,totalBytes:0,progress:u}):void 0})).url;else{const{uploadFileResumable:p}=await import("@donotdev/firebase"),{promise:u}=p(e,{basePath:r,filename:c,onProgress:s,metadata:{contentType:e.type}});o=(await u).url}return{url:o,filename:e.name,size:e.size,mimeType:e.type,uploadedAt:new Date().toISOString()}}catch(o){throw d(o,{userMessage:"Failed to upload file",severity:"error",context:{filename:e.name,fileSize:e.size}})}}async function P(e,t={}){const r=[],n=e.reduce((a,i)=>a+i.size,0);let s=0;for(const a of e){const i=t.onProgress?l=>{const o=l.bytesTransferred/l.totalBytes*a.size;t.onProgress({bytesTransferred:s+o,totalBytes:n,progress:(s+o)/n*100})}:void 0,c=await g(a,{...t,onProgress:i});r.push(c),s+=a.size}return r}async function M(e){try{if(f("storage"))await x("storage").delete(e.url);else{const{deleteFileByUrl:t}=await import("@donotdev/firebase");await t(e.url)}}catch(t){throw d(t,{userMessage:"Failed to delete file",severity:"error",context:{url:e.url,filename:e.filename}}),t}}function S(){return`${Date.now()}-${Math.random().toString(36).slice(2,9)}`}function h(e){const t=e.split(".");return t.length>1?t.pop().toLowerCase():""}function B(e,t){const r=t?h(t):"";if(e){if(e.startsWith("image/"))return"image";if(e.startsWith("video/"))return"video";if(e.startsWith("audio/"))return"audio";if(e==="application/pdf")return"pdf";if(e.includes("word")||e.includes("document"))return"doc";if(e.includes("excel")||e.includes("spreadsheet"))return"xls";if(e.includes("powerpoint")||e.includes("presentation"))return"ppt"}switch(r){case"pdf":return"pdf";case"doc":case"docx":return"doc";case"xls":case"xlsx":case"csv":return"xls";case"ppt":case"pptx":return"ppt";case"md":case"txt":return"text";case"html":case"htm":return"html";case"zip":case"rar":case"7z":return"archive";default:return"file"}}function E(e){if(e===0)return"0 B";const t=1024,r=["B","KB","MB","GB"],n=Math.floor(Math.log(e)/Math.log(t));return`${parseFloat((e/Math.pow(t,n)).toFixed(1))} ${r[n]}`}const w=["application/pdf","application/msword","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","application/vnd.ms-powerpoint","application/vnd.openxmlformats-officedocument.presentationml.presentation","text/plain","text/markdown","text/html","text/csv"],z=[".pdf",".doc",".docx",".xls",".xlsx",".ppt",".pptx",".txt",".md",".html",".csv"];function $(){return[...w,...z].join(",")}export{z as DOCUMENT_EXTENSIONS,w as DOCUMENT_MIME_TYPES,M as deleteFile,E as formatFileSize,S as generateFileId,$ as getDocumentAcceptString,h as getFileExtension,B as getFileIcon,g as uploadFile,P as uploadFiles};
@@ -1 +1 @@
1
- async function v(t,r={}){const{maxWidth:o=1920,maxHeight:n=1440,thumbWidth:s=300,thumbHeight:i=225,aspectRatio:e=4/3,quality:l=.85,transparentBackground:c=!0,crop:h}=r;return new Promise((u,d)=>{const a=new Image,g=new FileReader;g.onload=w=>{a.src=w.target?.result},g.onerror=()=>d(new Error("Failed to read file")),a.onload=async()=>{try{const{width:w,height:m}=x(h?h.width:a.width,h?h.height:a.height,o,n,e),b=await F(a,w,m,e,l,c,h),f=await F(a,s,i,e,.65,c,h);u({fullBlob:b,thumbBlob:f,width:w,height:m})}catch(w){d(w)}},a.onerror=()=>d(new Error("Failed to load image")),g.readAsDataURL(t)})}function x(t,r,o,n,s){let i=t,e=r;i>o&&(e=o/i*e,i=o),e>n&&(i=n/e*i,e=n);const l=i/e;return Math.abs(l-s)>.01&&(l>s?e=i/s:i=e*s),{width:Math.round(i),height:Math.round(e)}}async function F(t,r,o,n,s,i,e){const l=document.createElement("canvas"),c=l.getContext("2d");if(!c)throw new Error("Failed to get canvas context");l.width=r,l.height=o,i?c.clearRect(0,0,r,o):(c.fillStyle="#FFFFFF",c.fillRect(0,0,r,o));let h,u,d,a;if(e)h=e.x,u=e.y,d=e.width,a=e.height;else{const g=t.width/t.height;d=t.width,a=t.height,h=0,u=0,g>n?(d=t.height*n,h=(t.width-d)/2):g<n&&(a=t.width/n,u=(t.height-a)/2)}return c.drawImage(t,h,u,d,a,0,0,r,o),new Promise((g,w)=>{l.toBlob(m=>{m?g(m):w(new Error("Failed to convert canvas to blob"))},"image/webp",s)})}function y(t,r){return t.type.startsWith("image/")?r&&t.size>r?{valid:!1,error:`File size exceeds ${(r/1048576).toFixed(1)}MB limit`}:{valid:!0}:{valid:!1,error:"File must be an image"}}export{v as processImage,y as validateImageFile};
1
+ async function x(t,r={}){const{maxWidth:o=1920,maxHeight:a=1440,thumbWidth:d=300,thumbHeight:i=225,aspectRatio:e=4/3,quality:h=.85,transparentBackground:c=!0,crop:l}=r;return new Promise((f,s)=>{const n=new Image,u=new FileReader;u.onload=w=>{n.src=w.target?.result},u.onerror=()=>s(new Error("Failed to read file")),n.onload=async()=>{try{const{width:w,height:F}=g(l?l.width:n.width,l?l.height:n.height,o,a,e),m=await b(n,w,F,e,h,c,l),v=await b(n,d,i,e,.65,c,l);f({fullBlob:m,thumbBlob:v,width:w,height:F})}catch(w){s(w)}},n.onerror=()=>s(new Error("Failed to load image")),u.readAsDataURL(t)})}function g(t,r,o,a,d){let i=t,e=r;i>o&&(e=o/i*e,i=o),e>a&&(i=a/e*i,e=a);const h=i/e;return Math.abs(h-d)>.01&&(h>d?e=i/d:i=e*d),{width:Math.round(i),height:Math.round(e)}}async function b(t,r,o,a,d,i,e){const h=document.createElement("canvas"),c=h.getContext("2d");if(!c)throw new Error("Failed to get canvas context");h.width=r,h.height=o,i?c.clearRect(0,0,r,o):(c.fillStyle="#FFFFFF",c.fillRect(0,0,r,o));let l,f,s,n;if(e)l=e.x,f=e.y,s=e.width,n=e.height;else{const u=t.width/t.height;s=t.width,n=t.height,l=0,f=0,u>a?(s=t.height*a,l=(t.width-s)/2):u<a&&(n=t.width/a,f=(t.height-n)/2)}return c.drawImage(t,l,f,s,n,0,0,r,o),new Promise((u,w)=>{h.toBlob(F=>{F?u(F):w(new Error("Failed to convert canvas to blob"))},"image/webp",d)})}function y(t,r){return t.type.startsWith("image/")?r&&t.size>r?{valid:!1,error:`File size exceeds ${(r/1048576).toFixed(1)}MB limit`}:{valid:!0}:{valid:!1,error:"File must be an image"}}export{x as processImage,y as validateImageFile};
@@ -1 +1 @@
1
- {"version":3,"file":"imageStorage.d.ts","sourceRoot":"","sources":["../../src/utils/imageStorage.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE9C,iGAAiG;AACjG,KAAK,sBAAsB,GAAG,CAAC,QAAQ,EAAE;IACvC,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB,KAAK,IAAI,CAAC;AAEX,YAAY,EAAE,OAAO,EAAE,CAAC;AAExB,MAAM,WAAW,cAAc;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,UAAU,CAAC,EAAE,sBAAsB,CAAC;CACrC;AAYD;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,IAAI,EACd,SAAS,EAAE,IAAI,EACf,gBAAgB,EAAE,MAAM,EACxB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,OAAO,CAAC,CA6GlB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBjE"}
1
+ {"version":3,"file":"imageStorage.d.ts","sourceRoot":"","sources":["../../src/utils/imageStorage.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE9C,iGAAiG;AACjG,KAAK,sBAAsB,GAAG,CAAC,QAAQ,EAAE;IACvC,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB,KAAK,IAAI,CAAC;AAEX,YAAY,EAAE,OAAO,EAAE,CAAC;AAExB,MAAM,WAAW,cAAc;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,UAAU,CAAC,EAAE,sBAAsB,CAAC;CACrC;AAYD;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,IAAI,EACd,SAAS,EAAE,IAAI,EACf,gBAAgB,EAAE,MAAM,EACxB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,OAAO,CAAC,CA0HlB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBjE"}
@@ -1 +1 @@
1
- import{handleError as _,hasProvider as g,getProvider as w}from"@donotdev/core";function v(e){return e.replace(/[^a-zA-Z0-9.-]/g,"_").replace(/_{2,}/g,"_").toLowerCase()}async function B(e,t,o,d={}){const{storagePath:i="uploads/images",filename:f,onProgress:a}=d,y=Date.now(),r=(f||`${y}_${v(o)}`).replace(/\.[^/.]+$/,""),b=`${i}/${r}_full.webp`,h=`${i}/${r}_thumb.webp`;try{const c=new File([e],`${r}_full.webp`,{type:"image/webp"}),s=new File([t],`${r}_thumb.webp`,{type:"image/webp"});let n,u;if(g("storage")){const l=w("storage");n=(await l.upload(c,{storagePath:i,filename:`${r}_full.webp`,onProgress:a?m=>a({bytesTransferred:0,totalBytes:0,progress:m*.5}):void 0})).url,u=(await l.upload(s,{storagePath:i,filename:`${r}_thumb.webp`,onProgress:a?m=>a({bytesTransferred:0,totalBytes:0,progress:50+m*.5}):void 0})).url}else{const{uploadFileResumable:l}=await import("@donotdev/firebase"),m=a?p=>{a({bytesTransferred:p.bytesTransferred,totalBytes:p.totalBytes*2,progress:p.progress*.5})}:void 0,{promise:U}=l(c,{basePath:i,filename:`${r}_full.webp`,onProgress:m,metadata:{contentType:"image/webp"}});n=(await U).url;const P=a?p=>{a({bytesTransferred:p.bytesTransferred+e.size,totalBytes:e.size+t.size,progress:50+p.progress*.5})}:void 0,{promise:$}=l(s,{basePath:i,filename:`${r}_thumb.webp`,onProgress:P,metadata:{contentType:"image/webp"}});u=(await $).url}return{fullUrl:n,thumbUrl:u}}catch(c){try{if(g("storage")){const s=w("storage");await s.delete(b).catch(()=>{}),await s.delete(h).catch(()=>{})}else{const{getFileUrl:s,deleteFileByUrl:n}=await import("@donotdev/firebase"),u=await s(b).catch(()=>null),l=await s(h).catch(()=>null);u&&await n(u).catch(()=>{}),l&&await n(l).catch(()=>{})}}catch{}throw c}}async function F(e){try{if(g("storage")){const t=w("storage"),o=[t.delete(e.fullUrl)];e.thumbUrl&&o.push(t.delete(e.thumbUrl)),await Promise.all(o)}else{const{deleteFileByUrl:t}=await import("@donotdev/firebase"),o=[t(e.fullUrl)];e.thumbUrl&&o.push(t(e.thumbUrl)),await Promise.all(o)}}catch(t){throw _(t,{userMessage:"Failed to delete image",severity:"error",context:{fullUrl:e.fullUrl,thumbUrl:e.thumbUrl}}),t}}export{F as deleteImage,B as uploadImage};
1
+ import{handleError as F,hasProvider as f,getProvider as h}from"@donotdev/core";function R(e){return e.replace(/[^a-zA-Z0-9.-]/g,"_").replace(/_{2,}/g,"_").toLowerCase()}async function B(e,t,o,y={}){const{storagePath:n="uploads/images",filename:P,onProgress:a}=y,U=Date.now(),l=(P||`${U}_${R(o)}`).replace(/\.[^/.]+$/,""),d=`${n}/${l}_full.webp`,g=`${n}/${l}_thumb.webp`;try{const c=new File([e],`${l}_full.webp`,{type:"image/webp"}),s=new File([t],`${l}_thumb.webp`,{type:"image/webp"});let i,u;if(f("storage")){const r=h("storage");i=(await r.upload(c,{storagePath:n,filename:`${l}_full.webp`,onProgress:a?b=>a({bytesTransferred:0,totalBytes:0,progress:b*.5}):void 0})).url,u=(await r.upload(s,{storagePath:n,filename:`${l}_thumb.webp`,onProgress:a?b=>a({bytesTransferred:0,totalBytes:0,progress:50+b*.5}):void 0})).url}else{const{uploadFileResumable:r}=await import("@donotdev/firebase"),w=a?m=>{a({bytesTransferred:m.bytesTransferred,totalBytes:m.totalBytes*2,progress:m.progress*.5})}:void 0,{promise:p}=r(c,{basePath:n,filename:`${l}_full.webp`,onProgress:w,metadata:{contentType:"image/webp"}});i=(await p).url;const $=a?m=>{a({bytesTransferred:m.bytesTransferred+e.size,totalBytes:e.size+t.size,progress:50+m.progress*.5})}:void 0,{promise:_}=r(s,{basePath:n,filename:`${l}_thumb.webp`,onProgress:$,metadata:{contentType:"image/webp"}});u=(await _).url}return{fullUrl:i,thumbUrl:u}}catch(c){try{if(f("storage")){const s=h("storage");await s.delete(d).catch(()=>{}),await s.delete(g).catch(()=>{})}else{const{getFileUrl:s,deleteFileByUrl:i}=await import("@donotdev/firebase"),u=await s(d).catch(()=>null),r=await s(g).catch(()=>null);u&&await i(u).catch(()=>{}),r&&await i(r).catch(()=>{})}}catch{}throw c}}async function v(e){try{if(f("storage")){const t=h("storage"),o=[t.delete(e.fullUrl)];e.thumbUrl&&o.push(t.delete(e.thumbUrl)),await Promise.all(o)}else{const{deleteFileByUrl:t}=await import("@donotdev/firebase"),o=[t(e.fullUrl)];e.thumbUrl&&o.push(t(e.thumbUrl)),await Promise.all(o)}}catch(t){throw F(t,{userMessage:"Failed to delete image",severity:"error",context:{fullUrl:e.fullUrl,thumbUrl:e.thumbUrl}}),t}}export{v as deleteImage,B as uploadImage};
@@ -1 +1 @@
1
- async function d(e){const t=await e.arrayBuffer(),r=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(r)).map(a=>a.toString(16).padStart(2,"0")).join("")}function h(e){return URL.createObjectURL(e)}function u(e){e.startsWith("blob:")&&URL.revokeObjectURL(e)}async function l(e){return new Promise((t,r)=>{const a=new Image,i=new FileReader;i.onload=n=>{if(!n.target?.result){r(new Error("Failed to read file"));return}a.src=n.target.result},i.onerror=()=>r(new Error("Failed to read file")),a.onload=()=>{const n=document.createElement("canvas"),o=n.getContext("2d");if(!o){r(new Error("Failed to get canvas context"));return}n.width=a.height,n.height=a.width,o.translate(n.width/2,n.height/2),o.rotate(Math.PI/2),o.drawImage(a,-a.width/2,-a.height/2),n.toBlob(s=>{if(s){const c=new File([s],e.name,{type:e.type,lastModified:Date.now()});t(c)}else r(new Error("Failed to create blob from canvas"))},e.type,.95)},a.onerror=()=>r(new Error("Failed to load image")),i.readAsDataURL(e)})}class g{undoStack=[];redoStack=[];maxStackSize=50;push(t){this.undoStack.push(t),this.undoStack.length>this.maxStackSize&&this.undoStack.shift(),this.redoStack=[]}undo(){const t=this.undoStack.pop();return t?(this.redoStack.push(t),t):null}redo(){const t=this.redoStack.pop();return t?(this.undoStack.push(t),t):null}canUndo(){return this.undoStack.length>0}canRedo(){return this.redoStack.length>0}clear(){this.undoStack=[],this.redoStack=[]}}function S(e,t){return e.filter(r=>r.hash===t)}function w(){return`img_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}export{g as UndoRedoManager,h as createPreviewURL,S as findDuplicatesByHash,d as generateFileHash,w as generateImageId,u as revokePreviewURL,l as rotateImage90};
1
+ async function d(e){const t=await e.arrayBuffer(),r=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(r)).map(o=>o.toString(16).padStart(2,"0")).join("")}function h(e){return URL.createObjectURL(e)}function u(e){e.startsWith("blob:")&&URL.revokeObjectURL(e)}async function l(e){return new Promise((t,r)=>{const a=new Image,o=new FileReader;o.onload=n=>{if(!n.target?.result){r(new Error("Failed to read file"));return}a.src=n.target.result},o.onerror=()=>r(new Error("Failed to read file")),a.onload=()=>{const n=document.createElement("canvas"),i=n.getContext("2d");if(!i){r(new Error("Failed to get canvas context"));return}n.width=a.height,n.height=a.width,i.translate(n.width/2,n.height/2),i.rotate(Math.PI/2),i.drawImage(a,-a.width/2,-a.height/2),n.toBlob(s=>{if(s){const c=new File([s],e.name,{type:e.type,lastModified:Date.now()});t(c)}else r(new Error("Failed to create blob from canvas"))},e.type,.95)},a.onerror=()=>r(new Error("Failed to load image")),o.readAsDataURL(e)})}class f{undoStack=[];redoStack=[];maxStackSize=50;push(t){this.undoStack.push(t),this.undoStack.length>this.maxStackSize&&this.undoStack.shift(),this.redoStack=[]}undo(){const t=this.undoStack.pop();return t?(this.redoStack.push(t),t):null}redo(){const t=this.redoStack.pop();return t?(this.undoStack.push(t),t):null}canUndo(){return this.undoStack.length>0}canRedo(){return this.redoStack.length>0}clear(){this.undoStack=[],this.redoStack=[]}}function g(e,t){return e.filter(r=>r.hash===t)}function p(){return`img_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}export{f as UndoRedoManager,h as createPreviewURL,g as findDuplicatesByHash,d as generateFileHash,p as generateImageId,u as revokePreviewURL,l as rotateImage90};
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Pure filter matching utility — checks if an item value matches a filter value.
3
+ *
4
+ * Supports all built-in field types: text (contains), number/price (range),
5
+ * date/datetime (range), select (exact), multiselect (contains), address (formatted_address).
6
+ *
7
+ * Null/undefined handling for range filters:
8
+ * - MIN only → exclude null/undefined
9
+ * - MAX only → include null/undefined
10
+ * - MIN + MAX → exclude null/undefined
11
+ *
12
+ * @param itemValue - The item's field value to test
13
+ * @param filterValue - The filter criterion (string, range, date, array)
14
+ * @param fieldType - Entity field type (e.g. 'text', 'number', 'date', 'price')
15
+ * @returns true if item passes the filter
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import { matchesFilter } from '@donotdev/crud';
20
+ *
21
+ * matchesFilter('hello world', 'hello', 'text'); // true (contains)
22
+ * matchesFilter(42, { min: '10', max: '50' }, 'number'); // true (in range)
23
+ * matchesFilter(null, { min: '10' }, 'number'); // false (null excluded)
24
+ * ```
25
+ */
26
+ export declare function matchesFilter(itemValue: any, filterValue: string | {
27
+ min?: string;
28
+ max?: string;
29
+ } | string[] | {
30
+ date: string;
31
+ time?: string;
32
+ } | {
33
+ min?: {
34
+ date: string;
35
+ time?: string;
36
+ };
37
+ max?: {
38
+ date: string;
39
+ time?: string;
40
+ };
41
+ } | {
42
+ date: string;
43
+ time?: string;
44
+ }[], fieldType: string): boolean;
45
+ //# sourceMappingURL=matchesFilter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matchesFilter.d.ts","sourceRoot":"","sources":["../../src/utils/matchesFilter.ts"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,GAAG,EAEd,WAAW,EACP,MAAM,GACN;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9B,MAAM,EAAE,GACR;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/B;IACE,GAAG,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,GAAG,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACvC,GACD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,EAErC,SAAS,EAAE,MAAM,GAChB,OAAO,CAiVT"}
@@ -0,0 +1 @@
1
+ import{getFilterType as w}from"../fieldTypeRegistry";function T(n,t,e){if(!t)return!0;if(Array.isArray(t)){if(t.length===0)return!0;if(!(w(e)==="range"&&(e==="date"||e==="datetime-local"||e==="timestamp")))return t.some(s=>{if(typeof s=="object"&&"date"in s){const i=s.date;return(n instanceof Date?n.toISOString().split("T")[0]:new Date(n).toISOString().split("T")[0])===i}return String(n)===String(s)});const f=n instanceof Date?n.toISOString().split("T")[0]:new Date(n).toISOString().split("T")[0];return t.some(s=>typeof s=="string"?f===s:typeof s=="object"&&"date"in s?f===s.date:!1)}if(typeof t=="object"&&"date"in t&&!("min"in t)&&!Array.isArray(t)){if(!(w(e)==="range"&&(e==="date"||e==="datetime-local"||e==="timestamp")))return!1;const f=t.date;if(!f)return!0;if(n==null)return!1;const s=n instanceof Date?n.toISOString().split("T")[0]:new Date(n).toISOString().split("T")[0];if((e==="datetime-local"||e==="timestamp")&&t.time){const i=n instanceof Date?n.toISOString().slice(11,16):new Date(n).toISOString().slice(11,16);return s===f&&i===t.time}return s===f}if(typeof t=="object"&&"min"in t){const D=w(e);if(!D)return!0;const p=D==="range"&&(e==="date"||e==="datetime-local"||e==="timestamp"),f=D==="range"&&!p,s=e==="price",i=s&&n!=null&&typeof n=="object"?Number(n.amount):f&&n!=null?typeof n=="number"?n:Number(n):NaN;if(f||s){if(typeof t.min=="object"&&t.min!==null&&"date"in t.min)return!1;const r=t,g=typeof r.min=="string"&&r.min!=="",S=typeof r.max=="string"&&r.max!=="";return g&&!S?n==null||isNaN(i)?!1:i>=Number(r.min):!g&&S?n==null?!0:isNaN(i)?!1:i<=Number(r.max):g&&S?n==null||isNaN(i)?!1:i>=Number(r.min)&&i<=Number(r.max):!0}if(p){if(typeof t.min=="object"&&t.min!==null&&"date"in t.min&&!("min"in t.min)){const o=t,d=o.min,a=o.max,u=d?.date&&d.date!=="",b=a?.date&&a.date!=="";if(u&&!b){if(n==null)return!1;const c=n instanceof Date?n:new Date(n);if(isNaN(c.getTime()))return!1;const N=new Date(d.date+(d.time?`T${d.time}:00`:"T00:00:00"));return c>=N}if(!u&&b&&a){if(n==null)return!0;const c=n instanceof Date?n:new Date(n);if(isNaN(c.getTime()))return!1;const N=new Date(a.date+(a.time?`T${a.time}:00`:"T23:59:59"));return c<=N}if(u&&b&&a){if(n==null)return!1;const c=n instanceof Date?n:new Date(n);if(isNaN(c.getTime()))return!1;const N=new Date(d.date+(d.time?`T${d.time}:00`:"T00:00:00")),x=new Date(a.date+(a.time?`T${a.time}:00`:"T23:59:59"));return c>=N&&c<=x}return!0}const r=t,g=typeof r.min=="string"&&r.min!=="",S=typeof r.max=="string"&&r.max!=="";if(g&&!S){if(n==null)return!1;const o=n instanceof Date?n:new Date(n);return isNaN(o.getTime())?!1:o>=new Date(r.min)}if(!g&&S){if(n==null)return!0;const o=n instanceof Date?n:new Date(n);return isNaN(o.getTime())?!1:o<=new Date(r.max)}if(g&&S){if(n==null)return!1;const o=n instanceof Date?n:new Date(n);return isNaN(o.getTime())?!1:o>=new Date(r.min)&&o<=new Date(r.max)}return!0}}const m=w(e);if(!m)return!0;if(m==="address")return n==null?!1:typeof n=="object"&&"formatted_address"in n?String(n.formatted_address).toLowerCase().includes(String(t).toLowerCase()):!1;if(m==="multiselect"){if(!Array.isArray(n)||n.length===0)return!1;const D=String(t).toLowerCase();return n.some(p=>String(p).toLowerCase().includes(D))}return n==null?!1:String(n).toLowerCase().includes(String(t).toLowerCase())}export{T as matchesFilter};
@@ -1 +1 @@
1
- {"version":3,"file":"mergeWithOptimistic.d.ts","sourceRoot":"","sources":["../../src/utils/mergeWithOptimistic.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG/C,UAAU,MAAM;IACd,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,EAClD,SAAS,EAAE,CAAC,EAAE,EACd,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,GACzC,CAAC,EAAE,CA4BL"}
1
+ {"version":3,"file":"mergeWithOptimistic.d.ts","sourceRoot":"","sources":["../../src/utils/mergeWithOptimistic.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG/C,UAAU,MAAM;IACd,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,EAClD,SAAS,EAAE,CAAC,EAAE,EACd,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,GACzC,CAAC,EAAE,CAgCL"}
@@ -1 +1 @@
1
- import{CRUD_OPERATION as a}from"../types";function n(e,s){const o=[],p=new Set;for(const i of e){const t=s[i.id];t?.operation!==a.DELETE&&(t?.operation===a.UPDATE&&t.optimisticData?o.push(t.optimisticData):o.push(i),p.add(i.id))}for(const[i,t]of Object.entries(s))t.operation===a.ADD&&!p.has(i)&&t.optimisticData&&o.push(t.optimisticData);return o}export{n as mergeWithOptimistic};
1
+ import{CRUD_OPERATION as e}from"../types";function r(a,s){const o=[],n=new Set;for(const i of a){const t=s[i.id];t?.operation!==e.DELETE&&(t?.operation===e.UPDATE&&t.optimisticData?o.push(t.optimisticData):o.push(i),n.add(i.id))}for(const[i,t]of Object.entries(s))t.operation===e.ADD&&!n.has(i)&&t.optimisticData&&o.push(t.optimisticData);return o}export{r as mergeWithOptimistic};
@@ -1 +1 @@
1
- const r=/<script[\s\S]*?<\/script>/gi,e=/\s+on\w+\s*=\s*["'][^"']*["']/gi,i=/\s+(?:xlink:)?href\s*=\s*["']\s*javascript:[^"']*["']/gi,c=/\s+src\s*=\s*["']\s*javascript:[^"']*["']/gi;function t(s){return s.replace(r,"").replace(e,"").replace(i,"").replace(c,"")}export{t as sanitizeHtml};
1
+ const c=/<script[\s\S]*?<\/script>/gi,r=/\s+on\w+\s*=\s*["'][^"']*["']/gi,t=/\s+(?:xlink:)?href\s*=\s*["']\s*javascript:[^"']*["']/gi,e=/\s+src\s*=\s*["']\s*javascript:[^"']*["']/gi;function i(s){return s.replace(c,"").replace(r,"").replace(t,"").replace(e,"")}export{i as sanitizeHtml};
@@ -1 +1 @@
1
- import{getScopeValue as n,CRUD_OPERATORS as u}from"@donotdev/core";function c(e,t){if(!t)return e;const r=n(t.provider);return r?{...e,[t.field]:r}:e}function f(e,t){const r=e??{};if(!t||typeof t.field!="string")return r;const o=n(t.provider);if(!o)return r;const i={field:t.field,operator:u.EQ,value:o};return{...r,where:r.where?[...r.where,i]:[i]}}function p(e){return e?n(e.provider):null}export{p as getCurrentScopeValue,c as injectScope,f as injectScopeFilter};
1
+ import{getScopeValue as n,CRUD_OPERATORS as p}from"@donotdev/core";function l(r,o){if(!o)return r;const e=n(o.provider);return e?{...r,[o.field]:e}:r}function u(r,o){const e=r??{};if(!o||typeof o.field!="string")return e;const t=n(o.provider);if(!t)return e;const i={field:o.field,operator:p.EQ,value:t};return{...e,where:e.where?[...e.where,i]:[i]}}function f(r){return r?n(r.provider):null}export{f as getCurrentScopeValue,l as injectScope,u as injectScopeFilter};
@@ -1 +1 @@
1
- {"version":3,"file":"uploadValidation.d.ts","sourceRoot":"","sources":["../../src/utils/uploadValidation.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE9C;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGjD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAMzD;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,SAAK,GAAG,MAAM,EAAE,CAmDnE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAElD"}
1
+ {"version":3,"file":"uploadValidation.d.ts","sourceRoot":"","sources":["../../src/utils/uploadValidation.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE9C;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGjD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAMzD;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,SAAK,GAAG,MAAM,EAAE,CAqDnE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAElD"}
@@ -1 +1 @@
1
- "use client";function o(r){return!r||typeof r!="string"?!1:r.startsWith("https://")&&!r.startsWith("blob:")}function h(r){return!(!r||typeof r!="object"||!o(r.fullUrl)||r.thumbUrl&&!o(r.thumbUrl))}function i(r,l=""){const t=[];if(r==null)return t;if(typeof r=="string")return r.startsWith("blob:")&&t.push(l||"root"),t;if(typeof r!="object")return t;if(Array.isArray(r))r.forEach((e,s)=>{const n=l?`${l}[${s}]`:`[${s}]`;t.push(...i(e,n))});else{const e=r;if(e.fullUrl!==void 0&&e.thumbUrl!==void 0){const s=e.fullUrl,n=e.thumbUrl,u=typeof s=="string"&&!o(s),c=n&&typeof n=="string"&&!o(n);if(u||c){const f=l||"root";t.push(`${f}.fullUrl or ${f}.thumbUrl contains blob URL`)}}else Object.entries(e).forEach(([s,n])=>{const u=l?`${l}.${s}`:s;t.push(...i(n,u))})}return t}function b(r){return i(r).length>0}export{i as checkForBlobUrls,b as hasBlobUrls,o as isStorageUrl,h as validatePicture};
1
+ "use client";function s(r){return!r||typeof r!="string"?!1:r.startsWith("https://")&&!r.startsWith("blob:")}function c(r){return!(!r||typeof r!="object"||!s(r.fullUrl)||r.thumbUrl&&!s(r.thumbUrl))}function u(r,o=""){const t=[];if(r==null)return t;if(typeof r=="string")return r.startsWith("blob:")&&t.push(o||"root"),t;if(typeof r!="object")return t;if(Array.isArray(r))r.forEach((e,n)=>{const l=o?`${o}[${n}]`:`[${n}]`;t.push(...u(e,l))});else{const e=r;if(e.fullUrl!==void 0&&e.thumbUrl!==void 0){const n=e.fullUrl,l=e.thumbUrl,f=typeof n=="string"&&!s(n),b=l&&typeof l=="string"&&!s(l);if(f||b){const i=o||"root";t.push(`${i}.fullUrl or ${i}.thumbUrl contains blob URL`)}}else Object.entries(e).forEach(([n,l])=>{const f=o?`${o}.${n}`:n;t.push(...u(l,f))})}return t}function h(r){return u(r).length>0}export{u as checkForBlobUrls,h as hasBlobUrls,s as isStorageUrl,c as validatePicture};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@donotdev/crud",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE.md",
@@ -53,13 +53,13 @@
53
53
  "@dnd-kit/core": "^6.3.1",
54
54
  "@dnd-kit/sortable": "^10.0.0",
55
55
  "@dnd-kit/utilities": "^3.2.2",
56
- "@donotdev/components": "^0.0.19",
57
- "@donotdev/core": "^0.0.25",
56
+ "@donotdev/components": "^0.0.21",
57
+ "@donotdev/core": "^0.0.27",
58
58
  "@hookform/resolvers": "^5.2.2",
59
59
  "react-easy-crop": "^5.5.6"
60
60
  },
61
61
  "peerDependencies": {
62
- "@donotdev/firebase": "^0.0.12",
62
+ "@donotdev/firebase": "^0.0.14",
63
63
  "@tiptap/extension-placeholder": "^3.19.0",
64
64
  "@tiptap/pm": "^3.19.0",
65
65
  "@tiptap/react": "^3.19.0",
@@ -68,7 +68,7 @@
68
68
  "lucide-react": "^0.574.0",
69
69
  "react": "^19.2.4",
70
70
  "react-dom": "^19.2.4",
71
- "react-hook-form": "^7.71.1",
71
+ "react-hook-form": "^7.71.2",
72
72
  "valibot": "^1.2.0"
73
73
  },
74
74
  "peerDependenciesMeta": {
@@ -89,6 +89,9 @@
89
89
  },
90
90
  "firebase": {
91
91
  "optional": true
92
+ },
93
+ "tiptap": {
94
+ "optional": true
92
95
  }
93
96
  }
94
97
  }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=EntityFilters.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"EntityFilters.test.d.ts","sourceRoot":"","sources":["../../../src/components/__tests__/EntityFilters.test.tsx"],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- import{jsx as i}from"react/jsx-runtime";import{describe as d,it as r,expect as a,vi as t,beforeEach as c}from"vitest";import{render as n,screen as o}from"@testing-library/react";import{EntityFilters as s}from"../EntityFilters";import{defineEntity as u}from"@donotdev/core";t.mock("@donotdev/core",async()=>({...await t.importActual("@donotdev/core"),useTranslation:t.fn(()=>e=>e),handleError:t.fn()})),t.mock("@donotdev/components",()=>({Button:({children:e,...l})=>i("button",{...l,children:e}),Grid:({children:e})=>i("div",{children:e}),Combobox:({children:e})=>i("div",{children:e})})),t.mock("../hooks/useCrudFilters",()=>({useCrudFilters:t.fn(()=>({filters:{},setFilter:t.fn(),clearFilters:t.fn()}))})),d("EntityFilters",()=>{const e=u({name:"Product",collection:"products",fields:{title:{name:"title",label:"Title",type:"text",visibility:"user"},status:{name:"status",label:"Status",type:"select",visibility:"user",validation:{options:[{value:"active",label:"Active"},{value:"inactive",label:"Inactive"}]}}}});c(()=>{t.clearAllMocks()}),r("renders filters for entity fields",()=>{n(i(s,{entity:e})),a(o.getByRole("button",{name:/clear/i})).toBeDefined()}),r("renders with data prop",()=>{n(i(s,{entity:e,data:[{id:"1",title:"Product 1",status:"active"},{id:"2",title:"Product 2",status:"inactive"}]})),a(o.getByRole("button",{name:/clear/i})).toBeDefined()}),r("renders with sidebar variant",()=>{n(i(s,{entity:e,variant:"sidebar"})),a(o.getByRole("button",{name:/clear/i})).toBeDefined()})});
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=FormFieldRenderer.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"FormFieldRenderer.test.d.ts","sourceRoot":"","sources":["../../../src/components/__tests__/FormFieldRenderer.test.tsx"],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- import{jsx as n}from"react/jsx-runtime";import{describe as d,it as i,expect as a,vi as e,beforeEach as f}from"vitest";import{render as l}from"@testing-library/react";import{FormFieldRenderer as s}from"../FormFieldRenderer";e.mock("react-hook-form",()=>({useFormContext:e.fn(()=>({register:e.fn(),control:{},formState:{errors:{}}})),Controller:({render:t})=>{const o={onChange:e.fn(),onBlur:e.fn(),value:"",name:"test-field"};return t({field:o})}})),e.mock("../FieldRegistry",()=>({getFieldRegistry:e.fn(()=>({getComponent:e.fn(()=>()=>n("div",{children:"Mock Field"}))}))})),d("FormFieldRenderer",()=>{const t={name:"title",label:"Title",type:"text",visibility:"user",validation:{required:!0}},o=e.fn(r=>r);f(()=>{e.clearAllMocks()}),i("renders field with correct props",()=>{const{container:r}=l(n(s,{name:"title",config:t,t:o,control:{},errors:{}}));a(r).toBeDefined()}),i("renders textarea field for textarea type",()=>{const r={...t,type:"textarea",name:"description",label:"Description"},{container:c}=l(n(s,{name:"description",config:r,t:o,control:{},errors:{}}));a(c).toBeDefined()}),i("handles uncontrolled mode",()=>{const{container:r}=l(n(s,{name:"title",config:t,t:o,value:"",onChange:e.fn()}));a(r).toBeDefined()})});