@wix/agent-skills 1.16.3 → 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 (55) hide show
  1. package/package.json +1 -1
  2. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +134 -127
  3. package/skills/wix-app/references/SITE_PLUGIN.md +2 -2
  4. package/skills/wix-app/references/backend-event/COMMON-EVENTS.md +2 -2
  5. package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +182 -99
  6. package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +92 -48
  7. package/skills/wix-app/references/editor-react-component/BRANDED-COMPONENTS.md +15 -6
  8. package/skills/wix-app/references/editor-react-component/COMPONENT-CONTRACT.md +275 -0
  9. package/skills/wix-app/references/editor-react-component/COMPONENT-PREVIEW.md +29 -42
  10. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +153 -449
  11. package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +53 -29
  12. package/skills/wix-app/references/editor-react-component/DIRECTIONALITY.md +53 -158
  13. package/skills/wix-app/references/editor-react-component/EDITOR-EXTENSION-CONFIGURATION.md +78 -0
  14. package/skills/wix-app/references/editor-react-component/FUNCTION-HANDLERS.md +42 -134
  15. package/skills/wix-app/references/editor-react-component/MANIFEST-ERRORS.md +11 -3
  16. package/skills/wix-app/references/editor-react-component/PARTS.md +46 -24
  17. package/skills/wix-app/references/editor-react-component/PROPS-VS-CSS.md +63 -179
  18. package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +79 -163
  19. package/skills/wix-app/references/editor-react-component/SITE-CONTEXT-HOOKS.md +36 -21
  20. package/skills/wix-app/references/editor-react-component/SSR.md +30 -99
  21. package/skills/wix-base44-connector/SKILL.md +34 -17
  22. package/skills/wix-base44-connector/scripts/utils.js +33 -25
  23. package/skills/wix-headless/entry/bootstrap.mjs +9 -2
  24. package/skills/wix-headless/references/SDK_HANDOFF.md +1 -1
  25. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +42 -23
  26. package/skills/wix-headless/references/inline-recipes/how-to-code-pricing-plans.md +10 -8
  27. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-orders.md +27 -24
  28. package/skills/wix-headless/references/managed/AUTHENTICATION.md +5 -0
  29. package/skills/wix-manage/SKILL.md +11 -1
  30. package/skills/wix-manage/references/bookings/booking-system-integration-gaps.md +20 -13
  31. package/skills/wix-manage/references/bookings/end-to-end-booking-flow.md +24 -11
  32. package/skills/wix-manage/references/cms/cms-ecommerce-catalog-integration.md +5 -5
  33. package/skills/wix-manage/references/seo/manage-seo-tags.md +315 -0
  34. package/skills/wix-manage/references/seo/manage-url-redirects.md +250 -0
  35. package/skills/wix-manage/references/sites/query-sites.md +72 -161
  36. package/skills/wix-replatform/resources/rp-mapper/wix-business-solutions-taxonomy.md +5 -6
  37. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +13 -9
  38. package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +10 -7
  39. package/skills/wix-vibe-headless/platforms/base44.md +13 -10
  40. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +2 -0
  41. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-checkout.js +9 -8
  42. package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +4 -1
  43. package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartDrawer.jsx +23 -11
  44. package/skills/wix-vibe-headless/references/restaurants/app/context/OrderCartContext.jsx +1 -1
  45. package/skills/wix-vibe-headless/references/restaurants/app/rest/wix-restaurants-ordering.js +29 -31
  46. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +15 -8
  47. package/skills/wix-vibe-headless/references/storefront/app/components/CartDrawer.jsx +37 -38
  48. package/skills/wix-vibe-headless/references/storefront/app/context/CartContext.jsx +2 -2
  49. package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-cart.js +35 -35
  50. package/skills/wix-app/references/editor-react-component/A11Y-REVIEW-REFERENCE.md +0 -172
  51. package/skills/wix-app/references/editor-react-component/A11Y-REVIEW.md +0 -143
  52. package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +0 -516
  53. package/skills/wix-app/references/editor-react-component/COMPONENT-CONFIGURATION.md +0 -225
  54. package/skills/wix-app/references/editor-react-component/EDIT-FLOW.md +0 -6
  55. package/skills/wix-app/references/editor-react-component/REACT-PATTERNS.md +0 -95
@@ -1,11 +1,21 @@
1
1
  # Design States
2
2
 
3
- A design state styles an element differently per interaction (`hover`,
4
- `focus`, `disabled`, `invalid`) or per a selectable value in its data
5
- (`selected`, `active`, `open`, …). Author states in the component's `.tsx`
6
- and `.module.css`.
3
+ Use this reference when a named part changes appearance through interaction or
4
+ a selectable value. A design state styles an element differently for an
5
+ eligible interaction (`hover`, `focus`, `disabled`, `invalid`) or per a
6
+ selectable value in its data (`selected`, `active`, `open`, …). Author states
7
+ in the component's `.tsx` and `.module.css`.
7
8
 
8
- ## 1. Which states each element supports
9
+ ## Contents
10
+
11
+ - [Choose Supported States](#1-choose-supported-states)
12
+ - [Name the State Class](#2-name-the-state-class)
13
+ - [Author CSS](#3-author-css)
14
+ - [Wire React](#4-wire-react)
15
+ - [Use Prop-Triggered States on the Root Only](#5-use-prop-triggered-states-on-the-root-only)
16
+ - [Checklist](#checklist)
17
+
18
+ ## 1. Choose Supported States
9
19
 
10
20
  | Element | Author these states |
11
21
  |---|---|
@@ -17,43 +27,37 @@ and `.module.css`.
17
27
  | None of the above | no states — resting style only |
18
28
 
19
29
  An explicit `role` overrides the tag's implicit semantics: `<input role="button">`
20
- is a non-input control, and `<div role="checkbox">` is an input field.
30
+ is a non-input control, while `<div role="checkbox">` is an input field.
21
31
 
22
32
  A `focus` design state is an editor styling control, not the keyboard focus
23
33
  indicator itself. Do not add a global `--focus` modifier to a non-input control
24
- unless the user explicitly asks for an editable focus state. A control that
25
- restyles its own `outline`, `background`, or `border` MUST still carry a
26
- standalone `:focus-visible` rule — that rule is its only keyboard affordance.
34
+ unless the user explicitly requests editable focus styling. A control that
35
+ restyles its own outline, background, or border must still carry a standalone
36
+ `:focus-visible` rule as its keyboard affordance.
27
37
 
28
38
  A custom state may also be driven by a root-level boolean prop (e.g.
29
- `isFeatured`) instead of by markup or item data — see §5.
39
+ `isFeatured`) instead of by markup or item data — see §5. For an active-item
40
+ component, drive each item's `--active` class by comparing its index with the
41
+ active-index prop rather than storing a per-item boolean.
30
42
 
31
- For **active-item components** (tabs, slideshow, steps), the `--active` state on
32
- each item is driven by comparing the item's index to the active-index prop
33
- (`index === activeItem`), not by a per-item boolean flag — see
34
- [Active-item components](COMPONENT-API.md#active-item-components-one-body-visible-at-a-time)
35
- in [`COMPONENT-API.md`](COMPONENT-API.md).
36
-
37
- ## 2. Name the state class
43
+ ## 2. Name the State Class
38
44
 
39
45
  Flat: the element's own global class + `--<state>`. Because inner-part
40
- global classes are prefixed with the component name (see
41
- [`CSS-GUIDELINES.md`](CSS-GUIDELINES.md)), the state class is prefixed too —
46
+ global classes are prefixed with the component name, the state class is prefixed too —
42
47
  e.g. `pricing-card-cta--hover`, `pricing-card-plan-row--selected`. Never bare
43
48
  (`cta--hover` would collide with other components on the page) and never
44
49
  nested (`card__row--selected`).
45
50
 
46
- ## 3. CSS
51
+ ## 3. Author CSS
47
52
 
48
53
  Put the resting value in the bare class; put only the state override in the
49
54
  state selector.
50
55
 
51
56
  - **Native design state** — pair the pseudo-class with the `:global` modifier.
52
57
  Every exposed native state needs both selectors in the same rule; do not
53
- split the pair across states (for example, pseudo-only `hover` plus
54
- global-only `disabled`). A standalone `:focus-visible` accessibility rule on
55
- a non-input control is intentionally not an editor design state and therefore
56
- has no `:global` modifier.
58
+ split the pair across states. A standalone `:focus-visible` accessibility
59
+ rule on a non-input control is not an editor design state and has no global
60
+ modifier.
57
61
  - **Custom** — the `:global` modifier alone.
58
62
 
59
63
  The bare selector is the short **module** class (`.cta`); the `:global(...)`
@@ -79,10 +83,11 @@ state class is the **prefixed** global one.
79
83
  }
80
84
  ```
81
85
 
82
- ## 4. React
86
+ ## 4. Wire React
83
87
 
84
88
  - **Native** — render the correct interactive element (`<button>`, an
85
- interactive `role`, or a handler). Nothing else needed.
89
+ interactive `role`, or a handler). No custom state class is needed, but the
90
+ element must still satisfy the accessibility contract for its semantics.
86
91
  - **Custom** — toggle the global state class from the element's data.
87
92
  - **Inner elements** — every named inner element gets an `elementProps` entry;
88
93
  spread it so editor-driven states reach it. On a raw HTML element also merge
@@ -90,7 +95,8 @@ state class is the **prefixed** global one.
90
95
  spread alone suffices (it merges `className` itself). The `elementProps` key
91
96
  stays the **short** part name (`cta`) even though the element's global class
92
97
  is prefixed (`pricing-card-cta`) — don't rename the key to match the class.
93
- See [`COMPONENT-API.md`](COMPONENT-API.md).
98
+
99
+ Wire native and custom states as follows:
94
100
 
95
101
  ```tsx
96
102
  <button
@@ -101,12 +107,20 @@ state class is the **prefixed** global one.
101
107
  {label}
102
108
  </button>
103
109
 
104
- <li className={classNames('pricing-card-plan-row', styles.planRow, row.selected && 'pricing-card-plan-row--selected')}>
110
+ <li
111
+ {...elementProps?.planRow}
112
+ className={classNames(
113
+ 'pricing-card-plan-row',
114
+ styles.planRow,
115
+ row.selected && 'pricing-card-plan-row--selected',
116
+ elementProps?.planRow?.className,
117
+ )}
118
+ >
105
119
  {row.label}
106
120
  </li>
107
121
  ```
108
122
 
109
- ## 5. Prop-triggered states (root only)
123
+ ## 5. Use Prop-Triggered States on the Root Only
110
124
 
111
125
  A **prop-triggered** state is a custom state switched by a single boolean
112
126
  **prop**, rather than by interactive markup (native) or a per-item data flag
@@ -150,3 +164,13 @@ Rules:
150
164
  Prefer a native state (interactive markup) or a class trigger (per-item data
151
165
  such as `row.selected`) whenever one fits — those are the common cases and work
152
166
  at any depth. Reach for a prop trigger only for a root-level boolean switch.
167
+
168
+ ## Checklist
169
+
170
+ - [ ] Each named part declares only states its semantics or data supports.
171
+ - [ ] Eligible native design-state selectors pair the pseudo-class with the
172
+ prefixed global modifier.
173
+ - [ ] Non-input controls retain a standalone `:focus-visible` keyboard indicator.
174
+ - [ ] Custom state classes are flat, global, and prefixed by component and part.
175
+ - [ ] Named inner parts spread and merge their `elementProps` entry.
176
+ - [ ] `ElementState<boolean>` is used only for a component-level root state.
@@ -1,187 +1,82 @@
1
- # Component Directionality (RTL/LTR)
1
+ # Directionality (RTL/LTR)
2
2
 
3
- Rules and patterns for direction support in Editor React components.
3
+ Use these rules for component direction, logical layout, nested content, and
4
+ direction-dependent JavaScript.
4
5
 
5
- ---
6
+ ## Contents
6
7
 
7
- ## Rules
8
+ - [Root Contract](#root-contract)
9
+ - [Logical CSS](#logical-css)
10
+ - [Direction-Dependent Transforms](#direction-dependent-transforms)
11
+ - [Direction-Dependent JavaScript](#direction-dependent-javascript)
12
+ - [Nested `ReactNode` Content](#nested-reactnode-content)
13
+ - [Checklist](#checklist)
8
14
 
9
- Direction support is mandatory for every component. The pattern uses native HTML `dir` attributes for standards-compliant, accessible directionality support, with mandatory fallback classes on root components.
15
+ ## Root Contract
10
16
 
11
- ### Direction Resolution
17
+ Every component accepts `direction?: Direction`. Put `dir={direction}` and the
18
+ fallback class on the elected root; do not add a wrapper for them. Apply the
19
+ fallback class unconditionally so it works whenever `dir` is absent. Preserve
20
+ the scaffolded `dir`, root class, and `.fallbackDirection:not([dir])` wiring;
21
+ the generated component already demonstrates this contract.
12
22
 
13
- ```typescript
14
- const subComponentDirection = elementProps?.subComponent?.direction;
15
- ```
16
-
17
- - Sub-component directions only applied when explicitly set (to override inherited direction)
18
- - When undefined: inherits direction from parent via CSS inheritance
19
- - Root component always gets fallback class
20
-
21
- ### Direction Anti-Patterns
22
-
23
- ```scss
24
- /* ❌ Don't use CSS variables for direction */
25
- .component { direction: var(--component-direction, ltr); }
26
- ```
27
-
28
- ```tsx
29
- /* ❌ Don't use conditional logic for fallback class */
30
- className={classNames({
31
- [styles.fallbackDirection]: !direction
32
- })}
33
- ```
23
+ Do not set fallback direction with a React condition or a custom direction CSS
24
+ variable.
34
25
 
35
- ### RTL in SCSS
26
+ ## Logical CSS
36
27
 
37
- Use logical CSS properties — never physical `left`/`right`-only layouts. See §2.1 below.
28
+ Use logical inline-axis properties instead of physical left/right properties:
38
29
 
39
- ---
40
-
41
- ## Patterns
42
-
43
- ### Root Element Pattern
44
-
45
- Apply on main component only. `dir` and the fallback class go on whatever element is the root — never add a wrapper `<div>` to host them (see [`PARTS.md`](PARTS.md) Step 0).
46
-
47
- ```typescript
48
- <div
49
- id={id}
50
- dir={direction}
51
- className={classNames(
52
- 'profile-card',
53
- styles.root,
54
- className,
55
- styles.fallbackDirection,
56
- )}
57
- >
58
- ```
59
-
60
- ```typescript
61
- /* Root is the component's own semantic element — same attribute, same classes */
62
- <button
63
- type="button"
64
- id={id}
65
- dir={direction}
66
- className={classNames(
67
- 'like-button',
68
- styles.root,
69
- className,
70
- styles.fallbackDirection,
71
- )}
72
- >
73
- ```
74
-
75
- ```scss
76
- .fallbackDirection:not([dir]) {
77
- direction: var(--wix-opt-in-direction);
30
+ ```css
31
+ .element {
32
+ inset-inline-start: 0;
33
+ padding-inline-start: 8px;
34
+ margin-inline-end: 4px;
35
+ border-inline-end: 1px solid currentColor;
78
36
  }
79
37
  ```
80
38
 
81
- **Imports:**
82
-
83
- ```typescript
84
- import type { Direction } from '@wix/editor-react-types';
85
- ```
86
-
87
- ### Child Element Direction
88
-
89
- Only when explicitly specified:
90
-
91
- ```typescript
92
- const labelDirection = elementProps?.label?.direction;
93
-
94
- <span
95
- dir={labelDirection}
96
- >
97
- ```
98
-
99
- ### Runtime Direction Checking
100
-
101
- **Site direction hook:**
102
-
103
- Use the hook **only** when direction drives JavaScript behavior (keyboard navigation, animation logic, conditional rendering). For purely visual RTL, use logical CSS properties instead — see below.
104
-
105
- ```typescript
106
- import { useLanguageDirection } from '@wix/react-component-utils';
107
-
108
- const siteDirection = useLanguageDirection();
109
- const isRTL = siteDirection === 'rtl';
110
- ```
111
-
112
- See [`SITE-CONTEXT-HOOKS.md`](SITE-CONTEXT-HOOKS.md) for the full set of site context hooks.
39
+ Block-axis properties such as `top`, `bottom`, and `padding-block` do not need
40
+ directional conversion.
113
41
 
114
- **Fallback chain (for child components):**
42
+ ## Direction-Dependent Transforms
115
43
 
116
- ```typescript
117
- const isRTL = (direction || parentDirection || siteDirection) === 'rtl';
118
- ```
119
-
120
- **CSS Variable**
44
+ For directional transforms, use the platform multiplier:
121
45
 
122
- Use css variable `--wix-opt-in-direction-multiplier` when direction only affects visual appearance (transforms, spacing, layout):
123
-
124
- ```scss
125
- .scrollButton {
46
+ ```css
47
+ .arrow {
126
48
  scale: var(--wix-opt-in-direction-multiplier, 1) 1;
127
49
  }
128
50
  ```
129
51
 
130
- ### RTL Support — Use Logical CSS Properties
52
+ ## Direction-Dependent JavaScript
131
53
 
132
- **✅ Correct:**
54
+ Use `useLanguageDirection()` only when direction changes JavaScript behavior,
55
+ such as arrow-key order, scroll math, animation direction, or conditional
56
+ rendering. Purely visual direction belongs in logical CSS.
133
57
 
134
- ```scss
135
- .element {
136
- inset-inline-start: 0; // Instead of left
137
- inset-inline-end: 0; // Instead of right
138
- padding-inline-start: 8px; // Instead of padding-left
139
- margin-inline-end: 4px; // Instead of margin-right
140
- }
141
- ```
142
-
143
- **❌ Wrong:**
58
+ ```tsx
59
+ import { useLanguageDirection } from '@wix/react-component-utils';
144
60
 
145
- ```scss
146
- .element {
147
- padding-left: 8px;
148
- [dir='rtl'] & {
149
- padding-right: 8px; // Manual RTL - avoid
150
- }
151
- }
61
+ const siteDirection = useLanguageDirection();
62
+ const resolvedDirection = direction ?? siteDirection;
63
+ const isRtl = resolvedDirection === 'rtl';
152
64
  ```
153
65
 
154
- Use logical CSS properties (e.g., `margin-inline-start` not `margin-left`) for RTL support.
155
-
156
- ---
157
-
158
- ## Common Mistake: Manual RTL Handling
159
-
160
- **❌ Wrong:**
161
-
162
- ```scss
163
- .element {
164
- padding-left: 8px;
165
- [dir='rtl'] & {
166
- padding-right: 8px; // Manual overrides
167
- }
168
- }
169
- ```
66
+ ## Nested `ReactNode` Content
170
67
 
171
- **✅ Correct:**
68
+ Put `dir="ltr"` on the element that renders a `ReactNode` content prop. This
69
+ isolates arbitrary nested content from the parent component's direction so each
70
+ nested component can resolve its own contract.
172
71
 
173
- ```scss
174
- .element {
175
- padding-inline-start: 8px; // Auto RTL/LTR
176
- }
72
+ ```tsx
73
+ <div dir="ltr">{item.content}</div>
177
74
  ```
178
75
 
179
- ## Container Components and RTL Inheritance
76
+ ## Checklist
180
77
 
181
- Elements that render `React.ReactNode` content MUST have `dir="ltr"` to prevent RTL inheritance from the parent component:
182
-
183
- ```tsx
184
- <Accordion.Content dir="ltr">
185
- {item.content} {/* React.ReactNode */}
186
- </Accordion.Content>
187
- ```
78
+ - [ ] Root props include `direction?: Direction`.
79
+ - [ ] The elected root has `dir={direction}` and the unconditional fallback class.
80
+ - [ ] Direction-sensitive CSS uses logical properties.
81
+ - [ ] Runtime direction hooks are used only for JavaScript behavior.
82
+ - [ ] Every `ReactNode` content slot renders under `dir="ltr"`.
@@ -0,0 +1,78 @@
1
+ # Editor Extension Configuration
2
+
3
+ Use this reference to edit `<component-name>.extension.ts` after scaffolding and
4
+ before the final build. Preserve the scaffold's generated editor element,
5
+ client and editor resources, merge order, and defaults wiring. Manifest
6
+ generation rewrites
7
+ `<component-name>.generated.ts`; it does not rewrite the extension file.
8
+
9
+ For a new component, complete the scaffolded installation and layout fields.
10
+ For an existing component, change only the sizing, installation, or manifest
11
+ behavior requested by the user; preserve every other extension field.
12
+
13
+ ## Contents
14
+
15
+ - [Preserve the Extension Shape](#preserve-the-extension-shape)
16
+ - [Choose Initial Height](#choose-initial-height)
17
+ - [Choose Resize Direction](#choose-resize-direction)
18
+ - [Checklist](#checklist)
19
+
20
+ ## Preserve the Extension Shape
21
+
22
+ For a new component, the extension should continue to:
23
+
24
+ - import `editorElement` from `<component-name>.generated.ts`
25
+ - load `component.tsx?url` for the client and `component.preview.tsx?url` for
26
+ the editor
27
+ - apply `defaultProps` from `<component-name>.props.ts` through
28
+ `withEditorElementDefaults`
29
+ - merge layout overrides into the editor element after applying defaults
30
+
31
+ For an existing component, preserve its generated export shape. Older
32
+ extensions may import and spread `manifest.editorElement` and
33
+ `manifest.resources`; do not migrate that wiring during an unrelated edit.
34
+
35
+ Preserve the generated `defaultProps` import from `./<component-name>.props`.
36
+ That file remains the single source of truth.
37
+
38
+ ## Choose Initial Height
39
+
40
+ Determine from the component contract whether its own content decides its
41
+ height. Ask the user only when the requested behavior leaves this materially
42
+ ambiguous.
43
+
44
+ | Answer | Sizing type |
45
+ | --- | --- |
46
+ | Text or nested content should grow the component | `LAYOUT.SIZING_TYPE.content`; omit `pixels` |
47
+ | The component is a framed visual/control with a natural fixed height | `LAYOUT.SIZING_TYPE.pixels`; provide `pixels` |
48
+
49
+ Tiebreaker: if a designer should drag a height handle, use `pixels`; if height
50
+ should fit content, use `content`.
51
+
52
+ ## Choose Resize Direction
53
+
54
+ Allow an axis only when dragging it produces a meaningful result.
55
+
56
+ | Value | Use when |
57
+ | --- | --- |
58
+ | `horizontalAndVertical` | Content meaningfully fills both axes; default for framed visuals and most layouts |
59
+ | `horizontal` | Height is intrinsic or intentionally rigid |
60
+ | `vertical` | Width is intrinsic or intentionally rigid |
61
+ | `aspectRatio` | Distortion would break the component's identity |
62
+ | `none` | A parent fully owns size; do not use for a top-level component |
63
+
64
+ Edit the scaffolded `layout`, `installation`, and `resources` fields in place;
65
+ do not reconstruct the extension from an example. For a new component, add
66
+ `staticContainer: 'HOMEPAGE'`. For an existing component, preserve its current
67
+ `staticContainer` value unless the request explicitly changes installation
68
+ behavior.
69
+
70
+ ## Checklist
71
+
72
+ - [ ] Defaults are applied to the generated editor element before layout
73
+ overrides are merged.
74
+ - [ ] Client and editor resources still point to their generated entry files.
75
+ - [ ] The extension and `component.tsx` consume the same `defaultProps` source.
76
+ - [ ] Initial sizing and resize axes match component behavior.
77
+ - [ ] A new component has `staticContainer: 'HOMEPAGE'`; an existing
78
+ component keeps its prior installation behavior unless explicitly changed.
@@ -1,167 +1,75 @@
1
- # Function Event Handlers
1
+ # Function Handlers
2
2
 
3
- Rules and patterns for adding function event handler props to an Editor React component's TypeScript interface, wiring them to DOM events, and declaring custom callbacks.
3
+ Use this reference only when the component specification exposes callbacks to
4
+ site owners. Keep implementation-only handlers out of the public props type.
4
5
 
5
- ---
6
+ ## Standard SDK Handlers
6
7
 
7
- ## Rules
8
+ Use the exact SDK prop name and wire it to the matching React DOM event.
8
9
 
9
- ### Standard SDK Event Handlers
10
+ | SDK prop | React DOM prop | Type |
11
+ | --- | --- | --- |
12
+ | `onClick` | `onClick` | `(event: React.MouseEvent) => void` |
13
+ | `onDblClick` | `onDoubleClick` | `(event: React.MouseEvent) => void` |
14
+ | `onChange` | `onChange` | `(event: React.ChangeEvent<HTMLElement>) => void` |
15
+ | `onFocus` | `onFocus` | `(event: React.FocusEvent) => void` |
16
+ | `onBlur` | `onBlur` | `(event: React.FocusEvent) => void` |
17
+ | `onMouseIn` | `onMouseEnter` | `(event: React.MouseEvent) => void` |
18
+ | `onMouseOut` | `onMouseLeave` | `(event: React.MouseEvent) => void` |
10
19
 
11
- These are the standard event handler props the editor SDK exposes to site owners. Use the exact prop names — ZeroConfig and the manifest system recognize them.
20
+ Declare only the handlers the component actually exposes.
12
21
 
13
- | Prop name | React DOM event | Type |
14
- | ------------ | --------------- | ------------------------------------------------ |
15
- | `onClick` | `onClick` | `(event: React.MouseEvent) => void` |
16
- | `onDblClick` | `onDoubleClick` | `(event: React.MouseEvent) => void` |
17
- | `onChange` | `onChange` | `(event: React.ChangeEvent<HTMLElement>) => void` |
18
- | `onFocus` | `onFocus` | `(event: React.FocusEvent) => void` |
19
- | `onBlur` | `onBlur` | `(event: React.FocusEvent) => void` |
20
- | `onMouseIn` | `onMouseEnter` | `(event: React.MouseEvent) => void` |
21
- | `onMouseOut` | `onMouseLeave` | `(event: React.MouseEvent) => void` |
22
-
23
- Three props have a **name mismatch** between the SDK prop and the DOM event: `onDblClick` → `onDoubleClick`, `onMouseIn` → `onMouseEnter`, `onMouseOut` → `onMouseLeave`.
24
-
25
- ### Declaring Standard Handler Props
26
-
27
- Declare standard handlers inline with the exact SDK prop names and React event types:
28
-
29
- ```typescript
30
- interface MyComponentProps {
31
- label?: string;
22
+ ```tsx
23
+ export type ActionProps = {
32
24
  onClick?: (event: React.MouseEvent) => void;
33
25
  onDblClick?: (event: React.MouseEvent) => void;
34
- onChange?: (event: React.ChangeEvent<HTMLElement>) => void;
35
- onFocus?: (event: React.FocusEvent) => void;
36
- onBlur?: (event: React.FocusEvent) => void;
37
26
  onMouseIn?: (event: React.MouseEvent) => void;
38
27
  onMouseOut?: (event: React.MouseEvent) => void;
39
- }
40
- ```
41
-
42
- Only declare handlers the component actually exposes. Do not add all seven if the component only handles two.
43
-
44
- ### Wiring Standard Handlers to DOM Events
28
+ };
45
29
 
46
- Destructure the props and pass them to the correct DOM event — applying the name mappings:
30
+ export const Action: React.FC<ActionProps> = (props) => {
31
+ const { onClick, onDblClick, onMouseIn, onMouseOut } = props;
47
32
 
48
- ```typescript
49
- export const MyComponent = (props: MyComponentProps) => {
50
- const { onClick, onDblClick, onFocus, onBlur, onMouseIn, onMouseOut } = props;
51
33
  return (
52
- <div
34
+ <button
35
+ type="button"
53
36
  onClick={onClick}
54
37
  onDoubleClick={onDblClick}
55
- onFocus={onFocus}
56
- onBlur={onBlur}
57
38
  onMouseEnter={onMouseIn}
58
39
  onMouseLeave={onMouseOut}
59
- >
60
- {/* ... */}
61
- </div>
40
+ />
62
41
  );
63
42
  };
64
43
  ```
65
44
 
66
- ### Custom Callbacks
45
+ Do not expose DOM names such as `onDoubleClick`, `onMouseEnter`, or
46
+ `onMouseLeave` in the component API; zero config recognizes the SDK names.
67
47
 
68
- Component-specific callbacks that do not correspond to a DOM event (e.g., `onPlay`, `onPause`, `onEnded`, `onTimeupdate`) are **not** standard SDK event handlers. Type them as `() => void` — no React event parameter:
48
+ ## Custom Callbacks
69
49
 
70
- ```typescript
71
- interface VideoPlayerProps {
50
+ A component-level notification that is not one of the standard SDK DOM events
51
+ uses `() => void` unless the component contract explicitly defines a serializable
52
+ payload. Do not expose a React synthetic event for custom callbacks.
53
+
54
+ Use this pattern:
55
+
56
+ ```tsx
57
+ export type VideoPlayerProps = {
72
58
  onPlay?: () => void;
73
59
  onPause?: () => void;
74
60
  onEnded?: () => void;
75
- }
76
- ```
77
-
78
- Pass them directly to the underlying element — no name remapping needed:
61
+ };
79
62
 
80
- ```typescript
81
- export const VideoPlayer = (props: VideoPlayerProps) => {
63
+ export const VideoPlayer: React.FC<VideoPlayerProps> = (props) => {
82
64
  const { onPlay, onPause, onEnded } = props;
83
65
  return <video onPlay={onPlay} onPause={onPause} onEnded={onEnded} />;
84
66
  };
85
67
  ```
86
68
 
87
- ---
88
-
89
- ## Common Mistakes
90
-
91
- ### Passing SDK prop name directly to DOM instead of remapping
92
-
93
- **❌ Wrong:**
94
-
95
- ```typescript
96
- export const MyComponent = (props: MyComponentProps) => {
97
- const { onMouseIn, onMouseOut, onDblClick } = props;
98
- return (
99
- <div
100
- onMouseIn={onMouseIn} // ❌ not a valid React DOM prop
101
- onMouseOut={onMouseOut} // ❌ not a valid React DOM prop
102
- onDblClick={onDblClick} // ❌ not a valid React DOM prop
103
- />
104
- );
105
- };
106
- ```
107
-
108
- **✅ Correct:**
109
-
110
- ```typescript
111
- export const MyComponent = (props: MyComponentProps) => {
112
- const { onMouseIn, onMouseOut, onDblClick } = props;
113
- return (
114
- <div
115
- onMouseEnter={onMouseIn} // ✅ onMouseIn → onMouseEnter
116
- onMouseLeave={onMouseOut} // ✅ onMouseOut → onMouseLeave
117
- onDoubleClick={onDblClick} // ✅ onDblClick → onDoubleClick
118
- />
119
- );
120
- };
121
- ```
122
-
123
- ### Adding a React event parameter to custom callbacks
124
-
125
- **❌ Wrong:**
126
-
127
- ```typescript
128
- interface VideoPlayerProps {
129
- onPlay?: (event: React.SyntheticEvent) => void; // ❌ event param on custom callback
130
- onEnded?: (event: React.SyntheticEvent) => void; // ❌ event param on custom callback
131
- }
132
- ```
133
-
134
- **✅ Correct:**
135
-
136
- ```typescript
137
- interface VideoPlayerProps {
138
- onPlay?: () => void; // ✅ no event param
139
- onEnded?: () => void; // ✅ no event param
140
- }
141
- ```
142
-
143
- **Why:** Custom callbacks are component-level notifications to the site owner, not DOM event forwarders. They carry no event object — the SDK passes no event to them.
144
-
145
- ### Using the DOM event name as the SDK prop name
146
-
147
- **❌ Wrong:**
148
-
149
- ```typescript
150
- interface MyComponentProps {
151
- onDoubleClick?: (event: React.MouseEvent) => void; // ❌ DOM name, not SDK name
152
- onMouseEnter?: (event: React.MouseEvent) => void; // ❌ DOM name, not SDK name
153
- onMouseLeave?: (event: React.MouseEvent) => void; // ❌ DOM name, not SDK name
154
- }
155
- ```
156
-
157
- **✅ Correct:**
158
-
159
- ```typescript
160
- interface MyComponentProps {
161
- onDblClick?: (event: React.MouseEvent) => void; // ✅ SDK prop name
162
- onMouseIn?: (event: React.MouseEvent) => void; // ✅ SDK prop name
163
- onMouseOut?: (event: React.MouseEvent) => void; // ✅ SDK prop name
164
- }
165
- ```
69
+ ## Checklist
166
70
 
167
- **Why:** The SDK prop names (`onDblClick`, `onMouseIn`, `onMouseOut`) are what ZeroConfig and the manifest system register. Using DOM names breaks the editor's event wiring.
71
+ - [ ] The specification explicitly requires each public callback.
72
+ - [ ] Standard handler names match the SDK contract exactly.
73
+ - [ ] Mismatched SDK/DOM names are mapped at the rendered element.
74
+ - [ ] Custom callbacks do not leak React event objects.
75
+ - [ ] Internal handlers remain implementation details.