@wix/auto-patterns 1.15.0 → 1.17.0
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/cjs/components/AutoPatternsCollectionPageContent/AutoPatternsCollectionPageContent.js +16 -4
- package/dist/cjs/components/AutoPatternsCollectionPageContent/AutoPatternsCollectionPageContent.js.map +1 -1
- package/dist/cjs/components/AutoPatternsCollectionPageContent/SkeletonCollection.js +34 -0
- package/dist/cjs/components/AutoPatternsCollectionPageContent/SkeletonCollection.js.map +1 -0
- package/dist/cjs/components/AutoPatternsEntityPage/AutoPatternsEntityPage.js +1 -0
- package/dist/cjs/components/AutoPatternsEntityPage/AutoPatternsEntityPage.js.map +1 -1
- package/dist/cjs/components/AutoPatternsEntityPage/SkeletonEntity.js +198 -0
- package/dist/cjs/components/AutoPatternsEntityPage/SkeletonEntity.js.map +1 -0
- package/dist/cjs/components/AutoPatternsRoute/AutoPatternsPage.js +13 -3
- package/dist/cjs/components/AutoPatternsRoute/AutoPatternsPage.js.map +1 -1
- package/dist/cjs/components/AutoPatternsRoute/AutoPatternsRoutes.js +4 -4
- package/dist/cjs/components/AutoPatternsRoute/AutoPatternsRoutes.js.map +1 -1
- package/dist/cjs/hooks/useBaseTableFeatures.js +7 -2
- package/dist/cjs/hooks/useBaseTableFeatures.js.map +1 -1
- package/dist/cjs/hooks/useCollectionPageOnRowClickActions.js +49 -0
- package/dist/cjs/hooks/useCollectionPageOnRowClickActions.js.map +1 -0
- package/dist/cjs/hooks/useNavigationUtils.js +2 -2
- package/dist/cjs/hooks/useNavigationUtils.js.map +1 -1
- package/dist/cjs/providers/PatternsWizardOverridesContext.js +1 -1
- package/dist/cjs/providers/PatternsWizardOverridesContext.js.map +1 -1
- package/dist/cjs/providers/SchemaContext.js +4 -3
- package/dist/cjs/providers/SchemaContext.js.map +1 -1
- package/dist/cjs/types/CollectionPageConfig.js.map +1 -1
- package/dist/cjs/types/actions/base.js.map +1 -1
- package/dist/cjs/types/actions/collectionPageActions.js.map +1 -1
- package/dist/cjs/utils/actions/resolveAction.js +2 -1
- package/dist/cjs/utils/actions/resolveAction.js.map +1 -1
- package/dist/cjs/utils/actions/types.js.map +1 -1
- package/dist/docs/action_cell.md +233 -0
- package/dist/docs/app_config_structure.md +356 -0
- package/dist/docs/auto-patterns-guide.md +2467 -0
- package/dist/docs/bulk_actions.md +266 -0
- package/dist/docs/collection_page.md +54 -0
- package/dist/docs/collection_page_actions.md +343 -0
- package/dist/docs/custom_overrides.md +511 -0
- package/dist/docs/entity_page.md +104 -0
- package/dist/docs/entity_page_actions.md +92 -0
- package/dist/docs/index.md +76 -0
- package/dist/docs/installation.md +55 -0
- package/dist/docs/introduction.md +74 -0
- package/dist/docs/pages_configuration.md +129 -0
- package/dist/docs/recipe-bulk-operations.md +1352 -0
- package/dist/docs/recipe-crud-operations.md +805 -0
- package/dist/docs/recipe-customization.md +1703 -0
- package/dist/docs/recipe-first-dashboard.md +795 -0
- package/dist/docs/sdk_and_schema.md +215 -0
- package/dist/esm/components/AutoPatternsCollectionPageContent/AutoPatternsCollectionPageContent.js +7 -1
- package/dist/esm/components/AutoPatternsCollectionPageContent/AutoPatternsCollectionPageContent.js.map +1 -1
- package/dist/esm/components/AutoPatternsCollectionPageContent/SkeletonCollection.js +21 -0
- package/dist/esm/components/AutoPatternsCollectionPageContent/SkeletonCollection.js.map +1 -0
- package/dist/esm/components/AutoPatternsEntityPage/AutoPatternsEntityPage.js +3 -1
- package/dist/esm/components/AutoPatternsEntityPage/AutoPatternsEntityPage.js.map +1 -1
- package/dist/esm/components/AutoPatternsEntityPage/SkeletonEntity.js +91 -0
- package/dist/esm/components/AutoPatternsEntityPage/SkeletonEntity.js.map +1 -0
- package/dist/esm/components/AutoPatternsRoute/AutoPatternsPage.js +5 -1
- package/dist/esm/components/AutoPatternsRoute/AutoPatternsPage.js.map +1 -1
- package/dist/esm/components/AutoPatternsRoute/AutoPatternsRoutes.js +1 -1
- package/dist/esm/components/AutoPatternsRoute/AutoPatternsRoutes.js.map +1 -1
- package/dist/esm/hooks/useBaseTableFeatures.js +6 -1
- package/dist/esm/hooks/useBaseTableFeatures.js.map +1 -1
- package/dist/esm/hooks/useCollectionPageOnRowClickActions.js +45 -0
- package/dist/esm/hooks/useCollectionPageOnRowClickActions.js.map +1 -0
- package/dist/esm/hooks/useNavigationUtils.js +1 -1
- package/dist/esm/hooks/useNavigationUtils.js.map +1 -1
- package/dist/esm/providers/PatternsWizardOverridesContext.js.map +1 -1
- package/dist/esm/providers/SchemaContext.js +3 -2
- package/dist/esm/providers/SchemaContext.js.map +1 -1
- package/dist/esm/types/CollectionPageConfig.js.map +1 -1
- package/dist/esm/types/actions/base.js.map +1 -1
- package/dist/esm/types/actions/collectionPageActions.js.map +1 -1
- package/dist/esm/utils/actions/resolveAction.js +2 -1
- package/dist/esm/utils/actions/resolveAction.js.map +1 -1
- package/dist/esm/utils/actions/types.js.map +1 -1
- package/dist/types/components/AutoPatternsCollectionPageContent/AutoPatternsCollectionPageContent.d.ts.map +1 -1
- package/dist/types/components/AutoPatternsCollectionPageContent/SkeletonCollection.d.ts +5 -0
- package/dist/types/components/AutoPatternsCollectionPageContent/SkeletonCollection.d.ts.map +1 -0
- package/dist/types/components/AutoPatternsEntityPage/SkeletonEntity.d.ts +7 -0
- package/dist/types/components/AutoPatternsEntityPage/SkeletonEntity.d.ts.map +1 -0
- package/dist/types/components/AutoPatternsRoute/AutoPatternsPage.d.ts.map +1 -1
- package/dist/types/hooks/useBaseTableFeatures.d.ts +1 -1
- package/dist/types/hooks/useBaseTableFeatures.d.ts.map +1 -1
- package/dist/types/hooks/useCollectionPageOnRowClickActions.d.ts +7 -0
- package/dist/types/hooks/useCollectionPageOnRowClickActions.d.ts.map +1 -0
- package/dist/types/hooks/useTableFeatures.d.ts +1 -1
- package/dist/types/hooks/useTableGridSwitchFeatures.d.ts +1 -1
- package/dist/types/providers/PatternsWizardOverridesContext.d.ts +2 -2
- package/dist/types/providers/PatternsWizardOverridesContext.d.ts.map +1 -1
- package/dist/types/providers/SchemaContext.d.ts +2 -1
- package/dist/types/providers/SchemaContext.d.ts.map +1 -1
- package/dist/types/types/CollectionPageConfig.d.ts +2 -1
- package/dist/types/types/CollectionPageConfig.d.ts.map +1 -1
- package/dist/types/types/actions/base.d.ts +1 -0
- package/dist/types/types/actions/base.d.ts.map +1 -1
- package/dist/types/types/actions/collectionPageActions.d.ts +8 -0
- package/dist/types/types/actions/collectionPageActions.d.ts.map +1 -1
- package/dist/types/utils/actions/resolveAction.d.ts +1 -0
- package/dist/types/utils/actions/resolveAction.d.ts.map +1 -1
- package/dist/types/utils/actions/types.d.ts +1 -0
- package/dist/types/utils/actions/types.d.ts.map +1 -1
- package/package.json +26 -20
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
# Custom Overrides
|
|
2
|
+
|
|
3
|
+
## ⚠️ Override Rules
|
|
4
|
+
|
|
5
|
+
- **Custom overrides are restricted to the defined areas only** - attempting to override or modify any other aspect of `AutoPatternsApp` is prohibited and can cause unexpected behavior
|
|
6
|
+
- **Always verify override implementation** - when implementing custom overrides, you MUST ensure they are correctly imported and passed to the `PatternsWizardOverridesProvider`
|
|
7
|
+
|
|
8
|
+
The `PatternsWizardOverridesProvider` allows you to inject custom code to override default behaviors or add additional functionality. Below are the areas where overrides can be applied:
|
|
9
|
+
|
|
10
|
+
> **Note:** These are the only areas where overrides are supported. Avoid attempting to override or modify other parts of the system, as this is not supported and may lead to unexpected behavior.
|
|
11
|
+
|
|
12
|
+
## Folder Structure Organization
|
|
13
|
+
|
|
14
|
+
All custom overrides (components, modals, actions, columns, and other customizations) should be created in a `components` folder inside your page directory, not in a global `/src/components` folder. This keeps page-specific customizations organized alongside their respective pages.
|
|
15
|
+
|
|
16
|
+
### Recommended Structure:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
your-page/
|
|
20
|
+
├── page.tsx // Your main page component
|
|
21
|
+
├── MyCollectionConfig.patterns.json // Configuration file
|
|
22
|
+
└── components/ // Page-specific components folder
|
|
23
|
+
├── index.tsx // Exports all overrides for easy importing
|
|
24
|
+
├── actions/ // Custom actions
|
|
25
|
+
│ ├── index.tsx
|
|
26
|
+
│ └── myCustomAction.tsx
|
|
27
|
+
├── columns/ // Column overrides
|
|
28
|
+
│ ├── index.tsx
|
|
29
|
+
│ ├── name.ts
|
|
30
|
+
│ └── date.ts
|
|
31
|
+
└── customComponents/ // Custom entity page components
|
|
32
|
+
├── index.tsx
|
|
33
|
+
├── CustomNameField.tsx
|
|
34
|
+
└── InfoCard.tsx
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Importing Overrides in Your Page
|
|
38
|
+
|
|
39
|
+
In your page component, import from the local components folder:
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import * as modals from './components/modals';
|
|
43
|
+
import * as actions from './components/actions';
|
|
44
|
+
import * as columns from './components/columns';
|
|
45
|
+
import * as components from './components/customComponents';
|
|
46
|
+
|
|
47
|
+
<PatternsWizardOverridesProvider value={{ modals, actions, columns, components }}>
|
|
48
|
+
<AutoPatternsApp configuration={config as AppConfig} />
|
|
49
|
+
</PatternsWizardOverridesProvider>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Important: Updating Index Files
|
|
53
|
+
|
|
54
|
+
**When adding any new implementation (action, modal, column, or component), you MUST update the corresponding `index.tsx` file to export your new implementation.** The main page component imports from these index files, so they serve as the central export point for each type of override.
|
|
55
|
+
|
|
56
|
+
For example:
|
|
57
|
+
- Adding a new action → Update `./components/actions/index.tsx`
|
|
58
|
+
- Adding a new modal → Update `./components/modals/index.tsx`
|
|
59
|
+
- Adding a new column override → Update `./components/columns/index.tsx`
|
|
60
|
+
- Adding a new custom component → Update `./components/customComponents/index.tsx`
|
|
61
|
+
|
|
62
|
+
Without updating the index files, your implementations won't be available to the `PatternsWizardOverridesProvider`.
|
|
63
|
+
|
|
64
|
+
## ⚠️ Common Override Mistakes to Avoid
|
|
65
|
+
|
|
66
|
+
- Attempting to override unsupported areas
|
|
67
|
+
- Invalid column rendering functions
|
|
68
|
+
- Missing index file exports for new implementations
|
|
69
|
+
- Incorrect import paths or naming mismatches
|
|
70
|
+
|
|
71
|
+
## Columns
|
|
72
|
+
|
|
73
|
+
Each column in the table has a default rendering based on its field type. You can override this rendering by providing a custom function for the `column.id`. This allows you to customize how specific columns are displayed.
|
|
74
|
+
|
|
75
|
+
**Enhanced Column Overrides**: Column override can receive both the individual column `value` and the entire `row` data, enabling you to create complex columns that combine multiple field values from the same row.
|
|
76
|
+
|
|
77
|
+
### Function Signature
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
function columnOverride({ value, row }) {
|
|
81
|
+
// value: The individual column value
|
|
82
|
+
// row: The entire row object containing all field values
|
|
83
|
+
return <YourCustomRendering />;
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Understanding Row Data
|
|
88
|
+
|
|
89
|
+
**Important**: The `row` object contains all field values from the entity, where each property corresponds to a **field ID** from the collection schema. To access specific field values, use the exact field ID as defined in your collection schema.
|
|
90
|
+
|
|
91
|
+
For example, if your collection schema has these fields:
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"fields": [
|
|
95
|
+
{ "key": "name", "displayName": "Pet Name", "type": "TEXT" },
|
|
96
|
+
{ "key": "age", "displayName": "Age", "type": "NUMBER" },
|
|
97
|
+
{ "key": "isVaccinated", "displayName": "Vaccinated", "type": "BOOLEAN" },
|
|
98
|
+
{ "key": "lastActivity", "displayName": "Last Activity", "type": "DATETIME" }
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Then in your column override, you access these values using the field IDs:
|
|
104
|
+
```typescript
|
|
105
|
+
export function myColumn({ value, row }) {
|
|
106
|
+
// Access field values using their schema field IDs
|
|
107
|
+
const petName = row.name; // "name" field ID
|
|
108
|
+
const petAge = row.age; // "age" field ID
|
|
109
|
+
const isVaccinated = row.isVaccinated; // "isVaccinated" field ID
|
|
110
|
+
const lastActivity = row.lastActivity; // "lastActivity" field ID
|
|
111
|
+
|
|
112
|
+
return <YourCustomRendering />;
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Use Cases for Row Data Access
|
|
117
|
+
|
|
118
|
+
1. **Complex Display Columns**: Combine multiple fields into a single display (e.g., "Name (Age)" combining name and age fields)
|
|
119
|
+
2. **Conditional Rendering**: Show different content based on other field values in the same row
|
|
120
|
+
3. **Calculated Columns**: Create computed values using multiple row fields
|
|
121
|
+
4. **Cross-Field Validation Display**: Show validation status based on relationships between fields
|
|
122
|
+
|
|
123
|
+
### Example: Defining and Using Column Overrides
|
|
124
|
+
|
|
125
|
+
In `components/columns/name.tsx`:
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
import React from 'react';
|
|
129
|
+
|
|
130
|
+
export function name({ value, row }) {
|
|
131
|
+
// Simple value formatting
|
|
132
|
+
return <strong>{value}</strong>;
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
In `components/columns/petInfo.tsx`:
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
import React from 'react';
|
|
140
|
+
import { Box, Text } from '@wix/design-system';
|
|
141
|
+
|
|
142
|
+
export function petInfo({ value, row }) {
|
|
143
|
+
// Complex column combining multiple row values
|
|
144
|
+
return (
|
|
145
|
+
<Box direction="vertical" gap={1}>
|
|
146
|
+
<Text weight="bold">{row.name}</Text>
|
|
147
|
+
<Text size="small" skin="disabled">
|
|
148
|
+
{row.age} years old • {row.type}
|
|
149
|
+
</Text>
|
|
150
|
+
{row.isVaccinated && (
|
|
151
|
+
<Text size="tiny" skin="success">✓ Vaccinated</Text>
|
|
152
|
+
)}
|
|
153
|
+
</Box>
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
In `components/columns/status.tsx`:
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
import React from 'react';
|
|
162
|
+
import { Badge } from '@wix/design-system';
|
|
163
|
+
|
|
164
|
+
export function status({ value, row }) {
|
|
165
|
+
// Conditional rendering based on multiple row fields
|
|
166
|
+
if (row.isVaccinated && row.age > 1) {
|
|
167
|
+
return <Badge skin="success">Ready for Adoption</Badge>;
|
|
168
|
+
} else if (!row.isVaccinated) {
|
|
169
|
+
return <Badge skin="warning">Needs Vaccination</Badge>;
|
|
170
|
+
} else {
|
|
171
|
+
return <Badge skin="neutral">Too Young</Badge>;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
In `components/columns/fullName.tsx`:
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
import React from 'react';
|
|
180
|
+
|
|
181
|
+
export function fullName({ value, row }) {
|
|
182
|
+
// Calculated column using multiple fields
|
|
183
|
+
return `${row.name} (owned by ${row.owner})`;
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
In `components/columns/date.tsx`:
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
import React from 'react';
|
|
191
|
+
|
|
192
|
+
export function date({ value, row }) {
|
|
193
|
+
// Access to other row data for enhanced date formatting
|
|
194
|
+
const isRecent = row.lastActivity && new Date(row.lastActivity) > new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
|
|
195
|
+
|
|
196
|
+
return (
|
|
197
|
+
<span style={{ color: isRecent ? 'green' : 'inherit' }}>
|
|
198
|
+
<em>{new Date(value).toLocaleDateString()}</em>
|
|
199
|
+
{isRecent && ' (Recent)'}
|
|
200
|
+
</span>
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
In `components/columns/index.tsx`:
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
export * from './name';
|
|
209
|
+
export * from './petInfo';
|
|
210
|
+
export * from './status';
|
|
211
|
+
export * from './fullName';
|
|
212
|
+
export * from './date';
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Important:** Every time you add a new column override file, you must add a corresponding export line to this `index.tsx` file. For example, if you create `price.tsx`, you must add `export * from './price';` to the index file.
|
|
216
|
+
|
|
217
|
+
In the `PatternsWizardOverridesProvider`:
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
import * as columns from './components/columns';
|
|
221
|
+
|
|
222
|
+
<PatternsWizardOverridesProvider value={{ columns }}>
|
|
223
|
+
<AutoPatternsApp configuration={config as AppConfig} />
|
|
224
|
+
</PatternsWizardOverridesProvider>
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Visual Representation
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
your-page/
|
|
231
|
+
└── components/
|
|
232
|
+
└── columns/
|
|
233
|
+
├── index.tsx // Exports all column overrides
|
|
234
|
+
├── name.tsx // Simple value formatting
|
|
235
|
+
├── petInfo.tsx // Complex multi-field column
|
|
236
|
+
├── status.tsx // Conditional rendering column
|
|
237
|
+
├── fullName.tsx // Calculated column
|
|
238
|
+
└── date.tsx // Enhanced formatting with row context
|
|
239
|
+
|
|
240
|
+
PatternsWizardOverridesProvider
|
|
241
|
+
└── value.columns
|
|
242
|
+
├── name
|
|
243
|
+
├── petInfo
|
|
244
|
+
├── status
|
|
245
|
+
├── fullName
|
|
246
|
+
└── date
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Key Benefits of Row Data Access
|
|
250
|
+
|
|
251
|
+
1. **Reduced Configuration Complexity**: Instead of adding multiple columns, create one complex column that shows related information
|
|
252
|
+
2. **Better User Experience**: Present related data together in a logical, readable format
|
|
253
|
+
3. **Dynamic Content**: Show different content based on the state of other fields
|
|
254
|
+
4. **Data Relationships**: Highlight relationships between different field values in the same entity
|
|
255
|
+
|
|
256
|
+
### Important Guidelines
|
|
257
|
+
|
|
258
|
+
- **Performance**: Remember that column functions are called for every row, so keep calculations lightweight
|
|
259
|
+
- **Consistency**: When using row data, ensure the column header accurately represents what's displayed
|
|
260
|
+
- **Accessibility**: Maintain proper semantic structure when combining multiple values
|
|
261
|
+
|
|
262
|
+
## Components
|
|
263
|
+
|
|
264
|
+
Components allow you to create custom rendering for specific elements in the entity page. Each component has a unique `componentId` that corresponds to the ID specified in the layout configuration.
|
|
265
|
+
|
|
266
|
+
The custom components receive two essential props:
|
|
267
|
+
|
|
268
|
+
1. **form**: An instance of `UseFormReturn` from react-hook-form (re-exported through `@wix/auto-patterns/form`), giving you access to the form control, methods, and state.
|
|
269
|
+
2. **entity**: A key-value object where keys are field IDs from the collection schema and values are the current field values, providing access to the entity's data.
|
|
270
|
+
|
|
271
|
+
Custom components can serve two main purposes:
|
|
272
|
+
|
|
273
|
+
### 1. Standalone Custom Components
|
|
274
|
+
|
|
275
|
+
These components can display custom UI elements like notifications, information cards, or any other custom content that isn't directly tied to specific fields. These are useful for adding unique UI elements that enhance the entity page experience.
|
|
276
|
+
|
|
277
|
+
### 2. Field Rendering Overrides
|
|
278
|
+
|
|
279
|
+
You can use custom components to override the default rendering of one or more fields. This allows you to:
|
|
280
|
+
- Apply custom validation logic
|
|
281
|
+
- Create custom input components
|
|
282
|
+
- Combine multiple fields into a single UI component
|
|
283
|
+
- Add field-specific functionality not available in the default renderers
|
|
284
|
+
|
|
285
|
+
### Using the useController Hook for Field Overrides
|
|
286
|
+
|
|
287
|
+
When creating field overrides, use the `useController` hook from `@wix/auto-patterns/form` (a re-export of react-hook-form's hook) to connect your custom component to the form state:
|
|
288
|
+
|
|
289
|
+
```tsx
|
|
290
|
+
import { useController } from '@wix/auto-patterns/form'; // Always import from this path, not react-hook-form
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
The hook requires:
|
|
294
|
+
- **name**: The field name you want to edit (should match the schema field ID)
|
|
295
|
+
- **control**: Retrieved from `form.control`
|
|
296
|
+
- **defaultValue**: Set from `entity?.[fieldId]` when it exists
|
|
297
|
+
|
|
298
|
+
### Example: Defining a Custom Component
|
|
299
|
+
|
|
300
|
+
Here's an example of a custom component that overrides the rendering of the "name" field:
|
|
301
|
+
|
|
302
|
+
```tsx
|
|
303
|
+
import React, { FC } from 'react';
|
|
304
|
+
import { Box, Card, FormField, Input, Text } from '@wix/design-system';
|
|
305
|
+
import { useController } from '@wix/auto-patterns/form';
|
|
306
|
+
import { CustomComponentProps } from '@wix/auto-patterns/types';
|
|
307
|
+
|
|
308
|
+
export const customNameField: FC<CustomComponentProps> = ({ form, entity }) => {
|
|
309
|
+
// Create a controller for the name field
|
|
310
|
+
const controller = useController({
|
|
311
|
+
name: 'name', // Field ID from the schema
|
|
312
|
+
control: form.control, // Form control
|
|
313
|
+
defaultValue: entity?.name, // Default value from entity
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
return (
|
|
317
|
+
<FormField
|
|
318
|
+
label="Name"
|
|
319
|
+
required={true}
|
|
320
|
+
charCount={100}
|
|
321
|
+
// Connect field state to UI
|
|
322
|
+
status={controller.fieldState.invalid ? 'error' : undefined}
|
|
323
|
+
statusMessage={controller.fieldState.error?.message}
|
|
324
|
+
dataHook={`short-text-${controller.field.name}`}
|
|
325
|
+
>
|
|
326
|
+
<Input
|
|
327
|
+
// Connect field value and onChange
|
|
328
|
+
value={controller.field.value}
|
|
329
|
+
onChange={(e) => controller.field.onChange(e.target.value)}
|
|
330
|
+
dataHook={`short-text-${controller.field.name}`}
|
|
331
|
+
/>
|
|
332
|
+
</FormField>
|
|
333
|
+
);
|
|
334
|
+
};
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
### Example: Standalone Component (Not Field-Specific)
|
|
339
|
+
|
|
340
|
+
Custom components can also be used to add UI elements not tied to specific fields:
|
|
341
|
+
|
|
342
|
+
```tsx
|
|
343
|
+
import React, { FC } from 'react';
|
|
344
|
+
import { Box, Card, Text, Button } from '@wix/design-system';
|
|
345
|
+
import { CustomComponentProps } from '@wix/auto-patterns/types';
|
|
346
|
+
|
|
347
|
+
export const infoCard: FC<CustomComponentProps> = ({ entity }) => {
|
|
348
|
+
return (
|
|
349
|
+
<Card>
|
|
350
|
+
<Card.Content>
|
|
351
|
+
<Box direction="vertical" gap={2}>
|
|
352
|
+
<Text weight="bold">Important Information</Text>
|
|
353
|
+
<Text>
|
|
354
|
+
This custom component can display additional information or functionality
|
|
355
|
+
that isn't directly tied to a specific field.
|
|
356
|
+
</Text>
|
|
357
|
+
{entity?.isVaccinated ? (
|
|
358
|
+
<Text skin="success">This pet is vaccinated</Text>
|
|
359
|
+
) : (
|
|
360
|
+
<Text skin="warning">This pet needs vaccination</Text>
|
|
361
|
+
)}
|
|
362
|
+
</Box>
|
|
363
|
+
</Card.Content>
|
|
364
|
+
</Card>
|
|
365
|
+
);
|
|
366
|
+
};
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Connecting Components in the Provider
|
|
370
|
+
|
|
371
|
+
In your main page file, import and provide these components via the `PatternsWizardOverridesProvider`:
|
|
372
|
+
|
|
373
|
+
```tsx
|
|
374
|
+
import * as components from './components';
|
|
375
|
+
|
|
376
|
+
<PatternsWizardOverridesProvider value={{ components }}>
|
|
377
|
+
<AutoPatternsApp configuration={config as AppConfig} />
|
|
378
|
+
</PatternsWizardOverridesProvider>
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### Important Guidelines for Custom Components
|
|
382
|
+
|
|
383
|
+
1. **Always import from `@wix/auto-patterns/form`** instead of directly from `react-hook-form`
|
|
384
|
+
2. **Follow react-hook-form best practices** - the underlying infrastructure is built on react-hook-form
|
|
385
|
+
3. **Handle form state properly**:
|
|
386
|
+
- Use `controller.fieldState.invalid` for error state
|
|
387
|
+
- Use `controller.fieldState.error?.message` for error messages
|
|
388
|
+
- Connect `controller.field.value` to input values
|
|
389
|
+
- Use `controller.field.onChange` for change handlers
|
|
390
|
+
4. **Component rendering**:
|
|
391
|
+
- Choose appropriate design-system components based on the field type
|
|
392
|
+
- For text fields: `Input`
|
|
393
|
+
- For multi-line text: `InputArea`
|
|
394
|
+
- For checkboxes: `Checkbox`
|
|
395
|
+
- For dates: `DatePicker`
|
|
396
|
+
- For dropdowns: `Dropdown`
|
|
397
|
+
|
|
398
|
+
**Important:** Every time you create a new custom component, you must add a corresponding export line to the `./components/customComponents/index.tsx` file. For example, if you create `StatusIndicator.tsx`, you must add `export * from './StatusIndicator';` to the index file.
|
|
399
|
+
|
|
400
|
+
### Understanding Reactivity in Custom Components
|
|
401
|
+
|
|
402
|
+
5. **Reactivity and field value changes (IMPORTANT)**:
|
|
403
|
+
- **NEVER rely on the `entity` object for reactive UI** - it is not reactive to form changes
|
|
404
|
+
- For any reactive UI that needs to respond to field value changes in real-time:
|
|
405
|
+
- Use `form.watch('fieldName')` to observe field changes reactively
|
|
406
|
+
- Use `useController` hook when you need both read and write access to a field
|
|
407
|
+
|
|
408
|
+
#### Common Reactivity Issues and Solutions
|
|
409
|
+
|
|
410
|
+
##### Example: Conditional Display Based on Field Value
|
|
411
|
+
|
|
412
|
+
```tsx
|
|
413
|
+
// ❌ INCORRECT APPROACH (Non-reactive)
|
|
414
|
+
const CustomComponent: FC<CustomComponentProps> = ({ form, entity }) => {
|
|
415
|
+
// This won't update when the user changes the name in the form
|
|
416
|
+
const showSpecialMessage = entity?.name === 'special';
|
|
417
|
+
|
|
418
|
+
return (
|
|
419
|
+
<Box>
|
|
420
|
+
<Input
|
|
421
|
+
value={form.getValues('name')}
|
|
422
|
+
onChange={(e) => form.setValue('name', e.target.value)}
|
|
423
|
+
/>
|
|
424
|
+
|
|
425
|
+
{showSpecialMessage && (
|
|
426
|
+
<Text>Special message for special name!</Text>
|
|
427
|
+
)}
|
|
428
|
+
</Box>
|
|
429
|
+
);
|
|
430
|
+
};
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
```tsx
|
|
434
|
+
// ✅ CORRECT APPROACH (Reactive)
|
|
435
|
+
const CustomComponent: FC<CustomComponentProps> = ({ form, entity }) => {
|
|
436
|
+
// This WILL update whenever the name field changes
|
|
437
|
+
const nameValue = form.watch('name');
|
|
438
|
+
const showSpecialMessage = nameValue === 'special';
|
|
439
|
+
|
|
440
|
+
return (
|
|
441
|
+
<Box>
|
|
442
|
+
<Input
|
|
443
|
+
value={nameValue}
|
|
444
|
+
onChange={(e) => form.setValue('name', e.target.value)}
|
|
445
|
+
/>
|
|
446
|
+
|
|
447
|
+
{showSpecialMessage && (
|
|
448
|
+
<Text>Special message for special name!</Text>
|
|
449
|
+
)}
|
|
450
|
+
</Box>
|
|
451
|
+
);
|
|
452
|
+
};
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
##### When to Use the Entity Object
|
|
457
|
+
|
|
458
|
+
The `entity` object is useful for:
|
|
459
|
+
- Setting initial values
|
|
460
|
+
- Accessing read-only data that doesn't change
|
|
461
|
+
- Comparing form state with original values (e.g., detecting if changes were made)
|
|
462
|
+
- Initializing form fields with useController's defaultValue parameter
|
|
463
|
+
|
|
464
|
+
```tsx
|
|
465
|
+
// Example: Proper use of entity object with useController
|
|
466
|
+
const CustomComponent: FC<CustomComponentProps> = ({ form, entity }) => {
|
|
467
|
+
// Use entity for initialization via defaultValue
|
|
468
|
+
const controller = useController({
|
|
469
|
+
name: 'name', // Field ID from the schema
|
|
470
|
+
control: form.control,
|
|
471
|
+
defaultValue: entity?.name // Initialize from entity
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
// Use watch for reactive updates
|
|
475
|
+
const currentName = controller.field.value;
|
|
476
|
+
const hasChanges = entity?.name !== currentName;
|
|
477
|
+
|
|
478
|
+
return (
|
|
479
|
+
<Box>
|
|
480
|
+
<FormField label="Name">
|
|
481
|
+
<Input
|
|
482
|
+
value={currentName}
|
|
483
|
+
onChange={(e) => controller.field.onChange(e.target.value)}
|
|
484
|
+
/>
|
|
485
|
+
</FormField>
|
|
486
|
+
{hasChanges && (
|
|
487
|
+
<Text size="small">Original value: {entity?.name}</Text>
|
|
488
|
+
)}
|
|
489
|
+
</Box>
|
|
490
|
+
);
|
|
491
|
+
};
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
### Visual Representation
|
|
495
|
+
|
|
496
|
+
```
|
|
497
|
+
your-page/
|
|
498
|
+
└── components/
|
|
499
|
+
├── index.tsx // Exports all component overrides
|
|
500
|
+
├── customNameField.tsx // Field override component
|
|
501
|
+
├── combinedNameFields.tsx // Multiple fields override
|
|
502
|
+
└── infoCard.tsx // Standalone component
|
|
503
|
+
|
|
504
|
+
PatternsWizardOverridesProvider
|
|
505
|
+
└── value.components
|
|
506
|
+
├── customNameField
|
|
507
|
+
├── combinedNameFields
|
|
508
|
+
└── infoCard
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
By using these component overrides, you can tailor the behavior and appearance of your `AutoPatternsApp` to meet specific requirements beyond what the default rendering provides.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Entity Page Configuration
|
|
2
|
+
|
|
3
|
+
## ⚠️ Entity Page Requirements
|
|
4
|
+
|
|
5
|
+
All entity pages must have:
|
|
6
|
+
- **A route path with descriptive segment and dynamic parameter** (e.g., `/product/:entityId`, `/pet/:entityId`) - **never just `/:entityId`** as this conflicts with collection page routing
|
|
7
|
+
- **A matching `route.params` configuration** that maps the dynamic parameter
|
|
8
|
+
- **A reference to their parent collection page via `parentPageId`**
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
* Displays details for a **single entity**.
|
|
13
|
+
* Always tied to a single Wix collection.
|
|
14
|
+
* `entityTypeSource` is always `'cms'`.
|
|
15
|
+
|
|
16
|
+
> The custom actions must be defined inside the `moreActions` array.
|
|
17
|
+
|
|
18
|
+
> Note: You do not need to define a custom action to navigate to the entity page. This behavior is built-in — clicking on a row in the collection table automatically navigates to the corresponding entity page.
|
|
19
|
+
|
|
20
|
+
## Entity Page Layout Configuration
|
|
21
|
+
|
|
22
|
+
### Grid System
|
|
23
|
+
|
|
24
|
+
- **12-Column Grid**: The layout uses a 12-column grid system.
|
|
25
|
+
- The `span` property controls how many columns an item occupies (1-12).
|
|
26
|
+
- When items in a row exceed 12 columns total, the next item wraps to a new line.
|
|
27
|
+
- Example: If an item has `span: 8` and the next has `span: 5`, the second item will start a new line.
|
|
28
|
+
|
|
29
|
+
### Layout Structure
|
|
30
|
+
|
|
31
|
+
- **Main Section**: Contains primary entity information and most important fields.
|
|
32
|
+
- **Sidebar Section**: Contains secondary information, metadata, or supporting content.
|
|
33
|
+
- Both sections support cards that can contain fields, containers, and components.
|
|
34
|
+
|
|
35
|
+
### Detailed Layout Content Types
|
|
36
|
+
|
|
37
|
+
1. **Field Type**:
|
|
38
|
+
```typescript
|
|
39
|
+
{
|
|
40
|
+
type: 'field';
|
|
41
|
+
field: {
|
|
42
|
+
span?: number; // How many columns this field occupies (1-12)
|
|
43
|
+
fieldId: string; // Must match a valid field ID from the collection schema
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
2. **Container Type** (for grouping related fields):
|
|
49
|
+
```typescript
|
|
50
|
+
{
|
|
51
|
+
type: 'container';
|
|
52
|
+
container: {
|
|
53
|
+
span?: number; // How many columns this container occupies (1-12)
|
|
54
|
+
children: LayoutContent[]; // Can nest fields, other containers, or components
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
3. **Component Type** (for custom rendering):
|
|
60
|
+
```typescript
|
|
61
|
+
{
|
|
62
|
+
type: 'component';
|
|
63
|
+
component: {
|
|
64
|
+
span?: number; // How many columns this component occupies (1-12)
|
|
65
|
+
componentId: string; // ID matching a component override implementation
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Layout Best Practices
|
|
71
|
+
|
|
72
|
+
1. **Field Grouping**:
|
|
73
|
+
- Group related fields using containers
|
|
74
|
+
- Place frequently used fields at the top
|
|
75
|
+
- Consider the natural flow of data entry
|
|
76
|
+
|
|
77
|
+
2. **Main vs. Sidebar Usage**:
|
|
78
|
+
- Main section: Put primary entity information
|
|
79
|
+
- Sidebar: Place secondary information and metadata
|
|
80
|
+
|
|
81
|
+
3. **Responsive Considerations**:
|
|
82
|
+
- Use appropriate spans for different field types
|
|
83
|
+
- Text fields often benefit from larger spans
|
|
84
|
+
- Boolean fields can use smaller spans
|
|
85
|
+
|
|
86
|
+
4. **Nested Containers**:
|
|
87
|
+
- Use containers to create logical groupings
|
|
88
|
+
- Don't nest containers too deeply for clarity
|
|
89
|
+
- Consider using cards for major sections instead of deeply nested containers
|
|
90
|
+
|
|
91
|
+
5. **Image Handling**:
|
|
92
|
+
- For image fields, consider providing more space (larger span)
|
|
93
|
+
- Images are automatically rendered with proper controls when using the field type
|
|
94
|
+
|
|
95
|
+
## ⚠️ Common Entity Page Layout Mistakes to Avoid
|
|
96
|
+
|
|
97
|
+
- Using incorrect span values causing unexpected layout breaks
|
|
98
|
+
- Referencing non-existent field IDs in the layout
|
|
99
|
+
- Creating overly complex nested container structures
|
|
100
|
+
- Failing to properly register component overrides
|
|
101
|
+
- Confusing main and sidebar section usage (putting main content in sidebar)
|
|
102
|
+
- Exceeding 12 total columns in a row without realizing content will wrap
|
|
103
|
+
- Forgetting to specify the `collectionPagePath` value
|
|
104
|
+
- Missing required `type: 'card'` structure in layout sections
|