@donotdev/crud 0.0.26 → 0.0.28
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.js +2 -2
- package/dist/CrudStore.js +1 -1
- package/dist/FieldRegistry.js +1 -1
- package/dist/adapters/FunctionsAdapter.js +1 -1
- package/dist/builtinFieldTypes.d.ts +1 -2
- package/dist/builtinFieldTypes.d.ts.map +1 -1
- package/dist/builtinFieldTypes.js +1 -1
- package/dist/components/CrudButton.js +1 -1
- package/dist/components/CrudCard.js +1 -1
- package/dist/components/DateFilter.js +1 -1
- package/dist/components/DisplayFieldRenderer.d.ts.map +1 -1
- package/dist/components/DisplayFieldRenderer.js +1 -1
- package/dist/components/DisplayThumbnail.js +1 -1
- package/dist/components/EntityFilters.js +1 -1
- package/dist/components/FormFieldRenderer.js +1 -1
- package/dist/components/FormLayout.js +1 -1
- package/dist/components/controlled/complex/ControlledAddressField.js +1 -1
- package/dist/components/controlled/complex/ControlledDateField.js +1 -1
- package/dist/components/controlled/complex/ControlledFieldArrayField.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/ControlledMultiInputField.js +1 -1
- package/dist/components/controlled/complex/ControlledRichTextField.js +1 -1
- package/dist/components/controlled/complex/ControlledTimestampField.js +1 -1
- package/dist/components/controlled/complex/index.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/file/index.js +1 -1
- package/dist/components/controlled/index.js +1 -1
- package/dist/components/controlled/input/ControlledCheckboxField.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/ControlledGdprConsentField.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.js +1 -1
- package/dist/components/controlled/input/ControlledTextareaField.js +1 -1
- package/dist/components/controlled/input/index.js +1 -1
- package/dist/components/controlled/select/ControlledComboboxField.js +1 -1
- package/dist/components/controlled/select/ControlledDropdownField.js +1 -1
- package/dist/components/controlled/select/ControlledMultiDropdownField.js +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/controlled/select/index.js +1 -1
- package/dist/components/controlled/types.js +1 -1
- package/dist/components/fields/display/AvatarFieldDisplay.js +1 -1
- package/dist/components/fields/display/BadgeFieldDisplay.js +1 -1
- package/dist/components/fields/display/ButtonFieldDisplay.js +1 -1
- package/dist/components/fields/display/CheckboxFieldDisplay.js +1 -1
- package/dist/components/fields/display/DateFieldDisplay.js +1 -1
- package/dist/components/fields/display/DropdownDisplay.js +1 -1
- package/dist/components/fields/display/FileFieldDisplay.js +1 -1
- package/dist/components/fields/display/GeoPointFieldDisplay.js +1 -1
- package/dist/components/fields/display/HiddenFieldDisplay.js +1 -1
- package/dist/components/fields/display/ImageFieldDisplay.js +1 -1
- package/dist/components/fields/display/LinkFieldDisplay.js +1 -1
- package/dist/components/fields/display/MapFieldDisplay.js +1 -1
- package/dist/components/fields/display/MultiDropdownDisplay.js +1 -1
- package/dist/components/fields/display/MultiInputTextFieldDisplay.js +1 -1
- package/dist/components/fields/display/NumberFieldDisplay.js +1 -1
- package/dist/components/fields/display/PasswordFieldDisplay.js +1 -1
- package/dist/components/fields/display/PhoneNumberDisplay.js +1 -1
- package/dist/components/fields/display/RadioFieldDisplay.js +1 -1
- package/dist/components/fields/display/RangeFieldDisplay.js +1 -1
- package/dist/components/fields/display/ReferenceFieldDisplay.js +1 -1
- package/dist/components/fields/display/RichTextDisplay.js +2 -2
- package/dist/components/fields/display/TextAreaDisplay.js +1 -1
- package/dist/components/fields/display/TextFieldDisplay.js +1 -1
- package/dist/components/fields/display/TimestampFieldDisplay.js +1 -1
- package/dist/components/fields/display/index.js +1 -1
- package/dist/components/form/fields/AddressFieldComponent.js +1 -1
- package/dist/components/form/fields/AvatarFieldComponent.js +1 -1
- package/dist/components/form/fields/BadgeFieldComponent.js +1 -1
- package/dist/components/form/fields/ButtonFieldComponent.js +1 -1
- package/dist/components/form/fields/CheckboxFieldComponent.js +1 -1
- package/dist/components/form/fields/ComboboxComponent.js +1 -1
- package/dist/components/form/fields/CurrencyFieldComponent.js +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/DropdownComponent.js +1 -1
- package/dist/components/form/fields/DurationFieldComponent.js +1 -1
- package/dist/components/form/fields/FileFieldComponent.js +1 -1
- package/dist/components/form/fields/GdprConsentFieldComponent.js +1 -1
- package/dist/components/form/fields/GeoPointFieldComponent.js +1 -1
- package/dist/components/form/fields/HiddenFieldComponent.js +1 -1
- package/dist/components/form/fields/ImageFieldComponent.js +1 -1
- package/dist/components/form/fields/MapFieldComponent.js +1 -1
- package/dist/components/form/fields/MultiDropdownComponent.js +1 -1
- package/dist/components/form/fields/MultiInputTextFieldComponent.js +1 -1
- package/dist/components/form/fields/NumberFieldComponent.js +1 -1
- package/dist/components/form/fields/PasswordFieldComponent.js +1 -1
- package/dist/components/form/fields/PhoneNumberComponent.js +1 -1
- package/dist/components/form/fields/PriceFieldComponent.js +1 -1
- package/dist/components/form/fields/RadioFieldComponent.js +1 -1
- package/dist/components/form/fields/RangeFieldComponent.js +1 -1
- package/dist/components/form/fields/RatingFieldComponent.js +1 -1
- package/dist/components/form/fields/ReferenceFieldComponent.js +1 -1
- package/dist/components/form/fields/RichTextComponent.js +1 -1
- package/dist/components/form/fields/SwitchFieldComponent.js +1 -1
- package/dist/components/form/fields/TextAreaComponent.js +1 -1
- package/dist/components/form/fields/TextFieldComponent.js +1 -1
- package/dist/components/form/fields/TimestampFieldComponent.js +1 -1
- package/dist/components/form/fields/index.js +1 -1
- package/dist/components/form/fields/internal/TiptapEditor.js +2 -2
- package/dist/components/form/internal/ImageViewerDialog.js +1 -1
- package/dist/components/index.js +1 -1
- package/dist/contexts/UploadContext.js +1 -1
- package/dist/contexts/index.js +1 -1
- package/dist/fieldTypeRegistry.d.ts +4 -116
- package/dist/fieldTypeRegistry.d.ts.map +1 -1
- package/dist/fieldTypeRegistry.js +1 -1
- package/dist/fieldTypeRegistry.store.d.ts +17 -0
- package/dist/fieldTypeRegistry.store.d.ts.map +1 -0
- package/dist/fieldTypeRegistry.store.js +1 -0
- package/dist/fieldTypeRegistry.types.d.ts +53 -0
- package/dist/fieldTypeRegistry.types.d.ts.map +1 -0
- package/dist/fieldTypeRegistry.types.js +1 -0
- package/dist/forms/hooks/index.js +1 -1
- package/dist/forms/hooks/useController.js +1 -1
- package/dist/forms/hooks/useEntityField.js +1 -1
- package/dist/forms/hooks/useEntityForm.js +1 -1
- package/dist/forms/index.js +1 -1
- package/dist/forms/utils/buildInitialValues.js +1 -1
- package/dist/forms/utils/getFieldsForOperation.js +1 -1
- package/dist/forms/utils/index.js +1 -1
- package/dist/forms/utils/isFieldEditable.js +1 -1
- package/dist/forms/utils/translateFieldLabel.js +1 -1
- package/dist/forms/utils/validateEntity.js +1 -1
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/useCrudFilters.js +1 -1
- package/dist/hooks/useEntityFavorites.js +1 -1
- package/dist/hooks/useFieldConditions.js +1 -1
- package/dist/hooks/useFileUpload.js +1 -1
- package/dist/hooks/useReferenceResolver.js +1 -1
- package/dist/hooks/useRelatedItems.js +1 -1
- package/dist/hooks/useUnsavedChangesWarning.js +1 -1
- package/dist/index.js +1 -1
- package/dist/registerBuiltinFieldTypes.d.ts +10 -3
- package/dist/registerBuiltinFieldTypes.d.ts.map +1 -1
- package/dist/registerBuiltinFieldTypes.js +1 -1
- package/dist/stores/FormStore.js +1 -1
- package/dist/stores/UploadStore.js +1 -1
- package/dist/stores/index.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types.js +1 -1
- package/dist/useBaseCrudList.js +1 -1
- package/dist/useCrud.js +1 -1
- package/dist/useCrudCardList.js +1 -1
- package/dist/useCrudList.js +1 -1
- package/dist/utils/clientListProcessing.js +1 -1
- package/dist/utils/collections.js +1 -1
- package/dist/utils/fileStorage.js +1 -1
- package/dist/utils/imageProcessing.js +1 -1
- package/dist/utils/imageStorage.js +1 -1
- package/dist/utils/imageUtils.js +1 -1
- package/dist/utils/matchesFilter.js +1 -1
- package/dist/utils/mergeWithOptimistic.js +1 -1
- package/dist/utils/sanitizeHtml.js +1 -1
- package/dist/utils/scopeUtils.js +1 -1
- package/dist/utils/uploadValidation.js +1 -1
- package/dist/workflows/WorkflowPersistence.js +1 -1
- package/dist/workflows/defineWorkflow.js +1 -1
- package/dist/workflows/index.js +1 -1
- package/dist/workflows/useEntityWorkflow.js +1 -1
- package/package.json +5 -5
|
@@ -1,121 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* Coordinates schema registration, UI components, filter metadata, and display formatting.
|
|
5
|
-
*
|
|
6
|
-
* Built-in field types are auto-registered via side-effect import of
|
|
7
|
-
* `registerBuiltinFieldTypes.tsx`. This creates a circular dependency:
|
|
8
|
-
*
|
|
9
|
-
* fieldTypeRegistry → registerBuiltinFieldTypes → fieldTypeRegistry
|
|
10
|
-
*
|
|
11
|
-
* Safe because:
|
|
12
|
-
* - `registerBuiltinFieldType()` is a function declaration (hoisted in ESM)
|
|
13
|
-
* - `metadataRegistry` is lazily initialized via `getMetadataRegistry()`
|
|
14
|
-
* so it exists even when the module hasn't fully evaluated yet
|
|
15
|
-
* - `getFieldRegistry()` in FieldRegistry.ts is already lazy (singleton)
|
|
16
|
-
*
|
|
17
|
-
* This guarantees that ALL code paths (display, form, filter, Expo) get
|
|
18
|
-
* built-in formatters without each consumer needing a magic side-effect import.
|
|
19
|
-
*
|
|
20
|
-
* @version 0.0.2
|
|
21
|
-
* @since 0.0.1
|
|
22
|
-
* @author AMBROISE PARK Consulting
|
|
23
|
-
*/
|
|
24
|
-
import type { EntityField, FieldType } from '@donotdev/core';
|
|
25
|
-
/**
|
|
26
|
-
* Side-effect import — triggers `registerAllBuiltinFieldTypes()` at module load.
|
|
27
|
-
*
|
|
28
|
-
* Circular dependency with this file is intentional and safe (see fileoverview).
|
|
29
|
-
* Placing it here (the single lookup entry point) means every consumer —
|
|
30
|
-
* DisplayFieldRenderer, FormFieldRenderer, EntityFilters, CrudCard, Expo
|
|
31
|
-
* renderers — is covered without needing their own import.
|
|
32
|
-
*/
|
|
33
|
-
import './registerBuiltinFieldTypes';
|
|
34
|
-
import type { ControlledFieldProps, UncontrolledFieldProps } from './FieldRegistry';
|
|
35
|
-
import type { ComponentType, ReactElement } from 'react';
|
|
36
|
-
/**
|
|
37
|
-
* Filter type metadata for EntityFilters component
|
|
38
|
-
*/
|
|
39
|
-
export type FilterType = 'text' | 'range' | 'select' | 'none' | 'address' | 'multiselect' | 'rating';
|
|
40
|
-
/**
|
|
41
|
-
* Value type for type checking
|
|
42
|
-
*/
|
|
43
|
-
export type ValueType = 'string' | 'number' | 'boolean' | 'date' | 'object' | 'array';
|
|
44
|
-
/**
|
|
45
|
-
* Display formatter function
|
|
46
|
-
*/
|
|
47
|
-
export type DisplayFormatterOptions = {
|
|
48
|
-
compact?: boolean;
|
|
49
|
-
asString?: boolean;
|
|
50
|
-
/** Pre-resolved reference data: { collectionName: { id: displayLabel } } */
|
|
51
|
-
referenceData?: Record<string, Record<string, string>>;
|
|
52
|
-
};
|
|
53
|
-
export type DisplayFormatter = (value: any, config: EntityField, t: (key: string, options?: Record<string, any>) => string, options?: DisplayFormatterOptions) => string | ReactElement;
|
|
54
|
-
/**
|
|
55
|
-
* Component registration for a field type
|
|
56
|
-
*/
|
|
57
|
-
export interface ComponentRegistration {
|
|
58
|
-
controlled: ComponentType<ControlledFieldProps<any, any>>;
|
|
59
|
-
uncontrolled?: ComponentType<UncontrolledFieldProps>;
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Complete metadata for a built-in field type
|
|
63
|
-
*
|
|
64
|
-
* NOTE: Schemas are registered separately in @donotdev/core/schemas/getSchemaType.ts
|
|
65
|
-
* This registry only handles UI components + filter/display metadata
|
|
66
|
-
*/
|
|
67
|
-
export interface FieldTypeMetadata {
|
|
68
|
-
/** Field type identifier */
|
|
69
|
-
type: FieldType;
|
|
70
|
-
/** Whether this field type is filterable */
|
|
71
|
-
filterable?: boolean;
|
|
72
|
-
/** Filter UI type for EntityFilters */
|
|
73
|
-
filterType?: FilterType;
|
|
74
|
-
/** Display formatter function */
|
|
75
|
-
displayFormatter?: DisplayFormatter;
|
|
76
|
-
/** Runtime value type */
|
|
77
|
-
valueType?: ValueType;
|
|
78
|
-
/** UI components */
|
|
79
|
-
components?: ComponentRegistration;
|
|
80
|
-
}
|
|
1
|
+
import type { FieldTypeMetadata } from './fieldTypeRegistry.types';
|
|
2
|
+
export type { FilterType, ValueType, DisplayFormatterOptions, DisplayFormatter, ComponentRegistration, FieldTypeMetadata, } from './fieldTypeRegistry.types';
|
|
3
|
+
export { getFieldTypeMetadata, getFilterType, getDisplayFormatter, isFilterable, getValueType, clearFieldTypeRegistry, } from './fieldTypeRegistry.store';
|
|
81
4
|
/**
|
|
82
5
|
* Register a built-in field type with all metadata.
|
|
83
|
-
*
|
|
84
|
-
* Single registration point for framework built-ins. Coordinates:
|
|
85
|
-
* - UI component registration (via FieldRegistry singleton)
|
|
86
|
-
* - Filter / display metadata storage
|
|
87
|
-
*
|
|
88
|
-
* Schemas are registered separately in `@donotdev/core/schemas/getSchemaType.ts`
|
|
89
|
-
* because backend functions need them at module load without pulling in React.
|
|
90
|
-
*
|
|
91
|
-
* @param metadata - Complete field type metadata
|
|
6
|
+
* For internal/plugin use — consumers should use registerFieldType() instead.
|
|
92
7
|
*/
|
|
93
8
|
export declare function registerBuiltinFieldType(metadata: FieldTypeMetadata): void;
|
|
94
|
-
/**
|
|
95
|
-
* Get metadata for a field type
|
|
96
|
-
*/
|
|
97
|
-
export declare function getFieldTypeMetadata(type: string): FieldTypeMetadata | undefined;
|
|
98
|
-
/**
|
|
99
|
-
* Get filter type for a field type.
|
|
100
|
-
* Custom types (via `registerFieldType` with `filterType`) take precedence.
|
|
101
|
-
*/
|
|
102
|
-
export declare function getFilterType(type: string): FilterType | undefined;
|
|
103
|
-
/**
|
|
104
|
-
* Get display formatter for a field type.
|
|
105
|
-
* Custom types (via `registerFieldType` with `displayFormatter`) take precedence.
|
|
106
|
-
*/
|
|
107
|
-
export declare function getDisplayFormatter(type: string): DisplayFormatter | undefined;
|
|
108
|
-
/**
|
|
109
|
-
* Check if a field type is filterable.
|
|
110
|
-
* Custom types (via `registerFieldType` with `filterable`) take precedence.
|
|
111
|
-
*/
|
|
112
|
-
export declare function isFilterable(type: string): boolean;
|
|
113
|
-
/**
|
|
114
|
-
* Get value type for a field type
|
|
115
|
-
*/
|
|
116
|
-
export declare function getValueType(type: string): ValueType | undefined;
|
|
117
|
-
/**
|
|
118
|
-
* Clear registry (testing only)
|
|
119
|
-
*/
|
|
120
|
-
export declare function clearFieldTypeRegistry(): void;
|
|
121
9
|
//# sourceMappingURL=fieldTypeRegistry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fieldTypeRegistry.d.ts","sourceRoot":"","sources":["../src/fieldTypeRegistry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fieldTypeRegistry.d.ts","sourceRoot":"","sources":["../src/fieldTypeRegistry.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AASnE,YAAY,EACV,UAAU,EACV,SAAS,EACT,uBAAuB,EACvB,gBAAgB,EAChB,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,2BAA2B,CAAC;AAInC,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,mBAAmB,EACnB,YAAY,EACZ,YAAY,EACZ,sBAAsB,GACvB,MAAM,2BAA2B,CAAC;AAInC;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAa1E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{getFieldRegistry as i}from"./FieldRegistry";import"./registerBuiltinFieldTypes";
|
|
1
|
+
"use client";import{getFieldRegistry as i}from"./FieldRegistry";import{registerAllBuiltinFieldTypes as s}from"./registerBuiltinFieldTypes";import{setRegistrationInit as r,getMetadataRegistry as l}from"./fieldTypeRegistry.store";r(e=>{s(e,i())});import{getFieldTypeMetadata as o,getFilterType as p,getDisplayFormatter as g,isFilterable as y,getValueType as n,clearFieldTypeRegistry as F}from"./fieldTypeRegistry.store";function d(e){const{type:a,components:t}=e;t&&i().registerComponent(a,t.controlled,t.uncontrolled),l().set(a,e)}export{F as clearFieldTypeRegistry,g as getDisplayFormatter,o as getFieldTypeMetadata,p as getFilterType,n as getValueType,y as isFilterable,d as registerBuiltinFieldType};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { FieldTypeMetadata } from './fieldTypeRegistry.types';
|
|
2
|
+
import type { DisplayFormatter } from './fieldTypeRegistry.types';
|
|
3
|
+
import type { FilterType } from './fieldTypeRegistry.types';
|
|
4
|
+
import type { ValueType } from './fieldTypeRegistry.types';
|
|
5
|
+
/**
|
|
6
|
+
* Called once by fieldTypeRegistry.ts to wire the lazy init callback.
|
|
7
|
+
* Keeps this file free of imports from registerBuiltinFieldTypes.
|
|
8
|
+
*/
|
|
9
|
+
export declare function setRegistrationInit(fn: (registry: Map<string, FieldTypeMetadata>) => void): void;
|
|
10
|
+
export declare function getMetadataRegistry(): Map<string, FieldTypeMetadata>;
|
|
11
|
+
export declare function getFieldTypeMetadata(type: string): FieldTypeMetadata | undefined;
|
|
12
|
+
export declare function getFilterType(type: string): FilterType | undefined;
|
|
13
|
+
export declare function getDisplayFormatter(type: string): DisplayFormatter | undefined;
|
|
14
|
+
export declare function isFilterable(type: string): boolean;
|
|
15
|
+
export declare function getValueType(type: string): ValueType | undefined;
|
|
16
|
+
export declare function clearFieldTypeRegistry(): void;
|
|
17
|
+
//# sourceMappingURL=fieldTypeRegistry.store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fieldTypeRegistry.store.d.ts","sourceRoot":"","sources":["../src/fieldTypeRegistry.store.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAW3D;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,KAAK,IAAI,GACrD,IAAI,CAEN;AAED,wBAAgB,mBAAmB,IAAI,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAOpE;AAID,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,GACX,iBAAiB,GAAG,SAAS,CAE/B;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAIlE;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,GACX,gBAAgB,GAAG,SAAS,CAI9B;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGlD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAEhE;AAED,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{getFieldRegistry as a}from"./FieldRegistry";var r=null,i=!1,n=null;function l(t){n=t}function e(){return r||(r=new Map),i||(i=!0,n?.(r)),r}function s(t){return e().get(t)}function u(t){return a().getFilterType(t)||e().get(t)?.filterType}function g(t){return a().getDisplayFormatter(t)||e().get(t)?.displayFormatter}function o(t){return a().isFilterable(t)?!0:e().get(t)?.filterable??!1}function p(t){return e().get(t)?.valueType}function y(){e().clear()}export{y as clearFieldTypeRegistry,g as getDisplayFormatter,s as getFieldTypeMetadata,u as getFilterType,e as getMetadataRegistry,p as getValueType,o as isFilterable,l as setRegistrationInit};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Shared types for field type registry.
|
|
3
|
+
* Extracted to break circular dependency between fieldTypeRegistry ↔ registerBuiltinFieldTypes.
|
|
4
|
+
*/
|
|
5
|
+
import type { EntityField, FieldType } from '@donotdev/core';
|
|
6
|
+
import type { ControlledFieldProps, UncontrolledFieldProps } from './FieldRegistry';
|
|
7
|
+
import type { ComponentType, ReactElement } from 'react';
|
|
8
|
+
/**
|
|
9
|
+
* Filter type metadata for EntityFilters component
|
|
10
|
+
*/
|
|
11
|
+
export type FilterType = 'text' | 'range' | 'select' | 'none' | 'address' | 'multiselect' | 'rating';
|
|
12
|
+
/**
|
|
13
|
+
* Value type for type checking
|
|
14
|
+
*/
|
|
15
|
+
export type ValueType = 'string' | 'number' | 'boolean' | 'date' | 'object' | 'array';
|
|
16
|
+
/**
|
|
17
|
+
* Display formatter function
|
|
18
|
+
*/
|
|
19
|
+
export type DisplayFormatterOptions = {
|
|
20
|
+
compact?: boolean;
|
|
21
|
+
asString?: boolean;
|
|
22
|
+
/** Pre-resolved reference data: { collectionName: { id: displayLabel } } */
|
|
23
|
+
referenceData?: Record<string, Record<string, string>>;
|
|
24
|
+
};
|
|
25
|
+
export type DisplayFormatter = (value: any, config: EntityField, t: (key: string, options?: Record<string, any>) => string, options?: DisplayFormatterOptions) => string | ReactElement;
|
|
26
|
+
/**
|
|
27
|
+
* Component registration for a field type
|
|
28
|
+
*/
|
|
29
|
+
export interface ComponentRegistration {
|
|
30
|
+
controlled: ComponentType<ControlledFieldProps<any, any>>;
|
|
31
|
+
uncontrolled?: ComponentType<UncontrolledFieldProps>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Complete metadata for a built-in field type
|
|
35
|
+
*
|
|
36
|
+
* NOTE: Schemas are registered separately in @donotdev/core/schemas/getSchemaType.ts
|
|
37
|
+
* This registry only handles UI components + filter/display metadata
|
|
38
|
+
*/
|
|
39
|
+
export interface FieldTypeMetadata {
|
|
40
|
+
/** Field type identifier */
|
|
41
|
+
type: FieldType;
|
|
42
|
+
/** Whether this field type is filterable */
|
|
43
|
+
filterable?: boolean;
|
|
44
|
+
/** Filter UI type for EntityFilters */
|
|
45
|
+
filterType?: FilterType;
|
|
46
|
+
/** Display formatter function */
|
|
47
|
+
displayFormatter?: DisplayFormatter;
|
|
48
|
+
/** Runtime value type */
|
|
49
|
+
valueType?: ValueType;
|
|
50
|
+
/** UI components */
|
|
51
|
+
components?: ComponentRegistration;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=fieldTypeRegistry.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fieldTypeRegistry.types.d.ts","sourceRoot":"","sources":["../src/fieldTypeRegistry.types.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACpF,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAEzD;;GAEG;AACH,MAAM,MAAM,UAAU,GAClB,MAAM,GACN,OAAO,GACP,QAAQ,GACR,MAAM,GACN,SAAS,GACT,aAAa,GACb,QAAQ,CAAC;AAEb;;GAEG;AACH,MAAM,MAAM,SAAS,GACjB,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,MAAM,GACN,QAAQ,GACR,OAAO,CAAC;AAEZ;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4EAA4E;IAC5E,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACxD,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,CAC7B,KAAK,EAAE,GAAG,EACV,MAAM,EAAE,WAAW,EACnB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,MAAM,EACzD,OAAO,CAAC,EAAE,uBAAuB,KAC9B,MAAM,GAAG,YAAY,CAAC;AAE3B;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,aAAa,CAAC,oBAAoB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IAC1D,YAAY,CAAC,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC;CACtD;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,4BAA4B;IAC5B,IAAI,EAAE,SAAS,CAAC;IAChB,4CAA4C;IAC5C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,uCAAuC;IACvC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,iCAAiC;IACjC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,yBAAyB;IACzB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,oBAAoB;IACpB,UAAU,CAAC,EAAE,qBAAqB,CAAC;CACpC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useEntityForm as
|
|
1
|
+
import{useEntityForm as t}from"./useEntityForm";import{useEntityField as o}from"./useEntityField";import{useController as r}from"./useController";export{r as useController,o as useEntityField,t as useEntityForm};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{useController as
|
|
1
|
+
"use client";import{useController as o}from"react-hook-form";function r(e){return o(e)}export{r as useController};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{useMemo as o,useCallback as p}from"react";import{useController as v}from"./useController";import{formatValue as h}from"../../components/DisplayFieldRenderer";import{isFieldEditable as
|
|
1
|
+
"use client";import{useMemo as o,useCallback as p}from"react";import{useController as v}from"./useController";import{formatValue as h}from"../../components/DisplayFieldRenderer";import{isFieldEditable as g}from"../utils";function D(a,i){const{entity:b,operation:r,viewerRole:n,fields:u}=a,l=b.fields[i],e=o(()=>l?{...l,name:l.name||i,label:l.label||i}:{name:i,type:"text",label:i,visibility:"user"},[i,l]),s=o(()=>u.some(d=>d.name===i),[u,i]),c=o(()=>!s||r==="edit"&&e.visibility==="technical"&&e.editable===void 0?!1:g(e.editable,n,r),[s,r,e.visibility,e.editable,n]),{field:m,fieldState:t}=v({name:i,control:a.control}),f=o(()=>({error:t.error?.message,touched:t.isTouched,isDirty:t.isDirty}),[t.error?.message,t.isTouched,t.isDirty]),y=p(d=>h(m.value,e,a.t,d),[m.value,e,a.t]);return{field:m,meta:f,config:e,isEditable:c,isVisible:s,display:y}}export{D as useEntityField};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{valibotResolver as
|
|
1
|
+
"use client";import{valibotResolver as M}from"@hookform/resolvers/valibot";import{useMemo as d,useEffect as T,useRef as v,useCallback as w,createElement as se}from"react";import{useForm as oe}from"react-hook-form";import{toast as ie,ToastAction as ne}from"@donotdev/components";import{useLocalStorage as ue,BACKEND_GENERATED_FIELD_NAMES as ce,createSchemas as le}from"@donotdev/core";import{useFormStore as j,useFormStatus as de,useUploadProgress as fe}from"../../stores";import{useUploadStore as q}from"../../stores/UploadStore";import{checkForBlobUrls as z}from"../../utils/uploadValidation";import{getFieldsForOperation as me}from"../utils";import{buildInitialFromRecord as pe,buildSchemaDefaults as ge}from"../utils/buildInitialValues";const Se=i=>i;function G(i,E){const e={...i};for(const p of Object.keys(E)){const c=i[p],f=E[p];f!==null&&typeof f=="object"&&!Array.isArray(f)&&c!==null&&typeof c=="object"&&!Array.isArray(c)?e[p]=G(c,f):e[p]=f}return e}function be(i,E={}){const{formId:e,operation:p,defaultValues:c,viewerRole:f,mode:K="onBlur",t:Y}=E,g=Y??Se,U=f??"guest",n=p??(c?"edit":"create"),H=de(e??""),J=fe(e??""),V=d(()=>le(i),[i.name]),P=d(()=>M(V.create),[V.create]),C=d(()=>M(V.draft),[V.draft]),Q=d(()=>async(t,a,s)=>((t?.status??c?.status)==="draft"?C:P)(t,a,s),[P,C,c?.status]),F=d(()=>ge(i),[i]),$=c,u=d(()=>{if(n==="create")return F;if($)return pe(i,$)},[n,F,i,$]),o=oe({defaultValues:n==="create"?u:void 0,mode:K,resolver:Q,shouldUnregister:!1,shouldFocusError:!0}),D=v(o);T(()=>{D.current=o},[o]);const A=v(null);T(()=>{if(n==="edit"&&u){const t=u.id??null;t&&t!==A.current?(D.current.reset(u),A.current=t):!t&&A.current===null&&(D.current.reset(u),A.current="initialized")}},[n,u]);const k=c?.id,W=d(()=>{const t=`${i.name.toLowerCase()}-form-draft`;return n==="create"?t:k?`${t}-${k}`:`${t}-edit`},[i.name,n,k]),{value:b,setValue:x,removeValue:S}=ue(W,{defaultValue:null,syncAcrossTabs:!0}),y=v(!1);T(()=>{if(y.current)return;const t=a=>{const s=()=>{S(),a&&D.current.reset(a)};ie({toastType:"info",title:g("draft.restored",{defaultValue:"Draft restored"}),description:g("draft.restoredDescription",{defaultValue:"Your unsaved changes were recovered"}),action:se(ne,{altText:g("draft.discard",{defaultValue:"Discard"}),onClick:s},g("draft.discard",{defaultValue:"Discard"})),duration:8e3})};if(n==="create"&&!c){b&&(o.reset(b),t(F)),y.current=!0;return}if(n==="edit"&&u){if(b){const a=G(u,b);o.reset(a),t(u)}y.current=!0}},[n,c,b,o,u,S,g,F]);const O=v(!1),h=v(null);T(()=>{const t=o.watch(a=>{O.current||!y.current||(h.current&&clearTimeout(h.current),h.current=setTimeout(()=>{a&&Object.values(a).some(s=>s!=null&&s!=="")&&x(a)},3e3))});return()=>{t.unsubscribe(),h.current&&clearTimeout(h.current)}},[o,x]);const B=w(async()=>{if(!e)return!0;const t=q.getState(),a=j.getState();if(!t.hasPendingUploads(e))return!0;try{a.setUploading(e,0),await t.uploadAll(e),await new Promise(m=>setTimeout(m,50));let s=o.getValues(),r=z(s),l=0;const R=5;for(;r.length>0&&l<R;)l++,await new Promise(m=>setTimeout(m,100)),s=o.getValues(),r=z(s);if(r.length>0){const m=`Upload incomplete: files still pending at ${r.join(", ")}`;return a.setError(e,m),!1}return!0}catch(s){const r=s instanceof Error?s.message:"File upload failed";return j.getState().setError(e,r),!1}},[e,o]),L=w(t=>n!=="create"?t:Object.fromEntries(Object.entries(t).filter(([a])=>!ce.includes(a))),[n]),N=w(t=>{if(typeof window>"u")return;const a=Object.keys(t).find(r=>r!=="root"&&t[r]);if(!a)return;const s=document.querySelector(`input[name="${a}"][aria-invalid="true"], textarea[name="${a}"][aria-invalid="true"], select[name="${a}"][aria-invalid="true"]`);s&&(s.scrollIntoView({behavior:"smooth",block:"center"}),s.focus())},[]),_=o.handleSubmit,X=d(()=>((t,a)=>async s=>{s?.preventDefault?.();const r=e?j.getState():null;e&&r&&r.startSubmit(e),O.current=!0;try{if(!await B()){e&&r&&r.setError(e,"Upload failed");return}e&&r&&r.setValidating(e),await _(async(l,R)=>{e&&r&&r.setSubmitting(e);const m=L(l);try{await t(m,R),S(),e&&r&&r.setSuccess(e)}catch(I){const ae=I instanceof Error?I.message:"Submission failed";throw e&&r&&r.setError(e,ae),I}},l=>{e&&r&&r.setError(e,"Validation failed"),N(l),a?.(l)})(s)}catch{if(e&&r){const l=r.getStatus(e);l!=="error"&&l!=="idle"&&l!=="success"&&r.reset(e)}}finally{O.current=!1}}),[_,e,B,L,N,n,S]),Z=w(()=>{S(),o.reset(u),y.current=!1},[S,o,u]),ee=w(()=>{e&&(j.getState().cleanup(e),q.getState().cleanup(e))},[e]),te=d(()=>me(i,{operation:n,viewerRole:U,availableFields:void 0}),[i,n,U]),re=o.formState.isSubmitted||Object.keys(o.formState.touchedFields||{}).length>0;return{...o,handleSubmit:X,fields:te,operation:n,entity:i,t:g,viewerRole:U,formId:e,formStatus:e?H:"idle",uploadProgress:e?J:0,cleanup:ee,isDirty:o.formState.isDirty,hasUserInteracted:re,resetForm:Z,originalValues:u}}export{be as useEntityForm};
|
package/dist/forms/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useEntityForm as
|
|
1
|
+
import{useEntityForm as a}from"./hooks/useEntityForm";import{useEntityField as t}from"./hooks/useEntityField";import{useController as e}from"./hooks/useController";import{isFieldEditable as s,getFieldsForOperation as i,validateEntity as l,translateFieldLabel as r,translateLabel as o}from"./utils";export{i as getFieldsForOperation,s as isFieldEditable,r as translateFieldLabel,o as translateLabel,e as useController,t as useEntityField,a as useEntityForm,l as validateEntity};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function
|
|
1
|
+
function l(i,r){if(r in i)return i[r];const o=r.replace(/_([a-z])/g,(t,n)=>n.toUpperCase());if(o!==r&&o in i)return i[o]}function s(i,r){if(r in i)return!0;const o=r.replace(/_([a-z])/g,(t,n)=>n.toUpperCase());return o!==r&&o in i}function c(i,r){const o=r??{},t={...o};return Object.entries(i.fields).forEach(([n,e])=>{const p=l(t,n);p!==void 0&&!(n in t)&&(t[n]=p);const a=!s(o,n)||p===null||p===void 0;if(e.type==="switch"){if(p==null){const u=e.options?.fieldSpecific;t[n]=u?.uncheckedValue??!1}}else a&&(e.type==="price"?t[n]={amount:0,currency:"EUR",vatIncluded:!0,discountPercent:0}:e.type==="checkbox"||e.type==="boolean"?t[n]=!1:e.type==="text"||e.type==="textarea"||e.type==="email"||e.type==="url"||e.type==="tel"||e.type==="iban"||e.type==="password"||e.type==="color"?t[n]="":(e.type==="number"||e.type==="range"||e.type==="rating")&&(t[n]=void 0))}),t}function y(i){return c(i,{})}export{c as buildInitialFromRecord,y as buildSchemaDefaults};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isFieldVisible as
|
|
1
|
+
import{isFieldVisible as u}from"@donotdev/core";import{isFieldEditable as m}from"./isFieldEditable";function g(i,d){const{operation:e,viewerRole:r,availableFields:l}=d,n=r??"guest",f=i&&typeof i=="object"&&"fields"in i&&"name"in i?i.fields:i,b=Object.entries(f),s=[];for(const[a,p]of b){const t=p,o=t.visibility||"guest";if(!u(o,n)||e==="create"&&o==="technical"||e==="edit"&&l&&!l.includes(a))continue;let c=m(t.editable,n,e);e==="edit"&&o==="technical"&&t.editable===void 0&&(c=!1),s.push({name:a,config:t,editable:c})}return s}export{g as getFieldsForOperation};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isFieldEditable as
|
|
1
|
+
import{isFieldEditable as a}from"./isFieldEditable";import{getFieldsForOperation as t}from"./getFieldsForOperation";import{validateEntity as e}from"./validateEntity";import{translateFieldLabel as i,translateLabel as l}from"./translateFieldLabel";export{t as getFieldsForOperation,a as isFieldEditable,i as translateFieldLabel,l as translateLabel,e as validateEntity};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{hasRoleAccess as t,USER_ROLES as
|
|
1
|
+
import{hasRoleAccess as t,USER_ROLES as o}from"@donotdev/core";function s(e,i,r){return e===void 0||e===!0?!0:e===!1?!1:e==="admin"?t(i,o.ADMIN):e==="create-only"?r==="create":!0}export{s as isFieldEditable};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function
|
|
1
|
+
function i(e,r){if(typeof e=="string"&&e.includes(":")){const n=e.split(":"),t=n[1]??e,s=n[0];if(t.startsWith("status.")){const a=r(t);return a!==t&&a!==`${s}:${t}`?a:r(t,{ns:s})}return r(t,{ns:s})}return r(e)}function l(e,r,n){const t=r?.label||e;return i(t,n)}export{l as translateFieldLabel,i as translateLabel};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as o from"valibot";import{createSchemas as
|
|
1
|
+
import*as o from"valibot";import{createSchemas as i}from"@donotdev/core";function m(t,r,c="create"){const e=i(t),u={create:e.create,draft:e.draft,update:e.update,full:e.get}[c],s=o.safeParse(u,r);return s.success?{success:!0,data:s.output}:{success:!1,issues:s.issues.map(a=>({path:a.path?.map(p=>p.key).join(".")||"",message:a.message}))}}export{m as validateEntity};
|
package/dist/hooks/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useFileUpload as
|
|
1
|
+
import{useFileUpload as e}from"./useFileUpload";import{useUnsavedChangesWarning as s}from"./useUnsavedChangesWarning";import{useEntityFavorites as r}from"./useEntityFavorites";import{useCrudFilters as a}from"./useCrudFilters";import{useRelatedItems as o}from"./useRelatedItems";import{useFieldConditions as i}from"./useFieldConditions";import{useReferenceResolver as t}from"./useReferenceResolver";export{a as useCrudFilters,r as useEntityFavorites,i as useFieldConditions,e as useFileUpload,t as useReferenceResolver,o as useRelatedItems,s as useUnsavedChangesWarning};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useCallback as o}from"react";import{useCrudStore as s}from"../CrudStore";const
|
|
1
|
+
import{useCallback as o}from"react";import{useCrudStore as s}from"../CrudStore";const c={};function u(r){const{collection:e}=r,i=s(t=>t.collections[e]?.ui?.filters??c),l=o(t=>{s.getState().setFilters(e,t)},[e]),n=s(t=>t.collections[e]?.ui?.showFavoritesOnly??!1),a=o(t=>{s.getState().setShowFavoritesOnly(e,t)},[e]);return{filters:i,setFilters:l,showFavoritesOnly:n,setShowFavoritesOnly:a}}export{u as useCrudFilters};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useCallback as
|
|
1
|
+
import{useCallback as o}from"react";import{useLocalStorage as p}from"@donotdev/core";function y(s={}){const{storageKey:l,collection:u="entities"}=s,d=l||`favorites-${u}`,{value:t,setValue:a,isLoaded:c}=p(d,{defaultValue:[]}),n=o(e=>t.includes(e),[t]),v=o(e=>{a(i=>i.includes(e)?i.filter(r=>r!==e):[...i,e])},[a]),f=o(e=>{a(i=>i.includes(e)?i:[...i,e])},[a]),F=o(e=>{a(i=>i.filter(r=>r!==e))},[a]),m=o(()=>{a([])},[a]),g=o(e=>t.includes(e.id),[t]);return{favorites:t,isFavorite:n,toggleFavorite:v,addFavorite:f,removeFavorite:F,clearFavorites:m,favoritesFilter:g,isLoaded:c}}export{y as useEntityFavorites};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{useMemo as
|
|
1
|
+
"use client";import{useMemo as e}from"react";import{useWatch as c}from"react-hook-form";import{evaluateFieldConditions as f}from"@donotdev/core";function u(o,r){const t=c({control:r}),s=e(()=>o.some(n=>n.config.conditions),[o]);return e(()=>{if(!s)return{};const n={};for(const i of o)i.config.conditions&&(n[i.name]=f(i.config.conditions,t));return n},[o,t,s])}export{u as useFieldConditions};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{useState as
|
|
1
|
+
"use client";import{useState as T,useCallback as v,useEffect as A,useRef as g,startTransition as q}from"react";import{handleError as C}from"@donotdev/core";import{useUploadContext as G}from"../contexts/UploadContext";import{useUploadStore as N}from"../stores/UploadStore";let P=0;function W(s){if(s){const u=s.split("/").pop()?.split("?")[0];if(u)return`file-${u}`}P+=1;const a=typeof performance<"u"?performance.now():Date.now(),p=Math.random().toString(36).slice(2,11);return`file-${P}-${a}-${p}`}function H(s){return URL.createObjectURL(s)}function k(s){s.startsWith("blob:")&&URL.revokeObjectURL(s)}function K(s,a,p){return a.length>0&&!a.some(u=>{if(u.endsWith("/*")){const w=u.slice(0,-2);return s.type.startsWith(w)}return s.type===u})?{valid:!1,error:`File type ${s.type} not accepted`}:s.size>p?{valid:!1,error:`File exceeds ${(p/1048576).toFixed(0)}MB limit`}:{valid:!0}}function Q({name:s,value:a,onChange:p,multiple:u=!1,maxFiles:w=10,maxSize:$=10*1024*1024,accept:S=[],storagePath:V="uploads",uploadFn:h}){const U=G(),y=!!U,[d,c]=T([]),R=g(!1),E=g(null),x=g(a),L=g([]),F=g(!1),M=g(null);A(()=>{if(R.current){R.current=!1;return}const n=a?JSON.stringify((Array.isArray(a)?a:[a]).map(l=>l.fullUrl).filter(Boolean)):null;n!==E.current&&(E.current=n,x.current=a,q(()=>{if(a){const l=(Array.isArray(a)?a:[a]).filter(t=>t.fullUrl).map((t,r)=>({id:`${W(t.fullUrl)}-existing-${r}`,file:new File([],"existing"),previewURL:t.thumbUrl||t.fullUrl,progress:100,uploaded:t,error:null}));c(l)}else c([])}))},[a]),A(()=>{L.current=d},[d]),A(()=>{F.current&&(F.current=!1,M.current?.(d,!0))},[d]),A(()=>()=>{L.current.forEach(n=>k(n.previewURL))},[]);const f=v((n,l=!1)=>{const t=(l?n.filter(i=>!i.error):n.filter(i=>i.uploaded&&!i.error)).map(i=>i.uploaded?i.uploaded:l&&y?{fullUrl:i.previewURL,thumbUrl:i.previewURL}:null).filter(i=>i!==null);let r;u?r=t.length>0?t:null:r=t[0]||null;const e=x.current;(()=>{if(!r&&!e)return!1;if(!r||!e)return!0;if(u&&Array.isArray(r)&&Array.isArray(e)){if(r.length!==e.length)return!0;const i=r.map(m=>m.fullUrl).join(","),o=e.map(m=>m.fullUrl).join(",");return i!==o}return!u&&!Array.isArray(r)&&!Array.isArray(e)?r.fullUrl!==e.fullUrl:!0})()&&(R.current=!0,x.current=r,p(r))},[u,p,y]);M.current=f;const b=v(async()=>{if(!h)return;let n=[];if(c(t=>(n=t.filter(r=>!r.uploaded&&!r.error),n.length===0?t:t.map(r=>n.some(e=>e.id===r.id)?{...r,progress:0}:r))),n.length===0)return;const l=await Promise.allSettled(n.map(async t=>{try{const r=await h(t.file,e=>{c(i=>i.map(o=>o.id===t.id?{...o,progress:e}:o))});return{id:t.id,picture:r,error:null}}catch(r){const e=r instanceof Error?r.message:"Upload failed";return{id:t.id,picture:null,error:e}}}));c(t=>{const r=t.map(e=>{const i=l.find(o=>o.status==="fulfilled"&&o.value.id===e.id);if(i&&i.status==="fulfilled"){const o=i.value;return{...e,uploaded:o.picture,progress:o.picture?100:null,error:o.error}}return e});return f(r,!1),r})},[h,f]),j=g(b);j.current=b,A(()=>{if(!(!U||!s))return N.getState().registerUpload(U,s,async()=>{await j.current()},()=>L.current.some(n=>!n.uploaded&&!n.error)),()=>{N.getState().unregisterUpload(U,s)}},[U,s]);const O=v(async n=>{if(h){c(l=>l.map(t=>t.id===n.id?{...t,progress:0}:t));try{const l=await h(n.file,t=>{c(r=>r.map(e=>e.id===n.id?{...e,progress:t}:e))});c(t=>{const r=t.map(e=>e.id===n.id?{...e,uploaded:l,progress:100,error:null}:e);return f(r,!1),r})}catch(l){const t=l instanceof Error?l.message:"Upload failed";c(r=>r.map(e=>e.id===n.id?{...e,error:t,progress:null}:e))}}},[h,f]),z=v(n=>{c(l=>{const t=(u?w:1)-l.length;if(t<=0)return C(new Error("Maximum files reached"),{userMessage:u?`Maximum ${w} files allowed`:"Only one file allowed",severity:"warning",showNotification:!0}),l;const r=n.slice(0,t),e=[];for(const o of r){const m=K(o,S,$);if(!m.valid){C(new Error(m.error),{userMessage:m.error,severity:"warning",showNotification:!0});continue}e.push({id:W(),file:o,previewURL:H(o),progress:null,uploaded:null,error:null})}if(e.length===0)return l;const i=u?[...l,...e]:e;return y?F.current=!0:e.forEach(o=>O(o)),i})},[u,w,S,$,y,O,f]),B=v(n=>{c(l=>{const t=l.find(e=>e.id===n);t&&k(t.previewURL);const r=l.filter(e=>e.id!==n);return f(r,!1),r})},[f]),D=d.some(n=>!n.uploaded&&!n.error),I=d.some(n=>n.progress!==null&&n.progress<100),J=d.length>0?d.reduce((n,l)=>n+(l.progress??0),0)/d.length:0;return{files:d,addFiles:z,removeFile:B,hasPending:D,isUploading:I,progress:J,formId:U,isDeferred:y}}export{Q as useFileUpload};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{useMemo as p}from"react";import{buildReferenceLabel as v}from"../components/controlled/select/ControlledReferenceField";import{useCrudList as c}from"../useCrudList";function
|
|
1
|
+
"use client";import{useMemo as p}from"react";import{buildReferenceLabel as v}from"../components/controlled/select/ControlledReferenceField";import{useCrudList as c}from"../useCrudList";function R(n){const o=new Map;for(const i of Object.values(n.fields)){const e=i.validation?.reference;if(typeof e=="string"&&!o.has(e)){const l=i.options?.fieldSpecific;o.set(e,{collection:e,labelFields:l?.labelFields,displayField:l?.displayField})}}return Array.from(o.values())}function M(n){const o=p(()=>R(n),[n]),i=o[0],e=o[1],l=o[2],s=o[3],{items:d}=c(i?.collection??"__disabled_0__",{enabled:!!i}),{items:a}=c(e?.collection??"__disabled_1__",{enabled:!!e}),{items:f}=c(l?.collection??"__disabled_2__",{enabled:!!l}),{items:r}=c(s?.collection??"__disabled_3__",{enabled:!!s}),F=[{info:i,items:d},{info:e,items:a},{info:l,items:f},{info:s,items:r}];return p(()=>{const _={};for(const{info:t,items:m}of F){if(!t||!m.length)continue;const b={};for(const y of m){const u=y;b[u.id]=v(u,t.labelFields,t.displayField)}_[t.collection]=b}return _},[i?.collection,d,e?.collection,a,l?.collection,f,s?.collection,r])}export{M as useReferenceResolver};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{useMemo as
|
|
1
|
+
"use client";import{useMemo as h}from"react";function p(a,e,t,n,N={}){const{limit:m=3,tolerance:o=.2}=N,c=h(()=>{if(!e||!t||t.length===0||n.length===0)return[];const b=e.id;return t.filter(f=>f.id===b?!1:n.some(i=>{const r=a.fields[i];if(!r)return!1;const s=e[i],u=f[i];if(s==null||u==null)return!1;if(r.type==="number"||r.type==="range"||r.type==="year"){const l=Number(s),g=Number(u);if(isNaN(l)||isNaN(g))return!1;const d=Math.abs(l*o);return Math.abs(g-l)<=d}return String(s)===String(u)})).slice(0,m)},[e,t,n,a.fields,m,o]);return{items:c,hasItems:c.length>0}}export{p as useRelatedItems};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{useEffect as
|
|
1
|
+
"use client";import{useEffect as t}from"react";import{isClient as a}from"@donotdev/core";function u({isDirty:n,enabled:r=!0,message:e="You have unsaved changes. Are you sure you want to leave?"}){t(()=>{if(!r||!n||!a())return;const o=s=>(s.preventDefault(),s.returnValue=e,e);return window.addEventListener("beforeunload",o),()=>{window.removeEventListener("beforeunload",o)}},[n,r,e])}export{u as useUnsavedChangesWarning};
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export*from"./useCrud";export*from"./useCrudList";export*from"./useCrudCardList";export*from"./components";export*from"./stores";import{FunctionsAdapter as
|
|
1
|
+
export*from"./useCrud";export*from"./useCrudList";export*from"./useCrudCardList";export*from"./components";export*from"./stores";import{FunctionsAdapter as e}from"./adapters/FunctionsAdapter";import{getCrudService as a}from"./CrudService";import{useCrudStore as s}from"./CrudStore";import{OPTIMISTIC_STATUSES as t,CRUD_OPERATION as r}from"./types";import{loadDeterministicRange as i,upsertDeterministic as l,appendToCollection as o}from"./utils/collections";import{getFieldRegistry as p,registerFieldType as d,isFieldTypeRegistered as n}from"./FieldRegistry";import{registerBuiltinFieldType as m,getFieldTypeMetadata as F,getFilterType as u,getDisplayFormatter as f,isFilterable as y,getValueType as g,clearFieldTypeRegistry as c}from"./fieldTypeRegistry";import{registerBuiltinFieldTypes as T}from"./builtinFieldTypes";import{useEntityForm as S,useEntityField as C,useController as R,isFieldEditable as b,getFieldsForOperation as U,validateEntity as v,translateFieldLabel as E,translateLabel as h}from"./forms";import{UploadProvider as k,useUploadContext as W}from"./contexts";import{useFileUpload as w,useUnsavedChangesWarning as I,useEntityFavorites as x,useRelatedItems as B,useCrudFilters as D,useFieldConditions as O,useReferenceResolver as P}from"./hooks";import{isStorageUrl as A,validatePicture as L,checkForBlobUrls as M,hasBlobUrls as V}from"./utils/uploadValidation";import{defineWorkflow as _,useEntityWorkflow as N,saveWorkflowState as j,loadWorkflowState as q,clearWorkflowState as z}from"./workflows";import{formatValue as H}from"./components/DisplayFieldRenderer";import{buildReferenceLabel as J}from"./components/controlled/select/ControlledReferenceField";import{matchesFilter as K}from"./utils/matchesFilter";import{applyFilters as Q,applySearch as X,applySort as Y,getSearchableFields as Z}from"./utils/clientListProcessing";export{r as CRUD_OPERATION,e as FunctionsAdapter,t as OPTIMISTIC_STATUSES,k as UploadProvider,o as appendToCollection,Q as applyFilters,X as applySearch,Y as applySort,J as buildReferenceLabel,M as checkForBlobUrls,c as clearFieldTypeRegistry,z as clearWorkflowState,_ as defineWorkflow,H as formatValue,a as getCrudService,f as getDisplayFormatter,p as getFieldRegistry,F as getFieldTypeMetadata,U as getFieldsForOperation,u as getFilterType,Z as getSearchableFields,g as getValueType,V as hasBlobUrls,b as isFieldEditable,n as isFieldTypeRegistered,y as isFilterable,A as isStorageUrl,i as loadDeterministicRange,q as loadWorkflowState,K as matchesFilter,m as registerBuiltinFieldType,T as registerBuiltinFieldTypes,d as registerFieldType,j as saveWorkflowState,E as translateFieldLabel,h as translateLabel,l as upsertDeterministic,R as useController,D as useCrudFilters,s as useCrudStore,x as useEntityFavorites,C as useEntityField,S as useEntityForm,N as useEntityWorkflow,O as useFieldConditions,w as useFileUpload,P as useReferenceResolver,B as useRelatedItems,I as useUnsavedChangesWarning,W as useUploadContext,v as validateEntity,L as validatePicture};
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
import type { FieldTypeMetadata } from './fieldTypeRegistry.types';
|
|
1
2
|
/**
|
|
2
|
-
* Register all built-in field types with unified registry
|
|
3
|
-
* This is the single source of truth for framework built-ins
|
|
3
|
+
* Register all built-in field types with unified registry.
|
|
4
|
+
* This is the single source of truth for framework built-ins.
|
|
5
|
+
*
|
|
6
|
+
* Receives both registries as parameters to avoid circular imports
|
|
7
|
+
* (fieldTypeRegistry.ts ↔ registerBuiltinFieldTypes.tsx), which caused
|
|
8
|
+
* esbuild to tree-shake the entire registration module.
|
|
4
9
|
*/
|
|
5
|
-
export declare function registerAllBuiltinFieldTypes(
|
|
10
|
+
export declare function registerAllBuiltinFieldTypes(metadataRegistry: Map<string, FieldTypeMetadata>, fieldRegistry: {
|
|
11
|
+
registerComponent: (type: string, controlled: any, uncontrolled?: any) => void;
|
|
12
|
+
}): void;
|
|
6
13
|
//# sourceMappingURL=registerBuiltinFieldTypes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registerBuiltinFieldTypes.d.ts","sourceRoot":"","sources":["../src/registerBuiltinFieldTypes.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"registerBuiltinFieldTypes.d.ts","sourceRoot":"","sources":["../src/registerBuiltinFieldTypes.tsx"],"names":[],"mappings":"AA4FA,OAAO,KAAK,EACV,iBAAiB,EAElB,MAAM,2BAA2B,CAAC;AA8zBnC;;;;;;;GAOG;AACH,wBAAgB,4BAA4B,CAC1C,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,EAChD,aAAa,EAAE;IACb,iBAAiB,EAAE,CACjB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,GAAG,EACf,YAAY,CAAC,EAAE,GAAG,KACf,IAAI,CAAC;CACX,GACA,IAAI,CAuuBN"}
|