@wix/agent-skills 1.18.1 → 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 (74) hide show
  1. package/package.json +1 -1
  2. package/skills/wix-app/SKILL.md +13 -13
  3. package/skills/wix-app/references/APP_VALIDATION.md +7 -33
  4. package/skills/wix-app/references/BACKEND_API.md +151 -152
  5. package/skills/wix-app/references/DASHBOARD_PAGE.md +18 -14
  6. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +6 -3
  7. package/skills/wix-app/references/EXTENSION_REGISTRATION.md +12 -8
  8. package/skills/wix-app/references/WIX_PATTERNS_DOCS.md +23 -26
  9. package/skills/wix-app/references/dashboard-page/COLLECTION_TOOLKIT.md +7 -6
  10. package/skills/wix-app/references/dashboard-page/ENTITY_PAGE_TOOLKIT.md +71 -4
  11. package/skills/wix-app/references/dashboard-page/PATTERNS_BUNDLE_READING.md +67 -7
  12. package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +1 -1
  13. package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +9 -6
  14. package/skills/wix-app/references/editor-react-component/COMPONENT-CONTRACT.md +59 -89
  15. package/skills/wix-app/references/editor-react-component/COMPONENT-PREVIEW.md +23 -4
  16. package/skills/wix-base44-connector/SKILL.md +168 -48
  17. package/skills/wix-base44-connector/scripts/{utils.js → utils.cjs} +69 -48
  18. package/skills/wix-docs/SKILL.md +109 -111
  19. package/skills/wix-docs/references/API_SPEC_SEARCH.md +35 -23
  20. package/skills/wix-docs/references/CALLING.md +91 -0
  21. package/skills/wix-docs/references/EXTRACTING.md +5 -3
  22. package/skills/wix-headless/references/DOC_DISCOVERY.md +9 -3
  23. package/skills/wix-manage/SKILL.md +8 -2
  24. package/skills/wix-manage/references/bookings/booking-service-policy-setup.md +59 -33
  25. package/skills/wix-manage/references/bookings/bookings-staff-setup.md +45 -22
  26. package/skills/wix-manage/references/bookings/multi-resource-service-creation.md +70 -12
  27. package/skills/wix-manage/references/calendar/configure-default-business-hours.md +53 -17
  28. package/skills/wix-manage/references/seo/manage-content-plan.md +247 -0
  29. package/skills/wix-manage/references/seo/manage-seo-tags.md +59 -6
  30. package/skills/wix-manage/references/stores/change-store-currency.md +10 -0
  31. package/skills/wix-manage/references/stores/create-product-catalog-v3.md +17 -1
  32. package/skills/wix-manage/references/stores/update-product-with-options.md +9 -0
  33. package/skills/wix-vibe-headless/SKILL.md +17 -18
  34. package/skills/wix-vibe-headless/install/pin-agents-md.cjs +1 -1
  35. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed-with-install.md +119 -0
  36. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +61 -67
  37. package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +31 -29
  38. package/skills/wix-vibe-headless/platforms/base44.md +18 -7
  39. package/skills/wix-vibe-headless/platforms/generic.md +13 -12
  40. package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +4 -13
  41. package/skills/wix-vibe-headless/references/blog/seed/SEED.md +4 -8
  42. package/skills/wix-vibe-headless/references/blog/seed/{seed-blog.js → seed-blog.cjs} +2 -3
  43. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +5 -14
  44. package/skills/wix-vibe-headless/references/bookings/seed/SEED.md +5 -9
  45. package/skills/wix-vibe-headless/references/bookings/seed/{seed-bookings.js → seed-bookings.cjs} +2 -2
  46. package/skills/wix-vibe-headless/references/bookings/seed/{seed-rentals.js → seed-rentals.cjs} +3 -3
  47. package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +1 -1
  48. package/skills/wix-vibe-headless/references/cms/seed/SEED.md +2 -2
  49. package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +4 -13
  50. package/skills/wix-vibe-headless/references/events/seed/SEED.md +3 -7
  51. package/skills/wix-vibe-headless/references/events/seed/{seed-events.js → seed-events.cjs} +2 -2
  52. package/skills/wix-vibe-headless/references/forms/INSTRUCTIONS.md +2 -1
  53. package/skills/wix-vibe-headless/references/forms/seed/SEED.md +1 -1
  54. package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +4 -13
  55. package/skills/wix-vibe-headless/references/members/seed/SEED.md +2 -3
  56. package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +4 -13
  57. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectMedia.jsx +1 -1
  58. package/skills/wix-vibe-headless/references/portfolio/seed/SEED.md +3 -7
  59. package/skills/wix-vibe-headless/references/portfolio/seed/{seed-portfolio.js → seed-portfolio.cjs} +2 -2
  60. package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +5 -14
  61. package/skills/wix-vibe-headless/references/pricing-plans/app/components/OrderCard.jsx +1 -1
  62. package/skills/wix-vibe-headless/references/pricing-plans/seed/SEED.md +3 -7
  63. package/skills/wix-vibe-headless/references/pricing-plans/seed/{seed-pricing-plans.js → seed-pricing-plans.cjs} +2 -2
  64. package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +5 -15
  65. package/skills/wix-vibe-headless/references/restaurants/seed/SEED.md +3 -7
  66. package/skills/wix-vibe-headless/references/restaurants/seed/{seed-restaurants.js → seed-restaurants.cjs} +2 -2
  67. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +363 -327
  68. package/skills/wix-vibe-headless/references/storefront/app/context/CartContext.jsx +1 -0
  69. package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductDetail.js +2 -2
  70. package/skills/wix-vibe-headless/references/storefront/app/hooks/useShop.js +63 -78
  71. package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-catalog.js +59 -43
  72. package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +51 -14
  73. package/skills/wix-vibe-headless/references/storefront/seed/{seed-store.js → seed-store.cjs} +194 -28
  74. package/skills/wix-vibe-headless/references/storefront/app/pages/Shop.jsx +0 -75
@@ -1,10 +1,10 @@
1
1
  # Wix Dashboard Page Builder
2
2
 
3
- Dashboard pages appear in the site owner's Wix dashboard, where administrators manage data, configure settings, and perform admin tasks.
3
+ Dashboard pages appear in the site owner's Wix dashboard, where admins manage data and configure settings.
4
4
 
5
5
  ## Plan the Workflow Before the Components
6
6
 
7
- A dashboard page is a workflow, not a screen. The site owner has to understand the situation, focus on what needs attention, investigate one record, act, and see the result confirmed — so translate the prompt into those needs before choosing any component: which view fits, which drill-in surface, which data sources have to line up.
7
+ A dashboard page is a workflow, not a screen. The site owner has to understand the situation, focus on what needs attention, investigate one record, act, and see the result confirmed — so translate the prompt into those needs before choosing any component.
8
8
 
9
9
  Do this first because a bare filtered table answers "what are all the records" and none of "how many", "which one needs my attention", or "why did this happen" — and a table is what you get by default if the workflow was never named. Read [UX Success Model](dashboard-page/UX_SUCCESS_MODEL.md) now, and run its evaluation checklist before calling the page done. Which component serves each need: [Collection Toolkit](dashboard-page/COLLECTION_TOOLKIT.md).
10
10
 
@@ -33,7 +33,9 @@ wix generate --params '{"extensionType":"DASHBOARD_PAGE","title":"<title>","rout
33
33
 
34
34
  The CLI generates the folder, `page.tsx`, the builder file, the UUID, and the `src/extensions.ts` registration. After scaffolding, implement the page UI in the generated `page.tsx`.
35
35
 
36
- **Then, before writing UI:** resolve the package root and `Read <pkgRoot>/dist/dts-bundle/index.json` once, per [Prerequisites](WIX_PATTERNS_DOCS.md#prerequisites). Each Bash call is a fresh shell, so if you keep the path in a variable, set it again in every call.
36
+ **Never reuse `<route>` as a path prefix inside this page's `PatternsReactRouter`** — its location is already page-scoped, so a page scaffolded `route: "shifts"` still routes from `path="/"`, and `path="/shifts"` silently never matches. Page-relative paths: [Entity Page Toolkit](dashboard-page/ENTITY_PAGE_TOOLKIT.md).
37
+
38
+ **Then, before writing UI:** resolve the package root and `Read <pkgRoot>/dist/dts-bundle/index.json` once, per [Prerequisites](WIX_PATTERNS_DOCS.md#prerequisites). Each Bash call is a fresh shell — re-set the path variable in every call.
37
39
 
38
40
  ## Capabilities
39
41
 
@@ -41,7 +43,7 @@ A dashboard page runs as the **Wix user** — see [Identity and Elevation Requir
41
43
 
42
44
  ### Data Operations (Wix Data SDK)
43
45
 
44
- See [Wix Data Reference](data-collection/WIX_DATA.md) in the Data Collection reference for complete documentation.
46
+ See [Wix Data Reference](data-collection/WIX_DATA.md).
45
47
 
46
48
  - Read: `items.query('Collection').filter/sort.limit.find()` → `{ items, totalCount, hasNext }`
47
49
  - Write: `items.insert | update | remove`. Ensure collection permissions allow the action
@@ -50,7 +52,7 @@ See [Wix Data Reference](data-collection/WIX_DATA.md) in the Data Collection ref
50
52
 
51
53
  ### Dashboard APIs
52
54
 
53
- See [Dashboard API Reference](dashboard-page/DASHBOARD_API.md) for complete documentation including all methods, page IDs, and examples.
55
+ See [Dashboard API Reference](dashboard-page/DASHBOARD_API.md) for all methods, page IDs, and examples.
54
56
 
55
57
  **Key methods**, all on the `dashboard` object from `@wix/dashboard` (signatures, page IDs, and examples in the reference above):
56
58
 
@@ -62,13 +64,15 @@ See [Dashboard API Reference](dashboard-page/DASHBOARD_API.md) for complete docu
62
64
 
63
65
  **CRITICAL: Using Modals in Dashboard Pages**
64
66
 
65
- Dashboard Pages cannot use `<Modal />`. For a true dialog overlay you **MUST** use a dashboard modal extension — never a React modal, never the WDS `Modal` component. Reserve it for dialogs that neither write nor display a record this app lists (delete/discard confirmations, unsaved-changes prompts, informational notices), plus any dialog on a page that lists nothing (settings, config). They open via `dashboard.openModal()`, which integrates them with the dashboard lifecycle, state management, and navigation — implementation guide: [Dashboard Modal reference](DASHBOARD_MODAL.md).
67
+ Dashboard Pages cannot use `<Modal />`. For a true dialog overlay you **MUST** use a dashboard modal extension — never a React modal or the WDS `Modal` component. Reserve it for dialogs that neither write nor display a listed record (delete/discard confirmations, unsaved-changes prompts, notices), plus any dialog on a page that lists nothing (settings, config). They open via `dashboard.openModal()` — see [Dashboard Modal reference](DASHBOARD_MODAL.md).
66
68
 
67
- > **🛑 The test — does the dialog create, update, or display one record this page lists?** If yes, it is an `EntityPage`, not a modal — whether those records come from a CMS collection or an existing Wix app's SDK. **A create / "add new" form is included**: it writes the record, so it is an `EntityPage` even though nothing is being edited yet. "It's a simple data-entry dialog, not an entity edit" is the wrong reading, and it is the single most common way the patterns-first rule gets dropped after the table is already correct.
69
+ > **🛑 The test — does the dialog create, update, or display one record this page lists?** If yes, it is an `EntityPage`, not a modal — whether those records come from a CMS collection or an existing Wix app's SDK. **A create / "add new" form is included**: it writes the record, so it is an `EntityPage` even though nothing is being edited yet. "It's a simple data-entry dialog, not an entity edit" is the wrong reading — the most common way the patterns-first rule gets dropped after the table is already correct.
70
+ >
71
+ > The `EntityPage` comes from `@wix/patterns`, reached via `usePatternsNavigate().navigateToEntityPage`, with `useEntityPage` owning fetch/save/validation and `@wix/patterns/form` owning form state. Its route is registered with `PatternsReactRoute` inside `PatternsReactRouter` — so do not hand-roll page location state to fake a second view (`useState<PageLocation>` as a stand-in for a route); that is the router's job, and needing it is the signal you skipped one.
68
72
  >
69
- > The `EntityPage` comes from `@wix/patterns`, reached via `usePatternsNavigate().navigateToEntityPage`, with `useEntityPage` owning fetch/save/validation and `@wix/patterns/form` owning form state. Its route is registered with `PatternsReactRoute` inside `PatternsReactRouter` — so do not hand-roll page location state to fake a second view (`useState<PageLocation>`, a `location` cast on `withDashboard`); that is the router's job, and needing the cast is the signal you skipped it.
73
+ > That's not a rule against `withDashboard`: the router **requires** it above itself and a `location` prop, which the page gets from `dashboard.observeState` (a Wix CLI app passes no props to dashboard pages). Skip it and `PatternsReactRouter` throws at open, though typecheck, bundling, and `wix preview` all pass. Read `<pkgRoot>/dist/docs/withDashboard.md` (ships from 1.465.0; on older installs, `PatternsReactRouter.md`'s **Requirements**).
70
74
  >
71
- > **If this page lists nothing** — a settings page, an embedded-script config page — the rule does not apply and a dashboard modal is a normal choice. But "I built the list without `@wix/patterns`" is not an exception: a page that lists records should be a `CollectionPage`.
75
+ > **If this page lists nothing** (settings, config) the rule doesn't apply. But "I built the list without `@wix/patterns`" is not an exception: a page that lists records should be a `CollectionPage`.
72
76
  >
73
77
  > See [Entity create and edit](../SKILL.md#entity-create-and-edit) and [WIX_PATTERNS_DOCS.md](WIX_PATTERNS_DOCS.md); for the `useEntityPage` call itself, [Entity Page Toolkit](dashboard-page/ENTITY_PAGE_TOOLKIT.md).
74
78
 
@@ -76,7 +80,7 @@ Dashboard Pages cannot use `<Modal />`. For a true dialog overlay you **MUST** u
76
80
 
77
81
  ### Embedded Script Configuration API
78
82
 
79
- When building a dashboard page to configure an embedded script, see [Dynamic Parameters Reference](dashboard-page/DYNAMIC_PARAMETERS.md) for the implementation guide.
83
+ When building a dashboard page to configure an embedded script, see [Dynamic Parameters Reference](dashboard-page/DYNAMIC_PARAMETERS.md).
80
84
 
81
85
  **Key points:**
82
86
 
@@ -92,7 +96,7 @@ Each output below names the library that owns each part. Confirm every patterns
92
96
 
93
97
  **Request:** "Create a dashboard page to manage blog posts"
94
98
 
95
- **Output:** A `@wix/patterns` `CollectionPage` shell wrapping a `Table` driven by a collection state hook (`useTableCollection`), with the search, add/edit/delete row actions, and empty state supplied by the collection's own APIs. Add and edit navigate to an `EntityPage` (`navigateToEntityPage` + `useEntityPage`). WDS only for the leaf UI inside cells and the fields inside the entity page's cards. The provider lives in a parent component, in a separate file from the hook call.
99
+ **Output:** A `@wix/patterns` `CollectionPage` wrapping a `Table` driven by `useTableCollection`, with search, row actions, and empty state from the collection's own APIs. Add and edit navigate to an `EntityPage`. WDS only for leaf UI inside cells and entity-page cards; the provider sits in a parent component, in its own file.
96
100
 
97
101
  ### Settings Form
98
102
 
@@ -104,13 +108,13 @@ Each output below names the library that owns each part. Confirm every patterns
104
108
 
105
109
  **Request:** "Create an admin panel for customer orders"
106
110
 
107
- **Output:** A `@wix/patterns` `CollectionPage` + `Table`, with filters, sorting, and row actions from the collection APIs — **not** a hand-built WDS filter bar. Status badges are WDS leaf UI inside a cell. Viewing or editing an order opens an `EntityPage` via `usePatternsNavigate().navigateToEntityPage` — not a modal (see [Entity create and edit](../SKILL.md#entity-create-and-edit)). A Dashboard Modal appears only for the delete confirmation.
111
+ **Output:** A `@wix/patterns` `CollectionPage` + `Table`, with filters, sorting, and row actions from the collection APIs — **not** a hand-built WDS filter bar. Status badges are WDS leaf UI in a cell. Viewing or editing an order opens an `EntityPage` via `navigateToEntityPage`, not a modal; a Dashboard Modal appears only for the delete confirmation.
108
112
 
109
113
  ### Embedded Script Configuration
110
114
 
111
115
  **Request:** "Create a settings page for the coupon popup embedded script"
112
116
 
113
- **Output:** A `@wix/patterns` `SettingsPage` shell with WDS form fields for popup headline, coupon code, minimum cart value, and enable toggle. `embeddedScripts.getEmbeddedScript()` loads the parameters on mount and `embeddedScripts.embedScript()` saves them back — both sides string-converted, per [Dynamic Parameters](dashboard-page/DYNAMIC_PARAMETERS.md).
117
+ **Output:** A `@wix/patterns` `SettingsPage` with WDS form fields (popup headline, coupon code, minimum cart value, enable toggle). `embeddedScripts.getEmbeddedScript()` loads the parameters on mount, `embeddedScripts.embedScript()` saves them back — both sides string-converted, per [Dynamic Parameters](dashboard-page/DYNAMIC_PARAMETERS.md).
114
118
 
115
119
 
116
120
  ## API Spec Support
@@ -122,4 +126,4 @@ When an API specification is provided, you can call those endpoints — see [API
122
126
 
123
127
  Content layout inside the page shell — the 6px base unit, the 12-column grid, spacing tokens, form/display/marketing/wizard layouts: see [WDS Layout Reference](dashboard-page/WDS_LAYOUT.md).
124
128
 
125
- Remember the split: `@wix/patterns` owns the page shell and anything collection-shaped; that reference covers only the content you place inside it.
129
+ Remember the split: `@wix/patterns` owns the shell and anything collection-shaped; that reference covers only content placed inside.
@@ -131,6 +131,9 @@ extension configuration, and supporting files.
131
131
  all bodies, hide inactive accessibly.
132
132
  - Autoplay/loop: play/pause control, honor reduced motion, suppress autoplay in
133
133
  editor design mode.
134
- - `component.preview.tsx`: keep `withDefaults` and `withFallbackPlaceholder`,
135
- wrap the preview adapter when present, one crucial `requiredDataFields`
136
- entry, and `rootClassName` matching the root global class.
134
+ - `component.preview.tsx`: preserve this outer-to-inner composition, inline or
135
+ through component variables:
136
+ `withDefaults(withFallbackPlaceholder(PreviewOrComponent, options), defaultProps)`.
137
+ Keep `withDefaults` outermost, wrap the preview adapter when present, use one
138
+ crucial `requiredDataFields` entry, and match `rootClassName` to the root
139
+ global class.
@@ -1,19 +1,24 @@
1
1
 
2
2
  # Extension Registration
3
3
 
4
- `src/extensions.ts` is the single entry point that tells the build system which extensions exist. Without a `.use()` call for an extension, it does not load.
4
+ `src/extensions.ts` is the single entry point that tells the build system which extensions exist. Without a `.use()` call for an extension, it does not load. HTTP endpoints are file-based routes and do not use this registration mechanism.
5
5
 
6
6
  ## Registration is automatic via the CLI
7
7
 
8
- For every CLI-supported extension type, `wix generate --params` updates `src/extensions.ts` for you — you do NOT need to write the import or the `.use()` call by hand. Verify the file was updated after each `wix generate` invocation.
8
+ For every CLI-supported extension type, `wix generate --params` updates `src/extensions.ts` for you — you do NOT need to write the import or the `.use()` call by hand. Verify the file was updated after each `wix generate` invocation. The one exception is `HTTP_ENDPOINT`: it is file-based, `wix generate` does not touch `src/extensions.ts` for it, and an unchanged file after generating an endpoint is expected (see below).
9
9
 
10
- ## Extension types that require manual registration
10
+ ## HTTP endpoints: no registration
11
11
 
12
- | Type | Why manual |
13
- | --- | --- |
14
- | **Backend API** | Astro endpoints under `src/pages/api/` are auto-discovered by the runtime. They do not need to be added to `src/extensions.ts`. |
12
+ `wix generate --params '{"extensionType":"HTTP_ENDPOINT","name":"hello"}'`
13
+ creates the endpoint file without changing `src/extensions.ts`:
15
14
 
16
- Every other extension type is wired up automatically by the CLI.
15
+ | Project | Discovery directory | Example route |
16
+ | --- | --- | --- |
17
+ | `@wix/custom-extensions` (default `apiDir: "endpoints"`) | `src/endpoints/` | `hello.ts` → `/hello` |
18
+ | `@wix/astro` | `src/pages/api/` | `hello.ts` → `/api/hello` |
19
+
20
+ Leave `app()` unchanged. Do not add endpoint imports, `.use()` calls, or IDs.
21
+ See [BACKEND_API.md](BACKEND_API.md) for supported versions and frontend URLs.
17
22
 
18
23
  ## Manual recovery (when the CLI output drifts)
19
24
 
@@ -21,7 +26,6 @@ Edit `src/extensions.ts` directly only when:
21
26
 
22
27
  - The CLI failed mid-run and left the file out of sync
23
28
  - A user hand-edited the file and broke the chain
24
- - You're adding a Backend API helper (uncommon)
25
29
 
26
30
  Each extension file is a default export from `<folder>/<folder>.extension.ts`. In `src/extensions.ts`, import it as a default import using the camelCase of the folder name, then chain `.use(...)`:
27
31
 
@@ -33,7 +33,7 @@ try {
33
33
  "
34
34
  ```
35
35
 
36
- A bare `require.resolve` without the PnP-activation step throws in a Yarn Berry project even when the package is installed — run the whole snippet, not a shortened version.
36
+ A bare `require.resolve` without the PnP-activation step throws in a Yarn Berry project even when installed — run the whole snippet, not a shortened version.
37
37
 
38
38
  Then confirm the installed version actually ships the bundle index:
39
39
 
@@ -41,9 +41,9 @@ Then confirm the installed version actually ships the bundle index:
41
41
  ls <pkgRoot>/dist/dts-bundle/index.json
42
42
  ```
43
43
 
44
- **If it's missing, stop — do not look elsewhere for types or docs.** The installed `@wix/patterns` predates the index; it ships from **1.458.0** onward, so upgrade to at least that and re-run the check. A missing *file* is not the same as a name not being covered (see below): the mechanism itself isn't available yet.
44
+ **If it's missing, stop — do not look elsewhere for types or docs.** The installed `@wix/patterns` predates the index (ships from **1.458.0**); upgrade and re-run the check. Prefer **1.465.0**+ — the lookups below assume it (`OffsetQuery`, `useEntityPage`'s create route, `withDashboard.md`, a deprecation `status` in `dist/docs/index.json`, page-relative router paths). A missing *file* isn't the same as a name not being covered (see below).
45
45
 
46
- **Never inspect `node_modules` by hand** — no `ls`, no `find`, no `cat` of an arbitrary path, and that includes the sanctioned directories: never browse `dist/dts-bundle/` or `dist/docs/` looking around. Every lookup below names the exact file to `Read` — go straight to it.
46
+ **Never inspect `node_modules` by hand** — no `ls`, `find`, or `cat` of an arbitrary path, not even `dist/dts-bundle/` or `dist/docs/`. Every lookup below names the exact file to `Read` — go straight to it.
47
47
 
48
48
  ## Library Architecture
49
49
 
@@ -75,18 +75,17 @@ Common types only; `dist/dts-bundle/index.json` has the authoritative set. Creat
75
75
  | Provider | When to Use |
76
76
  | --- | --- |
77
77
  | `WixPatternsProvider` | **Default — start here.** Auto-detects the environment (BM, Essentials, Giza). |
78
- | `WixPatternsBMProvider` | Optional alternative for Yoshi BM Flow over Business Manager. |
79
- | `WixPatternsGizaProvider` | Optional alternative for Yoshi BM Flow over Giza. |
78
+ | `WixPatternsBMProvider` / `WixPatternsGizaProvider` | Optional alternatives for Yoshi BM Flow (Business Manager / Giza). |
80
79
  | `WixPatternsEssentialsProvider` | Yoshi Fullstack. |
81
80
  | `WixPatternsBaseProvider` | App does **not** run under Giza/WixEssentials and you inject services (i18n, sentry) yourself. |
82
81
 
83
- **Confirm the import path in the provider's own bundle** — they don't all share a subpath (`WixPatternsEssentialsProvider` and `WixPatternsBaseProvider` are under `@wix/patterns/essentials`). The project's `package.json` identifies the flow.
82
+ **Confirm the import path in the provider's own bundle** — not all share a subpath (`WixPatternsEssentialsProvider`, `WixPatternsBaseProvider` live under `@wix/patterns/essentials`).
84
83
 
85
84
  ### Keep Provider and Page Separate
86
85
 
87
- The provider **must** live in a parent component of the page content: hooks like `useTableCollection` need its context to already exist above them in the React tree.
86
+ The provider **must** be a parent of the page content: hooks like `useTableCollection` need its context above them in the tree.
88
87
 
89
- **Wrong:** calling `useTableCollection` in the same component that renders `WixPatternsProvider`. The hook runs before the provider exists above it, so it throws at runtime — and the JSX nesting looks right, which is what makes this hard to spot.
88
+ **Wrong:** calling `useTableCollection` in the component that renders `WixPatternsProvider` — the hook runs before the provider exists, so it throws at runtime even though the JSX looks right.
90
89
 
91
90
  **Correct — provider in root, page in a separate file:**
92
91
  ```tsx
@@ -102,7 +101,7 @@ function App() {
102
101
  }
103
102
 
104
103
  // MyCollectionPage.tsx
105
- import { Table, useTableCollection } from '@wix/patterns';
104
+ import { Table, useTableCollection, OffsetQuery } from '@wix/patterns';
106
105
  import { CollectionPage } from '@wix/patterns/page';
107
106
 
108
107
  function MyCollectionPage() {
@@ -111,7 +110,7 @@ function MyCollectionPage() {
111
110
  queryName: 'my-items',
112
111
  itemKey: (item) => item.id,
113
112
  itemName: (item) => item.name,
114
- fetchData: async () => ({ items: [], total: 0 }),
113
+ fetchData: async (query: OffsetQuery) => ({ items: [], total: 0 }),
115
114
  filters: {},
116
115
  });
117
116
  return (
@@ -124,7 +123,7 @@ function MyCollectionPage() {
124
123
 
125
124
  Keep the provider (and router, if any) in the app's root component and each page in its own file.
126
125
 
127
- For **multiple pages**, use the `@wix/patterns` routing solution (`PatternsReactRouter`, `PatternsReactRoute`, `usePatternsNavigate`) rather than a separate router; look the doc files up for setup.
126
+ For **multiple pages**, use the `@wix/patterns` routing solution (`PatternsReactRouter`, `PatternsReactRoute`, `usePatternsNavigate`) rather than a separate router. Read `PatternsReactRouter.md` and `withDashboard.md` for setup — the router reads page location from the dashboard context `withDashboard` renders, so it needs that wrapper above it with a `location` prop, and throws at render time without them. (it ships from **1.465.0**; no entry in `dist/docs/index.json` means an older install — use `PatternsReactRouter.md`'s **Requirements**.)
128
127
 
129
128
  ## How to Look Things Up
130
129
 
@@ -132,47 +131,45 @@ For **multiple pages**, use the `@wix/patterns` routing solution (`PatternsReact
132
131
 
133
132
  ### Finding the right name
134
133
 
135
- `Read <pkgRoot>/dist/dts-bundle/index.json` — one entry per name, grouped implicitly by its `category` field. Lookup is **exact-match only**: no fuzzy matching, no typo suggestions. If the exact key isn't there, scan the index you already hold for something close before concluding the name isn't covered.
134
+ `Read <pkgRoot>/dist/dts-bundle/index.json` — one entry per name, grouped implicitly by its `category` field. Lookup is **exact-match only** — no fuzzy matching. If the exact key isn't there, scan the index you already hold for something close before concluding the name isn't covered.
136
135
 
137
- Not every real `@wix/patterns` export is in this index — only the names these guides actually reference. If a name you need genuinely isn't there, **stop and say so rather than falling back to `node_modules`.**
136
+ Not every real export is in this index — only names these guides reference. If a needed name genuinely isn't there, **stop and say so rather than falling back to `node_modules`.**
138
137
 
139
138
  ### Reading doc files
140
139
 
141
- `Read <pkgRoot>/dist/docs/index.json` to resolve a name to its doc file — or a `symbols` alias, for the cases where the Storybook title doesn't match the export (`ExportTo.md` documents `ExportButton`) — then `Read <pkgRoot>/dist/docs/<file>.md` directly, the whole file, not piped through `head`. It covers more names than the bundle index above: it's produced for every documented component, not just the curated ones.
140
+ `Read <pkgRoot>/dist/docs/index.json` to resolve a name to its doc file — or a `symbols` alias, for cases where the Storybook title doesn't match the export (`ExportTo.md` documents `ExportButton`) — then `Read <pkgRoot>/dist/docs/<file>.md` directly, the whole file, not piped through `head`. It covers more names than the bundle index above — every documented component, not just the curated ones.
142
141
 
143
- **Always check the import statement inside the doc** — not everything comes from `@wix/patterns` (some use subpaths like `@wix/patterns/provider`).
142
+ **Always check the import statement inside the doc** — not everything comes from `@wix/patterns` (some use subpaths, e.g. `@wix/patterns/provider`).
143
+
144
+ A doc whose index entry has a `bundle` field does **not** list its props — its `### Props` points at that bundle. One without it carries its own table. Either way the doc owns prose, variations, BI events, and the import line.
144
145
 
145
146
  ### Reading the file the index names
146
147
 
147
- The mechanics of the file an index names — types the docs don't cover, which one-line stubs are answers rather than truncation, subpath entry points, cross-references, split compound-component docs — are in [Reading bundles and docs](dashboard-page/PATTERNS_BUNDLE_READING.md). Read it before your first `dist/dts-bundle/*.d.ts` of the session.
148
+ The mechanics of the file an index names — batching the reads, types docs don't cover, one-line stubs that are answers rather than truncation, subpath entry points, cross-references, split compound docs — are in [Reading bundles and docs](dashboard-page/PATTERNS_BUNDLE_READING.md). Read it before your first `dist/dts-bundle/*.d.ts` of the session.
148
149
 
149
150
  ## The Collection → Entity Flow
150
151
 
151
- A collection page and its item form are **two patterns pages**, not a page plus a modal. Getting the table right and then hand-building the "add item" form as a dashboard modal is the most common way this goes wrong.
152
+ A collection page and its item form are **two patterns pages**, not a page plus a modal. Reserve modals for dialogs that neither write nor display a listed record (a delete or discard confirmation, an unsaved-changes prompt); **a create / "add new" form is not one of them** — it writes the record, so it's an `EntityPage` regardless of size. A page that lists nothing is outside this rule — full test in [SKILL.md](../SKILL.md#entity-create-and-edit).
152
153
 
153
154
  | Step | What owns it |
154
155
  | --- | --- |
155
156
  | Navigate from a row / primary action to the item | `usePatternsNavigate()` → `navigateToEntityPage({ path, entity })` |
156
157
  | Register the route | `PatternsReactRoute` inside `PatternsReactRouter` |
157
158
  | Fetch, save, validation, dirty state, skeletons, errors | `useEntityPage({ fetch, onSave })` |
158
- | Form state and field binding | `useForm` / `useController` from `@wix/patterns/form` |
159
+ | Form state and field binding | `useForm` / `useController` from `@wix/patterns/form` — `useController`, never `register` |
159
160
  | Body layout | `EntityPage.Header`, `.MainContent`, `.AdditionalContent`, `.Card` |
160
161
  | The individual fields inside those cards | `@wix/design-system` (`FormField`, `Input`, `Text`) |
161
162
 
162
- Prefer `navigateToEntityPage` over a plain route change: the entity header (title, subtitle, breadcrumbs) renders immediately, without waiting for the fetch.
163
-
164
- Read `EntityPage.md`, `useEntityPage.md`, and `usePatternsNavigate.md` before implementing — and note `useCreateCollection` is **not** about creating items; it returns a function that initializes collection state.
165
-
166
- Three things about the `useEntityPage` call are worth getting right first time — both generics, what `onSave` receives, which params exist: [ENTITY_PAGE_TOOLKIT.md](dashboard-page/ENTITY_PAGE_TOOLKIT.md).
163
+ Prefer `navigateToEntityPage` over a plain route change — the entity header renders before the fetch resolves. **Every `path` above is page-relative**: the router roots at `path="/"` even on a page scaffolded `route: "shifts"`, so never repeat that name in a `path`, `parentPath`, or `navigateToEntityPage` call — it fails silently. See [ENTITY_PAGE_TOOLKIT.md](dashboard-page/ENTITY_PAGE_TOOLKIT.md).
167
164
 
168
- Reserve dashboard modals for dialogs that neither write nor display a listed record — a delete or discard confirmation, an unsaved-changes prompt. **A create / "add new" form is not one of them**: it writes the record, so it is an `EntityPage` even though nothing is being edited yet. Size and field count are not exceptions — a one-field create form is still an `EntityPage`. A page that lists no records is outside this rule.
165
+ Read `EntityPage.md`, `useEntityPage.md` and `usePatternsNavigate.md` before implementing, plus [ENTITY_PAGE_TOOLKIT.md](dashboard-page/ENTITY_PAGE_TOOLKIT.md) for the `useEntityPage` call itself (generics, `onSave`, params). Note `useCreateCollection` is **not** about creating items: it returns a function that initializes collection state.
169
166
 
170
167
  ## When Patterns Has No Equivalent
171
168
 
172
- A concept is only "missing" from patterns after you've checked `dist/dts-bundle/index.json` and `dist/docs/index.json` **and** searched by keyword within what you've read. Then, and only then:
169
+ A concept is only "missing" from patterns after you've checked `dist/dts-bundle/index.json` and `dist/docs/index.json` **and** searched by keyword within what you've read. Then:
173
170
 
174
171
  1. Look the component up in `@wix/design-system` via the `wix-design-system` skill.
175
172
  2. Render it *inside* the patterns page shell / collection, not as a replacement for it.
176
173
  3. If WDS lacks it too, compose from WDS primitives (`Box`, `Card`, `Text`) — never restyle patterns internals, never add another UI library.
177
174
 
178
- Anything page- or collection-shaped (page shell, header, table, grid, filters, sorting, paging, row and bulk actions) is patterns' territory. If you're about to build one from WDS parts, you skipped a lookup.
175
+ Anything page- or collection-shaped (shell, header, table, grid, filters, sorting, paging, row/bulk actions) is patterns' territory. Building one from WDS parts means a skipped lookup.
@@ -34,9 +34,9 @@ Everything below is a real name in the installed `@wix/patterns`. Confirm the pr
34
34
  | A fixed in-memory option list for a filter | `useStaticListFilterCollection` |
35
35
  | Sorting | `Sortable Columns`, `MultiLevelSorting` |
36
36
 
37
- **Ask for several names at once.** `docs`, `types` and `exports` all take a list — `types ComputedQuery OffsetQuery RangeItem`, `exports page form router` — and each call is a full model turn, so five one-name calls cost five turns for one call's worth of answer. `exports` with no argument lists the 31 entry points; that is a one-off orientation, not something to re-run.
37
+ **Read the index once, then go straight to files.** `dist/dts-bundle/index.json` answers every name in this table in a single read — resolve it once per session and keep it, rather than re-reading it per lookup. Each entry names the exact file to open next.
38
38
 
39
- **A factory or hook's doc is often empty where its signature should be** — `docs idNameArrayFilter` prints an `## API` heading with nothing under it, because the props table only exists for components. Ask `types idNameArrayFilter` instead and you get the signature: `<T extends { id: string; name: string }>(params?) => ArrayFilterState<T>`. That applies to every `use…` hook and every `…Filter` factory in the table above, and it is the difference between knowing the name and being able to call it.
39
+ **A factory or hook's doc is often empty where its signature should be** — the props table is generated for components, so `idNameArrayFilter`'s doc shows an `## API` heading with nothing under it. Its bundle has the signature: `<T extends { id: string; name: string }>(params?) => ArrayFilterState<T>`. That holds for every `use…` hook and every `…Filter` factory in the table above, and it is the difference between knowing a name and being able to call it — so for these, read the bundle the index names, not the doc.
40
40
 
41
41
  **A filter must narrow the result.** Declare it in the collection hook's `filters` map and read it inside `fetchData`, so the value reaches the query. Filter UI that renders but never changes the rows is a defect that looks like a feature — and it is the failure mode these components exist to prevent.
42
42
 
@@ -49,7 +49,7 @@ Everything below is a real name in the installed `@wix/patterns`. Confirm the pr
49
49
  | **Expanded row** | A couple of extra fields, no separate workspace needed. | The collection's own row expansion |
50
50
  | **Picker / bulk confirm** | Choosing records, or confirming an action on many. | `PickerModal` + `usePickerModal`, `bulkActionModal` |
51
51
 
52
- A dialog that creates, updates or displays one listed record is **not** a dashboard modal — a create / "add new" form included, since it writes the record. See [DASHBOARD_MODAL.md](../DASHBOARD_MODAL.md). A row the user cannot open is the second most common failure after the missing aggregate.
52
+ A dialog that creates, updates or displays one listed record is **not** a dashboard modal — a create / "add new" form included, since it writes the record. See [DASHBOARD_MODAL.md](../DASHBOARD_MODAL.md); for the create route itself — registering it, and the four params that differ from the edit call — [ENTITY_PAGE_TOOLKIT.md § Create route](ENTITY_PAGE_TOOLKIT.md#create-route). A row the user cannot open is the second most common failure after the missing aggregate.
53
53
 
54
54
  **Form state on an entity page** comes from `@wix/patterns/form` — `useForm` for the form, `useController` for a single field. That subpath re-exports `@wix/bex-core/form`, which wraps `react-hook-form`, so its API is react-hook-form's and only a handful of its names appear in the patterns docs: `FieldValues`, `ControllerProps` and most of the rest are documented by react-hook-form, not here. `Read <pkgRoot>/dist/dts-bundle/exports/form.d.ts` to see what the subpath actually gives you.
55
55
 
@@ -57,10 +57,11 @@ A dialog that creates, updates or displays one listed record is **not** a dashbo
57
57
 
58
58
  | Need | Component |
59
59
  | --- | --- |
60
- | Row actions | `PrimaryActions`, `SecondaryActions`, `More Actions`, `deleteSecondaryAction` |
61
- | Page-level button | `PrimaryPageButton`, `PrimaryActionButton` |
60
+ | Page header actions | `PrimaryActions`, `SecondaryActions`, `More Actions` — passed to the page header's `primaryAction`, `secondaryActions` and `moreActions` slots |
61
+ | Table toolbar button | `PrimaryActionButton` — the table's own `primaryActionButton` prop |
62
+ | Row actions | `deleteSecondaryAction`, in the row's `actionCell` |
62
63
  | Acting on a multi-row selection | `MultiBulkActionToolbar`, `bulkActionModal` |
63
- | Immediate feedback, then reconcile | `useOptimisticActions`, `CollectionOptimisticActions` |
64
+ | Immediate feedback, then reconcile | `useOptimisticActions(state.collection)` ✅ — not `useOptimisticActions(state)` ❌: `useTableCollection()` returns `TableState<T, F>`, and the hook takes the `CollectionState<T, F>` that state exposes as `state.collection`. Returns `CollectionOptimisticActions` |
64
65
  | A banner above the table | `TableTopNotification` |
65
66
 
66
67
  ## The states that are not the happy path
@@ -26,10 +26,29 @@ const state = useEntityPage<Shift, ShiftFormFields>({
26
26
  .updateShift(shiftId, { ...form.getValues(), ...widgetsFormData })
27
27
  .then((updatedEntity) => ({ updatedEntity })),
28
28
  form,
29
- parentPath: '/shifts',
29
+ parentPath: '/',
30
30
  });
31
31
  ```
32
32
 
33
+ **`parentPath` is relative to the router's own mount point — the dashboard page's
34
+ own root, not the page's `route` value.** A dashboard page scaffolded with
35
+ `{"route": "shifts"}` is served at `/dashboard/shifts`, but `PatternsReactRouter`
36
+ still sees its own location start fresh at `/` inside that page — so `parentPath`,
37
+ every `PatternsReactRoute`'s `path`, and the `path` passed to
38
+ `navigateToEntityPage()` / `navigateToCollectionPage()` must never repeat the
39
+ page's own `route`/name. `parentPath: '/shifts'` on a page whose `route` is
40
+ `"shifts"` is the single most common way this gets copied wrong — it looks like a
41
+ reasonable guess (name the parent after the page) and compiles, but the
42
+ collection route it points back to is registered at `path="/"`, not
43
+ `path="/shifts"`, so `parentPath` must match that: `'/'`. See [Create
44
+ route](#create-route) below for the full route registration.
45
+
46
+ From **1.465.0** the library's own docs state this rule — `PatternsReactRouter.md`,
47
+ `usePatternsNavigate.md` and `useEntityPage.md`'s **Create route**. On an older
48
+ install they don't, and their examples *demonstrate* the mistake
49
+ (`navigateToEntityPage({ path: '/shifts/new' })`, `navigateToCollectionPage({ path:
50
+ '/entities' })`); prefer this rule over what those examples show.
51
+
33
52
  `EntityPage` and `useEntityPage` are **root** exports. `@wix/patterns/page` holds `CollectionPage` and `WidgetsFormProvider` only, so importing the entity page from there is `TS2305: has no exported member` — the collection page and the entity page do not live in the same place. `Read <pkgRoot>/dist/dts-bundle/exports/page.d.ts` to see what that subpath actually gives you.
34
53
 
35
54
  ## Name both generics
@@ -54,9 +73,22 @@ Reaching for a `values`-shaped key on the `onSave` argument is the usual first g
54
73
 
55
74
  ## The params are a `Pick`
56
75
 
57
- `UseEntityPageParams` picks a fixed set off `EntityPageStateParams` — `fetch`, `onSave`, `saveSuccessToast`, `saveErrorToast`, `deleteAction`, `transformEntityToCollectionItem`, `isNewEntity`, `form`, `parentPageId`, `parentPath`, `parentReferrer`, `schemaSource`. Anything outside that list is an excess-property error on the object literal. `container` is the common guess and is not one of them: the hook calls `useWixPatternsContainer()` itself.
76
+ `UseEntityPageParams` picks a fixed set off `EntityPageStateParams` — `fetch`, `onSave`, `saveSuccessToast`, `saveErrorToast`, `deleteAction`, `transformEntityToCollectionItem`, `isNewEntity` (create vs edit — [Create route](#create-route)), `form`, `parentPageId`, `parentPath`, `parentReferrer`, `schemaSource`. Anything outside that list is an excess-property error on the object literal. `container` is the common guess and is not one of them: the hook calls `useWixPatternsContainer()` itself.
77
+
78
+ Confirm the shape rather than guessing — the hook's doc ends by pointing at the bundle rather than tabulating props, because props tables only exist for components. `Read <pkgRoot>/dist/dts-bundle/index.json`, then `Read` the bundled `.d.ts` for each of `useEntityPage`, `UseEntityPageParams`, and `OnSaveParams` at exactly the `file` path the index gives.
79
+
80
+ ## Create route
81
+
82
+ The example above is edit-only. "Add new" is an `EntityPage` too, and it is not the same call with the id left out. Four things differ, and three of them fail silently if you guess:
83
+
84
+ - The route is its own `PatternsReactRoute type="createEntity"`. One component can serve both entity routes; the route is what tells them apart.
85
+ - `navigateToEntityPage({ path })` — omit `entity`. It exists so the header can render a title before the fetch resolves, and a create route has no record to give it. A placeholder is worse than nothing: until `fetch` resolves it *is* `state.entity`.
86
+ - `fetch` is required on the create route too, and `{ entity: undefined }` is the create case built into its return type — not a loading state, and there is no `fetch`-less variant.
87
+ - `isNewEntity` is the only param that tells the page which route it is on. Omitted, a create page that seeds defaults through `fetch` is announced to the collection as an *update*: the collection changes a row it does not have, the new record never appears in the list, and the only trace is a `Fetched page info for updated entity not found` console error.
58
88
 
59
- Confirm the shape rather than guessing — the hook's doc has an empty API section, because props tables only exist for components. `Read <pkgRoot>/dist/dts-bundle/index.json`, then `Read` the bundled `.d.ts` for each of `useEntityPage`, `UseEntityPageParams`, and `OnSaveParams` at exactly the `file` path the index gives.
89
+ `Read <pkgRoot>/dist/docs/useEntityPage.md` before writing one — its **Create route** section carries the worked component that serves both routes off one `useParams` answer, and the `boolean | (() => boolean)` getter form for `isNewEntity`.
90
+
91
+ **If that file has no `Create route` heading, the installed `@wix/patterns` predates 1.464.0.** Upgrade and re-read rather than working around it: on those versions `navigateToEntityPage` types `entity` as required, so omitting it does not compile, and passing the placeholder that satisfies it is the failure the bullet above describes.
60
92
 
61
93
  ## Around the call
62
94
 
@@ -64,10 +96,45 @@ Confirm the shape rather than guessing — the hook's doc has an empty API secti
64
96
  | --- | --- |
65
97
  | Getting here from the collection page | `usePatternsNavigate()` → `navigateToEntityPage({ path, entity })` |
66
98
  | Registering the route | `PatternsReactRoute` inside `PatternsReactRouter` |
67
- | Form state and field binding | `useForm` / `useController` from `@wix/patterns/form` |
99
+ | Form state and field binding | `useForm` / `useController` from `@wix/patterns/form` — `useController`, never `register` |
68
100
  | Body layout | `EntityPage.Header`, `.MainContent`, `.AdditionalContent`, `.Card` |
69
101
  | The fields inside those cards | `@wix/design-system` (`FormField`, `Input`, `Text`) |
70
102
 
103
+ Every `path` in that first row — the route's own `path`, `parentPath`, and the `path` argument to `navigateToEntityPage`/`navigateToCollectionPage` — is relative to the page's own root, never to its `route`/name. See the `parentPath` note under [The call](#the-call) above; it is the same rule everywhere a path appears in this table.
104
+
71
105
  `@wix/patterns/form` re-exports `@wix/bex-core/form`, which wraps `react-hook-form` — so `form.getValues()`, `form.reset()` and the rest are react-hook-form's API, documented there rather than in the patterns docs.
72
106
 
107
+ ## Binding a field: `useController`, never `register`
108
+
109
+ `register` returns props for a plain `<input>`, and WDS components are not one. Two ways it fails:
110
+
111
+ `<Input {...register('qty')} />` does not compile — `register` always returns `min`/`max` as `string | number`, whatever options you passed, and WDS types them `number | undefined`. The error names `InputProps`, which reads like a WDS bug and isn't.
112
+
113
+ `<Input ref={register('qty').ref} />` **does** compile and is wrong. `Input`'s `ref` is its imperative handle (`Ref<InputImperativeActions>`); `register`'s ref is `(instance: any) => void`, so it accepts that and binds the handle rather than the `<input>`. The field never registers, validation never sees it, and nothing reports it.
114
+
115
+ Bind through value/onChange instead:
116
+
117
+ ```tsx
118
+ import { useController, useForm } from '@wix/patterns/form';
119
+ import { FormField, Input } from '@wix/design-system';
120
+
121
+ type ProductForm = { name: string; qty: number };
122
+
123
+ function NameField({ form }: { form: ReturnType<typeof useForm<ProductForm>> }) {
124
+ const { field, fieldState } = useController({
125
+ name: 'name',
126
+ control: form.control,
127
+ rules: { required: 'Name is required' },
128
+ });
129
+
130
+ return (
131
+ <FormField label="Name" required status={fieldState.error ? 'error' : undefined} statusMessage={fieldState.error?.message}>
132
+ <Input value={field.value} onChange={field.onChange} onBlur={field.onBlur} />
133
+ </FormField>
134
+ );
135
+ }
136
+ ```
137
+
138
+ Rules live in `rules`, not on the WDS component. If you need `register` for a DOM concern such as input masking, `Input` takes `inputRef?: React.Ref<HTMLInputElement>` — pass the ref there, never to `ref`.
139
+
73
140
  A dialog that creates, updates or displays one listed record is **not** a dashboard modal — a create / "add new" form included, since it writes the record. See [DASHBOARD_MODAL.md](../DASHBOARD_MODAL.md).
@@ -1,14 +1,54 @@
1
1
  # Reading `@wix/patterns` Bundles and Docs
2
2
 
3
- > **Scope.** You are here because a lookup in `dist/dts-bundle/index.json` or
4
- > `dist/docs/index.json` gave you an entry and you are about to open the file it names. Getting to that index in the first
5
- > place — resolving the package root, the version floor, the docs lookup, and the rule
3
+ > **Precondition: an index entry.** Every path below is the `file` (or `bundle`) field of an entry
4
+ > in `<pkgRoot>/dist/dts-bundle/index.json` or `<pkgRoot>/dist/docs/index.json`. If you haven't
5
+ > read that index this session, you have no path to open — read it before anything else here.
6
+ > Getting to it — resolving the package root, the version floor, the docs lookup, and the rule
6
7
  > against browsing `node_modules` by hand — is in
7
8
  > [WIX_PATTERNS_DOCS.md](../WIX_PATTERNS_DOCS.md). Nothing here replaces those steps.
8
9
 
10
+ ## Read the index once, then open its files in one call
11
+
12
+ One index read covers the whole page. So name every symbol you plan to write — components, hooks,
13
+ state types, prop types — look them all up in the index you now hold, and open what it named in a
14
+ single call with one `Read` per file:
15
+
16
+ ```
17
+ call 1 Read <pkgRoot>/dist/docs/index.json
18
+ Read <pkgRoot>/dist/dts-bundle/index.json
19
+
20
+ call 2 Read <pkgRoot>/dist/docs/Table.md <- docs entry's `file`
21
+ Read <pkgRoot>/dist/docs/useTableCollection.md
22
+ Read <pkgRoot>/dist/dts-bundle/components/Table.d.ts <- its `bundle`
23
+ Read <pkgRoot>/dist/dts-bundle/hooks/useTableCollection.d.ts
24
+ Read <pkgRoot>/dist/dts-bundle/types/TableState.d.ts <- bundle entry's `file`
25
+ ```
26
+
27
+ Two calls, not twenty-two — and nothing is lost by batching, because there is nothing to learn
28
+ between the files: every path came out of the same index and `bytes` already told you each size.
29
+ The same files opened one per call re-send the whole conversation once per file, which is where a
30
+ lookup session's token cost actually goes. Batch the follow-ups the same way: when a doc names an
31
+ example file, or a stub names another bundle (below), collect them and read them together.
32
+
33
+ ## Where props live
34
+
35
+ From `@wix/patterns` **1.460.0** onward a doc does not repeat props that the bundle already
36
+ describes. Which one holds them is stated in the doc's own index entry:
37
+
38
+ | `dist/docs/index.json` entry | where the props are |
39
+ | --- | --- |
40
+ | has a `bundle` field | that bundle — the doc's `### Props` is a pointer to it, on purpose |
41
+ | no `bundle` field | the doc's own `### Props` table, as before |
42
+
43
+ Roughly 74 of 167 docs point at a bundle and 62 still carry a table, so expect both. When a doc
44
+ says `Read \`dist/dts-bundle/...\``, that **is** the props answer — read the named file rather
45
+ than treating the doc as incomplete. The bundle is the better source anyway: it keeps the
46
+ `extends` clause with its exclusions, so `Omit<PopoverMenuItemProps, 'text' | 'prefixIcon' | 'onClick'>` tells
47
+ you what you do *not* inherit, which the old doc link did not.
48
+
9
49
  ## Types the docs don't cover
10
50
 
11
- The docs cover components and props, not the types those props use — `Filter<T>`, `RangeItem<T>`, `CursorQuery`, a `...Props` interface. `Read <pkgRoot>/dist/dts-bundle/index.json`, look up the type name, then `Read <pkgRoot>/dist/dts-bundle/<entry.file>` using exactly the `file` path the index gives — **never reconstruct the path from the name**; bundles are nested one directory per kind (`components/Table.d.ts`, `hooks/useForm.d.ts`, `types/RangeItem.d.ts`, …), so guessing `<Name>.d.ts` at the top level is wrong by construction.
51
+ The same bundles also hold the types those props use — `Filter<T>`, `RangeItem<T>`, `CursorQuery`, a `...Props` interface. `Read <pkgRoot>/dist/dts-bundle/index.json`, look up the type name, then `Read <pkgRoot>/dist/dts-bundle/<entry.file>` using exactly the `file` path the index gives — **never reconstruct the path from the name**; bundles are nested one directory per kind (`components/Table.d.ts`, `hooks/useForm.d.ts`, `types/RangeItem.d.ts`, …), so guessing `<Name>.d.ts` at the top level is wrong by construction.
12
52
 
13
53
  Several of these types (`RangeItem`, `Filter`, `CursorQuery`, the filter factory functions) actually live in `@wix/bex-core` — the bundle already resolves and inlines the real declaration, so you get the full shape with no deep, undeclared `@wix/bex-core/dist/types/...` path to chase. Still always import it from `@wix/patterns`, per the index's `importPath` field, never from wherever the bundle says it's really declared.
14
54
 
@@ -32,9 +72,24 @@ An empty body with a **"Produced by"** note means: call that hook or factory to
32
72
 
33
73
  A stub saying **"cut here because it has its own bundle"** means the same thing for a shape you *do* write: it wasn't copied in twice, so look the name up and read its own file.
34
74
 
35
- Every bundle fits in a single read; the index's `bytes` field says how big before you open it. So a bundle is never partially shown — if something looks missing, it was cut on purpose and the stub names where to find it.
75
+ Every bundle fits in a single read; the index's `bytes` field says how big before you open it. So a bundle is never partially shown — if something looks missing, it was cut on purpose. Both stubs above name where to find it.
76
+
77
+ ### The one that doesn't: a bare `import`
78
+
79
+ A plain `import { X } from '<module>'` at the top of a bundle, with no note attached, is the third shape you will meet — and unlike the two above it does **not** tell you where to look. What to do depends on the path, not the name:
80
+
81
+ **A normal entry point** — `react`, `react-hook-form`, `history`, `@wix/design-system`. Resolve it the ordinary way. For `@wix/design-system` names use the `wix-design-system` skill; don't read WDS files directly.
82
+
83
+ **A deep internal path** — `@wix/design-system/dist/types/DropdownLayout`, `@wix/bex-utils/@wix/bi-logger-os-data/v2/types`. This is an upstream defect: the bundle recorded where the type is *declared* instead of where it is exported. Two things follow, and the second is the one that saves you time:
84
+
85
+ - Never import that path in your own code, and don't go read the file it points at. It is not a public entry point, and the name is often not re-exported from the package root either — `DropdownLayoutOption` is not exported from `@wix/design-system`, so there is no shorter import to substitute.
86
+ - You usually don't need the declaration at all. Where the type is a **prop you fill in** — WDS option shapes like `SingleSelectFilter`'s and `AutoCompleteFilter`'s `items` — look the *component* up in the `wix-design-system` skill and use the shape its docs show. Where it is a **pass-through you never construct** — the BI logger params behind optional fields like `biAdditionalInfo` — pass what the patterns doc shows, or omit it; it is optional.
87
+
88
+ If a name you genuinely need stays unresolved after that, stop and say so, and name the bundle and the exact import path that dead-ended. Do not guess a shape and do not go spelunking in `node_modules` — a wrong guess compiles here and breaks at runtime, which is worse than the missing type.
89
+
90
+ A handful of names carry `"status": "unreachable"` — plus `"unexported": true` from **1.465.0** — with a message saying not to import them (the `...BaseProps` interfaces a component's props `extends`). Read those for the props they contribute; don't write an import for them.
36
91
 
37
- A handful of names carry `"status": "unreachable"` with a message saying not to import them (the `...BaseProps` interfaces a component's props `extends`). Read those for the props they contribute; don't write an import for them.
92
+ `status` also carries `"deprecated"`, and there the `statusMessage` names the replacement — `PrimaryPageButton` says *"Use `PrimaryActions` component instead."* Check it before you commit to a name — nothing else in the lookup path will stop you, since a deprecated component still compiles and still renders. If the index calls a name deprecated, use what its message names instead.
38
93
 
39
94
  ## Subpath entry points
40
95
 
@@ -49,4 +104,9 @@ Links to `https://www.docs.wixdesignsystem.com/` are external (Wix Design System
49
104
  ## Tips
50
105
 
51
106
  - **Compound components** have separate docs per sub-part: `CollectionPage.md`, `CollectionPage.Header.md`, `CollectionPage.Content.md`.
52
- - **Hook docs** list configuration options as props in the API table.
107
+ - **Hook docs** list configuration options as props — in the API table when the doc has no
108
+ `bundle` field, otherwise in the bundle it points at.
109
+ - **Heavy examples live beside the doc.** A variation whose code was long is written out
110
+ separately, and the doc keeps the heading, the description and an exact path:
111
+ `Example code: read \`dist/docs/ToolbarFilters/apply-changes.tsx\``. Read that path only if you
112
+ need that particular variation — the heading and description are usually enough to choose.
@@ -25,7 +25,7 @@ import type { A11y, Direction } from '@wix/editor-react-types';
25
25
  import { convertA11yKeysToHtmlFormat } from '@wix/react-component-utils';
26
26
 
27
27
  export type TabsProps = {
28
- id?: string;
28
+ id: string;
29
29
  className?: string;
30
30
  direction?: Direction;
31
31
  a11y?: A11y;