@wix/auto-patterns 1.19.0 → 1.20.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/AutoPatternsTable/AutoPatternsTable.js +4 -2
- package/dist/cjs/components/AutoPatternsTable/AutoPatternsTable.js.map +1 -1
- package/dist/cjs/hooks/useTableFeatures.js +9 -1
- package/dist/cjs/hooks/useTableFeatures.js.map +1 -1
- package/dist/cjs/providers/ErrorContext.js +64 -0
- package/dist/cjs/providers/ErrorContext.js.map +1 -0
- package/dist/cjs/providers/PatternsWizardOverridesContext.js +1 -1
- package/dist/cjs/providers/PatternsWizardOverridesContext.js.map +1 -1
- package/dist/cjs/providers/RootAppProvider.js +16 -8
- package/dist/cjs/providers/RootAppProvider.js.map +1 -1
- package/dist/cjs/providers/SchemaContext.js +7 -2
- package/dist/cjs/providers/SchemaContext.js.map +1 -1
- package/dist/cjs/providers/index.js +6 -0
- package/dist/cjs/providers/index.js.map +1 -1
- package/dist/cjs/types/CollectionPageConfig.js.map +1 -1
- package/dist/cjs/types/actions/collectionPageActions.js.map +1 -1
- package/dist/cjs/types/types.js.map +1 -1
- package/dist/docs/action_cell.md +21 -8
- package/dist/docs/app_config_structure.md +2 -1
- package/dist/docs/auto-patterns-guide.md +416 -116
- package/dist/docs/bulk_actions.md +20 -7
- package/dist/docs/collection_page_actions.md +44 -18
- package/dist/docs/custom_overrides.md +318 -71
- package/dist/docs/index.md +1 -1
- package/dist/docs/installation.md +8 -9
- package/dist/docs/introduction.md +3 -2
- package/dist/docs/wix_fqdn_custom_data_source.md +111 -54
- package/dist/esm/components/AutoPatternsTable/AutoPatternsTable.js +4 -2
- package/dist/esm/components/AutoPatternsTable/AutoPatternsTable.js.map +1 -1
- package/dist/esm/hooks/useTableFeatures.js +10 -2
- package/dist/esm/hooks/useTableFeatures.js.map +1 -1
- package/dist/esm/providers/ErrorContext.js +44 -0
- package/dist/esm/providers/ErrorContext.js.map +1 -0
- package/dist/esm/providers/PatternsWizardOverridesContext.js.map +1 -1
- package/dist/esm/providers/RootAppProvider.js +2 -1
- package/dist/esm/providers/RootAppProvider.js.map +1 -1
- package/dist/esm/providers/SchemaContext.js +6 -1
- package/dist/esm/providers/SchemaContext.js.map +1 -1
- package/dist/esm/providers/index.js +1 -0
- package/dist/esm/providers/index.js.map +1 -1
- package/dist/esm/types/CollectionPageConfig.js.map +1 -1
- package/dist/esm/types/actions/collectionPageActions.js.map +1 -1
- package/dist/esm/types/types.js.map +1 -1
- package/dist/types/components/AutoPatternsTable/AutoPatternsTable.d.ts.map +1 -1
- package/dist/types/hooks/useTableFeatures.d.ts +6 -0
- package/dist/types/hooks/useTableFeatures.d.ts.map +1 -1
- package/dist/types/providers/ErrorContext.d.ts +11 -0
- package/dist/types/providers/ErrorContext.d.ts.map +1 -0
- package/dist/types/providers/PatternsWizardOverridesContext.d.ts +2 -0
- package/dist/types/providers/PatternsWizardOverridesContext.d.ts.map +1 -1
- package/dist/types/providers/RootAppProvider.d.ts.map +1 -1
- package/dist/types/providers/SchemaContext.d.ts.map +1 -1
- package/dist/types/providers/index.d.ts +1 -0
- package/dist/types/providers/index.d.ts.map +1 -1
- package/dist/types/types/CollectionPageConfig.d.ts +3 -0
- package/dist/types/types/CollectionPageConfig.d.ts.map +1 -1
- package/dist/types/types/actions/collectionPageActions.d.ts +7 -0
- package/dist/types/types/actions/collectionPageActions.d.ts.map +1 -1
- package/dist/types/types/types.d.ts +1 -5
- package/dist/types/types/types.d.ts.map +1 -1
- package/package.json +9 -9
|
@@ -38,7 +38,7 @@ This document serves as a comprehensive guide for AI agents to correctly generat
|
|
|
38
38
|
|
|
39
39
|
* Pages array MUST contain exactly two pages.
|
|
40
40
|
* Components array inside collectionPage MUST contain exactly one component with a layout array.
|
|
41
|
-
* Configuration MUST come only from a
|
|
41
|
+
* Configuration MUST come only from a TypeScript file.
|
|
42
42
|
* DO NOT fill optional fields unless explicitly requested.
|
|
43
43
|
* Select up to 3 columns initially that best represent the entity.
|
|
44
44
|
* Every collection page MUST include a create action that allows users to create new entities by navigating to the entity page.
|
|
@@ -71,7 +71,8 @@ This guide instructs on how to correctly integrate the `AutoPatternsApp` compone
|
|
|
71
71
|
# Component Purpose
|
|
72
72
|
|
|
73
73
|
The `AutoPatternsApp` is a page-level component used to display a data collection either as a Table or Grid.
|
|
74
|
-
It is configured using a
|
|
74
|
+
It is configured using a TypeScript file conforming to the `AppConfig` interface and supports overrides for advanced use-cases.
|
|
75
|
+
|
|
75
76
|
|
|
76
77
|
---
|
|
77
78
|
|
|
@@ -79,7 +80,8 @@ It is configured using a JSON file conforming to the `AppConfig` interface and s
|
|
|
79
80
|
|
|
80
81
|
## ⚠️ Configuration Rules
|
|
81
82
|
|
|
82
|
-
- **Configuration must come only from a
|
|
83
|
+
- **Configuration must come only from a TypeScript file** - never inline or from other sources
|
|
84
|
+
- **Always use proper TypeScript typing**: `export const config: AppConfig = { ... }`
|
|
83
85
|
- **DO NOT fill optional fields unless explicitly requested** - leave optional properties undefined to avoid unnecessary complexity
|
|
84
86
|
- **After each configuration change, verify that the configuration strictly aligns with the structure described below** - any configuration entries not defined in this structure must be removed
|
|
85
87
|
- **When generating config for the first time, select up to 3 columns from the schema that best represent the entity**
|
|
@@ -751,7 +753,7 @@ Custom collection page actions execute JavaScript code that you define for colle
|
|
|
751
753
|
├── page.tsx
|
|
752
754
|
└── components/
|
|
753
755
|
└── actions/
|
|
754
|
-
├── index.tsx // Exports
|
|
756
|
+
├── index.tsx // Exports useActions hook
|
|
755
757
|
└── exportCollection.tsx // Your custom collection action
|
|
756
758
|
```
|
|
757
759
|
|
|
@@ -798,10 +800,17 @@ Custom collection page actions execute JavaScript code that you define for colle
|
|
|
798
800
|
|
|
799
801
|
3. Export your action in `actions/index.tsx`:
|
|
800
802
|
```typescript
|
|
801
|
-
|
|
803
|
+
import { exportCollection } from './exportCollection';
|
|
804
|
+
|
|
805
|
+
export const useActions = () => {
|
|
806
|
+
// You can access React context and other hooks here
|
|
807
|
+
return {
|
|
808
|
+
exportCollection
|
|
809
|
+
};
|
|
810
|
+
};
|
|
802
811
|
```
|
|
803
812
|
|
|
804
|
-
4. Configure the action in your
|
|
813
|
+
4. Configure the action in your TypeScript configuration:
|
|
805
814
|
```json
|
|
806
815
|
{
|
|
807
816
|
"id": "exportCollection", // MUST match the function name exactly
|
|
@@ -816,11 +825,17 @@ Custom collection page actions execute JavaScript code that you define for colle
|
|
|
816
825
|
|
|
817
826
|
5. Register your action in the `PatternsWizardOverridesProvider`:
|
|
818
827
|
```typescript
|
|
819
|
-
import
|
|
828
|
+
import { useActions } from '../components/actions';
|
|
829
|
+
|
|
830
|
+
export default function YourPage() {
|
|
831
|
+
const actions = useActions();
|
|
820
832
|
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
833
|
+
return (
|
|
834
|
+
<PatternsWizardOverridesProvider value={{ actions }}>
|
|
835
|
+
<AutoPatternsApp configuration={config} />
|
|
836
|
+
</PatternsWizardOverridesProvider>
|
|
837
|
+
);
|
|
838
|
+
}
|
|
824
839
|
```
|
|
825
840
|
|
|
826
841
|
## Key Points for Custom Collection Page Actions:
|
|
@@ -860,7 +875,7 @@ Row click actions are configured at the table level using the `onRowClick` prope
|
|
|
860
875
|
|
|
861
876
|
### Implementation Requirements
|
|
862
877
|
|
|
863
|
-
⚠️ **CRITICAL**: When you configure `onRowClick` in your
|
|
878
|
+
⚠️ **CRITICAL**: When you configure `onRowClick` in your TypeScript configuration, you MUST provide a complete working implementation. The Auto Patterns framework cannot function without it.
|
|
864
879
|
|
|
865
880
|
Custom row click actions use the `CustomActionCollectionPageActionOnRowClickResolver` type and MUST return a `ResolvedAction` object with all required properties:
|
|
866
881
|
|
|
@@ -938,7 +953,18 @@ export const openSidePanel: CustomActionCollectionPageActionOnRowClickResolver =
|
|
|
938
953
|
};
|
|
939
954
|
```
|
|
940
955
|
|
|
941
|
-
**Step 2:
|
|
956
|
+
**Step 2: Export your action in `actions/index.tsx`**:
|
|
957
|
+
```typescript
|
|
958
|
+
import { openSidePanel } from './openSidePanel';
|
|
959
|
+
|
|
960
|
+
export const useActions = () => {
|
|
961
|
+
return {
|
|
962
|
+
openSidePanel
|
|
963
|
+
};
|
|
964
|
+
};
|
|
965
|
+
```
|
|
966
|
+
|
|
967
|
+
**Step 3: Configure in TypeScript**:
|
|
942
968
|
```json
|
|
943
969
|
{
|
|
944
970
|
"type": "Table",
|
|
@@ -952,17 +978,19 @@ export const openSidePanel: CustomActionCollectionPageActionOnRowClickResolver =
|
|
|
952
978
|
}
|
|
953
979
|
```
|
|
954
980
|
|
|
955
|
-
**Step
|
|
981
|
+
**Step 4: Register in `PatternsWizardOverridesProvider`**:
|
|
956
982
|
```typescript
|
|
957
|
-
|
|
958
|
-
export * from './openSidePanel';
|
|
983
|
+
import { useActions } from '../components/actions';
|
|
959
984
|
|
|
960
|
-
|
|
961
|
-
|
|
985
|
+
export default function YourPage() {
|
|
986
|
+
const actions = useActions();
|
|
962
987
|
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
988
|
+
return (
|
|
989
|
+
<PatternsWizardOverridesProvider value={{ actions }}>
|
|
990
|
+
<AutoPatternsApp configuration={config} />
|
|
991
|
+
</PatternsWizardOverridesProvider>
|
|
992
|
+
);
|
|
993
|
+
}
|
|
966
994
|
```
|
|
967
995
|
|
|
968
996
|
#### 2. Direct Data Manipulation
|
|
@@ -1009,7 +1037,7 @@ export const quickToggle: CustomActionCollectionPageActionOnRowClickResolver = (
|
|
|
1009
1037
|
- You can still navigate to the entity page programmatically if needed using the SDK navigation utilities
|
|
1010
1038
|
|
|
1011
1039
|
### Key Points for Custom Row Click Actions:
|
|
1012
|
-
- **MANDATORY IMPLEMENTATION**: If you configure `onRowClick` in
|
|
1040
|
+
- **MANDATORY IMPLEMENTATION**: If you configure `onRowClick` in TypeScript configuration, you MUST provide a complete working implementation - the framework cannot function without it
|
|
1013
1041
|
- The action `id` in the configuration MUST exactly match the function name exported from your actions folder
|
|
1014
1042
|
- The implementation must use the `CustomActionCollectionPageActionOnRowClickResolver` type
|
|
1015
1043
|
- **Required Return Object**: Must return an object with `label`, `icon`, and `onClick` properties - all are required
|
|
@@ -1417,7 +1445,7 @@ Custom actions execute JavaScript code that you define. These actions receive pa
|
|
|
1417
1445
|
├── page.tsx
|
|
1418
1446
|
└── components/
|
|
1419
1447
|
└── actions/
|
|
1420
|
-
├── index.tsx // Exports
|
|
1448
|
+
├── index.tsx // Exports useActions hook
|
|
1421
1449
|
└── downloadPetDetails.tsx // Your custom action (name = action id)
|
|
1422
1450
|
```
|
|
1423
1451
|
|
|
@@ -1460,12 +1488,19 @@ Custom actions execute JavaScript code that you define. These actions receive pa
|
|
|
1460
1488
|
|
|
1461
1489
|
3. Export your action in `actions/index.tsx`:
|
|
1462
1490
|
```typescript
|
|
1463
|
-
|
|
1491
|
+
import { downloadPetDetails } from './downloadPetDetails';
|
|
1492
|
+
|
|
1493
|
+
export const useActions = () => {
|
|
1494
|
+
// You can access React context and other hooks here
|
|
1495
|
+
return {
|
|
1496
|
+
downloadPetDetails
|
|
1497
|
+
};
|
|
1498
|
+
};
|
|
1464
1499
|
```
|
|
1465
1500
|
|
|
1466
|
-
**Important:** Every time you create a new action, you must
|
|
1501
|
+
**Important:** Every time you create a new action, you must import it and add it to the `useActions` hook return object in this `index.tsx` file. For example, if you create `sendEmail.tsx`, you must add `import { sendEmail } from './sendEmail';` and include `sendEmail` in the return object.
|
|
1467
1502
|
|
|
1468
|
-
4. Configure the action in your
|
|
1503
|
+
4. Configure the action in your TypeScript configuration:
|
|
1469
1504
|
```ts
|
|
1470
1505
|
{
|
|
1471
1506
|
"id": "downloadPetDetails", // MUST match the function name exactly
|
|
@@ -1476,11 +1511,17 @@ Custom actions execute JavaScript code that you define. These actions receive pa
|
|
|
1476
1511
|
|
|
1477
1512
|
5. Register your action in the `PatternsWizardOverridesProvider`:
|
|
1478
1513
|
```typescript
|
|
1479
|
-
import
|
|
1514
|
+
import { useActions } from '../components/actions';
|
|
1480
1515
|
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1516
|
+
export default function YourPage() {
|
|
1517
|
+
const actions = useActions();
|
|
1518
|
+
|
|
1519
|
+
return (
|
|
1520
|
+
<PatternsWizardOverridesProvider value={{ actions }}>
|
|
1521
|
+
<AutoPatternsApp configuration={config} />
|
|
1522
|
+
</PatternsWizardOverridesProvider>
|
|
1523
|
+
);
|
|
1524
|
+
}
|
|
1484
1525
|
```
|
|
1485
1526
|
|
|
1486
1527
|
### Key Points for Custom Actions:
|
|
@@ -1613,7 +1654,7 @@ Custom bulk actions execute JavaScript code that you define for bulk operations.
|
|
|
1613
1654
|
├── page.tsx
|
|
1614
1655
|
└── components/
|
|
1615
1656
|
└── actions/
|
|
1616
|
-
├── index.tsx // Exports
|
|
1657
|
+
├── index.tsx // Exports useActions hook
|
|
1617
1658
|
└── bulkExportPets.tsx // Your custom bulk action
|
|
1618
1659
|
```
|
|
1619
1660
|
|
|
@@ -1675,10 +1716,17 @@ Custom bulk actions execute JavaScript code that you define for bulk operations.
|
|
|
1675
1716
|
|
|
1676
1717
|
3. Export your action in `actions/index.tsx`:
|
|
1677
1718
|
```typescript
|
|
1678
|
-
|
|
1719
|
+
import { bulkExportPets } from './bulkExportPets';
|
|
1720
|
+
|
|
1721
|
+
export const useActions = () => {
|
|
1722
|
+
// You can access React context and other hooks here
|
|
1723
|
+
return {
|
|
1724
|
+
bulkExportPets
|
|
1725
|
+
};
|
|
1726
|
+
};
|
|
1679
1727
|
```
|
|
1680
1728
|
|
|
1681
|
-
4. Configure the action in your
|
|
1729
|
+
4. Configure the action in your TypeScript configuration:
|
|
1682
1730
|
```json
|
|
1683
1731
|
{
|
|
1684
1732
|
"id": "bulkExportPets", // MUST match the function name exactly
|
|
@@ -1689,11 +1737,17 @@ Custom bulk actions execute JavaScript code that you define for bulk operations.
|
|
|
1689
1737
|
|
|
1690
1738
|
5. Register your action in the `PatternsWizardOverridesProvider`:
|
|
1691
1739
|
```typescript
|
|
1692
|
-
import
|
|
1740
|
+
import { useActions } from '../components/actions';
|
|
1693
1741
|
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1742
|
+
export default function YourPage() {
|
|
1743
|
+
const actions = useActions();
|
|
1744
|
+
|
|
1745
|
+
return (
|
|
1746
|
+
<PatternsWizardOverridesProvider value={{ actions }}>
|
|
1747
|
+
<AutoPatternsApp configuration={config} />
|
|
1748
|
+
</PatternsWizardOverridesProvider>
|
|
1749
|
+
);
|
|
1750
|
+
}
|
|
1697
1751
|
```
|
|
1698
1752
|
|
|
1699
1753
|
### Key Points for Custom Bulk Actions:
|
|
@@ -2037,18 +2091,18 @@ npm install @wix/auto-patterns @wix/patterns @wix/design-system
|
|
|
2037
2091
|
- **Import `AutoPatternsApp` only from `@wix/auto-patterns`** - never from other packages
|
|
2038
2092
|
- **CRITICAL:** Always import `AppConfig` as a type import: `import type { AppConfig } from '@wix/auto-patterns/types'` - never import it as a value import
|
|
2039
2093
|
|
|
2040
|
-
## 2. Create AppConfig
|
|
2094
|
+
## 2. Create AppConfig TypeScript File
|
|
2041
2095
|
|
|
2042
|
-
Save this configuration as a `{collectionName}Config.patterns.
|
|
2096
|
+
Save this configuration as a `{collectionName}Config.patterns.ts` file in the same directory as your page.tsx component.
|
|
2043
2097
|
|
|
2044
2098
|
For example:
|
|
2045
|
-
- For a "WixPets" collection: `petsConfig.patterns.
|
|
2046
|
-
- For a "Products" collection: `productsConfig.patterns.
|
|
2047
|
-
- For a "Users" collection: `usersConfig.patterns.
|
|
2099
|
+
- For a "WixPets" collection: `petsConfig.patterns.ts`
|
|
2100
|
+
- For a "Products" collection: `productsConfig.patterns.ts`
|
|
2101
|
+
- For a "Users" collection: `usersConfig.patterns.ts`
|
|
2048
2102
|
|
|
2049
2103
|
## Render the Collection Page Component
|
|
2050
2104
|
|
|
2051
|
-
Inside your page component, import the
|
|
2105
|
+
Inside your page component, import the TypeScript configuration and use the `AutoPatternsApp` component. Since this is a page-level component, it should be the only component rendered on the page. Any other content or components should be removed to ensure proper functionality and avoid conflicts.
|
|
2052
2106
|
|
|
2053
2107
|
### Page Component Example:
|
|
2054
2108
|
|
|
@@ -2058,17 +2112,16 @@ import { WixDesignSystemProvider } from '@wix/design-system';
|
|
|
2058
2112
|
import '@wix/design-system/styles.global.css';
|
|
2059
2113
|
import { WixPatternsProvider } from '@wix/patterns/provider';
|
|
2060
2114
|
import { PatternsWizardOverridesProvider, AutoPatternsApp } from '@wix/auto-patterns';
|
|
2061
|
-
import type { AppConfig } from '@wix/auto-patterns/types';
|
|
2062
2115
|
import { withDashboard } from '@wix/patterns';
|
|
2063
2116
|
|
|
2064
|
-
import config from './MyCollectionConfig.patterns
|
|
2117
|
+
import { config } from './MyCollectionConfig.patterns';
|
|
2065
2118
|
|
|
2066
2119
|
const Index: FC = () => {
|
|
2067
2120
|
return (
|
|
2068
2121
|
<WixDesignSystemProvider features={{ newColorsBranding: true }}>
|
|
2069
2122
|
<WixPatternsProvider>
|
|
2070
2123
|
<PatternsWizardOverridesProvider value={{ }}>
|
|
2071
|
-
<AutoPatternsApp configuration={config
|
|
2124
|
+
<AutoPatternsApp configuration={config} />
|
|
2072
2125
|
</PatternsWizardOverridesProvider>
|
|
2073
2126
|
</WixPatternsProvider>
|
|
2074
2127
|
</WixDesignSystemProvider>
|
|
@@ -2093,67 +2146,91 @@ The `PatternsWizardOverridesProvider` allows you to inject custom code to overri
|
|
|
2093
2146
|
|
|
2094
2147
|
## Folder Structure Organization
|
|
2095
2148
|
|
|
2096
|
-
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.
|
|
2149
|
+
All custom overrides (components, modals, actions, columns, sections, 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.
|
|
2097
2150
|
|
|
2098
2151
|
### Recommended Structure:
|
|
2099
2152
|
|
|
2100
2153
|
```
|
|
2101
2154
|
your-page/
|
|
2102
2155
|
├── page.tsx // Your main page component
|
|
2103
|
-
├── MyCollectionConfig.patterns.
|
|
2156
|
+
├── MyCollectionConfig.patterns.ts // Configuration file
|
|
2104
2157
|
└── components/ // Page-specific components folder
|
|
2105
|
-
├── index.tsx // Exports all
|
|
2158
|
+
├── index.tsx // Exports all override hooks for easy importing
|
|
2106
2159
|
├── actions/ // Custom actions
|
|
2107
|
-
│ ├── index.tsx
|
|
2160
|
+
│ ├── index.tsx // Exports useActions hook
|
|
2108
2161
|
│ └── myCustomAction.tsx
|
|
2109
2162
|
├── columns/ // Column overrides
|
|
2110
|
-
│ ├── index.tsx
|
|
2163
|
+
│ ├── index.tsx // Exports useColumns hook
|
|
2111
2164
|
│ ├── name.ts
|
|
2112
2165
|
│ └── date.ts
|
|
2113
2166
|
├── customComponents/ // Custom entity page components
|
|
2114
|
-
│ ├── index.tsx
|
|
2167
|
+
│ ├── index.tsx // Exports useComponents hook
|
|
2115
2168
|
│ ├── CustomNameField.tsx
|
|
2116
2169
|
│ └── InfoCard.tsx
|
|
2170
|
+
├── modals/ // Custom modals
|
|
2171
|
+
│ ├── index.tsx // Exports useModals hook
|
|
2172
|
+
│ └── myCustomModal.tsx
|
|
2117
2173
|
└── customDataSources/ // Custom data sources
|
|
2174
|
+
│ ├── index.tsx // Exports useCustomDataSources hook
|
|
2175
|
+
│ └── myCustomDataSource.ts
|
|
2176
|
+
├── sections/ // Section renderers
|
|
2177
|
+
│ ├── index.tsx
|
|
2178
|
+
│ └── groupByType.ts
|
|
2179
|
+
└── customComponents/ // Custom entity page components
|
|
2118
2180
|
├── index.tsx
|
|
2119
|
-
|
|
2181
|
+
├── CustomNameField.tsx
|
|
2182
|
+
└── InfoCard.tsx
|
|
2120
2183
|
```
|
|
2121
2184
|
|
|
2122
|
-
###
|
|
2185
|
+
### Using Override Hooks in Your Page
|
|
2123
2186
|
|
|
2124
|
-
In your page component,
|
|
2187
|
+
In your page component, use the hook-based approach to access React context and other hooks:
|
|
2125
2188
|
|
|
2126
2189
|
```tsx
|
|
2127
|
-
import
|
|
2128
|
-
import
|
|
2129
|
-
import
|
|
2130
|
-
import
|
|
2131
|
-
import
|
|
2190
|
+
import { useActions } from '../components/actions';
|
|
2191
|
+
import { useColumns } from '../components/columns';
|
|
2192
|
+
import { useSections } from '../components/sections';
|
|
2193
|
+
import { useComponents } from '../components/customComponents';
|
|
2194
|
+
import { useModals } from '../components/modals';
|
|
2195
|
+
import { useCustomDataSources } from '../components/customDataSources';
|
|
2196
|
+
|
|
2197
|
+
export default function YourPage() {
|
|
2198
|
+
const actions = useActions();
|
|
2199
|
+
const columns = useColumns();
|
|
2200
|
+
const sections = useSections();
|
|
2201
|
+
const components = useComponents();
|
|
2202
|
+
const modals = useModals();
|
|
2203
|
+
const customDataSources = useCustomDataSources();
|
|
2132
2204
|
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2205
|
+
return (
|
|
2206
|
+
<PatternsWizardOverridesProvider value={{ actions, columns, sections, components, modals, customDataSources }}>
|
|
2207
|
+
<AutoPatternsApp configuration={config} />
|
|
2208
|
+
</PatternsWizardOverridesProvider>
|
|
2209
|
+
);
|
|
2210
|
+
}
|
|
2136
2211
|
```
|
|
2137
2212
|
|
|
2138
|
-
### Important: Updating Index Files
|
|
2213
|
+
### Important: Updating Hook Index Files
|
|
2139
2214
|
|
|
2140
|
-
**When adding any new implementation (action, modal, column, or component), you MUST update the corresponding `index.tsx` file to
|
|
2215
|
+
**When adding any new implementation (action, modal, column, section or component), you MUST update the corresponding hook in the `index.tsx` file to include your new implementation.** The main page component uses these hooks, so they serve as the central export point for each type of override.
|
|
2141
2216
|
|
|
2142
2217
|
For example:
|
|
2143
|
-
- Adding a new action → Update
|
|
2144
|
-
- Adding a new modal → Update
|
|
2145
|
-
- Adding a new column override → Update
|
|
2146
|
-
- Adding a new
|
|
2147
|
-
- Adding a new custom
|
|
2218
|
+
- Adding a new action → Update `../components/actions/index.tsx` to include the new action in the `useActions` hook
|
|
2219
|
+
- Adding a new modal → Update `../components/modals/index.tsx` to include the new modal in the `useModals` hook
|
|
2220
|
+
- Adding a new column override → Update `../components/columns/index.tsx` to include the new column in the `useColumns` hook
|
|
2221
|
+
- Adding a new section renderer → Update `../components/sections/index.tsx` to include the new section in the `useSections` hook
|
|
2222
|
+
- Adding a new custom component → Update `../components/customComponents/index.tsx` to include the new component in the `useComponents` hook
|
|
2223
|
+
- Adding a new custom data source → Update `../components/customDataSources/index.tsx` to include the new data source in the `useCustomDataSources` hook
|
|
2148
2224
|
|
|
2149
|
-
Without updating the index files, your implementations won't be available to the `PatternsWizardOverridesProvider`.
|
|
2225
|
+
Without updating the hook index files, your implementations won't be available to the `PatternsWizardOverridesProvider`.
|
|
2150
2226
|
|
|
2151
2227
|
## ⚠️ Common Override Mistakes to Avoid
|
|
2152
2228
|
|
|
2153
2229
|
- Attempting to override unsupported areas
|
|
2154
2230
|
- Invalid column rendering functions
|
|
2155
|
-
- Missing index file exports for new implementations
|
|
2231
|
+
- Missing hook index file exports for new implementations
|
|
2156
2232
|
- Incorrect import paths or naming mismatches
|
|
2233
|
+
- Forgetting to import and use the hook in the main page component
|
|
2157
2234
|
|
|
2158
2235
|
## Columns
|
|
2159
2236
|
|
|
@@ -2292,23 +2369,40 @@ export function date({ value, row }) {
|
|
|
2292
2369
|
In `components/columns/index.tsx`:
|
|
2293
2370
|
|
|
2294
2371
|
```ts
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2372
|
+
import { name } from './name';
|
|
2373
|
+
import { petInfo } from './petInfo';
|
|
2374
|
+
import { status } from './status';
|
|
2375
|
+
import { fullName } from './fullName';
|
|
2376
|
+
import { date } from './date';
|
|
2377
|
+
|
|
2378
|
+
export const useColumns = () => {
|
|
2379
|
+
// You can access React context and other hooks here
|
|
2380
|
+
return {
|
|
2381
|
+
name,
|
|
2382
|
+
petInfo,
|
|
2383
|
+
status,
|
|
2384
|
+
fullName,
|
|
2385
|
+
date
|
|
2386
|
+
};
|
|
2387
|
+
};
|
|
2300
2388
|
```
|
|
2301
2389
|
|
|
2302
|
-
**Important:** Every time you add a new column override file, you must
|
|
2390
|
+
**Important:** Every time you add a new column override file, you must import it and add it to the `useColumns` hook return object in this `index.tsx` file. For example, if you create `price.tsx`, you must add `import { price } from './price';` and include `price` in the return object.
|
|
2303
2391
|
|
|
2304
|
-
In the
|
|
2392
|
+
In the main page component:
|
|
2305
2393
|
|
|
2306
2394
|
```tsx
|
|
2307
|
-
import
|
|
2395
|
+
import { useColumns } from '../components/columns';
|
|
2308
2396
|
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2397
|
+
export default function YourPage() {
|
|
2398
|
+
const columns = useColumns();
|
|
2399
|
+
|
|
2400
|
+
return (
|
|
2401
|
+
<PatternsWizardOverridesProvider value={{ columns }}>
|
|
2402
|
+
<AutoPatternsApp configuration={config} />
|
|
2403
|
+
</PatternsWizardOverridesProvider>
|
|
2404
|
+
);
|
|
2405
|
+
}
|
|
2312
2406
|
```
|
|
2313
2407
|
|
|
2314
2408
|
### Visual Representation
|
|
@@ -2317,7 +2411,7 @@ import * as columns from './components/columns';
|
|
|
2317
2411
|
your-page/
|
|
2318
2412
|
└── components/
|
|
2319
2413
|
└── columns/
|
|
2320
|
-
├── index.tsx // Exports
|
|
2414
|
+
├── index.tsx // Exports useColumns hook
|
|
2321
2415
|
├── name.tsx // Simple value formatting
|
|
2322
2416
|
├── petInfo.tsx // Complex multi-field column
|
|
2323
2417
|
├── status.tsx // Conditional rendering column
|
|
@@ -2325,7 +2419,7 @@ your-page/
|
|
|
2325
2419
|
└── date.tsx // Enhanced formatting with row context
|
|
2326
2420
|
|
|
2327
2421
|
PatternsWizardOverridesProvider
|
|
2328
|
-
└── value.columns
|
|
2422
|
+
└── value.columns (from useColumns hook)
|
|
2329
2423
|
├── name
|
|
2330
2424
|
├── petInfo
|
|
2331
2425
|
├── status
|
|
@@ -2453,16 +2547,37 @@ export const infoCard: FC<CustomComponentProps> = ({ entity }) => {
|
|
|
2453
2547
|
};
|
|
2454
2548
|
```
|
|
2455
2549
|
|
|
2456
|
-
### Connecting Components
|
|
2550
|
+
### Connecting Components with Hooks
|
|
2457
2551
|
|
|
2458
|
-
In
|
|
2552
|
+
In `components/customComponents/index.tsx`:
|
|
2459
2553
|
|
|
2460
2554
|
```tsx
|
|
2461
|
-
import
|
|
2555
|
+
import { customNameField } from './customNameField';
|
|
2556
|
+
import { infoCard } from './infoCard';
|
|
2462
2557
|
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2558
|
+
export const useComponents = () => {
|
|
2559
|
+
// You can access React context and other hooks here
|
|
2560
|
+
return {
|
|
2561
|
+
customNameField,
|
|
2562
|
+
infoCard
|
|
2563
|
+
};
|
|
2564
|
+
};
|
|
2565
|
+
```
|
|
2566
|
+
|
|
2567
|
+
In your main page file:
|
|
2568
|
+
|
|
2569
|
+
```tsx
|
|
2570
|
+
import { useComponents } from '../components/customComponents';
|
|
2571
|
+
|
|
2572
|
+
export default function YourPage() {
|
|
2573
|
+
const components = useComponents();
|
|
2574
|
+
|
|
2575
|
+
return (
|
|
2576
|
+
<PatternsWizardOverridesProvider value={{ components }}>
|
|
2577
|
+
<AutoPatternsApp configuration={config} />
|
|
2578
|
+
</PatternsWizardOverridesProvider>
|
|
2579
|
+
);
|
|
2580
|
+
}
|
|
2466
2581
|
```
|
|
2467
2582
|
|
|
2468
2583
|
### Important Guidelines for Custom Components
|
|
@@ -2482,7 +2597,7 @@ import * as components from './components';
|
|
|
2482
2597
|
- For dates: `DatePicker`
|
|
2483
2598
|
- For dropdowns: `Dropdown`
|
|
2484
2599
|
|
|
2485
|
-
**Important:** Every time you create a new custom component, you must
|
|
2600
|
+
**Important:** Every time you create a new custom component, you must import it and add it to the `useComponents` hook return object in the `./components/customComponents/index.tsx` file. For example, if you create `StatusIndicator.tsx`, you must add `import { StatusIndicator } from './StatusIndicator';` and include `StatusIndicator` in the return object.
|
|
2486
2601
|
|
|
2487
2602
|
### Understanding Reactivity in Custom Components
|
|
2488
2603
|
|
|
@@ -2583,13 +2698,14 @@ const CustomComponent: FC<CustomComponentProps> = ({ form, entity }) => {
|
|
|
2583
2698
|
```
|
|
2584
2699
|
your-page/
|
|
2585
2700
|
└── components/
|
|
2586
|
-
├──
|
|
2587
|
-
├──
|
|
2588
|
-
├──
|
|
2589
|
-
|
|
2701
|
+
├── customComponents/
|
|
2702
|
+
│ ├── index.tsx // Exports useComponents hook
|
|
2703
|
+
│ ├── customNameField.tsx // Field override component
|
|
2704
|
+
│ ├── combinedNameFields.tsx // Multiple fields override
|
|
2705
|
+
│ └── infoCard.tsx // Standalone component
|
|
2590
2706
|
|
|
2591
2707
|
PatternsWizardOverridesProvider
|
|
2592
|
-
└── value.components
|
|
2708
|
+
└── value.components (from useComponents hook)
|
|
2593
2709
|
├── customNameField
|
|
2594
2710
|
├── combinedNameFields
|
|
2595
2711
|
└── infoCard
|
|
@@ -2616,25 +2732,62 @@ When implementing a custom data source, you need to modify the `collection` conf
|
|
|
2616
2732
|
}
|
|
2617
2733
|
}
|
|
2618
2734
|
```
|
|
2735
|
+
## Sections
|
|
2736
|
+
|
|
2737
|
+
Sections allow you to group table rows under section headers, making it easier to organize and navigate through large datasets. This feature is especially useful when you want to categorize entities by specific criteria.
|
|
2738
|
+
|
|
2739
|
+
The sections feature supports both Table and TableGridSwitch components. When enabled, the table will render section headers that group related rows together.
|
|
2740
|
+
|
|
2741
|
+
### Configuring Sections
|
|
2742
|
+
|
|
2743
|
+
To enable sections, add the `sections` configuration to your table configuration:
|
|
2744
|
+
|
|
2745
|
+
```json
|
|
2746
|
+
{
|
|
2747
|
+
"type": "collectionPage",
|
|
2748
|
+
"collectionPage": {
|
|
2749
|
+
"components": [
|
|
2750
|
+
{
|
|
2751
|
+
"collection": {
|
|
2752
|
+
"collectionId": "WixPets"
|
|
2753
|
+
},
|
|
2754
|
+
"layout": [
|
|
2755
|
+
{
|
|
2756
|
+
"type": "Table",
|
|
2757
|
+
"table": {
|
|
2758
|
+
"columns": [...],
|
|
2759
|
+
"sections": {
|
|
2760
|
+
"id": "groupByType"
|
|
2761
|
+
}
|
|
2762
|
+
}
|
|
2763
|
+
}
|
|
2764
|
+
]
|
|
2765
|
+
}
|
|
2766
|
+
]
|
|
2767
|
+
}
|
|
2768
|
+
}
|
|
2769
|
+
```
|
|
2619
2770
|
|
|
2620
2771
|
**Key Properties:**
|
|
2621
2772
|
- `entityTypeSource`: Must be set to `"custom"` instead of `"cms"`
|
|
2622
2773
|
- `custom.id`: A unique identifier for your custom data source implementation
|
|
2623
2774
|
|
|
2624
|
-
### Custom Data Source
|
|
2775
|
+
### Custom Data Source Hook Structure
|
|
2625
2776
|
|
|
2626
|
-
Custom data sources are implemented through the `
|
|
2777
|
+
Custom data sources are implemented through the `useCustomDataSources` hook in your `PatternsWizardOverridesProvider`:
|
|
2627
2778
|
|
|
2628
2779
|
```tsx
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
}}>
|
|
2636
|
-
|
|
2637
|
-
</PatternsWizardOverridesProvider>
|
|
2780
|
+
import { useCustomDataSources } from '../components/customDataSources';
|
|
2781
|
+
|
|
2782
|
+
export default function YourPage() {
|
|
2783
|
+
const customDataSources = useCustomDataSources();
|
|
2784
|
+
|
|
2785
|
+
return (
|
|
2786
|
+
<PatternsWizardOverridesProvider value={{ customDataSources }}>
|
|
2787
|
+
<AutoPatternsApp configuration={config} />
|
|
2788
|
+
</PatternsWizardOverridesProvider>
|
|
2789
|
+
);
|
|
2790
|
+
}
|
|
2638
2791
|
```
|
|
2639
2792
|
|
|
2640
2793
|
### Implementation Components
|
|
@@ -2678,6 +2831,21 @@ export const myCustomDataSource = async (collectionId: string, context: any) =>
|
|
|
2678
2831
|
};
|
|
2679
2832
|
```
|
|
2680
2833
|
|
|
2834
|
+
### Hook Implementation
|
|
2835
|
+
|
|
2836
|
+
In `components/customDataSources/index.tsx`:
|
|
2837
|
+
|
|
2838
|
+
```tsx
|
|
2839
|
+
import { myCustomDataSource } from './myCustomDataSource';
|
|
2840
|
+
|
|
2841
|
+
export const useCustomDataSources = () => {
|
|
2842
|
+
// You can access React context and other hooks here
|
|
2843
|
+
return {
|
|
2844
|
+
myCustomDataSource
|
|
2845
|
+
};
|
|
2846
|
+
};
|
|
2847
|
+
```
|
|
2848
|
+
|
|
2681
2849
|
### Field Type Mapping
|
|
2682
2850
|
|
|
2683
2851
|
When implementing custom data sources, you need to map your data source field types to AutoPatterns field types:
|
|
@@ -2723,32 +2891,164 @@ actions: {
|
|
|
2723
2891
|
```
|
|
2724
2892
|
your-page/
|
|
2725
2893
|
├── page.tsx // Your main page component
|
|
2726
|
-
├── MyCollectionConfig.patterns.
|
|
2894
|
+
├── MyCollectionConfig.patterns.ts // Configuration file
|
|
2727
2895
|
└── components/ // Page-specific components folder
|
|
2728
|
-
├── index.tsx // Exports all
|
|
2896
|
+
├── index.tsx // Exports all override hooks for easy importing
|
|
2729
2897
|
├── customDataSources/ // Custom data sources
|
|
2730
|
-
│ ├── index.tsx
|
|
2898
|
+
│ ├── index.tsx // Exports useCustomDataSources hook
|
|
2731
2899
|
│ └── myCustomDataSource.ts
|
|
2732
2900
|
├── actions/ // Custom actions
|
|
2733
|
-
│ ├── index.tsx
|
|
2901
|
+
│ ├── index.tsx // Exports useActions hook
|
|
2734
2902
|
│ └── myCustomAction.tsx
|
|
2735
2903
|
└── columns/ // Column overrides
|
|
2736
|
-
├── index.tsx
|
|
2904
|
+
├── index.tsx // Exports useColumns hook
|
|
2737
2905
|
└── myColumn.tsx
|
|
2738
2906
|
```
|
|
2739
2907
|
|
|
2740
2908
|
### Registering Custom Data Sources
|
|
2741
2909
|
|
|
2742
|
-
In your page component,
|
|
2910
|
+
In your page component, use the hook to access React context and other hooks:
|
|
2911
|
+
|
|
2912
|
+
```tsx
|
|
2913
|
+
import { useCustomDataSources } from '../components/customDataSources';
|
|
2914
|
+
|
|
2915
|
+
export default function YourPage() {
|
|
2916
|
+
const customDataSources = useCustomDataSources();
|
|
2917
|
+
|
|
2918
|
+
return (
|
|
2919
|
+
<PatternsWizardOverridesProvider value={{ customDataSources }}>
|
|
2920
|
+
<AutoPatternsApp configuration={config} />
|
|
2921
|
+
</PatternsWizardOverridesProvider>
|
|
2922
|
+
);
|
|
2923
|
+
}
|
|
2924
|
+
```
|
|
2925
|
+
|
|
2926
|
+
**Important:** Every time you create a new custom data source, you must import it and add it to the `useCustomDataSources` hook return object in the `./components/customDataSources/index.tsx` file. For example, if you create `myDataSource.ts`, you must add `import { myDataSource } from './myDataSource';` and include `myDataSource` in the return object.
|
|
2927
|
+
|
|
2928
|
+
### Creating Section Renderers
|
|
2929
|
+
|
|
2930
|
+
Section renderers are functions that determine how to group items and what information to display in section headers. They must be provided through the `PatternsWizardOverridesProvider`.
|
|
2931
|
+
|
|
2932
|
+
#### Function Signature
|
|
2933
|
+
|
|
2934
|
+
```tsx
|
|
2935
|
+
function sectionRenderer(item: any): Section
|
|
2936
|
+
```
|
|
2937
|
+
|
|
2938
|
+
Where `Section` is the interface from @wix/patterns (re-exported from auto-patterns):
|
|
2939
|
+
|
|
2940
|
+
```tsx
|
|
2941
|
+
interface Section {
|
|
2942
|
+
id: string;
|
|
2943
|
+
title: string;
|
|
2944
|
+
primaryAction?: {
|
|
2945
|
+
id: string;
|
|
2946
|
+
label: string;
|
|
2947
|
+
prefixIcon?: React.ReactElement;
|
|
2948
|
+
onClick: () => void;
|
|
2949
|
+
};
|
|
2950
|
+
}
|
|
2951
|
+
```
|
|
2952
|
+
|
|
2953
|
+
The section renderer receives an item and returns:
|
|
2954
|
+
- **id**: A unique identifier for the section (items with the same id are grouped together)
|
|
2955
|
+
- **title**: The text displayed in the section header
|
|
2956
|
+
- **primaryAction** (optional): An action button displayed in the section header
|
|
2957
|
+
|
|
2958
|
+
#### Example: Section Renderer Implementation
|
|
2959
|
+
|
|
2960
|
+
In `components/sections/groupByType.ts`:
|
|
2961
|
+
|
|
2962
|
+
```tsx
|
|
2963
|
+
import { ChevronDown } from '@wix/wix-ui-icons-common';
|
|
2964
|
+
import { Section } from '@wix/patterns';
|
|
2965
|
+
|
|
2966
|
+
// Section renderer function that returns the Section type
|
|
2967
|
+
export function groupByType(item: any): Section {
|
|
2968
|
+
const petType = item.type || 'other';
|
|
2969
|
+
|
|
2970
|
+
return {
|
|
2971
|
+
id: petType.toLowerCase(),
|
|
2972
|
+
title: `${petType.charAt(0).toUpperCase()}${petType.slice(1)}s`,
|
|
2973
|
+
primaryAction: {
|
|
2974
|
+
id: 'show-all-pets',
|
|
2975
|
+
label: 'Show All',
|
|
2976
|
+
prefixIcon: <ChevronDown />,
|
|
2977
|
+
onClick: () => {
|
|
2978
|
+
// Custom action when section header is clicked
|
|
2979
|
+
console.log(`Showing all ${petType}s`);
|
|
2980
|
+
},
|
|
2981
|
+
},
|
|
2982
|
+
};
|
|
2983
|
+
}
|
|
2984
|
+
```
|
|
2985
|
+
|
|
2986
|
+
In `components/sections/index.tsx`:
|
|
2987
|
+
|
|
2988
|
+
```tsx
|
|
2989
|
+
export * from './groupByType';
|
|
2990
|
+
```
|
|
2991
|
+
|
|
2992
|
+
#### Advanced Example: Multi-Field Grouping
|
|
2743
2993
|
|
|
2744
2994
|
```tsx
|
|
2745
|
-
import
|
|
2995
|
+
import { Badge } from '@wix/design-system';
|
|
2996
|
+
import { Section } from '@wix/patterns';
|
|
2997
|
+
|
|
2998
|
+
export function groupByAgeAndVaccination(item: any): Section {
|
|
2999
|
+
const age = item.age || 0;
|
|
3000
|
+
const isVaccinated = item.isVaccinated || false;
|
|
3001
|
+
|
|
3002
|
+
let sectionId: string;
|
|
3003
|
+
let sectionTitle: string;
|
|
3004
|
+
|
|
3005
|
+
if (age < 1) {
|
|
3006
|
+
sectionId = 'puppies';
|
|
3007
|
+
sectionTitle = 'Puppies (Under 1 year)';
|
|
3008
|
+
} else if (age >= 1 && age <= 5) {
|
|
3009
|
+
sectionId = isVaccinated ? 'young-vaccinated' : 'young-unvaccinated';
|
|
3010
|
+
sectionTitle = `Young Adults (1-5 years) - ${isVaccinated ? 'Vaccinated' : 'Not Vaccinated'}`;
|
|
3011
|
+
} else {
|
|
3012
|
+
sectionId = 'seniors';
|
|
3013
|
+
sectionTitle = 'Senior Pets (5+ years)';
|
|
3014
|
+
}
|
|
2746
3015
|
|
|
2747
|
-
|
|
3016
|
+
return {
|
|
3017
|
+
id: sectionId,
|
|
3018
|
+
title: sectionTitle,
|
|
3019
|
+
primaryAction: age < 1 ? {
|
|
3020
|
+
id: 'special-care',
|
|
3021
|
+
label: 'Special Care Info',
|
|
3022
|
+
onClick: () => {
|
|
3023
|
+
// Show special care information for puppies
|
|
3024
|
+
},
|
|
3025
|
+
} : undefined,
|
|
3026
|
+
};
|
|
3027
|
+
}
|
|
3028
|
+
```
|
|
3029
|
+
|
|
3030
|
+
### Using Sections in Your Page
|
|
3031
|
+
|
|
3032
|
+
Import and register your section renderers:
|
|
3033
|
+
|
|
3034
|
+
```tsx
|
|
3035
|
+
import * as sections from './components/sections';
|
|
3036
|
+
import * as columns from './components/columns';
|
|
3037
|
+
import * as actions from './components/actions';
|
|
3038
|
+
|
|
3039
|
+
<PatternsWizardOverridesProvider value={{ sections, columns, actions }}>
|
|
2748
3040
|
<AutoPatternsApp configuration={config as AppConfig} />
|
|
2749
3041
|
</PatternsWizardOverridesProvider>
|
|
2750
3042
|
```
|
|
2751
3043
|
|
|
2752
|
-
|
|
3044
|
+
### Important Notes
|
|
3045
|
+
|
|
3046
|
+
- **Grouping Logic**: Items are grouped by the `id` returned from the section renderer. Items with the same `id` will appear under the same section header.
|
|
3047
|
+
- **Section Order**: Sections appear in the order they first appear in the data, not alphabetically.
|
|
3048
|
+
- **Performance**: Section renderers are called for every item, so keep the logic lightweight.
|
|
3049
|
+
- **TableGridSwitch**: Sections work in both table and grid views when using TableGridSwitch.
|
|
3050
|
+
|
|
3051
|
+
|
|
3052
|
+
By implementing sections, you can significantly improve the user experience when dealing with large datasets by providing logical groupings that make information easier to find and understand.
|
|
2753
3053
|
|
|
2754
3054
|
---
|