@wix/auto-patterns 1.17.0 → 1.19.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.
Files changed (45) hide show
  1. package/dist/cjs/dataSourceAdapters/cms/cmsAdapter.js +0 -2
  2. package/dist/cjs/dataSourceAdapters/cms/cmsAdapter.js.map +1 -1
  3. package/dist/cjs/dataSourceAdapters/cms/fetchCmsData.js.map +1 -1
  4. package/dist/cjs/dataSourceAdapters/cms/filterUtils.js.map +1 -1
  5. package/dist/cjs/dataSourceAdapters/cms/sortUtils.js.map +1 -1
  6. package/dist/cjs/hooks/useColumns.js +7 -5
  7. package/dist/cjs/hooks/useColumns.js.map +1 -1
  8. package/dist/cjs/types/types.js.map +1 -1
  9. package/dist/docs/action_cell.md +1 -1
  10. package/dist/docs/app_config_structure.md +73 -3
  11. package/dist/docs/auto-patterns-guide.md +367 -80
  12. package/dist/docs/bulk_actions.md +1 -1
  13. package/dist/docs/collection_page.md +1 -1
  14. package/dist/docs/collection_page_actions.md +1 -1
  15. package/dist/docs/config_schema.md +184 -0
  16. package/dist/docs/custom_overrides.md +163 -4
  17. package/dist/docs/entity_page.md +0 -1
  18. package/dist/docs/index.md +5 -7
  19. package/dist/docs/schema_config.md +174 -0
  20. package/dist/docs/sdk_utilities.md +97 -0
  21. package/dist/docs/wix_fqdn_custom_data_source.md +201 -0
  22. package/dist/esm/dataSourceAdapters/cms/cmsAdapter.js +0 -2
  23. package/dist/esm/dataSourceAdapters/cms/cmsAdapter.js.map +1 -1
  24. package/dist/esm/dataSourceAdapters/cms/fetchCmsData.js.map +1 -1
  25. package/dist/esm/dataSourceAdapters/cms/filterUtils.js.map +1 -1
  26. package/dist/esm/dataSourceAdapters/cms/sortUtils.js.map +1 -1
  27. package/dist/esm/hooks/useColumns.js +3 -1
  28. package/dist/esm/hooks/useColumns.js.map +1 -1
  29. package/dist/esm/types/types.js.map +1 -1
  30. package/dist/types/dataSourceAdapters/cms/cmsAdapter.d.ts.map +1 -1
  31. package/dist/types/dataSourceAdapters/cms/fetchCmsData.d.ts +2 -3
  32. package/dist/types/dataSourceAdapters/cms/fetchCmsData.d.ts.map +1 -1
  33. package/dist/types/dataSourceAdapters/cms/filterUtils.d.ts +3 -4
  34. package/dist/types/dataSourceAdapters/cms/filterUtils.d.ts.map +1 -1
  35. package/dist/types/dataSourceAdapters/cms/sortUtils.d.ts +2 -3
  36. package/dist/types/dataSourceAdapters/cms/sortUtils.d.ts.map +1 -1
  37. package/dist/types/hooks/useColumns.d.ts.map +1 -1
  38. package/dist/types/types/types.d.ts +13 -3
  39. package/dist/types/types/types.d.ts.map +1 -1
  40. package/package.json +4 -4
  41. package/dist/docs/recipe-bulk-operations.md +0 -1352
  42. package/dist/docs/recipe-crud-operations.md +0 -805
  43. package/dist/docs/recipe-customization.md +0 -1703
  44. package/dist/docs/recipe-first-dashboard.md +0 -795
  45. package/dist/docs/sdk_and_schema.md +0 -215
@@ -1,805 +0,0 @@
1
- # Recipe 2: Adding CRUD Operations to Your Dashboard
2
-
3
- **Use Case**: "I have a basic dashboard but need to add Create, Edit, Delete functionality"
4
-
5
- ---
6
-
7
- ## SDK Utilities
8
-
9
- The `sdk` parameter provides access to Auto Patterns utilities and context. Available in custom actions across all action types (ActionCell, BulkActions, CollectionPage actions, and EntityPage Actions).
10
-
11
- ### Key SDK Utilities
12
- The only functions exist in sdk are:
13
-
14
- • **closeModal** - `closeModal(): void`
15
- - Closes the currently open modal
16
- - Example: `sdk.closeModal()` after saving or canceling
17
-
18
- • **getOptimisticActions** - `getOptimisticActions(collectionId): OptimisticActions`
19
- - Provides optimistic UI updates for immediate user feedback
20
- - Supports create, update, delete operations with automatic rollback on failure
21
- - Example: `sdk.getOptimisticActions(sdk.collectionId).updateOne(item, { ... })`
22
-
23
- • **getSchema** - `getSchema(collectionId): SchemaConfig | undefined`
24
- - Access to collection schema information (fields, types, validation)
25
- - Useful for dynamic operations based on collection structure
26
- - Example: `const schema = sdk.getSchema(sdk.collectionId)`
27
-
28
- • **collectionId** - `string`
29
- - Current collection context identifier
30
- - Available in all action contexts for referencing the active collection
31
- - Example: `sdk.collectionId` to get the current collection ID
32
-
33
- ---
34
-
35
- ## OptimisticActions
36
-
37
- Provides immediate UI updates with automatic server synchronization and error recovery.
38
-
39
- ### Usage Rules
40
-
41
- **Use OptimisticActions for:**
42
- - Data modification operations (create, update, delete)
43
- - Operations requiring immediate visual feedback
44
-
45
- **Do NOT use for:**
46
- - Read-only operations
47
- - Operations requiring server confirmation first
48
-
49
- ### Core Pattern
50
-
51
- ```typescript
52
- // Get instances from SDK (see SDK Utilities section)
53
- const optimisticActions = sdk.getOptimisticActions(sdk.collectionId);
54
- const schema = sdk.getSchema(sdk.collectionId);
55
-
56
- optimisticActions.operation(items, {
57
- submit: async (items) => schema.actions.serverMethod(items),
58
- successToast: 'Success message',
59
- errorToast: (err, {retry}) => ({ text: 'Error message', action: { text: 'Retry', onClick: retry }})
60
- });
61
- ```
62
-
63
- ### Available Operations
64
-
65
- #### Create Operations
66
- - `createOne(item: T, params: OptimisticParams<T>): void`
67
- - `createMany(items: T[], params: OptimisticParams<T>): void`
68
-
69
- #### Update Operations
70
- - `updateOne(item: T, params: OptimisticParams<T>): void`
71
- - `updateMany(items: T[], params: OptimisticParams<T>): void`
72
- - `updateAll(transformFn: (item: T) => Partial<T>, params: OptimisticParams<T>): void`
73
-
74
- #### Delete Operations
75
- - `deleteOne(item: T, params: OptimisticParams<T> & { showUndoToast: true }): void`
76
- - `deleteMany(items: T[], params: OptimisticParams<T> & { showUndoToast: true }): void`
77
- - `deleteAll(params: OptimisticParams<T> & { showUndoToast: true }): void`
78
-
79
- ### Type Definitions
80
-
81
- ```typescript
82
- interface OptimisticParams<T> {
83
- submit: (items: T[]) => Promise<any>;
84
- successToast: string | ToastConfig;
85
- errorToast: (error: Error, actions: { retry: () => void }) => ToastConfig | string;
86
- showUndoToast?: boolean; // Required: true for delete operations
87
- }
88
-
89
- interface ToastConfig {
90
- text: string;
91
- action?: { text: string; onClick: () => void };
92
- }
93
- ```
94
-
95
- ### Validation Requirements
96
-
97
- **Before using optimistic actions:**
98
- - Verify `sdk.getOptimisticActions(collectionId)` returns valid instance
99
- - Verify `sdk.getSchema(collectionId)` returns valid schema
100
- - For delete operations: `showUndoToast: true` is mandatory
101
- - All `submit` functions must return a Promise
102
-
103
- **SDK Parameter:** Available in custom actions and modals. See SDK Utilities section for complete interface.
104
-
105
- ---
106
-
107
- ## SchemaConfig Usage
108
-
109
- SchemaConfig provides complete collection metadata and server actions. Essential for dynamic operations and accessing collection structure information.
110
-
111
- ### Key Properties
112
-
113
- • **id** - `string`
114
- - Collection identifier (e.g., "WixPets")
115
- - Example: `schema.id === "WixPets"`
116
-
117
- • **idField** - `string`
118
- - Primary key field name (usually "_id")
119
- - Required for all update/delete operations
120
- - Example: `const id = item[schema.idField]`
121
-
122
- • **displayField** - `string`
123
- - Main field for displaying items (name, title, etc.)
124
- - Used in UI components for item identification
125
- - Example: `const label = item[schema.displayField]`
126
-
127
- • **fields** - `Record<string, Field | undefined>`
128
- - Complete field definitions with types and metadata
129
- - Useful for dynamic form generation or validation
130
- - Example: `schema.fields.name.type === 'TEXT'`
131
-
132
- • **actions** - Server operation functions
133
- - Pre-configured API calls for CRUD operations
134
- - Use with optimistic actions for best UX
135
- - Example: `await schema.actions.update(item)`
136
-
137
- ### Available Schema Actions
138
-
139
- - schema.actions.create(item) // Create single item
140
- - schema.actions.update(item) // Update single item
141
- - schema.actions.delete(itemId) // Delete by ID
142
- - schema.actions.bulkUpdate(updates) // Update multiple items
143
- - schema.actions.bulkDelete(itemIds) // Delete multiple items
144
-
145
- ### Schema Validation Checklist
146
-
147
- Before using schema in operations:
148
-
149
- ✓ Check if schema exists: `if (!schema) return;`
150
- ✓ Verify required fields exist on items
151
- ✓ Use `schema.idField` for ID operations
152
- ✓ Use `schema.displayField` for UI display
153
- ✓ Use `schema.actions` for server operations
154
-
155
- ### Common Usage Patterns
156
-
157
- - **ActionCell**: Use `schema.actions.update()` or `schema.actions.delete()` for single item operations
158
- - **BulkActions**: Use `schema.actions.bulkUpdate()` or `schema.actions.bulkDelete()` for multiple items
159
- - **Dynamic UI**: Use `schema.fields` to build forms or validate data
160
- - **Error Messages**: Use `schema.displayField` to create meaningful user feedback
161
-
162
- ---
163
-
164
- ## Filters Configuration Notes
165
-
166
- To configure filters in a `collectionPage`, add a `filters` property inside the page's component configuration object. Each filter must reference a valid field by its `fieldId`, and the supported types are:
167
-
168
- * `numberConfig`: used with fields of type `NUMBER`
169
- * `dateConfig`: used with fields of type `DATETIME`
170
- * `booleanConfig`: used with fields of type `BOOLEAN`
171
- * `enumConfig`: used with fields of type `ARRAY` or `ARRAY_STRING`
172
-
173
- ### Enum Configuration Implementation
174
-
175
- When implementing enum filters, you must ask the user to provide the possible option values. Never invent or assume enum values. Here's how to properly handle enumConfig:
176
-
177
- #### Example: User-Provided Enum Implementation
178
-
179
- 1. First, collect the possible values from the user:
180
- ```
181
- User requests: "I need a filter for pet types."
182
- You ask: "What are the possible values for pet types that should be available in the filter?"
183
- User responds: "dog, cat, bird, rabbit, fish"
184
- ```
185
-
186
- 2. Then, create the `enumConfig` structure:
187
- ```json
188
- "enumConfig": {
189
- "options": [
190
- { "value": "dog", "label": "Dog" },
191
- { "value": "cat", "label": "Cat" },
192
- { "value": "bird", "label": "Bird" },
193
- { "value": "rabbit", "label": "Rabbit" },
194
- { "value": "fish", "label": "Fish" }
195
- ],
196
- "selectionMode": "multiple",
197
- "optionType": "checkbox"
198
- }
199
- ```
200
-
201
- Notice how the `label` is derived from the `value` by capitalizing the first letter. The user's exact values become the `value` property.
202
-
203
- ### Grouping Filters with Section Title
204
-
205
- * Filters can be grouped by sections using the `sectionTitle` property.
206
- * If multiple filter items share the same `sectionTitle`, they will be displayed together in a grouped section in the UI.
207
- * Filters without a `sectionTitle` will appear in a default section or be displayed individually.
208
- * Grouping helps maintain clarity, especially when dealing with multiple filter options.
209
-
210
- ### Key Guidelines
211
-
212
- * **openByDefault**: Automatically expands the filter accordion when the filters panel is opened.
213
- * **tagLabel**: Specifies the label displayed in a Tag component on the table or grid once the filter is active. For example, if the tagLabel is "Age", the filter display might show: `Age: 7`.
214
- * **maxInlineFilters**: Limits the number of filters shown inline in the table toolbar. Others are accessible via the panel. Default is 0.
215
- * **dateConfig.mode**:
216
-
217
- * `ONLY_PREDEFINED`: user can select only from preset options
218
- * `ONLY_CUSTOM`: user must select a custom date range manually (no presets)
219
- * `COMBINE`: both options available
220
- * **dateConfig.presets** must be omitted if mode is `ONLY_CUSTOM`.
221
- * **dateConfig.includeTime**: Controls whether time selection is also enabled alongside date (default is `true`).
222
-
223
- ---
224
-
225
- # Collection Page Actions
226
-
227
- ## ⚠️ Required Actions
228
-
229
- - **Every collection page must include a create action that navigates to the entity page for adding new entities** - this is essential for user workflow
230
-
231
- The `actions` property is an optional object within the `collectionPage` configuration, but it is strongly recommended to always include primaryActions with a create action for better user experience.
232
-
233
- ## `primaryActions` and `secondaryActions` Structure
234
-
235
- Both `primaryActions` and `secondaryActions` are optional and share the same underlying structure for defining how actions are displayed. They can be configured in one of two ways:
236
-
237
- ### A. Action Layout (`type: "action"`)
238
- * **Description**: This layout is used to display a single, prominent page-level action. For example, a "Create New Item" button.
239
- * **`action.item`**: Contains the configuration for the single action.
240
-
241
- ### B. Action Menu Layout (`type: "menu"`)
242
- * **Description**: This layout groups several page-level actions, often rendered as a dropdown menu or a set of related buttons under a common label.
243
- * **`menu.label`**: A string that serves as the title or accessible label for the group of actions.
244
- * **`menu.items`**: A flat array of action configurations, which can include divider objects for visual separation.
245
-
246
- ## Individual Action Configuration
247
-
248
- Each individual action, whether standalone in an `action` layout or part of an `items` array in a `menu` layout, is defined by the action item structure (see `AppConfig Structure`).
249
-
250
- In addition to these common properties, each action item must specify a `type` which determines the action's behavior and additional required configuration.
251
-
252
- ### 1. `type: "create"`
253
- * **Purpose**: Navigates to an entity page, allowing the user to create a new item in the specified collection.
254
- * **Details**:
255
- * `create.mode`: Must be `'page'`.
256
- * `create.page.id`: Must be the `id` of an existing `entityPage` in your `AppConfig`. This entity page should be set up to handle the creation of new entities for the `collection.collectionId`.
257
-
258
- ### 2. `type: "custom"`
259
- * **Purpose**: Executes custom JavaScript logic defined in your application's overrides.
260
- * **Details**:
261
- * The `custom` object in the configuration is typically empty. The functionality is determined by a custom action resolver function that you implement and register in the `actions` section of your `PatternsWizardOverridesProvider`. The `id` of this action item must exactly match the name (key) of the registered custom action resolver. The resolver will receive parameters including `collectionId`.
262
-
263
- ### 3. `type: "divider"`
264
- * **Purpose**: Creates a visual separator between action groups in menus and lists.
265
- * **Details**:
266
- * Divider actions require no additional configuration beyond `{ "type": "divider" }`.
267
- * Used within flat arrays to create logical groupings.
268
-
269
- ## Note on `secondaryActions`
270
-
271
- `secondaryActions` follow the exact same structural rules (`type: "action"` or `type: "menu"`) and use the same action item options as `primaryActions`. They are typically used for less prominent or less frequently used page-level actions, often rendered in a secondary position or within a "more options" style menu.
272
-
273
- ## Custom Collection Page Action Configuration
274
-
275
- Custom collection page actions execute JavaScript code that you define for collection-level operations. These actions receive parameters that give them access to collection context and utilities. Here's how to implement a custom collection page action:
276
-
277
- 1. First, create the actions folder structure in your page folder:
278
- ```
279
- your-page/
280
- ├── page.tsx
281
- └── components/
282
- └── actions/
283
- ├── index.tsx // Exports all actions
284
- └── exportCollection.tsx // Your custom collection action
285
- ```
286
-
287
- 2. Create your collection action handler in `exportCollection.tsx`:
288
- ```typescript
289
- import { CustomActionCollectionPageActionResolver } from '@wix/auto-patterns';
290
- import React from 'react';
291
- import { Download } from '@wix/ui-icons-common';
292
-
293
- // IMPORTANT: Function name MUST match the action id in your configuration
294
- export const exportCollection: CustomActionCollectionPageActionResolver = (params) => {
295
- const { actionParams, sdk } = params;
296
- const { collectionId } = actionParams;
297
-
298
- return {
299
- label: 'Export Collection',
300
- icon: <Download />,
301
- onClick: () => {
302
- // sdk is provided to custom action resolvers (see SDK Utilities section)
303
- const optimisticActions = sdk.getOptimisticActions(collectionId);
304
- const schema = sdk.getSchema(collectionId);
305
-
306
- // Example: Mark entire collection as exported
307
- optimisticActions.updateAll(
308
- (item) => ({ lastExported: new Date() }),
309
- {
310
- submit: async () => {
311
- // Your collection export logic here
312
- console.log(`Exporting collection: ${collectionId}`);
313
- // Export and update all items on server
314
- return await schema.actions.bulkUpdate({ lastExported: new Date() });
315
- },
316
- successToast: 'Collection exported successfully',
317
- errorToast: (err, {retry}) => ({
318
- text: 'Export failed',
319
- action: { text: 'Retry', onClick: retry }
320
- })
321
- }
322
- );
323
- },
324
- };
325
- };
326
- ```
327
-
328
- 3. Export your action in `actions/index.tsx`:
329
- ```typescript
330
- export * from './exportCollection';
331
- ```
332
-
333
- 4. Configure the action in your JSON configuration:
334
- ```json
335
- {
336
- "id": "exportCollection", // MUST match the function name exactly
337
- "type": "custom", // REQUIRED: Must be exactly "custom"
338
- "label": "Export Collection", // Optional: Displayed text
339
- "collection": {
340
- "collectionId": "WixPets",
341
- "entityTypeSource": "cms"
342
- }
343
- }
344
- ```
345
-
346
- 5. Register your action in the `PatternsWizardOverridesProvider`:
347
- ```typescript
348
- import * as actions from './components/actions';
349
-
350
- <PatternsWizardOverridesProvider value={{ actions }}>
351
- <AutoPatternsApp configuration={config as AppConfig} />
352
- </PatternsWizardOverridesProvider>
353
- ```
354
-
355
- ## Key Points for Custom Collection Page Actions:
356
- - The action `id` in the configuration MUST exactly match the function name exported from your actions folder
357
- - The function name and file name should follow a consistent naming convention (e.g., camelCase)
358
- - The implementation must be exported as a named export (not default export)
359
- - The implementation must use the `CustomActionCollectionPageActionResolver` type
360
- - Access collection context through `actionParams.collectionId`
361
-
362
- ---
363
-
364
- ## Custom Row Click Actions
365
-
366
- In addition to page-level actions, you can also customize what happens when users click on individual rows in your collection table. By default, clicking a row navigates to the entity page, but you can override this behavior with custom logic.
367
-
368
- **Before You Start:**
369
- - Only configure `onRowClick` if you need custom behavior (e.g., opening modals, side panels, custom actions)
370
- - If you just want navigation to entity page, don't configure `onRowClick` - it's the default behavior
371
- - Once you configure `onRowClick`, you must provide a complete working implementation
372
-
373
- ### Configuration
374
-
375
- Row click actions are configured at the table level using the `onRowClick` property:
376
-
377
- ```json
378
- {
379
- "type": "Table",
380
- "table": {
381
- "columns": [...],
382
- "onRowClick": {
383
- "id": "handleRowClick", // MUST match the function name exactly
384
- "type": "custom", // REQUIRED: Must be exactly "custom"
385
- }
386
- }
387
- }
388
- ```
389
-
390
- ### Implementation Requirements
391
-
392
- ⚠️ **CRITICAL**: When you configure `onRowClick` in your JSON, you MUST provide a complete working implementation. The Auto Patterns framework cannot function without it.
393
-
394
- Custom row click actions use the `CustomActionCollectionPageActionOnRowClickResolver` type and MUST return a `ResolvedAction` object with all required properties:
395
-
396
- #### Required Return Object Structure:
397
- ```typescript
398
- return {
399
- label: string, // REQUIRED: Action label
400
- icon: ReactElement, // REQUIRED: Icon component
401
- onClick: () => void // REQUIRED: Click handler function
402
- };
403
- ```
404
-
405
- #### Complete Implementation Example:
406
-
407
- ```typescript
408
- import { CustomActionCollectionPageActionOnRowClickResolver } from '@wix/auto-patterns';
409
- import React from 'react';
410
- import { More } from '@wix/wix-ui-icons-common';
411
-
412
- // IMPORTANT: Function name MUST match the action id in your configuration
413
- export const handleRowClick: CustomActionCollectionPageActionOnRowClickResolver = (params) => {
414
- const { actionParams, sdk } = params;
415
- const { item } = actionParams; // The clicked row's data
416
-
417
- return {
418
- label: 'View Details', // REQUIRED
419
- icon: <More />, // REQUIRED
420
- onClick: () => { // REQUIRED
421
- // Your custom row click logic here
422
- console.log('Row clicked:', item);
423
-
424
- // Example: Show a custom modal, perform an action, etc.
425
- // You can access all SDK utilities here (see SDK Utilities section)
426
- const optimisticActions = sdk.getOptimisticActions(sdk.collectionId);
427
- const schema = sdk.getSchema(sdk.collectionId);
428
-
429
- // Your custom logic...
430
- },
431
- };
432
- };
433
- ```
434
-
435
- ### Common Use Cases and Complete Examples
436
-
437
- #### 1. Opening a Side Panel Modal
438
-
439
- This is a complete working example for opening a side panel when clicking a row:
440
-
441
- **Step 1: Create the row click action** (`components/actions/openSidePanel.tsx`):
442
- ```typescript
443
- import { CustomActionCollectionPageActionOnRowClickResolver } from '@wix/auto-patterns';
444
- import React from 'react';
445
- import { More } from '@wix/wix-ui-icons-common';
446
-
447
- export const openSidePanel: CustomActionCollectionPageActionOnRowClickResolver = (params) => {
448
- const { actionParams, sdk } = params;
449
- const { item } = actionParams;
450
-
451
- return {
452
- label: 'View Details',
453
- icon: <More />,
454
- onClick: () => {
455
- // Open a custom modal with the item data
456
- // You need to implement the modal opening mechanism
457
- // This could be through a modal context, state management, etc.
458
- console.log('Opening side panel for:', item);
459
-
460
- // Example: Using a global modal state (you need to implement this)
461
- // window.dispatchEvent(new CustomEvent('openSidePanel', { detail: item }));
462
-
463
- // Or use a modal service/context that you've set up
464
- // modalService.openSidePanel(item);
465
- },
466
- };
467
- };
468
- ```
469
-
470
- **Step 2: Configure in JSON**:
471
- ```json
472
- {
473
- "type": "Table",
474
- "table": {
475
- "onRowClick": {
476
- "id": "openSidePanel",
477
- "type": "custom"
478
- },
479
- "columns": [...]
480
- }
481
- }
482
- ```
483
-
484
- **Step 3: Export and Register**:
485
- ```typescript
486
- // components/actions/index.tsx
487
- export * from './openSidePanel';
488
-
489
- // page.tsx
490
- import * as actions from './components/actions';
491
-
492
- <PatternsWizardOverridesProvider value={{ actions }}>
493
- <AutoPatternsApp configuration={config as AppConfig} />
494
- </PatternsWizardOverridesProvider>
495
- ```
496
-
497
- #### 2. Direct Data Manipulation
498
-
499
- ```typescript
500
- export const quickToggle: CustomActionCollectionPageActionOnRowClickResolver = (params) => {
501
- const { actionParams, sdk } = params;
502
- const { item } = actionParams;
503
-
504
- return {
505
- label: 'Quick Toggle',
506
- icon: <Toggle />,
507
- onClick: () => {
508
- const optimisticActions = sdk.getOptimisticActions(sdk.collectionId);
509
- const schema = sdk.getSchema(sdk.collectionId);
510
-
511
- // Example: Toggle a boolean field
512
- const updatedItem = { ...item, isActive: !item.isActive };
513
-
514
- optimisticActions.updateOne(updatedItem, {
515
- submit: async (items) => schema.actions.update(items[0]),
516
- successToast: `${item.name} toggled successfully`,
517
- errorToast: (err, {retry}) => ({
518
- text: 'Toggle failed',
519
- action: { text: 'Retry', onClick: retry }
520
- })
521
- });
522
- },
523
- };
524
- };
525
- ```
526
-
527
- ### Default vs Custom Behavior
528
-
529
- **Default Behavior (when `onRowClick` is not configured):**
530
- - Clicking a row automatically navigates to the entity page
531
- - Uses the `entityPageId` configuration to determine the target page
532
- - Passes the selected item's data to the entity page
533
-
534
- **Custom Behavior (when `onRowClick` is configured):**
535
- - Default navigation is **disabled**
536
- - Your custom action function is executed instead
537
- - You have complete control over the row click behavior
538
- - You can still navigate to the entity page programmatically if needed using the SDK navigation utilities
539
-
540
- ### Key Points for Custom Row Click Actions:
541
- - **MANDATORY IMPLEMENTATION**: If you configure `onRowClick` in JSON, you MUST provide a complete working implementation - the framework cannot function without it
542
- - The action `id` in the configuration MUST exactly match the function name exported from your actions folder
543
- - The implementation must use the `CustomActionCollectionPageActionOnRowClickResolver` type
544
- - **Required Return Object**: Must return an object with `label`, `icon`, and `onClick` properties - all are required
545
- - Access the clicked item's data through `actionParams.item`
546
- - The implementation must be exported as a named export and registered in your `PatternsWizardOverridesProvider`
547
- - When `onRowClick` is configured, the default navigation to entity page is completely disabled
548
- - **Complete Setup Required**: You need to create the action file, export it in the index, and register it in the provider - missing any step will cause errors
549
-
550
- ## Validation Checklist for Collection Page Actions
551
-
552
- ✓ Every collection page must include a create action.
553
- ✓ `actions` is an optional property of `collectionPage`.
554
- ✓ `primaryActions` and `secondaryActions` (if defined) have a valid `type` ("action" or "menu").
555
- ✓ If `type: "action"`, `action.item` is a valid action item configuration.
556
- ✓ If `type: "menu"`, `menu.items` is an array of valid action item configurations that can include dividers.
557
- ✓ Each action item contains a unique `id`, and the full `collection` object (`collectionId`, `entityTypeSource: 'cms'`).
558
- ✓ Each action item has a supported `type` (`create`, `custom`) and its corresponding configuration block (e.g., `create` block for `type: "create"`).
559
- ✓ `create` actions specify a `create.page.id` that matches an existing `entityPage` ID in the configuration.
560
- ✓ `custom` actions (identified by their main `id`) correspond to an action resolver function name registered in the `actions` override.
561
- ✓ Divider actions use `{ "type": "divider" }` format and require no additional properties.
562
- ✓ If `onRowClick` is configured in table layout, it must have a valid `id` and `type: "custom"`.
563
- ✓ **CRITICAL**: Custom row click actions must have corresponding implementations registered in the `actions` override - configuration without implementation will cause errors.
564
- ✓ Custom row click action implementations must return an object with `label`, `icon`, and `onClick` properties - all are required.
565
- ✓ Custom row click action implementations must be exported as named exports and included in the actions index file.
566
- ✓ `onRowClick` is optional - when not configured, rows navigate to entity page by default.
567
- ✓ **IMPORTANT**: Configuring `onRowClick` completely disables default navigation - you must handle all row click logic in your custom implementation.
568
-
569
- ---
570
-
571
- ## ActionCell Configuration
572
-
573
- The ActionCell feature adds an interactive action column to collection tables or grid views, enabling users to perform operations on individual entities.
574
-
575
- ### Placement and Structure
576
-
577
- The ActionCell has a two-level structure:
578
- * `primaryAction`: A single prominent action shown directly in the table/grid row
579
- * `secondaryActions`: Additional actions shown in a dropdown menu
580
-
581
- Both properties are optional, but at least one should be provided for the ActionCell to be useful.
582
-
583
- ### Inline Secondary Actions
584
-
585
- **New Feature**: By default, all secondary actions are hidden in a popover menu that appears when the user hovers over or clicks the "more actions" button. However, you can now configure some secondary actions to display inline directly in the table row for improved accessibility and reduced clicks.
586
-
587
- ### Action Types Reference
588
-
589
- 1. **Update Action** (`type: "update"`):
590
- - ✓ Use when: Editing entity fields or navigating to a detailed edit page
591
- - ✓ Common scenarios:
592
- - Full entity editing (use page mode)
593
- - ✓ Built-in functionality: No custom implementation needed
594
-
595
- 2. **Delete Action** (`type: "delete"`):
596
- - ✓ Use when: Removing entities with confirmation
597
- - ✓ Common scenarios:
598
- - Deleting records with confirmation
599
- - Soft-delete with status update
600
- - ✓ Built-in functionality: No custom implementation needed
601
-
602
- 3. **Custom Action** (`type: "custom"`):
603
- - ✓ Use when: Executing custom JavaScript without UI
604
- - ✓ Common scenarios:
605
- - API calls
606
- - Browser interactions (alerts, downloads)
607
- - Complex operations
608
- - ⚠️ Requires implementation: Must register action in overrides
609
-
610
- ### Action Appearance: The `skin` Property
611
-
612
- All action types support the optional `skin` property to customize the visual appearance of action buttons. The skin determines the button's color scheme and visual emphasis.
613
-
614
- #### Skin Values by Action Type:
615
-
616
- **Primary Actions** support these skin values:
617
- - `"standard"` - Default appearance (blue primary button)
618
- - `"inverted"` - Inverted color scheme
619
- - `"premium"` - Premium styling for premium features
620
-
621
- **Secondary Actions** support these skin values:
622
- - `"dark"` - Dark appearance
623
- - `"destructive"` - Red appearance for dangerous actions (ideal for delete operations)
624
- - `"premium"` - Premium styling for premium features
625
-
626
- ### Type Selection Decision Tree
627
-
628
- When choosing an action type, follow this decision process:
629
-
630
- 1. IF editing entity fields:
631
- → Use `type: "update"`
632
- a. IF complex edits → Use `mode: "page"`
633
-
634
- 2. IF removing entities:
635
- → Use `type: "delete"`
636
-
637
- 3. IF executing custom logic without UI:
638
- → Use `type: "custom"`
639
- - MUST implement action handler
640
- - MUST register with `actions` override
641
-
642
- ### Update Action Configuration
643
-
644
- Update actions edit entities by navigating to an entity page.
645
-
646
- #### Validation Rules:
647
-
648
- 1. If `update.mode` is `"page"`:
649
- - `update.page` must exist
650
- - `update.page.id` must match an entity page ID in the configuration
651
-
652
- ### Delete Action Configuration
653
-
654
- Delete actions remove entities with a confirmation modal.
655
-
656
- #### Validation Rules:
657
-
658
- 1. `delete.mode` must be `"modal"` (currently only modal is supported)
659
- 2. `delete.modal` object must exist
660
- 3. The modal properties (title, description, actions, feedback) are all optional
661
-
662
- ### Custom Action Configuration
663
-
664
- Custom actions execute JavaScript code that you define. These actions receive parameters that give them access to entity data and utilities. Here's how to implement a custom action:
665
-
666
- 1. First, create the actions folder structure in your page folder:
667
- ```
668
- your-page/
669
- ├── page.tsx
670
- └── components/
671
- └── actions/
672
- ├── index.tsx // Exports all actions
673
- └── downloadPetDetails.tsx // Your custom action (name = action id)
674
- ```
675
-
676
- 2. Create your action handler in `downloadPetDetails.tsx` (note: the filename and function name MUST match your action id):
677
- ```typescript
678
- import { CustomActionCellActionResolver } from '@wix/auto-patterns';
679
- import { Download } from '@wix/wix-ui-icons-common';
680
- import React from 'react';
681
-
682
- // IMPORTANT: Function name MUST match the action id in your configuration
683
- export const downloadPetDetails: CustomActionCellActionResolver = (params) => {
684
- const { actionParams, sdk } = params;
685
- const { item } = actionParams;
686
-
687
- return {
688
- label: 'Download Details',
689
- icon: <Download />,
690
- onClick: () => {
691
- // sdk is provided to custom action resolvers (see SDK Utilities section)
692
- const optimisticActions = sdk.getOptimisticActions(sdk.collectionId);
693
- const schema = sdk.getSchema(sdk.collectionId);
694
-
695
- // Example: Mark pet as downloaded
696
- const updatedItem = { ...item, lastDownloaded: new Date() };
697
- optimisticActions.updateOne(updatedItem, {
698
- submit: async (items) => {
699
- // Your download logic here + update server
700
- return await schema.actions.update(items[0]);
701
- },
702
- successToast: 'Pet details downloaded',
703
- errorToast: (err, {retry}) => ({
704
- text: 'Download failed',
705
- action: { text: 'Retry', onClick: retry }
706
- })
707
- });
708
- },
709
- };
710
- };
711
- ```
712
-
713
- 3. Export your action in `actions/index.tsx`:
714
- ```typescript
715
- export * from './downloadPetDetails';
716
- ```
717
-
718
- **Important:** Every time you create a new action, you must add a corresponding export line to this `index.tsx` file. For example, if you create `sendEmail.tsx`, you must add `export * from './sendEmail';` to the index file.
719
-
720
- 4. Configure the action in your JSON configuration:
721
- ```ts
722
- {
723
- "id": "downloadPetDetails", // MUST match the function name exactly
724
- "type": "custom", // REQUIRED: Must be exactly "custom"
725
- "label": "Download Details", // Optional: Displayed text
726
- }
727
- ```
728
-
729
- 5. Register your action in the `PatternsWizardOverridesProvider`:
730
- ```typescript
731
- import * as actions from './components/actions';
732
-
733
- <PatternsWizardOverridesProvider value={{ actions }}>
734
- <AutoPatternsApp configuration={config as AppConfig} />
735
- </PatternsWizardOverridesProvider>
736
- ```
737
-
738
- ### Key Points for Custom Actions:
739
- - The action `id` in the configuration MUST exactly match the function name exported from your actions folder
740
- - The function name and file name should follow a consistent naming convention (e.g., camelCase)
741
- - The implementation must be exported as a named export (not default export)
742
- - The implementation must use the `CustomActionCellActionResolver` type
743
-
744
- #### Validation Rules for Custom Actions:
745
-
746
- 1. `id` must:
747
- - Match exactly the function name of the custom action implementation
748
- - Be registered in the `actions` property of your `PatternsWizardOverridesProvider`
749
- - Follow JavaScript identifier naming rules (camelCase recommended)
750
-
751
- 2. The implementation must return an object with:
752
- - `label`: Text displayed for the action
753
- - `icon`: An Icon component from "@wix/wix-ui-icons-common"
754
- - `onClick`: Handler function for the action
755
-
756
- 3. The implementation must:
757
- - Use the correct type: `CustomActionCellActionResolver`
758
- - Be exported as a named export
759
- - Have a filename matching the function name
760
-
761
- ### Key Implementation Decisions
762
-
763
- Follow this decision process when implementing ActionCell:
764
-
765
- 1. **Basic Decision**: Decide which actions users need to perform on entities:
766
- - Edit entities? → Use `update` actions
767
- - Delete entities? → Use `delete` actions
768
- - Custom operations? → Use `custom` actions
769
-
770
- 2. **Primary vs Secondary**: Choose the most common/important action as primary:
771
- - Most common operation (typically Edit) → Place in `primaryAction.item`
772
- - Less common operations → Place in `secondaryActions.items` array
773
-
774
- 3. **Inline Secondary Actions Strategy**:
775
- - **Action Prioritization**: Order `secondaryActions.items` by frequency of use (most used first)
776
- - **Inline Count**: Use `inlineCount: 1-3` for optimal UX (avoid cluttering)
777
- - **Visibility Control**:
778
- - Use `inlineAlwaysVisible: false` (default) for cleaner visual appearance
779
- - Use `inlineAlwaysVisible: true` only for critical actions requiring constant visibility
780
-
781
- 4. **Update Action Mode**:
782
- - Complex, full-entity edits → Use `mode: "page"` to navigate to entity page
783
-
784
- 5. **Custom Implementation**:
785
- - For `custom` actions, you must provide implementations in your code and register them with `PatternsWizardOverridesProvider`
786
-
787
- ### ActionCell Validation Checklist
788
-
789
- AI agents should verify these requirements before generating ActionCell configurations:
790
-
791
- ✓ ActionCell is placed directly inside `table` or `grid` configuration
792
- ✓ Each action has a unique `id` and correct `type` value
793
- ✓ Each action type only includes its required field(s)
794
- ✓ Update page action refers to a valid entity page ID
795
- ✓ Delete action has a modal configuration
796
- ✓ Custom actions match implementations in overrides
797
- ✓ At least one of `primaryAction` or `secondaryActions` is provided
798
- ✓ `inlineCount` (if specified) is a non-negative number ≤ total secondary actions count
799
- ✓ `inlineAlwaysVisible` (if specified) is a boolean value
800
- ✓ Inline secondary actions configuration is applied only when secondary actions exist
801
- ✓ `skin` property (if specified) uses valid skin values:
802
- - Primary actions: `"standard"`, `"inverted"`, `"premium"`
803
- - Secondary actions: `"dark"`, `"destructive"`, `"premium"`
804
-
805
- ---