@donotdev/crud 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/CrudService.d.ts +9 -0
- package/dist/CrudService.d.ts.map +1 -1
- package/dist/CrudService.js +2 -2
- package/dist/CrudStore.d.ts.map +1 -1
- package/dist/CrudStore.js +1 -1
- package/dist/FieldRegistry.d.ts +2 -12
- package/dist/FieldRegistry.d.ts.map +1 -1
- package/dist/FieldRegistry.js +1 -1
- package/dist/components/CrudButton.d.ts +1 -0
- package/dist/components/CrudButton.d.ts.map +1 -1
- package/dist/components/CrudCard.d.ts +1 -1
- package/dist/components/CrudCard.d.ts.map +1 -1
- package/dist/components/CrudCard.js +1 -1
- package/dist/components/DisplayFieldRenderer.d.ts +1 -0
- package/dist/components/DisplayFieldRenderer.d.ts.map +1 -1
- package/dist/components/DisplayFieldRenderer.js +1 -1
- package/dist/components/DisplayThumbnail.d.ts +1 -9
- package/dist/components/DisplayThumbnail.d.ts.map +1 -1
- package/dist/components/DisplayThumbnail.js +1 -1
- package/dist/components/EntityFilters.d.ts +1 -0
- package/dist/components/EntityFilters.d.ts.map +1 -1
- package/dist/components/FormFieldRenderer.d.ts +1 -0
- package/dist/components/FormFieldRenderer.d.ts.map +1 -1
- package/dist/components/FormFieldRenderer.js +1 -1
- package/dist/components/FormLayout.d.ts +1 -0
- package/dist/components/FormLayout.d.ts.map +1 -1
- package/dist/components/controlled/complex/ControlledAddressField.js +1 -1
- package/dist/components/controlled/complex/ControlledDateField.d.ts.map +1 -1
- package/dist/components/controlled/complex/ControlledDateField.js +1 -1
- package/dist/components/controlled/complex/ControlledGeoPointField.js +1 -1
- package/dist/components/controlled/complex/ControlledMapField.js +1 -1
- package/dist/components/controlled/complex/ControlledRichTextField.js +1 -1
- package/dist/components/controlled/complex/ControlledTimestampField.d.ts.map +1 -1
- package/dist/components/controlled/complex/ControlledTimestampField.js +1 -1
- package/dist/components/controlled/file/ControlledDocumentField.js +1 -1
- package/dist/components/controlled/file/ControlledFileField.js +1 -1
- package/dist/components/controlled/file/ControlledImageField.js +1 -1
- package/dist/components/controlled/file/ControlledMultiDocumentField.js +1 -1
- package/dist/components/controlled/file/ControlledMultiFileField.js +1 -1
- package/dist/components/controlled/file/ControlledMultiImageField.js +1 -1
- package/dist/components/controlled/input/ControlledCurrencyField.js +1 -1
- package/dist/components/controlled/input/ControlledDurationField.js +1 -1
- package/dist/components/controlled/input/ControlledNumberField.js +1 -1
- package/dist/components/controlled/input/ControlledPasswordField.js +1 -1
- package/dist/components/controlled/input/ControlledPhoneField.js +1 -1
- package/dist/components/controlled/input/ControlledPriceField.js +1 -1
- package/dist/components/controlled/input/ControlledRangeField.js +1 -1
- package/dist/components/controlled/input/ControlledRatingField.js +1 -1
- package/dist/components/controlled/input/ControlledSwitchField.js +1 -1
- package/dist/components/controlled/input/ControlledTextField.d.ts +5 -5
- package/dist/components/controlled/input/ControlledTextField.d.ts.map +1 -1
- package/dist/components/controlled/input/ControlledTextField.js +1 -1
- package/dist/components/controlled/input/ControlledTextareaField.js +1 -1
- package/dist/components/controlled/select/ControlledComboboxField.js +1 -1
- package/dist/components/controlled/select/ControlledDropdownField.d.ts +2 -4
- package/dist/components/controlled/select/ControlledDropdownField.d.ts.map +1 -1
- package/dist/components/controlled/select/ControlledDropdownField.js +1 -1
- package/dist/components/controlled/select/ControlledMultiDropdownField.d.ts +2 -4
- package/dist/components/controlled/select/ControlledMultiDropdownField.d.ts.map +1 -1
- package/dist/components/controlled/select/ControlledMultiDropdownField.js +1 -1
- package/dist/components/controlled/select/ControlledRadioField.d.ts +2 -4
- package/dist/components/controlled/select/ControlledRadioField.d.ts.map +1 -1
- package/dist/components/controlled/select/ControlledRadioField.js +1 -1
- package/dist/components/controlled/select/ControlledReferenceField.js +1 -1
- package/dist/components/controlled/select/ControlledYearField.js +1 -1
- package/dist/components/fields/display/DateFieldDisplay.d.ts.map +1 -1
- package/dist/components/fields/display/DateFieldDisplay.js +1 -1
- package/dist/components/fields/display/NumberFieldDisplay.d.ts.map +1 -1
- package/dist/components/fields/display/NumberFieldDisplay.js +1 -1
- package/dist/components/fields/display/TextFieldDisplay.js +1 -1
- package/dist/components/fields/display/TimestampFieldDisplay.d.ts.map +1 -1
- package/dist/components/fields/display/TimestampFieldDisplay.js +1 -1
- package/dist/components/form/fields/CurrencyFieldComponent.d.ts.map +1 -1
- package/dist/components/form/fields/CurrencyFieldComponent.js +1 -1
- package/dist/components/form/fields/DateFieldComponent.d.ts +2 -2
- package/dist/components/form/fields/DateFieldComponent.d.ts.map +1 -1
- package/dist/components/form/fields/DateFieldComponent.js +1 -1
- package/dist/components/form/fields/DocumentFieldComponent.js +1 -1
- package/dist/components/form/fields/FileFieldComponent.js +1 -1
- package/dist/components/form/fields/ImageFieldComponent.d.ts.map +1 -1
- package/dist/components/form/fields/ImageFieldComponent.js +1 -1
- package/dist/components/form/fields/TextFieldComponent.d.ts +2 -2
- package/dist/components/form/fields/TextFieldComponent.d.ts.map +1 -1
- package/dist/components/form/fields/TextFieldComponent.js +1 -1
- package/dist/components/form/fields/TimestampFieldComponent.d.ts +2 -2
- package/dist/components/form/fields/TimestampFieldComponent.d.ts.map +1 -1
- package/dist/contexts/UploadContext.d.ts +1 -0
- package/dist/contexts/UploadContext.d.ts.map +1 -1
- package/dist/fieldTypeRegistry.store.d.ts.map +1 -1
- package/dist/fieldTypeRegistry.store.js +1 -1
- package/dist/fieldTypeRegistry.types.d.ts +4 -0
- package/dist/fieldTypeRegistry.types.d.ts.map +1 -1
- package/dist/forms/hooks/useEntityForm.d.ts.map +1 -1
- package/dist/forms/hooks/useEntityForm.js +1 -1
- package/dist/forms/types.d.ts +5 -0
- package/dist/forms/types.d.ts.map +1 -1
- package/dist/forms/utils/buildInitialValues.d.ts.map +1 -1
- package/dist/forms/utils/buildInitialValues.js +1 -1
- package/dist/forms/utils/getFieldsForOperation.d.ts.map +1 -1
- package/dist/forms/utils/getFieldsForOperation.js +1 -1
- package/dist/forms/utils/isFieldEditable.d.ts +7 -1
- package/dist/forms/utils/isFieldEditable.d.ts.map +1 -1
- package/dist/forms/utils/isFieldEditable.js +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/useCrudFilters.d.ts +2 -0
- package/dist/hooks/useCrudFilters.d.ts.map +1 -1
- package/dist/hooks/useCrudPageSize.d.ts +29 -0
- package/dist/hooks/useCrudPageSize.d.ts.map +1 -0
- package/dist/hooks/useCrudPageSize.js +1 -0
- package/dist/hooks/useEntityFavorites.d.ts +2 -0
- package/dist/hooks/useEntityFavorites.d.ts.map +1 -1
- package/dist/hooks/useFileUpload.d.ts.map +1 -1
- package/dist/hooks/useFileUpload.js +1 -1
- package/dist/hooks/useReferenceResolver.d.ts +1 -1
- package/dist/hooks/useReferenceResolver.d.ts.map +1 -1
- package/dist/hooks/useReferenceResolver.js +1 -1
- package/dist/hooks/useRelatedItems.d.ts +2 -0
- package/dist/hooks/useRelatedItems.d.ts.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/registerBuiltinFieldTypes.d.ts.map +1 -1
- package/dist/registerBuiltinFieldTypes.js +1 -1
- package/dist/stores/FormStore.d.ts +2 -0
- package/dist/stores/FormStore.d.ts.map +1 -1
- package/dist/stores/FormStore.js +1 -1
- package/dist/stores/UploadStore.d.ts +9 -3
- package/dist/stores/UploadStore.d.ts.map +1 -1
- package/dist/stores/UploadStore.js +1 -1
- package/dist/symbol-index.json +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/useCrud.d.ts +1 -0
- package/dist/useCrud.d.ts.map +1 -1
- package/dist/useCrud.js +1 -1
- package/dist/useCrudCardList.d.ts +5 -3
- package/dist/useCrudCardList.d.ts.map +1 -1
- package/dist/useCrudList.d.ts +5 -3
- package/dist/useCrudList.d.ts.map +1 -1
- package/dist/utils/clientListProcessing.d.ts +21 -2
- package/dist/utils/clientListProcessing.d.ts.map +1 -1
- package/dist/utils/clientListProcessing.js +1 -1
- package/dist/utils/fileStorage.d.ts +2 -0
- package/dist/utils/fileStorage.d.ts.map +1 -1
- package/dist/utils/fileStorage.js +1 -1
- package/dist/utils/imageProcessing.d.ts.map +1 -1
- package/dist/utils/imageProcessing.js +1 -1
- package/dist/utils/imageStorage.d.ts +2 -0
- package/dist/utils/imageStorage.d.ts.map +1 -1
- package/dist/utils/imageStorage.js +1 -1
- package/guidelines/COMPONENTS.md +234 -0
- package/guidelines/CRUD.md +340 -0
- package/guidelines/GOTCHAS.md +46 -0
- package/package.json +7 -4
package/dist/types.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ export declare const OPTIMISTIC_STATUSES: {
|
|
|
20
20
|
readonly CONFIRMED: "confirmed";
|
|
21
21
|
readonly FAILED: "failed";
|
|
22
22
|
};
|
|
23
|
+
/** Union of optimistic operation status values: 'pending' | 'confirmed' | 'failed'. */
|
|
23
24
|
export type OptimisticStatus = (typeof OPTIMISTIC_STATUSES)[keyof typeof OPTIMISTIC_STATUSES];
|
|
24
25
|
/** Optimistic mutation operation kind */
|
|
25
26
|
export declare const CRUD_OPERATION: {
|
|
@@ -29,6 +30,7 @@ export declare const CRUD_OPERATION: {
|
|
|
29
30
|
readonly SET: "set";
|
|
30
31
|
readonly DELETE: "delete";
|
|
31
32
|
};
|
|
33
|
+
/** Union of CRUD mutation operation kinds: 'add' | 'update' | 'set' | 'delete'. */
|
|
32
34
|
export type CrudOperation = (typeof CRUD_OPERATION)[keyof typeof CRUD_OPERATION];
|
|
33
35
|
/**
|
|
34
36
|
* Optimistic operation metadata
|
|
@@ -60,6 +62,8 @@ export type FilterState = Record<string, string | string[] | {
|
|
|
60
62
|
export interface CollectionUIState {
|
|
61
63
|
filters: FilterState;
|
|
62
64
|
showFavoritesOnly: boolean;
|
|
65
|
+
/** Persisted items-per-page preference (survives navigation) */
|
|
66
|
+
pageSize?: number;
|
|
63
67
|
}
|
|
64
68
|
/**
|
|
65
69
|
* CRUD store state interface
|
|
@@ -101,8 +105,10 @@ export interface CrudActions {
|
|
|
101
105
|
clearError: (collection: string) => void;
|
|
102
106
|
setFilters: (collection: string, filters: FilterState) => void;
|
|
103
107
|
setShowFavoritesOnly: (collection: string, show: boolean) => void;
|
|
108
|
+
setPageSize: (collection: string, pageSize: number) => void;
|
|
104
109
|
getFilters: (collection: string) => FilterState;
|
|
105
110
|
getShowFavoritesOnly: (collection: string) => boolean;
|
|
111
|
+
getPageSize: (collection: string) => number | undefined;
|
|
106
112
|
/** Add item optimistically (before server confirms) */
|
|
107
113
|
addOptimistic: (collection: string, tempId: string, data: unknown) => void;
|
|
108
114
|
/** Confirm optimistic add - replace temp item with real item */
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,YAAY,EACZ,oBAAoB,EACpB,cAAc,EACf,MAAM,gBAAgB,CAAC;AAExB;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;CAItB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAC1B,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,OAAO,mBAAmB,CAAC,CAAC;AAEjE,yCAAyC;AACzC,eAAO,MAAM,cAAc;;;IAGzB,0EAA0E;;;CAGlE,CAAC;AAEX,MAAM,MAAM,aAAa,GACvB,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,OAAO,cAAc,CAAC,CAAC;AAEvD;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,OAAO,GAAG,IAAI,CAAC;IAC7B,iEAAiE;IACjE,cAAc,EAAE,OAAO,CAAC;IACxB,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,EAAE,aAAa,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,CAC9B,MAAM,EACN,MAAM,GAAG,MAAM,EAAE,GAAG;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CACnD,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,WAAW,CAAC;IACrB,iBAAiB,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/useCrud.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export declare const EMPTY_OPTIMISTIC: Record<string, unknown>;
|
|
|
6
6
|
* Get the current CrudService instance (for use in callbacks)
|
|
7
7
|
*/
|
|
8
8
|
export declare function getCrudServiceInstance(): CrudServiceInterface | null;
|
|
9
|
+
/** Options for the {@link useCrud} hook. */
|
|
9
10
|
export interface UseCrudOptions<T> {
|
|
10
11
|
schema?: dndevSchema<T>;
|
|
11
12
|
/** Entity definition - auto-generates schema if schema not provided */
|
package/dist/useCrud.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCrud.d.ts","sourceRoot":"","sources":["../src/useCrud.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useCrud.d.ts","sourceRoot":"","sources":["../src/useCrud.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EACV,WAAW,EACX,MAAM,EACN,aAAa,EACb,gBAAgB,EAChB,OAAO,EACP,WAAW,EAEZ,MAAM,gBAAgB,CAAC;AAMxB,OAAO,KAAK,EACV,oBAAoB,EACpB,YAAY,EAEb,MAAM,SAAS,CAAC;AAKjB,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,CAAC;AACtD,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,CAAC;AAe5D;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,oBAAoB,GAAG,IAAI,CAEpE;AAMD,4CAA4C;AAC5C,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACxB,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC,CAAE,SAAQ,OAAO,CAAC,CAAC,CAAC;IAElD,gCAAgC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,QAAQ,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACvC,8BAA8B;IAC9B,aAAa,EAAE,YAAY,CAAC;IAC5B,wDAAwD;IACxD,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC;CACjC;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,QAAQ,GAAG,aAAa,CAAC;AACtD,wBAAgB,OAAO,CAAC,CAAC,GAAG,OAAO,EACjC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,GAC1B,aAAa,CAAC,CAAC,CAAC,CAAC;AACpB,wBAAgB,OAAO,CAAC,CAAC,GAAG,OAAO,EACjC,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,GAC1B,aAAa,CAAC,CAAC,CAAC,CAAC"}
|
package/dist/useCrud.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{useEffect as
|
|
1
|
+
"use client";import{useEffect as L,useMemo as y,useCallback as i}from"react";import{useFeatureConsent as W,FRAMEWORK_FEATURES as Q,FEATURE_STATUS as h,handleError as V,isClient as Z,createSchemas as $,DEGRADED_CRUD_API as B,getGlobalSingleton as H}from"@donotdev/core";import{getCrudService as J}from"./CrudService";import{useCrudStore as u}from"./CrudStore";import{injectScope as P,injectScopeFilter as X}from"./utils/scopeUtils";const re={},ce={};function N(){return H("crud-service",()=>({service:null,initPromise:null,errorNotified:!1}))}function o(){return N().service}function ne(l,d={}){const S=W(Q.CRUD),U=u(e=>e.crudService),g=S&&!U,p=S?g?h.INITIALIZING:h.READY:h.DEGRADED,m=l==="status",v=!m&&typeof l=="object"?l:d.entity,r=m?"__status__":typeof l=="string"?l:l.collection,a=v?.scope,_=d.noCache??!1,C=d.staleTime,f=y(()=>({noCache:_,staleTime:C}),[_,C]),s=y(()=>{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(v)return $(v)}},[m,d.schema,v?.name,r]),w=u(e=>e.collections[r]?.loading||!1),E=u(e=>e.collections[r]?.error||null),F=null;L(()=>{if(!Z()||!S||!s)return;const{crudService:e}=u.getState(),t=N();e||t.service||t.initPromise||(t.initPromise=(async()=>{try{if(t.service||u.getState().crudService)return;const c=J();t.service=c,c.setStore(u),await c.initialize(),t.errorNotified=!1,u.getState().setCrudService(c)}catch(c){t.errorNotified||(V(c,{userMessage:"Failed to initialize CRUD service.",context:{collection:r},severity:"error"}),t.errorNotified=!0)}finally{t.initPromise=null}})())},[S,r,s?"hasSchema":"noSchema"]);const T=g||w,x=p===h.READY,M=i(async e=>{const t=o();return!t||!s?null:t.get(r,e,s.get,f)},[r,s?"hasSchema":"noSchema",f]),Y=i(async(e,t,c)=>{const n=o();if(!n||!s)return;const D=P(t,a),z=D?.status==="draft"?s.draft:s.create;await n.set(r,e,D,z,c)},[r,s?"hasSchema":"noSchema",a?.provider]),G=i(async(e,t,c)=>{const n=o();n&&await n.update(r,e,t,s?.update,c)},[r,s]),j=i(async(e,t)=>{const c=o();c&&await c.delete(r,e,t)},[r]),k=i(async(e,t)=>{const c=o();if(!c||!s)return"";const n=P(e,a),I=n?.status==="draft"?s.draft:s.create;return c.add(r,n,I,t)},[r,s?"hasSchema":"noSchema",a?.provider]),q=i(async e=>{const t=o();if(!t||!s)return[];const c=X(e,a);return(await t.query(r,c,s.list,f)).items},[r,s?"hasSchema":"noSchema",f,a?.provider]),A=i((e,t)=>{const c=o();return!c||!s?()=>{}:c.subscribe(r,e,t,s.get)},[r,s?"hasSchema":"noSchema"]),b=i((e,t)=>{const c=o();return!c||!s?()=>{}:c.subscribeToCollection(r,e,t,s.list)},[r,s?"hasSchema":"noSchema"]),R=i(async()=>{const e=o();e&&await e.invalidateCollection(r)},[r]);return m?p:x?{status:h.READY,data:F,loading:T,error:E,get:M,set:Y,update:G,delete:j,add:k,query:q,subscribe:A,subscribeToCollection:b,invalidate:R,isAvailable:!0,_collection:r,_schemas:s,_cacheOptions:f,_scope:a}:{...B,status:p,loading:T,error:E,subscribe:A,subscribeToCollection:b,invalidate:R,_collection:r,_schemas:s,_cacheOptions:f,_scope:a}}export{re as EMPTY_DATA,ce as EMPTY_OPTIMISTIC,o as getCrudServiceInstance,ne as useCrud};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Entity, FeatureStatus, QueryOptions } from '@donotdev/core';
|
|
2
2
|
import type { UseCrudOptions } from './useCrud';
|
|
3
|
-
import type { ClientSortConfig } from './utils/clientListProcessing';
|
|
3
|
+
import type { ClientSort, ClientSortConfig } from './utils/clientListProcessing';
|
|
4
|
+
/** Options for the {@link useCrudCardList} hook. */
|
|
4
5
|
export interface UseCrudCardListOptions<T> extends UseCrudOptions<T> {
|
|
5
6
|
/** Automatically fetch data on mount (default: true) */
|
|
6
7
|
enabled?: boolean;
|
|
@@ -8,9 +9,10 @@ export interface UseCrudCardListOptions<T> extends UseCrudOptions<T> {
|
|
|
8
9
|
queryOptions?: QueryOptions;
|
|
9
10
|
/** Client-side search query. Applied after filters. */
|
|
10
11
|
searchQuery?: string;
|
|
11
|
-
/** Client-side sort config. Defaults to entity.defaultSort.
|
|
12
|
-
clientSort?: ClientSortConfig | null;
|
|
12
|
+
/** Client-side sort: field config, comparator function, or null to disable. Defaults to entity.defaultSort. */
|
|
13
|
+
clientSort?: ClientSort<T> | ClientSortConfig | null;
|
|
13
14
|
}
|
|
15
|
+
/** Return type of the {@link useCrudCardList} hook. */
|
|
14
16
|
export interface UseCrudCardListReturn<T> {
|
|
15
17
|
status: FeatureStatus;
|
|
16
18
|
data: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCrudCardList.d.ts","sourceRoot":"","sources":["../src/useCrudCardList.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAa1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"useCrudCardList.d.ts","sourceRoot":"","sources":["../src/useCrudCardList.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAa1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEjF,oDAAoD;AACpD,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,+GAA+G;IAC/G,UAAU,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,gBAAgB,GAAG,IAAI,CAAC;CACtD;AAED,uDAAuD;AACvD,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"}
|
package/dist/useCrudList.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Entity, FeatureStatus } from '@donotdev/core';
|
|
2
2
|
import type { QueryOptions } from '@donotdev/core';
|
|
3
3
|
import type { UseCrudOptions } from './useCrud';
|
|
4
|
-
import type { ClientSortConfig } from './utils/clientListProcessing';
|
|
4
|
+
import type { ClientSort, ClientSortConfig } from './utils/clientListProcessing';
|
|
5
|
+
/** Options for the {@link useCrudList} hook. */
|
|
5
6
|
export interface UseCrudListOptions<T> extends UseCrudOptions<T> {
|
|
6
7
|
/** Automatically fetch data on mount (default: true) */
|
|
7
8
|
enabled?: boolean;
|
|
@@ -20,9 +21,10 @@ export interface UseCrudListOptions<T> extends UseCrudOptions<T> {
|
|
|
20
21
|
queryOptions?: QueryOptions;
|
|
21
22
|
/** Client-side search query. Applied after filters. */
|
|
22
23
|
searchQuery?: string;
|
|
23
|
-
/** Client-side sort config. Defaults to entity.defaultSort.
|
|
24
|
-
clientSort?: ClientSortConfig | null;
|
|
24
|
+
/** Client-side sort: field config, comparator function, or null to disable. Defaults to entity.defaultSort. */
|
|
25
|
+
clientSort?: ClientSort<T> | ClientSortConfig | null;
|
|
25
26
|
}
|
|
27
|
+
/** Return type of the {@link useCrudList} hook. */
|
|
26
28
|
export interface UseCrudListReturn<T> {
|
|
27
29
|
status: FeatureStatus;
|
|
28
30
|
data: {
|
|
@@ -1 +1 @@
|
|
|
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;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAcnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;
|
|
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;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAcnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEjF,gDAAgD;AAChD,MAAM,WAAW,kBAAkB,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;IAC9D,wDAAwD;IACxD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC1C,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,+GAA+G;IAC/G,UAAU,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,gBAAgB,GAAG,IAAI,CAAC;CACtD;AAED,mDAAmD;AACnD,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;IACrB,6EAA6E;IAC7E,aAAa,EAAE,QAAQ,GAAG,QAAQ,CAAC;CACpC;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"}
|
|
@@ -21,6 +21,21 @@ export interface ClientSortConfig {
|
|
|
21
21
|
field: string;
|
|
22
22
|
direction?: 'asc' | 'desc';
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Client-side sort: field-based config or custom comparator function.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* // Field-based
|
|
30
|
+
* const sort: ClientSort = { field: 'price', direction: 'desc' };
|
|
31
|
+
*
|
|
32
|
+
* // Custom comparator (multi-key, status priority, etc.)
|
|
33
|
+
* const sort: ClientSort<Apartment> = (a, b) =>
|
|
34
|
+
* STATUS_PRIORITY[a.status] - STATUS_PRIORITY[b.status]
|
|
35
|
+
* || a.date.localeCompare(b.date);
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export type ClientSort<T = Record<string, unknown>> = ClientSortConfig | ((a: T, b: T) => number);
|
|
24
39
|
/**
|
|
25
40
|
* Apply filter state to items using entity field type metadata.
|
|
26
41
|
* Typically called automatically by `useCrudList`/`useCrudCardList` via `processed`.
|
|
@@ -65,18 +80,22 @@ export declare function getSearchableFields(entity: Entity): string[];
|
|
|
65
80
|
export declare function applySearch<T extends Record<string, any>>(items: T[], query: string, entity: Entity): T[];
|
|
66
81
|
/**
|
|
67
82
|
* Apply client-side sorting to items.
|
|
83
|
+
* Accepts a field-based config or a custom comparator function.
|
|
68
84
|
* Handles null/undefined values by sorting them last.
|
|
69
85
|
* Supports number, string, Date, and price ({ amount }) comparisons.
|
|
70
86
|
*
|
|
71
87
|
* @param items - Items to sort
|
|
72
|
-
* @param sort - Sort configuration (field + direction)
|
|
88
|
+
* @param sort - Sort configuration (field + direction) or comparator function
|
|
73
89
|
* @returns Sorted items (new array, original unchanged)
|
|
74
90
|
*
|
|
75
91
|
* @example
|
|
76
92
|
* ```typescript
|
|
77
93
|
* import { applySort } from '@donotdev/crud';
|
|
94
|
+
* // Field-based
|
|
78
95
|
* const sorted = applySort(items, { field: 'createdAt', direction: 'desc' });
|
|
96
|
+
* // Custom comparator
|
|
97
|
+
* const sorted = applySort(items, (a, b) => a.priority - b.priority);
|
|
79
98
|
* ```
|
|
80
99
|
*/
|
|
81
|
-
export declare function applySort<T extends Record<string, any>>(items: T[], sort:
|
|
100
|
+
export declare function applySort<T extends Record<string, any>>(items: T[], sort: ClientSort<T>): T[];
|
|
82
101
|
//# sourceMappingURL=clientListProcessing.d.ts.map
|
|
@@ -1 +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;AAK7C,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
|
|
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;AAK7C,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;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC9C,gBAAgB,GAChB,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC,CAAC;AAE7B;;;;;;;;;;;;;;;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;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACrD,KAAK,EAAE,CAAC,EAAE,EACV,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAClB,CAAC,EAAE,CAwCL"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{matchesFilter as u}from"./matchesFilter";import{getValueType as c}from"../fieldTypeRegistry.store";function
|
|
1
|
+
import{matchesFilter as u}from"./matchesFilter";import{getValueType as c}from"../fieldTypeRegistry.store";function m(t,i,f){const l=Object.entries(i);return l.length===0?t:t.filter(r=>l.every(([o,s])=>{const n=f.fields[o]?.type||"text";return u(r[o],s,n)}))}function a(t){if(t.search?.fields&&t.search.fields.length>0)return t.search.fields;const i=new Set(["string"]),f=[];for(const[l,r]of Object.entries(t.fields)){if(r.visibility==="hidden"||r.visibility==="technical")continue;const o=c(r.type);o&&i.has(o)&&f.push(l)}return f}function h(t,i,f){if(!i||i.trim()==="")return t;const l=i.toLowerCase(),r=a(f);return r.length===0?t.filter(o=>Object.values(o).some(s=>s==null?!1:String(s).toLowerCase().includes(l))):t.filter(o=>r.some(s=>{const e=o[s];return e==null?!1:typeof e=="object"&&"formatted_address"in e?String(e.formatted_address).toLowerCase().includes(l):String(e).toLowerCase().includes(l)}))}function b(t,i){if(typeof i=="function")return[...t].sort(i);const{field:f,direction:l="asc"}=i,r=l==="desc"?-1:1;return[...t].sort((o,s)=>{const e=o[f],n=s[f];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{m as applyFilters,h as applySearch,b as applySort,a as getSearchableFields};
|
|
@@ -18,6 +18,8 @@ export interface UploadFileOptions {
|
|
|
18
18
|
filename?: string;
|
|
19
19
|
/** Progress callback */
|
|
20
20
|
onProgress?: UploadProgressCallback;
|
|
21
|
+
/** AbortSignal to cancel the upload */
|
|
22
|
+
signal?: AbortSignal;
|
|
21
23
|
}
|
|
22
24
|
/**
|
|
23
25
|
* Upload a file to storage with progress tracking.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileStorage.d.ts","sourceRoot":"","sources":["../../src/utils/fileStorage.ts"],"names":[],"mappings":"AAeA,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;
|
|
1
|
+
{"version":3,"file":"fileStorage.d.ts","sourceRoot":"","sources":["../../src/utils/fileStorage.ts"],"names":[],"mappings":"AAeA,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;IACpC,uCAAuC;IACvC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAYD;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,IAAI,EACV,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,SAAS,CAAC,CAkCpB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,IAAI,EAAE,EACb,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,SAAS,EAAE,CAAC,CAgCtB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAWhE;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
|
|
1
|
+
"use client";import{handleError as d,getProvider as p}from"@donotdev/core";function x(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,signal:o}=t,a=Date.now(),c=x(e.name),i=n||`${a}_${c}`,l=`${r}/${i}`;try{return{url:(await p("storage").upload(e,{storagePath:r,filename:i,onProgress:s?f=>s({bytesTransferred:0,totalBytes:0,progress:f}):void 0,signal:o})).url,filename:e.name,size:e.size,mimeType:e.type,uploadedAt:new Date().toISOString()}}catch(u){throw d(u,{userMessage:"Failed to upload file",severity:"error",context:{filename:e.name,fileSize:e.size}})}}async function F(e,t={}){const r=[],n=e.reduce((o,a)=>o+a.size,0);let s=0;for(const o of e){if(t.signal?.aborted)throw new Error("Upload cancelled");const a=t.onProgress?i=>{const l=i.bytesTransferred/i.totalBytes*o.size;t.onProgress({bytesTransferred:s+l,totalBytes:n,progress:(s+l)/n*100})}:void 0,c=await g(o,{...t,onProgress:a});r.push(c),s+=o.size}return r}async function M(e){try{await p("storage").delete(e.url)}catch(t){throw d(t,{userMessage:"Failed to delete file",severity:"error",context:{url:e.url,filename:e.filename}}),t}}function P(){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 S(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 m=["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"],w=[".pdf",".doc",".docx",".xls",".xlsx",".ppt",".pptx",".txt",".md",".html",".csv"];function B(){return[...m,...w].join(",")}export{w as DOCUMENT_EXTENSIONS,m as DOCUMENT_MIME_TYPES,M as deleteFile,E as formatFileSize,P as generateFileId,B as getDocumentAcceptString,h as getFileExtension,S as getFileIcon,g as uploadFile,F as uploadFiles};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"imageProcessing.d.ts","sourceRoot":"","sources":["../../src/utils/imageProcessing.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,IAAI,CAAC;IACf,SAAS,EAAE,IAAI,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,IAAI,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAChE;
|
|
1
|
+
{"version":3,"file":"imageProcessing.d.ts","sourceRoot":"","sources":["../../src/utils/imageProcessing.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,IAAI,CAAC;IACf,SAAS,EAAE,IAAI,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,IAAI,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAChE;AAiBD;;GAEG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,IAAI,EACV,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,cAAc,CAAC,CAyEzB;AAmHD;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,IAAI,EACV,YAAY,CAAC,EAAE,MAAM,GACpB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAgBpC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
async function
|
|
1
|
+
const F=new WeakMap;function W(e){return JSON.stringify({maxWidth:e.maxWidth,maxHeight:e.maxHeight,thumbWidth:e.thumbWidth,thumbHeight:e.thumbHeight,aspectRatio:e.aspectRatio,quality:e.quality,crop:e.crop})}async function H(e,h={}){const r=W(h),n=F.get(e);if(n?.has(r))return n.get(r);const{maxWidth:l=1920,maxHeight:t=1440,thumbWidth:i=300,thumbHeight:o=225,aspectRatio:c=4/3,quality:w=.85,crop:a}=h;return new Promise((u,d)=>{const s=new Image,f=new FileReader;f.onload=g=>{s.src=g.target?.result},f.onerror=()=>d(new Error("Failed to read file")),s.onload=async()=>{try{const{width:g,height:b}=E(a?a.width:s.width,a?a.height:s.height,l,t,c),v=await y(s,g,b,c,w,a),M=await y(s,i,o,c,.65,a),x={fullBlob:v,thumbBlob:M,width:g,height:b};let m=F.get(e);m||(m=new Map,F.set(e,m)),m.set(r,x),u(x)}catch(g){d(g)}},s.onerror=()=>d(new Error("Failed to load image")),f.readAsDataURL(e)})}function E(e,h,r,n,l){let t=e,i=h;t>r&&(i=r/t*i,t=r),i>n&&(t=n/i*t,i=n);const o=t/i;return Math.abs(o-l)>.01&&(o>l?i=t/l:t=i*l),{width:Math.round(t),height:Math.round(i)}}async function y(e,h,r,n,l,t){const i=document.createElement("canvas"),o=i.getContext("2d");if(!o)throw new Error("Failed to get canvas context");i.width=h,i.height=r,o.fillStyle="#FFFFFF",o.fillRect(0,0,h,r);let c,w,a,u;if(t)c=t.x,w=t.y,a=t.width,u=t.height;else{const d=e.width/e.height;a=e.width,u=e.height,c=0,w=0,d>n?(a=e.height*n,c=(e.width-a)/2):d<n&&(u=e.width/n,w=(e.height-u)/2)}return o.drawImage(e,c,w,a,u,0,0,h,r),new Promise((d,s)=>{i.toBlob(f=>{f?d(f):s(new Error("Failed to convert canvas to blob"))},"image/webp",l)})}function B(e,h){return e.type.startsWith("image/")?h&&e.size>h?{valid:!1,error:`File size exceeds ${(h/1048576).toFixed(1)}MB limit`}:{valid:!0}:{valid:!1,error:"File must be an image"}}export{H as processImage,B as validateImageFile};
|
|
@@ -18,6 +18,8 @@ export interface UploadImageOptions {
|
|
|
18
18
|
filename?: string;
|
|
19
19
|
/** Progress callback */
|
|
20
20
|
onProgress?: UploadProgressCallback;
|
|
21
|
+
/** AbortSignal to cancel the upload */
|
|
22
|
+
signal?: AbortSignal;
|
|
21
23
|
}
|
|
22
24
|
/**
|
|
23
25
|
* Upload full and thumbnail images to storage with progress tracking.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"imageStorage.d.ts","sourceRoot":"","sources":["../../src/utils/imageStorage.ts"],"names":[],"mappings":"AAcA,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;
|
|
1
|
+
{"version":3,"file":"imageStorage.d.ts","sourceRoot":"","sources":["../../src/utils/imageStorage.ts"],"names":[],"mappings":"AAcA,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;IACpC,uCAAuC;IACvC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;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,CA0ElB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAcjE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{handleError as
|
|
1
|
+
import{handleError as $,getProvider as m}from"@donotdev/core";function U(e){return e.replace(/[^a-zA-Z0-9.-]/g,"_").replace(/_{2,}/g,"_").toLowerCase()}async function x(e,t,r,f={}){const{storagePath:a="uploads/images",filename:g,onProgress:o,signal:n}=f,w=Date.now(),l=(g||`${w}_${U(r)}`).replace(/\.[^/.]+$/,""),p=`${a}/${l}_full.webp`,y=`${a}/${l}_thumb.webp`;try{const u=new File([e],`${l}_full.webp`,{type:"image/webp"}),s=new File([t],`${l}_thumb.webp`,{type:"image/webp"});let h,b;const c=m("storage"),d=await c.upload(u,{storagePath:a,filename:`${l}_full.webp`,onProgress:o?i=>o({bytesTransferred:0,totalBytes:0,progress:i*.5}):void 0,signal:n});if(h=d.url,n?.aborted){try{await c.delete(d.url)}catch{}throw new Error("Upload cancelled")}return b=(await c.upload(s,{storagePath:a,filename:`${l}_thumb.webp`,onProgress:o?i=>o({bytesTransferred:0,totalBytes:0,progress:50+i*.5}):void 0,signal:n})).url,{fullUrl:h,thumbUrl:b}}catch(u){try{const s=m("storage");await s.delete(p).catch(()=>{}),await s.delete(y).catch(()=>{})}catch{}throw u}}async function E(e){try{const t=m("storage"),r=[t.delete(e.fullUrl)];e.thumbUrl&&r.push(t.delete(e.thumbUrl)),await Promise.all(r)}catch(t){throw $(t,{userMessage:"Failed to delete image",severity:"error",context:{fullUrl:e.fullUrl,thumbUrl:e.thumbUrl}}),t}}export{E as deleteImage,x as uploadImage};
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# CRUD Components Reference
|
|
2
|
+
|
|
3
|
+
**Import:** `@donotdev/crud`
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Hooks
|
|
8
|
+
|
|
9
|
+
### useCrud
|
|
10
|
+
Single document CRUD actions (add, update, delete, get, subscribe).
|
|
11
|
+
|
|
12
|
+
```tsx
|
|
13
|
+
const { add, update, delete: remove, get, data, loading, error } = useCrud(carEntity);
|
|
14
|
+
await add({ name: 'Tesla', year: 2024 });
|
|
15
|
+
await remove('doc-id');
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### useCrudList
|
|
19
|
+
Paginated list with automatic loading. For data tables.
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
const { items, loading, refresh } = useCrudList(productEntity);
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### useCrudCardList
|
|
26
|
+
Card-based list with infinite scroll.
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
const { items, loading, refresh } = useCrudCardList(articleEntity);
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Form Components
|
|
35
|
+
|
|
36
|
+
### EntityFormRenderer
|
|
37
|
+
Auto-render full entity form from definition.
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
<EntityFormRenderer
|
|
41
|
+
entity={productEntity}
|
|
42
|
+
operation="create"
|
|
43
|
+
onSubmit={handleSubmit}
|
|
44
|
+
/>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### FormFieldRenderer
|
|
48
|
+
Render single field. Used inside custom forms.
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
<FormFieldRenderer field={field} control={form.control} />
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### EntityList
|
|
55
|
+
Data table for entity collection.
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
<EntityList entity={userEntity} onRowClick={(user) => edit(user.id)} />
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### EntityCardList
|
|
62
|
+
Card grid for entity collection.
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
<EntityCardList entity={productEntity} renderCard={(item) => <ProductCard {...item} />} />
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Form Building Blocks
|
|
71
|
+
|
|
72
|
+
For custom forms, use these low-level utilities:
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
import { useEntityForm, getFieldsForOperation, validateEntity } from '@donotdev/crud';
|
|
76
|
+
|
|
77
|
+
const { register, handleSubmit, fields, formState } = useEntityForm(productEntity, {
|
|
78
|
+
operation: 'create'
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
| Export | Purpose |
|
|
83
|
+
|--------|---------|
|
|
84
|
+
| `useEntityForm` | React Hook Form wrapper for entities |
|
|
85
|
+
| `useEntityField` | Single field hook |
|
|
86
|
+
| `getFieldsForOperation` | Get editable fields for create/edit |
|
|
87
|
+
| `validateEntity` | Validate data against entity schema |
|
|
88
|
+
| `isFieldEditable` | Check if field is editable |
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Field Types (Built-in)
|
|
93
|
+
|
|
94
|
+
Field components are auto-rendered by `FormFieldRenderer`. You don't import them directly.
|
|
95
|
+
|
|
96
|
+
### Text Inputs
|
|
97
|
+
- `text` - Single-line text input
|
|
98
|
+
- `email` - Email input with validation
|
|
99
|
+
- `tel` - Phone number input
|
|
100
|
+
- `url` - URL input
|
|
101
|
+
- `color` - Color picker
|
|
102
|
+
- `password` - Password input (masked)
|
|
103
|
+
- `textarea` - Multi-line text input
|
|
104
|
+
- `richtext` - Rich text editor
|
|
105
|
+
|
|
106
|
+
### Numbers
|
|
107
|
+
- `number` - Numeric input
|
|
108
|
+
- `range` - Slider input
|
|
109
|
+
- `rating` - Star rating input (1-5, configurable max)
|
|
110
|
+
|
|
111
|
+
**Rating + comment (e.g. reviews):** Use two fields on the same entity - `rating` (type `rating`) for stars and `comment` (type `textarea`) for the text. The form renders them as separate rows; no composite field type needed.
|
|
112
|
+
|
|
113
|
+
### Boolean
|
|
114
|
+
- `checkbox` - Checkbox input
|
|
115
|
+
- `boolean` - Alias for checkbox
|
|
116
|
+
- `switch` - Toggle switch
|
|
117
|
+
|
|
118
|
+
### Dates & Time
|
|
119
|
+
- `date` - Date picker
|
|
120
|
+
- `datetime-local` - Date and time picker
|
|
121
|
+
- `time` - Time picker
|
|
122
|
+
- `week` - Week picker
|
|
123
|
+
- `month` - Month picker
|
|
124
|
+
- `timestamp` - Timestamp (Firestore Timestamp)
|
|
125
|
+
|
|
126
|
+
### Selection
|
|
127
|
+
- `select` - Dropdown select
|
|
128
|
+
- `combobox` - Searchable dropdown
|
|
129
|
+
- `multiselect` - Multiple selection dropdown
|
|
130
|
+
- `radio` - Radio button group
|
|
131
|
+
|
|
132
|
+
### Files & Media
|
|
133
|
+
- `file` - Single file upload
|
|
134
|
+
- `files` - Multiple file uploads
|
|
135
|
+
- `document` - Document upload (PDF, etc.)
|
|
136
|
+
- `documents` - Multiple document uploads
|
|
137
|
+
- `image` - Single image upload
|
|
138
|
+
- `images` - Multiple image uploads
|
|
139
|
+
|
|
140
|
+
### Complex Types
|
|
141
|
+
- `geopoint` - Geographic coordinates (lat/lng)
|
|
142
|
+
- `address` - Address input with autocomplete
|
|
143
|
+
- `map` - Map picker
|
|
144
|
+
- `array` - Array of text inputs
|
|
145
|
+
|
|
146
|
+
### Special
|
|
147
|
+
- `avatar` - Avatar image upload
|
|
148
|
+
- `badge` - Badge display
|
|
149
|
+
- `hidden` - Hidden field (not displayed)
|
|
150
|
+
- `submit` - Submit button (uncontrolled)
|
|
151
|
+
- `reset` - Reset button (uncontrolled)
|
|
152
|
+
|
|
153
|
+
To add custom field types:
|
|
154
|
+
```tsx
|
|
155
|
+
import { useController, registerFieldType } from '@donotdev/crud';
|
|
156
|
+
import type { ControlledFieldProps } from '@donotdev/crud';
|
|
157
|
+
|
|
158
|
+
// Custom controlled component MUST use framework's useController (not react-hook-form's)
|
|
159
|
+
function ScoreField({
|
|
160
|
+
fieldConfig,
|
|
161
|
+
control,
|
|
162
|
+
errors,
|
|
163
|
+
t,
|
|
164
|
+
onChange
|
|
165
|
+
}: ControlledFieldProps) {
|
|
166
|
+
// REQUIRED: Use framework's useController - ensures type compatibility
|
|
167
|
+
const { field, fieldState } = useController({
|
|
168
|
+
name: fieldConfig.name,
|
|
169
|
+
control: control,
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
<div>
|
|
174
|
+
<label>{t(fieldConfig.label)}</label>
|
|
175
|
+
{/* Use field.value and field.onChange */}
|
|
176
|
+
<input
|
|
177
|
+
type="number"
|
|
178
|
+
value={field.value ?? 0}
|
|
179
|
+
onChange={(e) => {
|
|
180
|
+
const value = Number(e.target.value);
|
|
181
|
+
field.onChange(value);
|
|
182
|
+
onChange?.(value);
|
|
183
|
+
}}
|
|
184
|
+
min={0}
|
|
185
|
+
max={10}
|
|
186
|
+
/>
|
|
187
|
+
{fieldState?.error && (
|
|
188
|
+
<span className="error">{fieldState.error.message}</span>
|
|
189
|
+
)}
|
|
190
|
+
</div>
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
registerFieldType({
|
|
195
|
+
type: 'score',
|
|
196
|
+
controlledComponent: ScoreField,
|
|
197
|
+
});
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**Important:**
|
|
201
|
+
- Custom controlled components receive `control` prop, NOT `field` prop
|
|
202
|
+
- You must use **framework's `useController`** (from `@donotdev/crud`), NOT `react-hook-form`'s useController
|
|
203
|
+
- This ensures type compatibility - no type assertions needed
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Service & Store
|
|
208
|
+
|
|
209
|
+
Direct access (rarely needed):
|
|
210
|
+
|
|
211
|
+
```tsx
|
|
212
|
+
import { getCrudService, useCrudStore } from '@donotdev/crud';
|
|
213
|
+
|
|
214
|
+
const service = getCrudService();
|
|
215
|
+
await service.query('products', { where: [['active', '==', true]] });
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Collection Utilities
|
|
221
|
+
|
|
222
|
+
```tsx
|
|
223
|
+
import { loadDeterministicRange, upsertDeterministic, appendToCollection } from '@donotdev/crud';
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
| Utility | Purpose |
|
|
227
|
+
|---------|---------|
|
|
228
|
+
| `loadDeterministicRange` | Paginated loading with deterministic IDs |
|
|
229
|
+
| `upsertDeterministic` | Insert or update with deterministic ID |
|
|
230
|
+
| `appendToCollection` | Add to collection end |
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
**JSDoc in IDE** - Hover over any import for full props and examples.
|