@wix/agent-skills 1.16.2 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/package.json +1 -1
  2. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +134 -120
  3. package/skills/wix-app/references/EMBEDDED_SCRIPT.md +6 -0
  4. package/skills/wix-app/references/SITE_PLUGIN.md +2 -2
  5. package/skills/wix-app/references/backend-event/COMMON-EVENTS.md +2 -2
  6. package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +182 -99
  7. package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +92 -47
  8. package/skills/wix-app/references/editor-react-component/BRANDED-COMPONENTS.md +15 -6
  9. package/skills/wix-app/references/editor-react-component/COMPONENT-CONTRACT.md +275 -0
  10. package/skills/wix-app/references/editor-react-component/COMPONENT-PREVIEW.md +29 -42
  11. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +153 -449
  12. package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +66 -19
  13. package/skills/wix-app/references/editor-react-component/DIRECTIONALITY.md +53 -158
  14. package/skills/wix-app/references/editor-react-component/EDITOR-EXTENSION-CONFIGURATION.md +78 -0
  15. package/skills/wix-app/references/editor-react-component/FUNCTION-HANDLERS.md +42 -134
  16. package/skills/wix-app/references/editor-react-component/MANIFEST-ERRORS.md +27 -0
  17. package/skills/wix-app/references/editor-react-component/PARTS.md +45 -24
  18. package/skills/wix-app/references/editor-react-component/PROPS-VS-CSS.md +63 -179
  19. package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +79 -163
  20. package/skills/wix-app/references/editor-react-component/SITE-CONTEXT-HOOKS.md +36 -21
  21. package/skills/wix-app/references/editor-react-component/SSR.md +30 -99
  22. package/skills/wix-base44-connector/SKILL.md +34 -17
  23. package/skills/wix-base44-connector/scripts/utils.js +33 -25
  24. package/skills/wix-headless/entry/bootstrap.mjs +9 -2
  25. package/skills/wix-headless/references/SDK_HANDOFF.md +1 -1
  26. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +42 -23
  27. package/skills/wix-headless/references/inline-recipes/how-to-code-pricing-plans.md +10 -8
  28. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-orders.md +27 -24
  29. package/skills/wix-headless/references/managed/AUTHENTICATION.md +5 -0
  30. package/skills/wix-manage/SKILL.md +14 -2
  31. package/skills/wix-manage/references/bookings/booking-system-integration-gaps.md +20 -13
  32. package/skills/wix-manage/references/bookings/create-class-service.md +1 -1
  33. package/skills/wix-manage/references/bookings/end-to-end-booking-flow.md +24 -11
  34. package/skills/wix-manage/references/cms/cms-ecommerce-catalog-integration.md +5 -5
  35. package/skills/wix-manage/references/rich-content/author-ricos-rich-content.md +182 -5
  36. package/skills/wix-manage/references/seo/manage-seo-tags.md +315 -0
  37. package/skills/wix-manage/references/seo/manage-url-redirects.md +250 -0
  38. package/skills/wix-manage/references/sites/query-sites.md +72 -161
  39. package/skills/wix-replatform/resources/rp-mapper/wix-business-solutions-taxonomy.md +5 -6
  40. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +13 -9
  41. package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +10 -7
  42. package/skills/wix-vibe-headless/platforms/base44.md +13 -10
  43. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +2 -0
  44. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-checkout.js +9 -8
  45. package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +4 -1
  46. package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartDrawer.jsx +23 -11
  47. package/skills/wix-vibe-headless/references/restaurants/app/context/OrderCartContext.jsx +1 -1
  48. package/skills/wix-vibe-headless/references/restaurants/app/rest/wix-restaurants-ordering.js +29 -31
  49. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +15 -8
  50. package/skills/wix-vibe-headless/references/storefront/app/components/CartDrawer.jsx +37 -38
  51. package/skills/wix-vibe-headless/references/storefront/app/context/CartContext.jsx +2 -2
  52. package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-cart.js +35 -35
  53. package/skills/wix-app/references/editor-react-component/A11Y-REVIEW-REFERENCE.md +0 -172
  54. package/skills/wix-app/references/editor-react-component/A11Y-REVIEW.md +0 -143
  55. package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +0 -484
  56. package/skills/wix-app/references/editor-react-component/COMPONENT-CONFIGURATION.md +0 -225
  57. package/skills/wix-app/references/editor-react-component/EDIT-FLOW.md +0 -6
  58. package/skills/wix-app/references/editor-react-component/REACT-PATTERNS.md +0 -95
@@ -1,484 +0,0 @@
1
- # Component API
2
-
3
- Rules and patterns for props structure, elementProps, data types, file structure, containers, data-driven components, and array props.
4
-
5
- ---
6
-
7
- ## Should This Use elementProps or CSS?
8
-
9
- ```
10
- Is this element a named part (carries a global class string)?
11
- │
12
- ├─ YES
13
- │ └─ ✅ It gets an elementProps entry — spread it + merge its className.
14
- │ Add config fields inside the entry only as needed
15
- │ (data, direction, event handlers).
16
- │
17
- └─ NO → purely visual/decorative non-part
18
- (icons, separators, decorations, layout wrappers,
19
- elements only hidden/shown via CSS)
20
- └─ ❌ CSS class only — no elementProps entry
21
- ```
22
-
23
- ---
24
-
25
- ## Rules
26
-
27
- ### Component Props Structure
28
-
29
- ```typescript
30
- interface ComponentProps {
31
- // Identity
32
- id?: string;
33
- className?: string;
34
-
35
- // Mandatory features (from @wix/editor-react-types)
36
- direction?: Direction;
37
- a11y?: A11y; // ALL ARIA attributes come through this (ariaLabel, role, etc.)
38
-
39
- // Component-specific props (NO children unless container-type - see container rules below)
40
- label?: string;
41
- items?: Array<ItemType>;
42
- // ... from specification
43
- // NEVER add: ariaLabel, ariaDescribedBy, role, etc. - use a11y prop instead
44
-
45
- // Sub-component configuration (only if needed - see elementProps rules)
46
- elementProps?: {
47
- [partName]?: {
48
- [configProp]?: string | boolean | number; // Only include if element needs config beyond className
49
- direction?: Direction;
50
- };
51
- };
52
- }
53
- ```
54
-
55
- ### Propagate `elementProps` to inner elements
56
-
57
- `elementProps` is a map keyed by the manifest's inner-element keys; each entry
58
- carries that element's `className` (the editor sets it — this is how design
59
- states reach the element) plus any data.
60
-
61
- **Every named inner element — every element that carries a global class
62
- string — gets an `elementProps` entry, and you spread that entry onto the
63
- element.** This is mandatory, even when the element needs no other config:
64
- without it the editor cannot style that element or drive its states.
65
-
66
- How `className` gets merged depends on what the element is:
67
-
68
- - **Raw HTML element** (`<button>`, `<li>`, `<div>`): merge
69
- `elementProps?.<key>.className` inline, alongside the global string and module
70
- class — there's no component to do it.
71
- - **Sub-component built with this skill** (`<Inner/>`): the spread alone is
72
- enough. `className` rides along inside it, and the sub-component merges it onto
73
- its own root (every skill component merges its incoming `className`). Don't
74
- merge it again at the call site.
75
-
76
- ```tsx
77
- interface PlanCardProps {
78
- className?: string;
79
- elementProps?: {
80
- cta?: { className?: string; href?: string };
81
- };
82
- }
83
-
84
- // Raw HTML element — spread + merge className inline.
85
- // Note: the elementProps key is the short part name (`cta`), while the global
86
- // class is prefixed with the component name (`plan-card-cta`). Keep them as-is.
87
- <button {...elementProps?.cta} className={classNames('plan-card-cta', styles.cta, elementProps?.cta?.className)}>
88
- {label}
89
- </button>
90
-
91
- // Sub-component built with this skill — spread is enough (it merges className itself):
92
- <PlanRow {...elementProps?.planRow} />
93
- ```
94
-
95
- **Non-parts** (module-class-only elements: icons, decorations, separators,
96
- layout wrappers — no global class) get no entry. Style them with CSS.
97
-
98
- **Inside each entry**, add only the config the element needs (data, direction,
99
- event handlers). Never add a bare `className?` as the *only* field to decide
100
- whether an element qualifies — `className` always flows through; the entry
101
- exists because the element is a named part.
102
-
103
- ### What Qualifies as a Part
104
-
105
- See [`PARTS.md`](PARTS.md) for root election (Step 0), the mandatory filter, and full rules. The root gets no `elementProps` entry — its `className`, `a11y`, and `direction` arrive as top-level props.
106
-
107
- ### Derived values are not props
108
-
109
- If a displayed value can be computed with a simple pure function from
110
- other props and/or internal state, compute it internally — don't
111
- expose it as a prop. Expose only the source inputs (use numeric types
112
- when arithmetic is needed: `price: number`, not `price: string`).
113
-
114
- **Example:** subtotal = `price × quantity` → computed inside the component, not a prop.
115
-
116
- ### Data-Driven Components (NO children in exported props)
117
-
118
- - Component's **exported interface** must NOT accept `children` prop
119
- - ALL content MUST come through explicit named props (see "Derived values" above for what stays internal):
120
- - Text (labels, placeholders, messages) → `label`, `text`, `placeholder`, etc.
121
- - Media (images, videos, icons) → `imageSrc`, `videoUrl`, `iconName`, etc.
122
- - Links (URLs, hrefs) → `link`, `href`, `url`, etc.
123
- - Collections (list items, options, menu items) → `items`, `options`, `menuItems`, etc.
124
- - **Internal implementation** can use children for composition between sub-components
125
- - Hardcoded values are ONLY for fallback defaults when props are undefined
126
-
127
- **Exception — Container-type components:** Components whose purpose is to wrap arbitrary child elements (e.g., BoxContainer) MAY accept `children: React.ReactNode`. This applies only to structural containers — data-driven leaf components (Button, Tabs, Accordion, etc.) must NOT use `children`.
128
-
129
- ### Array Props: Data on Parent Only
130
-
131
- When the parent component defines an array prop (e.g., `items`), child/item components receive a single item directly. They do NOT redeclare the data structure in their own props.
132
-
133
- ### Array Element Types: Always Objects with Named Keys
134
-
135
- Array elements MUST be objects with named keys. This enables stable item identity (each item can carry its own `id`/`key`), non-breaking extension (new fields can be added later without changing the prop signature), and semantic naming (each value has meaning instead of being an opaque scalar).
136
-
137
- **Allowed forms:**
138
-
139
- - Inline object literal: `Array<{ key: ValueType, ... }>`
140
- - Named interface where the interface itself is an object with named keys (e.g. `Array<AccordionItem>` is OK because `AccordionItem` is `{ name, content }`)
141
-
142
- **Never allowed as the array element:**
143
-
144
- - Primitives: `Array<string>`, `Array<number>`, `Array<boolean>`
145
- - Leaf data types from `@wix/editor-react-types`: `Array<Image>`, `Array<Link>`, `Array<Video>`, `Array<Audio>`, `Array<VectorArt>`, `Array<RichText>`. Wrap them in an object instead.
146
- - Nested arrays: `Array<Array<{cover: image, caption: string}>>` `Array<{items: Array<image>, caption: string}>`
147
-
148
- **❌ Wrong:**
149
-
150
- ```typescript
151
- tags: Array<string>;
152
- prices: Array<number>;
153
- flags: Array<boolean>;
154
- images: Array<Image>;
155
- links: Array<Link>;
156
- nestedArrays: Array<Array<any>>
157
- ```
158
-
159
- **✅ Correct:**
160
-
161
- ```typescript
162
- tags: Array<{ label: string }>;
163
- prices: Array<{ amount: number }>;
164
- flags: Array<{ enabled: boolean }>;
165
- gallery: Array<{ image: Image, caption?: string }>;
166
- links: Array<{ link: Link, label: string }>;
167
- items: Array<AccordionItem>; // AccordionItem is { name, content }
168
- ```
169
-
170
- ### Container Components (Blackbox Content)
171
-
172
- When a component specification indicates a "container" or "slot" area where users can add nested content, use `React.ReactNode` for that content prop.
173
-
174
- **When to use `React.ReactNode` for a content prop:**
175
-
176
- - The specification describes a "container" or "content area"
177
- - Users should be able to add arbitrary nested components
178
- - The component doesn't control what goes inside that area
179
-
180
- **RTL Support:** Elements that render `React.ReactNode` content MUST have `dir="ltr"` to prevent RTL inheritance from the parent component. See [`DIRECTIONALITY.md`](DIRECTIONALITY.md).
181
-
182
- ### Component Data Types
183
-
184
- When creating TypeScript interfaces for component props, use types from `@wix/editor-react-types` for more complex types, to see the allowed type from this library, look at the following file `node_modules/@wix/react-component-schema/dist/editor-react-types.d.ts`:
185
-
186
- ```typescript
187
- import type { Link } from "@wix/editor-react-types"; // Reference at node_modules/@wix/react-component-schema/dist/editor-react-types.d.ts
188
- ```
189
-
190
- For **function event handler props** (`onClick`, `onDblClick`, `onChange`, `onFocus`, `onBlur`, `onMouseIn`, `onMouseOut`) and custom callbacks, follow [`FUNCTION-HANDLERS.md`](FUNCTION-HANDLERS.md). Key rules:
191
-
192
- - Use the exact SDK prop names from that file — the manifest system recognizes them
193
- - Wire them to the correct DOM events (note: `onDblClick` → `onDoubleClick`, `onMouseIn` → `onMouseEnter`, `onMouseOut` → `onMouseLeave`)
194
- - Custom callbacks not tied to DOM events use `() => void` (no React event parameter)
195
-
196
- ### External resources are forbidden
197
-
198
- All resources rendered or fetched by the component (images, icons, fonts,
199
- videos, audio, JSON data, etc.) MUST come from Wix services. Never reference
200
- or call external (non-Wix) hosts — no `unsplash.com`, `placehold.co`,
201
- `picsum.photos`, third-party CDN icon sets, or any custom backend the user
202
- hasn't asked for. This rule covers both `src`/`href` attributes and any
203
- runtime fetching.
204
-
205
- Allowed image hosts: `static.wixstatic.com` (and other `*.wixstatic.com`
206
- subdomains). Allowed data: values supplied through props (populated by the
207
- editor) or imported local assets bundled with the component.
208
-
209
- ### Default values for `Image` props
210
-
211
- Image defaults belong in the `<componentName>.props.ts` file's exported
212
- `defaultProps` constant (consumed by `withDefaults(Component, defaultProps)` in
213
- `component.tsx`). Use a Wix-hosted image from the Free-from-Wix public
214
- media catalog and populate **only** `uri`, `url`, and `alt` — leave
215
- `width`, `height`, `focalPoint`, etc. unset so the editor fills them when
216
- the user picks a real image.
217
-
218
- By default, use the canonical fallback URL from the examples below for
219
- every `Image` default (`url` and `uri` derived from the same `fileName`).
220
- **Only when the user explicitly asks for different/better default images**,
221
- fetch candidates from the Wix Free-from-Wix catalog:
222
-
223
- ```
224
- GET https://publicmedia.wix.com/public/light_items?guid=bca5cb9f-45d2-4b11-8d6c-c9a7e7bd2873%3Aglobal%3Awix&pageSize=20&pageNumber=1&language=en&tags=free&mediaType=picture
225
- ```
226
-
227
- The endpoint is unauthenticated. Pick an item whose `displayTags` /
228
- `title` fit the component's purpose, then build the `Image` default from
229
- its `fileName`:
230
-
231
- - `url` → `` `https://static.wixstatic.com/media/${fileName}` ``
232
- - `uri` → `fileName`
233
- - `alt` → a short human description (use the item's `title` or
234
- `displayTags`)
235
-
236
- Do not call this endpoint when the user hasn't asked for it — the
237
- canonical fallback URL is fine for unattended scaffolds.
238
-
239
- **Default image pool — use a different image for each slot:**
240
-
241
- | # | fileName | Description |
242
- |---|----------|-------------|
243
- | 1 | `11062b_2f97b87dcea2446fa48e9ad9c5457ae1~mv2.jpg` | Tropical beach aerial |
244
- | 2 | `11062b_73f31c7e7d3544c69dc8ecd8d34c5717~mv2.jpg` | Dead Sea landscape |
245
- | 3 | `11062b_3682ebfcb08e4da5b3168b62819a1e68~mv2.jpg` | Palm tree sunset |
246
- | 4 | `11062b_45e67783d39c4963ab9e4fc418173233~mv2.jpg` | Abstract pink waves |
247
- | 5 | `11062b_4c11f014b0d04948b2e6f554076bc40a~mv2.jpg` | Coastal village aerial |
248
-
249
- When a component needs **more than one** image default, cycle through
250
- the pool above so every slot gets a visually distinct image. For a
251
- single image, use image #1.
252
-
253
- **Single `Image` prop:**
254
-
255
- ```typescript
256
- export const defaultProps = {
257
- image: {
258
- url: "https://static.wixstatic.com/media/11062b_2f97b87dcea2446fa48e9ad9c5457ae1~mv2.jpg",
259
- uri: "11062b_2f97b87dcea2446fa48e9ad9c5457ae1~mv2.jpg",
260
- alt: "Default image",
261
- },
262
- } as const satisfies Omit<ExampleComponentProps, "id" | "className">;
263
- ```
264
-
265
- **Array of objects with an `Image` field:**
266
-
267
- ```typescript
268
- export const defaultProps = {
269
- cards: [
270
- {
271
- title: "First card",
272
- image: {
273
- url: "https://static.wixstatic.com/media/11062b_2f97b87dcea2446fa48e9ad9c5457ae1~mv2.jpg",
274
- uri: "11062b_2f97b87dcea2446fa48e9ad9c5457ae1~mv2.jpg",
275
- alt: "First card image",
276
- },
277
- },
278
- {
279
- title: "Second card",
280
- image: {
281
- url: "https://static.wixstatic.com/media/11062b_73f31c7e7d3544c69dc8ecd8d34c5717~mv2.jpg",
282
- uri: "11062b_73f31c7e7d3544c69dc8ecd8d34c5717~mv2.jpg",
283
- alt: "Second card image",
284
- },
285
- },
286
- ],
287
- } as const satisfies Omit<ExampleComponentProps, "id" | "className">;
288
- ```
289
-
290
- **Inline fallback for HTML `src` / `href`:** when rendering a raw HTML
291
- attribute that takes a URL (`<img src>`, `<source src>`, `<video poster>`,
292
- `<a href>` for an image link, etc.) and the value could be empty, fall
293
- back to the same Wix-hosted URL — never to an external host or a relative
294
- path that doesn't exist:
295
-
296
- ```tsx
297
- <img
298
- src={
299
- image?.url ||
300
- "https://static.wixstatic.com/media/11062b_2f97b87dcea2446fa48e9ad9c5457ae1~mv2.jpg"
301
- }
302
- alt={image?.alt || "Default image"}
303
- />
304
- ```
305
-
306
- ### Component File Splitting
307
-
308
- Split logical UI pieces into separate named components. Never write inline JSX blocks for distinct complex UI pieces.
309
-
310
- **File structure for complex components (many subcomponents):**
311
-
312
- ```
313
- ComponentName/
314
- ├── components/ # Subcomponents folder
315
- │ ├── SubComponent1/
316
- │ │ ├── SubComponent1.tsx
317
- │ │ ├── SubComponent1.module.scss
318
- │ │ └── index.ts
319
- │ └── SubComponent2/
320
- │ ├── SubComponent2.tsx
321
- │ └── index.ts
322
- ├── hooks/ # Custom hooks folder
323
- │ ├── index.ts
324
- │ └── useCustomHook.ts
325
- ```
326
-
327
- **When to extract a sub-component:**
328
-
329
- - JSX block represents a logical complex unit (button, control, section, item)
330
- - Component has its own props interface
331
- - Logic is reusable or testable independently
332
- - Block has more than 15-20 lines of JSX
333
-
334
- ---
335
-
336
- ## Patterns
337
-
338
- ### Data-Driven Pattern
339
-
340
- **❌ Wrong:**
341
-
342
- ```typescript
343
- export interface ButtonProps {
344
- children: React.ReactNode; // ❌
345
- }
346
- <Button>Click Me</Button>
347
- ```
348
-
349
- **✅ Correct:**
350
-
351
- ```typescript
352
- export interface ButtonProps {
353
- label?: string;
354
- icon?: string;
355
- }
356
- <Button label={label} icon={icon} />
357
- ```
358
-
359
- Component controls rendering internally:
360
-
361
- ```typescript
362
- const List = ({ items }) => (
363
- <div>
364
- {items.map(item => (
365
- <ListItem key={item.id}>{item.label}</ListItem>
366
- ))}
367
- </div>
368
- );
369
- ```
370
-
371
- ### Array Props Pattern
372
-
373
- Parent defines array structure, child receives single item:
374
-
375
- ```typescript
376
- // Parent
377
- interface ParentProps {
378
- items: Array<AccordionItem>; // Array defined here
379
- }
380
-
381
- interface AccordionItem {
382
- name: string;
383
- content: React.ReactNode;
384
- }
385
-
386
- // Child receives single item
387
- interface ChildProps {
388
- item: AccordionItem & { id: string }; // Single item
389
- isOpen?: boolean;
390
- }
391
-
392
- // Parent maps
393
- items.map((item, index) => (
394
- <Child key={index} item={{ ...item, id: index.toString() }} />
395
- ))
396
- ```
397
-
398
- ### Container Components Pattern
399
-
400
- For "container" or "slot" areas, use `React.ReactNode`:
401
-
402
- ```typescript
403
- interface AccordionItem {
404
- name: string;
405
- content: React.ReactNode; // Users add any content here
406
- }
407
-
408
- // Render
409
- {items.map((item, index) => (
410
- <div key={index} dir="ltr">
411
- {typeof item.content === 'function' ? item.content({}) : item.content}
412
- </div>
413
- ))}
414
- ```
415
-
416
- ---
417
-
418
- ## Common Mistakes
419
-
420
- ### Using children prop in exported interface
421
-
422
- **❌ Wrong:**
423
-
424
- ```typescript
425
- export interface CardProps {
426
- children: React.ReactNode; // ❌ children + React.ReactNode both forbidden
427
- }
428
- <Card><CardHeader>Title</CardHeader></Card>
429
- ```
430
-
431
- **✅ Correct:**
432
-
433
- ```typescript
434
- export interface CardProps {
435
- title: string;
436
- content: React.ReactNode;
437
- }
438
- <Card title="Title" content={<div>Content</div>} />
439
- ```
440
-
441
- ### Adding elementProps for CSS-only elements
442
-
443
- **❌ Wrong:**
444
-
445
- ```typescript
446
- elementProps?: {
447
- icon?: { className?: string; } // ❌ Only className
448
- separator?: { className?: string; } // ❌ Only className
449
- }
450
- ```
451
-
452
- **✅ Correct:**
453
-
454
- ```typescript
455
- // No elementProps for purely visual elements (including conditionally displayed)
456
- // Style via CSS classes directly
457
- ```
458
-
459
- **Why:** Don't declare a `className?:` field — `className` already flows through each named inner element's `elementProps` entry (see "Propagate `elementProps` to inner elements"). Conditional display is controlled via CSS, not React props.
460
-
461
- ### Using T[] array syntax
462
-
463
- Use `Array<T>` over `T[]`.
464
-
465
- **❌ Wrong:**
466
-
467
- ```typescript
468
- interface ComponentProps {
469
- items: Item[]; // ❌ Wrong syntax
470
- tags: string[]; // ❌ Wrong syntax
471
- tags: Array<string>; // ❌ Element must be an object with named keys
472
- }
473
- ```
474
-
475
- **✅ Correct:**
476
-
477
- ```typescript
478
- interface ComponentProps {
479
- items: Array<Item>; // ✅ Correct syntax
480
- tags: Array<{ label: string }>; // ✅ Element is an object with named keys
481
- }
482
- ```
483
-
484
- See also: [Array Element Types: Always Objects with Named Keys](#array-element-types-always-objects-with-named-keys) — items must be objects with named keys.
@@ -1,225 +0,0 @@
1
- # Component Configuration
2
-
3
- After scaffolding the component and running `npx wix build && npx wix generate manifest`,
4
- configure the component's behavior in the editor by writing **partial
5
- manifest overrides** in the component's hand-edited extension file
6
- (`<ComponentName>.extension.ts`). That file imports the auto-generated
7
- manifest and spreads it; specific fields are overridden inline. Re-running
8
- this command regenerates each `<ComponentName>.generated.ts`
9
- companion but never touches the overrides authored in the extension file.
10
-
11
- ---
12
-
13
- ## 1. Verifying that height sizing type meets user needs
14
-
15
- Set `installation.initialSize.height.sizingType` based on whether the
16
- component's own content decides how tall it is.
17
-
18
- ### Heuristic — one question
19
-
20
- **Does the component's own content decide how tall it is?**
21
-
22
- - **Yes — height should grow with text the user types or children they drop inside** → `LAYOUT.SIZING_TYPE.content`. Omit `pixels`.
23
- - **No — the component is a framed visual** (a graphic, an embedded media surface, a form control with a standard height, an empty placeholder) → `LAYOUT.SIZING_TYPE.pixels`. Provide a `pixels` default that matches its natural visual size.
24
-
25
- **Tiebreaker:** if a designer would drag a handle to set the height, it's `pixels`. If the height should just fit whatever is inside, it's `content`.
26
-
27
- ### Where to write the override
28
-
29
- ```ts
30
- import { extensions } from '@wix/astro/builders';
31
- import { LAYOUT } from '@wix/react-component-schema';
32
- import { manifest } from './ComponentName.generated';
33
-
34
- const componentExtension = extensions.editorReactComponent({
35
- // …other fields…
36
- installation: {
37
- initialSize: {
38
- width: {
39
- sizingType: LAYOUT.SIZING_TYPE.pixels,
40
- pixels: 250,
41
- },
42
- height: {
43
- sizingType: LAYOUT.SIZING_TYPE.updateMe,
44
- },
45
- },
46
- },
47
- });
48
- ```
49
-
50
- ### Examples
51
-
52
- **Content-driven** (`LAYOUT.SIZING_TYPE.content`) — testimonial card,
53
- FAQ accordion, pricing tier, blog-post body, list/grid of arbitrary
54
- children:
55
-
56
- ```ts
57
- height: {
58
- sizingType: LAYOUT.SIZING_TYPE.content,
59
- }
60
- ```
61
-
62
- **Framed visual** (`LAYOUT.SIZING_TYPE.pixels`) — hero banner with a
63
- fixed image, video embed, color-picker swatch grid, OTP input, empty
64
- placeholder slot:
65
-
66
- ```ts
67
- height: {
68
- sizingType: LAYOUT.SIZING_TYPE.pixels,
69
- pixels: 320,
70
- }
71
- ```
72
-
73
- ---
74
-
75
- ## 2. Verifying that resize direction meets user needs
76
-
77
- Set `editorElement.layout.resizeDirection` based on which axes the
78
- designer should be able to control with a drag handle. Allow an axis
79
- if dragging it produces a meaningful, intended change. Disallow it if
80
- dragging would do nothing visible or would break the component's
81
- identity.
82
-
83
- ### Heuristic — which axes are meaningful?
84
-
85
- | Choice | When to use |
86
- |--------|-------------|
87
- | `horizontalAndVertical` | Content fills or stretches in both axes. Hero, carousel, gallery, card grid, embed, form control, any framed visual. **Default for most components.** |
88
- | `horizontal` | Height is rigid/intrinsic — cannot meaningfully stretch. Breadcrumb, tag row, nav bar, single-line input, slider rail. |
89
- | `vertical` | Width is rigid/intrinsic. Vertical stack, ribbon, sidebar rail. |
90
- | `aspectRatio` | Distortion breaks identity — logo, illustration, animation. |
91
- | `none` | Size fully owned by a parent layout. Never for top-level components. |
92
-
93
- **Tiebreaker:** if a drag handle on an axis would feel inert or wrong
94
- to a designer, take it away.
95
-
96
- ### Where to write the override
97
-
98
- ```ts
99
- import { extensions } from '@wix/astro/builders';
100
- import { LAYOUT } from '@wix/react-component-schema';
101
- import { manifest } from './ComponentName.generated';
102
-
103
- const componentExtension = extensions.editorReactComponent({
104
- // …other fields…
105
- editorElement: {
106
- ...manifest.editorElement,
107
- layout: {
108
- resizeDirection: LAYOUT.RESIZE_DIRECTION._selectedResizeDirection_,
109
- },
110
- },
111
- });
112
- ```
113
-
114
- ### Examples
115
-
116
- ```ts
117
- // hero, carousel, gallery, card grid, embed, form
118
- resizeDirection: LAYOUT.RESIZE_DIRECTION.horizontalAndVertical,
119
-
120
- // breadcrumb, tag row, nav bar, slider rail
121
- resizeDirection: LAYOUT.RESIZE_DIRECTION.horizontal,
122
-
123
- // logo, illustration, animation
124
- resizeDirection: LAYOUT.RESIZE_DIRECTION.aspectRatio,
125
- ```
126
-
127
- ---
128
-
129
- ## 3. Wiring defaults into the manifest
130
-
131
- 1. **Define and export `defaultProps` from `<componentName>.props.ts`** — this is the single source of truth used by both `component.tsx` and the extension file.
132
- 2. **Import `componentUrl` from `'./component.tsx?url'`** (the wrapped component), not from `'./ComponentName.tsx?url'` (the raw component).
133
- 3. **Wrap `editorElement` with `withEditorElementDefaults`** using the same `defaultProps`.
134
-
135
- ```ts
136
- import { withEditorElementDefaults } from '@wix/react-component-utils';
137
- import componentUrl from './component.tsx?url';
138
- import { defaultProps } from './<componentName>.props';
139
-
140
- // in the extension:
141
- editorElement: withEditorElementDefaults({
142
- ...manifest.editorElement,
143
- }, defaultProps),
144
- resources: {
145
- ...manifest.resources,
146
- client: { componentUrl },
147
- },
148
- ```
149
-
150
- ---
151
-
152
- ## 4. Enabling automatic installation on Harmony editor
153
-
154
- **Always include `"staticContainer": "HOMEPAGE"`** in `installation` so the
155
- component is automatically installed on the Harmony editor.
156
-
157
- ```ts
158
- const componentExtension = extensions.editorReactComponent({
159
- // …other fields…
160
- installation: {
161
- // …other fields…
162
- staticContainer: 'HOMEPAGE',
163
- },
164
- });
165
- ```
166
-
167
- ---
168
-
169
- ## 5. Adding range constraints for numeric props
170
-
171
- The zero-config pipeline reads `@min` and `@max` JSDoc tags on numeric props and
172
- emits them as `number: { min, max }` in the generated manifest. Add these tags
173
- directly on the prop in the component's props interface — no extension file
174
- override is needed.
175
-
176
- ### Heuristic — does this number have a fixed domain?
177
-
178
- | Scenario | Action |
179
- |----------|--------|
180
- | Rating 0–5, column count 1–6, items per row 1–4 | Add `@min` / `@max` |
181
- | Volume 0–100, playback speed 0.5–5, autoplay delay 0.5–30 | Add `@min` / `@max` |
182
- | Geo coordinates, zoom level | Add `@min` / `@max` |
183
- | Arbitrary count, free-form price, unconstrained input | Omit — leave as `number` |
184
- | Semantic index (active tab, active slide, active item) | Omit — upper bound is driven by the component's own item count, not a fixed domain |
185
-
186
- ### How to write the tags
187
-
188
- Add `@min` and `@max` inline in the JSDoc comment for the prop in `<componentName>.props.ts`:
189
-
190
- ```ts
191
- export interface RatingWidgetProps {
192
- /** @min 0 @max 5 */
193
- rating: number;
194
- }
195
- ```
196
-
197
- Zero-config picks these up during `npx wix build && npx wix generate manifest`
198
- and emits:
199
-
200
- ```ts
201
- rating: {
202
- dataType: 'number',
203
- number: { min: '0', max: '5' },
204
- }
205
- ```
206
-
207
- ### Examples
208
-
209
- ```ts
210
- // Star rating 0–5
211
- /** @min 0 @max 5 */
212
- rating: number;
213
-
214
- // Volume 0–100
215
- /** @min 0 @max 100 */
216
- volume: number;
217
-
218
- // Playback speed 0.5–5
219
- /** @min 0.5 @max 5 */
220
- speed: number;
221
-
222
- // Column count 1–6
223
- /** @min 1 @max 6 */
224
- columns: number;
225
- ```