@wix/ditto-codegen-public 1.0.217 → 1.0.219

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 (31) hide show
  1. package/dist/examples-apps/react-builder/component.tsx +117 -0
  2. package/dist/examples-apps/react-builder/components/Badge.tsx +14 -0
  3. package/dist/examples-apps/react-builder/components/Button.tsx +31 -0
  4. package/dist/examples-apps/react-builder/components/Counter.tsx +14 -0
  5. package/dist/examples-apps/react-builder/components/FeaturedImage.tsx +31 -0
  6. package/dist/examples-apps/react-builder/components/SocialLinks.tsx +61 -0
  7. package/dist/examples-apps/react-builder/components/Subtitle.tsx +11 -0
  8. package/dist/examples-apps/react-builder/components/Tags.tsx +25 -0
  9. package/dist/examples-apps/react-builder/components/Title.tsx +11 -0
  10. package/dist/examples-apps/react-builder/components/index.ts +8 -0
  11. package/dist/examples-apps/react-builder/manifest.json +325 -0
  12. package/dist/examples-apps/react-builder/style.css +197 -0
  13. package/dist/examples-apps/react-builder/types.ts +68 -0
  14. package/dist/out.js +615 -61
  15. package/dist/wix-cli-templates/src/site/components/my-component/component.tsx +8 -5
  16. package/dist/wix-cli-templates/src/site/components/my-component/manifest.json +14 -0
  17. package/dist/wix-cli-templates/src/site/components/my-component/{styles.module.css → style.css} +1 -1
  18. package/package.json +2 -2
  19. package/dist/examples-apps/inventory-countdown/.nvmrc +0 -1
  20. package/dist/examples-apps/inventory-countdown/README.md +0 -21
  21. package/dist/examples-apps/inventory-countdown/package-lock.json +0 -7457
  22. package/dist/examples-apps/inventory-countdown/package.json +0 -33
  23. package/dist/examples-apps/inventory-countdown/src/assets/stock-counter/site-plugin-logo.svg +0 -27
  24. package/dist/examples-apps/inventory-countdown/src/env.d.ts +0 -4
  25. package/dist/examples-apps/inventory-countdown/src/site/plugins/custom-elements/stock-counter/consts.ts +0 -1
  26. package/dist/examples-apps/inventory-countdown/src/site/plugins/custom-elements/stock-counter/panel.tsx +0 -81
  27. package/dist/examples-apps/inventory-countdown/src/site/plugins/custom-elements/stock-counter/plugin.json +0 -24
  28. package/dist/examples-apps/inventory-countdown/src/site/plugins/custom-elements/stock-counter/plugin.module.css +0 -4
  29. package/dist/examples-apps/inventory-countdown/src/site/plugins/custom-elements/stock-counter/plugin.tsx +0 -132
  30. package/dist/examples-apps/inventory-countdown/tsconfig.json +0 -8
  31. package/dist/examples-apps/inventory-countdown/wix.config.json +0 -5
package/dist/out.js CHANGED
@@ -75693,15 +75693,24 @@ var require_load_examples = __commonJS({
75693
75693
  ]
75694
75694
  }
75695
75695
  },
75696
- InventoryCountdown: {
75697
- path: "inventory-countdown",
75698
- description: "A site plugin that displays real-time inventory countdown for products, showing stock levels and urgency messaging to encourage purchases",
75696
+ ReactBuilder: {
75697
+ path: "react-builder",
75698
+ description: "A React builder component with all builder features",
75699
75699
  files: {
75700
75700
  [types_1.ExtensionType.SITE_COMPONENT]: [
75701
- "inventory-countdown/src/site/plugins/custom-elements/stock-counter/plugin.tsx",
75702
- "inventory-countdown/src/site/plugins/custom-elements/stock-counter/plugin.module.css",
75703
- "inventory-countdown/src/site/plugins/custom-elements/stock-counter/panel.tsx",
75704
- "inventory-countdown/src/site/plugins/custom-elements/stock-counter/consts.ts"
75701
+ "react-builder/component.tsx",
75702
+ "react-builder/style.css",
75703
+ "react-builder/manifest.json",
75704
+ "react-builder/types.ts",
75705
+ "react-builder/components/Badge.tsx",
75706
+ "react-builder/components/Button.tsx",
75707
+ "react-builder/components/Counter.tsx",
75708
+ "react-builder/components/FeaturedImage.tsx",
75709
+ "react-builder/components/index.ts",
75710
+ "react-builder/components/SocialLinks.tsx",
75711
+ "react-builder/components/Subtitle.tsx",
75712
+ "react-builder/components/Tags.tsx",
75713
+ "react-builder/components/Title.tsx"
75705
75714
  ]
75706
75715
  }
75707
75716
  },
@@ -75791,7 +75800,7 @@ var require_load_examples = __commonJS({
75791
75800
  ],
75792
75801
  [types_1.ExtensionType.EMBEDDED_SCRIPT]: [appsExamples.CouponPopup],
75793
75802
  [types_1.ExtensionType.SERVICE_PLUGIN]: [appsExamples.SPISExample],
75794
- [types_1.ExtensionType.SITE_COMPONENT]: [appsExamples.InventoryCountdown],
75803
+ [types_1.ExtensionType.SITE_COMPONENT]: [appsExamples.ReactBuilder],
75795
75804
  [types_1.ExtensionType.SITE_WIDGET]: [appsExamples.CustomElementWidget],
75796
75805
  [types_1.ExtensionType.BACKEND_EVENT]: [
75797
75806
  appsExamples.ProductCreatedLogger,
@@ -91352,32 +91361,563 @@ var require_site_component_instructions = __commonJS({
91352
91361
  exports2.siteComponentInstructions = void 0;
91353
91362
  var typescript_quality_guidelines_1 = require_typescript_quality_guidelines();
91354
91363
  var siteComponentRole = "You are a senior Wix CLI App Developer and React expert. Your job is to produce a beautiful, production\u2011quality site component quickly and correctly.";
91355
- var siteComponentImplementationGuidelines = `<rules>
91356
- - Return ONLY a JSON object matching the schema { path, content, type } (no prose, no markdown)
91357
- - type must be "typescript"; content must be the COMPLETE file source
91358
- - Do NOT add dependencies; do NOT use @wix/design-system or @wix/wix-ui-icons-common
91359
- - Do NOT invent types/modules/props; use only what exists in the scaffold and standard libs
91360
- </rules>
91364
+ var coreDocumentation = `Wix Component Model: Contract between implementation (React, CSS) and Wix ecosystem, enabling users to:
91365
+
91366
+ - Interact with inner elements (selection, removal)
91367
+ - Edit component style and props
91368
+
91369
+ This contract is the "Component Manifest".`;
91370
+ var dataTypesDocumentation = `Data types for storage in the Wix system:
91371
+
91372
+ - **text**: Simple text value
91373
+ - **textEnum**: Predefined textual values to choose from
91374
+ - **number**: Any number
91375
+ - **booleanValue**: true/false value
91376
+ - **a11y**: Object with selected A11Y fields
91377
+ - **link**: Wix Link object
91378
+ - **image**: Wix Image object
91379
+ - **video**: Wix Video object
91380
+ - **vectorArt**: Wix Sanitized Vector Art object
91381
+ - **localDate**: ISO-8601 local date (YYYY-MM-DD)
91382
+ - **localTime**: ISO-8601 local time (hh:mm[:ss][.sss])
91383
+ - **webUrl**: URL with http/https scheme
91384
+ - **richText**: HTML text with inline CSS styling
91385
+ - **arrayItems**: Array type of data
91386
+ - **direction**: HTML dir attribute direction
91387
+ - **menuItems**: Array of menu items
91388
+
91389
+ ### DataItem Fields
91390
+
91391
+ - dataType (DataType): Type of data being configured
91392
+ - displayName (string): Display name, max 100 chars
91393
+ - text (Text): Limitations on text input (maxLength, minLength, pattern)
91394
+ - textEnum (TextEnum): Required list of options with value and displayName
91395
+ - number (Number): Restrictions (minimum, maximum, multipleOf)
91396
+ - link (Link): Link support definition with linkTypes array
91397
+ - arrayItems (ArrayItems): Array data type definition
91398
+ - richTextAbilities (RichTextAbilities[]): Rich text formatting abilities
91399
+
91400
+ ### Link Types
91401
+ externalLink, anchorLink, emailLink, phoneLink, dynamicPageLink, pageLink, whatsAppLink, documentLink, popupLink, addressLink, edgeAnchorLinks, loginToWixLink
91402
+
91403
+ ### RichText Abilities
91404
+ font, fontFamily, fontSize, fontStyle, fontWeight, textDecoration, color, backgroundColor, letterSpacing, textAlign, direction, marginStart, marginEnd, bulletedList, numberedList, seoTag
91405
+
91406
+ ### Example: ArrayItems with Complex Objects
91407
+ \`\`\`json
91408
+ {
91409
+ "dataType": "arrayItems",
91410
+ "displayName": "Feature List",
91411
+ "arrayItems": {
91412
+ "data": {
91413
+ "items": {
91414
+ "title": { "dataType": "text", "displayName": "Title" },
91415
+ "description": { "dataType": "text", "displayName": "Description" },
91416
+ "icon": { "dataType": "vectorArt", "displayName": "Icon" }
91417
+ }
91418
+ },
91419
+ "maxSize": 6
91420
+ }
91421
+ }
91422
+ \`\`\`
91361
91423
 
91362
- <style_guidelines>
91363
- - Prefer simple, elegant UI using inline styles (no CSS imports)
91364
- - Use semantic HTML and accessible patterns (aria-*, roles, focus styles)
91365
- - Favor flex layouts, spacing, readable typography; avoid visual clutter
91366
- - Keep responsiveness lightweight (flex/wrap/percentages); avoid heavy logic
91367
- </style_guidelines>
91424
+ ### Example: Link with Types
91425
+ \`\`\`json
91426
+ {
91427
+ "dataType": "link",
91428
+ "displayName": "Button Link",
91429
+ "link": { "linkTypes": ["externalLink", "pageLink"] }
91430
+ }
91431
+ \`\`\``;
91432
+ var cssPropertiesDocumentation = `CSS Properties are defined as a map of cssPropertyKey to css-property-item in the manifest.
91433
+
91434
+ ### CSS Property Item Fields
91435
+ - displayName (string): Display name, max 100 chars
91436
+ - defaultValue (Value): Default CSS value
91437
+ - display (Display): Options for display property with displayValues array
91438
+
91439
+ ### Display Values
91440
+ none, block, inline, flow, flowRoot, table, flex, grid, list_item, contents, inline_block, inline_table, inline_flex, inline_grid
91441
+
91442
+ **Multi-word values use underscores**: inline_flex, inline_block, inline_grid, flow_root, list_item
91443
+
91444
+ ### CSS Shorthand Properties
91445
+ - border: Derives borderWidth, borderStyle, borderColor, and all directional variants
91446
+ - background: Derives backgroundColor, backgroundImage, backgroundSize, etc.
91447
+ - margin: Derives marginTop, marginRight, marginBottom, marginLeft
91448
+ - padding: Derives paddingTop, paddingRight, paddingBottom, paddingLeft
91449
+ - font: Derives fontFamily, fontSize, fontWeight, fontStyle, lineHeight
91450
+ - borderRadius: Derives all corner radius variants
91451
+
91452
+ ### Common CSS Property Types
91453
+ backgroundColor, color, font, padding, margin, border, borderRadius, boxShadow, opacity, display, gap, width, height, maxWidth, maxHeight, textAlign, flexDirection, alignItems, justifyContent, objectFit`;
91454
+ var editorElementDocumentation = `The editor element defines element behaviors in the editor and the element tree.
91455
+
91456
+ ### Main Properties
91457
+ - **selector** (string): Direct className from React (e.g., className="my-component" \u2192 "selector": ".my-component"). One class only\u2014no compound (.a.b) or descendant (.a .b) selectors. Min 4, max 50 chars
91458
+ - **displayName** (string): Human friendly name on editor stage. Min 4, max 20 chars
91459
+ - **cssProperties** (map): CSS-API of this element
91460
+ - **data** (map): Data-API of this element, manifested as props
91461
+ - **elements** (map): Map of inner-elements with editor behavior definitions
91462
+ - **layout** (Layout): Layout capabilities of the component
91463
+ - **archetype** (Archetype): Component archetype for AI model classification
91464
+
91465
+ ### Archetype Options
91466
+ Button, LoginButton, Image, Gallery, Video, Audio, Text, TextInput, RichTextEditor, SignatureInput, Checkbox, RadioGroup, Switch, Dropdown, DatePicker, TimePicker, Ratings, RatingInput, Menu, Pagination, Slider, Container, Carousel, Accordion, Tabs, ProgressBar, Upload, Social, Breadcrumbs, SearchBox, Map, Line, Logo, Avatar, Captcha, VectorArt, AnimatedGraphic, Cart, ContactForm`;
91467
+ var layoutDocumentation = `Layout capabilities define how the component can be resized and positioned.
91468
+
91469
+ ### EditorElementLayout Fields
91470
+ - **resizeDirection**: horizontal, vertical, horizontalAndVertical, aspectRatio
91471
+ - **contentResizeDirection**: horizontal, vertical, horizontalAndVertical, none
91472
+ - **disableStretching** (boolean): Prevent stretch capability
91473
+ - **disablePositioning** (boolean): Prevent free positioning
91474
+ - **disableRotation** (boolean): Prevent rotation capability`;
91475
+ var elementsDocumentation = `Elements define the structure and behavior of nested components in the editor.
91476
+
91477
+ ### ElementItem
91478
+ - elementType: always use "inlineElement"
91479
+ - inlineElement (InlineElement): Element definition
91480
+
91481
+ ### InlineElement Fields
91482
+ - selector (string): Direct className from React, 4-50 chars
91483
+ - displayName (string): Human friendly name, 4-20 chars
91484
+ - cssProperties (map): CSS-API of this element
91485
+ - data (map): Data API of this element
91486
+ - elements (map): Map of inner elements
91487
+ - behaviors (Behaviors): Editor behaviors
91488
+ - archetype (Archetype): Component archetype
91489
+
91490
+ ### Behaviors
91491
+ - selectable (bool): true
91492
+ - removable (bool): true
91493
+
91494
+ **CRITICAL**: Always set selectable: true and removable: true for all elements.`;
91495
+ var propsDocumentation = `### Standard Props (always present)
91496
+ - **className** (string): CSS classes for styling - MUST be applied to root element
91497
+ - **id** (string): Unique identifier - MUST be applied to root element
91498
+ - **wix** (Wix): Wix system props including elementsRemovalState
91499
+
91500
+ ### wix.elementsRemovalState
91501
+ Contains keys of removed elements. Any element marked as REMOVED should not be rendered.
91502
+ \`\`\`typescript
91503
+ type REMOVED = 'REMOVED';
91504
+ interface Wix { elementsRemovalState?: Record<string, REMOVED> }
91505
+ \`\`\`
91368
91506
 
91369
- <engineering_guidelines>
91370
- - Implement a functional React + TypeScript component with a typed Props interface
91371
- - Keep the component small, pure, and readable; remove dead code/unused imports
91372
- - Use React hooks where needed; avoid unnecessary re-renders
91373
- - Name things clearly; avoid magic numbers; extract tiny helpers if it improves clarity
91374
- </engineering_guidelines>
91507
+ ### elementProps (nested element data)
91508
+ When manifest defines \`elements\` with \`data\`, props appear in elementProps namespace:
91509
+ \`\`\`typescript
91510
+ interface elementProps {
91511
+ [dataKey: string]: DataType; // Data items from element
91512
+ elementProps?: Record<string, elementProps>; // Nested child elements
91513
+ wix?: Wix; // Element-level removal state
91514
+ }
91515
+ \`\`\`
91375
91516
 
91376
- ${typescript_quality_guidelines_1.typescriptQualityGuidelines}
91377
- `;
91517
+ Example with nested elements:
91518
+ \`\`\`typescript
91519
+ interface CardProps {
91520
+ className: string;
91521
+ id: string;
91522
+ wix?: Wix;
91523
+ elementProps: {
91524
+ imageWrapper?: {
91525
+ image: Image;
91526
+ elementProps?: {
91527
+ badge?: { badgeText: Text };
91528
+ };
91529
+ };
91530
+ contentArea?: {
91531
+ elementProps?: {
91532
+ title?: { titleText: Text };
91533
+ button?: { buttonText: Text; buttonLink: Link };
91534
+ };
91535
+ };
91536
+ };
91537
+ }
91538
+ \`\`\`
91539
+
91540
+ ### Data Type Runtime Values
91541
+ - **text**: string
91542
+ - **textEnum**: string (selected value)
91543
+ - **number**: number
91544
+ - **booleanValue**: boolean
91545
+ - **link**: { href: string; target?: string; rel?: string }
91546
+ - **image**: { uri: string; url: string; name?: string; alt?: string; width?: number; height?: number }
91547
+ - **richText**: string (HTML with inline CSS)
91548
+ - **arrayItems**: Array<DataType | Record<string, DataType>>`;
91549
+ var componentElementsGuidelines = `**CRITICAL - One Element = One Manifest Entry**:
91550
+ Each distinct visual part = separate manifest element. NEVER group multiple interactive items.
91551
+
91552
+ Examples:
91553
+ - 3 buttons \u2192 3 separate elements (NOT 1 "buttons" element)
91554
+ - Image + text \u2192 2 separate elements (NOT 1 "hero" element)
91555
+
91556
+ **WHY**: Users edit each independently. Different text, links, styling per item.
91557
+
91558
+ ### Top Level Rules
91559
+
91560
+ **CRITICAL - Data Scoping**:
91561
+ - **editorElement.data** - ONLY component-wide behavior/layout config, NEVER inner elements content
91562
+ - \u2713 Config: Layout enums, numbers (columns: 3, speed: 500)
91563
+ - \u2717 NEVER: Text, links, images that belong to elements
91564
+ - \u2717 NEVER: show... booleans (use removable: true on elements instead)
91565
+ - **elements[key].data** - Content for THAT element
91566
+ - \u2713 Element-specific: title text, button link, image, price, description
91567
+
91568
+ **editorElement.cssProperties** - ONLY container, NEVER child CSS:
91569
+ - \u2713 Container styles (backgroundColor, padding, gap)
91570
+ - \u2717 Child CSS (goes in element's own cssProperties)
91571
+
91572
+ **Display CSS** (required in manifest): "display": { "display": { "displayValues": ["none", "block"] } }`;
91573
+ var componentManifestGuidelines = `Manifest = contract between component and Wix. More detail = more configurable.
91574
+
91575
+ **CRITICAL - Three-Way Synchronization**: Manifest MUST match React/CSS exactly:
91576
+
91577
+ - React prop names \u2194 manifest data keys
91578
+ - React classNames \u2194 CSS selectors \u2194 manifest selectors
91579
+ - Each manifest selector = direct className from React element
91580
+ - React: className="product-card__badge" \u2192 Manifest: "selector": ".product-card__badge"
91581
+ - NOT descendant paths (\u2717 .parent .child)
91582
+ - CSS defaults \u2194 manifest cssProperties defaultValue
91583
+
91584
+ **Rules**:
91585
+ - Max editability (expose all content)
91586
+ - Data VS CSS properties: anything that can be defined in css should be exposed in the manifest via css properties, never data
91587
+ - Adhere to length constraints
91588
+ - Whenever the component has repeated data (e.g. lists, collections), ALWAYS use the "arrayItems" data type`;
91589
+ var componentReactGuidelines = `### General Instructions
91590
+ - Import ./style.css, pure function, SSR-safe (no browser APIs at module scope, guard hooks)
91591
+ - Apply className and id to root: \`<div className={\`my-component \${className}\`} id={id}>\`
91592
+ - Top-level className MUST match manifest editorElement.selector
91593
+ - Pattern: \`className={\`base \${className}\`}\` where base = selector without dot
91594
+ - Sync with manifest (see Component Manifest Guidelines)
91595
+ - Component MUST react to prop changes. If state is initialized from props, update it when props change using useEffect with prop dependencies. Never ignore prop updates
91596
+ - Conditionally render ALL elements per wix.elementsRemovalState (all removable)
91597
+ - **All user-facing content must come from props** - text, media, links, labels, arrays should be controlled by manifest data
91598
+ - Hardcoded values are ONLY for fallback defaults when props are undefined
91599
+ - Links/media from manifest only, never hardcode URLs
91600
+ - Map a11y to DOM attributes, declare types at top, include wix prop
91601
+ - Default export, no TS errors/unused vars/TODOs
91602
+ - Code must compile and pass linting on first try
91603
+
91604
+ ### Component Hierarchy
91605
+ Three component types based on their role:
91606
+
91607
+ **1. Leaf Components** - Render content only, no children:
91608
+ \`\`\`ts
91609
+ type LeafComponent<TProps> = (props: TProps & { className: string }) => React.JSX.Element;
91610
+ \`\`\`
91611
+
91612
+ **2. Container Components** - Render child sub-components:
91613
+ \`\`\`ts
91614
+ type ContainerComponent<TProps> = (
91615
+ props: TProps & {
91616
+ className: string;
91617
+ elementProps?: Record<string, any>;
91618
+ wix?: Wix;
91619
+ }
91620
+ ) => React.JSX.Element;
91621
+ \`\`\`
91622
+
91623
+ **3. Root Component** - The exported default, receives all builder props:
91624
+ \`\`\`ts
91625
+ type RootComponent<TProps> = (
91626
+ props: TProps & {
91627
+ id?: string;
91628
+ className: string;
91629
+ elementProps?: Record<string, any>;
91630
+ wix?: Wix;
91631
+ }
91632
+ ) => React.JSX.Element;
91633
+ \`\`\`
91634
+
91635
+ ### Sub-Component Pattern for Nested Elements
91636
+ Extract every distinct UI unit into a named sub-component at module scope. This includes:
91637
+ - **Manifest elements** - matching keys in manifest elements
91638
+ - **Logical units** - buttons, icons, controls, sections, or any reusable piece of JSX
91639
+ Never write inline JSX blocks for distinct UI pieces; always extract them into named components.
91640
+
91641
+ 1. Give it a unique **nickname** (valid CSS classname, matches manifest element key)
91642
+ 2. Pass the nickname as \`className\`
91643
+ 3. Create a separate function component for each element
91644
+ 4. Pass data props to components with single spread: \`{...elementProps?.['childKey']}\`
91645
+ 5. **Self-Contained Components**: Sub-components must be complete, self-contained units. Never wrap a sub-component with semantic elements that add behavior
91646
+
91647
+ ### Props & State
91648
+ 1. Declare props according to manifest data structure
91649
+ 2. Component MUST react to prop changes. If state is initialized from props, update via useEffect with prop dependencies
91650
+ 3. **Default each field independently**, never the entire element object:
91651
+ - **Primitive fields**: Use inline fallbacks: \`props?.badgeText || 'Default'\`
91652
+ - **Complex fields**: Define default arrays props outside the component. Use props directly: \`(props?.items?.length > 0) ? props?.items : DEFAULT_ITEMS\` with optional chaining
91653
+ 4. Create a typed props interface for each component - **ALL data props must be optional** (use \`?\`)
91654
+ 5. If state is initialized from props, sync via useEffect:
91655
+ \`\`\`tsx
91656
+ const [value, setValue] = useState(props.initialValue);
91657
+ useEffect(() => { setValue(props.initialValue); }, [props.initialValue]);
91658
+ \`\`\`
91659
+
91660
+ ### Conditional Rendering
91661
+ - Conditionally render ALL elements per wix.elementsRemovalState (all removable)
91662
+ - Pattern: \`{!removalState['elementKey'] && <Element />}\` where \`removalState = wix?.elementsRemovalState || {}\`
91663
+
91664
+ ### Links & Media
91665
+ - **Links**: <a> for navigation, <button> for internal logic
91666
+ - Pattern: \`link?.href || '#'\`, prevent default if \`!link?.href || link.href === '#'\`
91667
+ - Example: \`<a href={link?.href || '#'} target={link?.target} rel={link?.rel} onClick={handleClick}>\`
91668
+ - **elementProps**: Props may be partial. Default EACH data field independently, never the entire element object
91669
+ - Single data field: \`elementProps?.badge?.badgeText || 'Default'\`
91670
+ - **Arrays**: Check length: \`(items?.length > 0) ? items : defaults\`, add safety: \`if (!item?.property) return null\`
91671
+
91672
+ ### TypeScript (Strict)
91673
+ - Valid TS, no compilation errors, no \`any\`
91674
+ - Type safety: Don't compare incompatible types (e.g. \`type Player = 'X' | 'O'\` vs \`'Draw'\` \u2192 expand type: \`type Winner = Player | 'Draw'\`)
91675
+ - Define interfaces for props/data, no any (prefer strict typing)
91676
+
91677
+ ### ESLint Rules
91678
+ 1. No unused vars/params/imports (\`@typescript-eslint/no-unused-vars\`)
91679
+ 2. No external images: \`img\` \`src\` not \`https://...\` (allowed: local imports, \`wixstatic.com\`, variables)
91680
+ 3. SSR-safe: No \`window\`/\`document\` at module scope/constructor, guard browser APIs in \`useEffect\`/handlers
91681
+ 4. No \`dangerouslySetInnerHTML\` or inline \`<style>\` tags - use CSS variables or inline \`style\` prop for dynamic values
91682
+ 5. No \`window.fetch\` (\`no-restricted-properties\`)
91683
+ 6. Hooks (\`exhaustive-deps\`): ALL values from component scope used inside \`useEffect\`/\`useCallback\` MUST be in dependency array
91684
+ - Functions used in \`useEffect\`: declare inside the hook and wrap in \`useCallback\`, or include in dependency array
91685
+ - Event handlers (e.g., \`handleMouseMove\`, \`handleClick\`) used in effects MUST be wrapped in \`useCallback\` or included in dependency array
91686
+ - Props/state/functions from component scope must be in dependency array
91687
+ - Example: \`const handler = useCallback(() => {...}, [dep1, dep2]); useEffect(() => { el.addEventListener('event', handler); }, [handler]);\`
91688
+ 7. Use \`const\`/\`let\` (no \`var\`), no unknown JSX properties`;
91689
+ var componentCssGuidelines = `### CSS Guidelines
91690
+ - **No inline styles for static values** - use CSS classes instead. Inline styles allowed ONLY for JS-computed dynamic values
91691
+ - Sync with manifest (see Component Manifest Guidelines)
91692
+ - Each selector once only, \`box-sizing: border-box\` all elements
91693
+ - NO \`transition: all\`, NO media queries (except \`prefers-reduced-motion\`)
91694
+ - Root display: Declare \`--display: [value]\` CSS variable, then use \`display: var(--display)\` on root element
91695
+ - ALWAYS use \`pointer-events: auto\` on elements defined in manifest (editorElement or nested) or any selectors targeting them
91696
+
91697
+ ### Responsive Design
91698
+ Components live in user-resizable bounding boxes (300-1200px) within varying viewports (375-1920px).
91699
+
91700
+ **CSS Approach**: Rely on modern CSS (flexbox, grid, \`clamp()\` for typography, \`min()\`, \`max()\`) for fluid responsiveness without media queries.
91701
+
91702
+ **Layered Strategy**:
91703
+ - **Layout structure** (Container): \`grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))\` or \`flex-wrap: wrap\`
91704
+ - **Typography** (Viewport): \`clamp()\` for fluid typography
91705
+ - **Spacing**: Fixed or tight clamp spacing (\u226450% variation)
91706
+ - **Root element**: \`width: 100%; height: 100%\`
91707
+
91708
+ **Component Types**:
91709
+ - Most (cards, forms): \`width: 100%\`, grid/flex, fixed spacing
91710
+ - Overlays (modals): Can have \`max-width\`, fixed dimensions
91711
+ - Readable content: \`width: 100%\` root, \`max-width\` inner wrapper`;
91712
+ var designGuidelines = `### 1. Spacing as Communication
91713
+ Spacing communicates relationships and hierarchy\u2014not decoration.
91714
+
91715
+ **Semantic Roles**:
91716
+ - **Padding**: Internal breathing room. Prevents cramped layouts
91717
+ - **Gap**: Relationship indicator. Consistent gaps = visual unity
91718
+ - **Margin**: Section separation. Clear boundaries between major blocks
91719
+ - **Whitespace**: Focus amplifier. Strategic emptiness = premium feel
91720
+
91721
+ **Spacing Scale**:
91722
+ | Relationship | Value | Use Case |
91723
+ |---|---|---|
91724
+ | Tight (icon + label) | 0.25-0.5rem (4-8px) | Clustering related items |
91725
+ | Same category | 1-1.5rem (16-24px) | Card sections, form fields |
91726
+ | Different sections | 2-3rem (32-48px) | Major content blocks |
91727
+ | Emphasis/Drama | 4rem+ (64px+) | Hero content, luxury feel |
91728
+
91729
+ **Generous Whitespace Examples**: 1.5rem/24px, 2rem/32px, 2.5rem/40px create sophistication and clarity. Design clean, spacious layouts that breathe.
91730
+
91731
+ ### 2. Alignment as Intent
91732
+ Every alignment choice must support comprehension and flow\u2014never default.
91733
+
91734
+ **Principles**: Proximity (group related), Consistency (same pattern for same type), Balance (distribute visual weight), Scanability (guide the eye).
91735
+
91736
+ | Element Type | Horizontal | Vertical |
91737
+ |---|---|---|
91738
+ | Body text, lists | Left | Top |
91739
+ | Headlines, CTAs | Center | Center |
91740
+ | Metadata, timestamps | Right | \u2014 |
91741
+ | Form inputs | Stretch | \u2014 |
91742
+
91743
+ ### 3. Layout Patterns
91744
+ Choose the pattern that serves the component's purpose\u2014don't default to the first idea.
91745
+
91746
+ | Pattern | When to Use | Spacing Strategy | Best For |
91747
+ |---|---|---|---|
91748
+ | **Single-Column** | Simple, focused (hero, single CTA) | Generous vertical gaps (2-3rem) | Focused actions, mobile-first |
91749
+ | **Two-Column Split** | Contrasting content (image + text) | Balance weight with whitespace | Product cards, profiles |
91750
+ | **Grid/Multi-Column** | Repeating items (galleries, cards) | Consistent gaps, subtle depth | Collections, dashboards |
91751
+ | **Stacked + Emphasis** | Primary + metadata (pricing) | Large top element, smaller secondary | Pricing, announcements |
91752
+
91753
+ ### 4. Visual Consistency
91754
+ All similar elements must share the same visual DNA.
91755
+
91756
+ **Corner Radius**:
91757
+ - Sharp (0-4px): Editorial, Luxury, Technical
91758
+ - Rounded (6-12px): Contemporary, Professional [DEFAULT]
91759
+ - Rule: All buttons same radius, all cards same radius, all inputs same radius
91760
+
91761
+ **Shadow Levels (max 3)**:
91762
+ - Rest: \`0 1px 2px rgba(0,0,0,0.05)\`
91763
+ - Hover: \`0 4px 12px rgba(0,0,0,0.08)\`
91764
+ - Floating: \`0 8px 24px rgba(0,0,0,0.12)\`
91765
+
91766
+ **Borders**: Consistent weight (all 1px or all 2px). Don't mix styles.
91767
+ **Element Heights**: All primary buttons same height, all inputs same height.
91768
+
91769
+ ### 5. Color Strategy
91770
+ Color creates hierarchy, zones, and rhythm\u2014not just decoration.
91771
+
91772
+ **Token Usage**:
91773
+ - **Backgrounds**: Use accent tints (accent-3, accent-4) for section backgrounds, base-1 for primary
91774
+ - **Depth**: Mid-tone shades for layering, subtle background shifts for distinction
91775
+ - **Emphasis**: Vibrant accents (accent-1, accent-2) for CTAs, highlights, focus states
91776
+ - **Text**: High contrast for readability. Primary on base, secondary with reduced opacity or shade
91777
+
91778
+ **Principles**:
91779
+ - Embrace the full palette\u2014don't limit to monochromatic unless context demands it
91780
+ - Create visual interest through color variety
91781
+ - Use color purposefully for hierarchy and zones, not decoration
91782
+ - Ensure sufficient contrast (WCAG AA minimum)
91783
+
91784
+ ### 6. Typography as Structure
91785
+ Typography creates hierarchy without relying on color.
91786
+
91787
+ **Font Selection & Pairing Principles**:
91788
+ 1. **Establish Clear Hierarchy**: Use font size and weight to create visual hierarchy
91789
+ 2. **Maintain Consistency**: Apply font stack and sizing scale consistently
91790
+ 3. **Anchor & Pair**: Pair fonts that complement each other
91791
+
91792
+ **Hierarchy Rules**:
91793
+ - Max 3 levels per component
91794
+ - Size contrast: Headlines 1.5-2x body size minimum
91795
+ - Weight contrast: 700 for emphasis, 400-500 for body
91796
+
91797
+ **Legibility**:
91798
+ - Line-height: 1.5-1.7 (body), 1.1-1.3 (headings)
91799
+ - Line length: 45-75 characters (optimal readability)
91800
+ - Avoid orphans (no single word on final line)
91801
+
91802
+ ### 7. Motion System
91803
+ All animations: pure CSS, smooth, purposeful.
91804
+
91805
+ **Timing**:
91806
+ | Interaction | Duration | Easing |
91807
+ |---|---|---|
91808
+ | Hover, click | 150-200ms | \`ease-out\` |
91809
+ | Active states | 250ms | \`ease-out\` |
91810
+ | Content reveals | 400-500ms | \`ease-out\` or \`cubic-bezier(0.34, 1.56, 0.64, 1)\` (spring) |
91811
+
91812
+ **Standard Reveal Animation**:
91813
+ \`\`\`css
91814
+ @keyframes contentAppear {
91815
+ from { opacity: 0; transform: translateY(10px); }
91816
+ to { opacity: 1; transform: translateY(0); }
91817
+ }
91818
+ \`\`\`
91819
+
91820
+ **Rules**:
91821
+ - Only animate \`transform\` and \`opacity\` (GPU-accelerated)
91822
+ - Respect \`prefers-reduced-motion\` (only allowed media query)
91823
+ - No looping (except loading spinners)
91824
+
91825
+ ### 8. Creative Exploration
91826
+ **Push beyond the obvious**. Award-winning design comes from exploring multiple creative directions.
91827
+
91828
+ **Trigger Questions**:
91829
+ 1. "What are 3 different layout approaches for this?" \u2192 Sketch mentally before choosing
91830
+ 2. "What would make a user say 'wow'?" \u2192 Aim for delight, not just function
91831
+ 3. "How can proportion create interest?" \u2192 Vary sizes, use asymmetry intentionally
91832
+ 4. "What interaction details would feel polished?" \u2192 Hover states, micro-animations
91833
+
91834
+ **Pattern Ideas**:
91835
+ - **Cards**: Asymmetric grids (60/40 split), overlapping elements with z-index, thick accent border (3-4px) on one side, color blocking backgrounds, typography-first (massive headline as anchor)
91836
+ - **Lists & Collections**: Alternating styles (bordered vs shadow), spotlight pattern (every 3rd item larger), color rhythm (alternating backgrounds), horizontal scroll with varied widths
91837
+ - **Interactive Elements**: Split buttons (action + dropdown), icons in colored circles, progress with color transitions, large toggles with smooth transitions
91838
+ - **Content Hierarchy**: Large numbers (3-4x size for stats), quote callouts (thick left border + tinted background), whitespace as divider (4rem+), pill badges (tight padding, accent background)
91839
+ - **Spacing Drama**: Don't be shy\u2014use 40-64px padding for hero sections. Tight clustering (4-8px) + huge gaps (40px+) between groups. Asymmetric margins (24px top, 40px bottom)
91840
+
91841
+ ### 9. Forbidden Patterns (Anti-LLM-Default)
91842
+ **Never use these unless explicitly requested**:
91843
+ - Generic shadows: \`box-shadow: 0 2px 4px rgba(0,0,0,0.1)\` \u2192 Use the shadow levels above
91844
+ - Default browser outlines \u2192 Implement custom accessible focus states
91845
+ - Decorative accent lines above titles \u2192 Use whitespace and typography instead
91846
+ - Emojis or decorative shapes \u2192 Avoid unless core to request
91847
+ - Looping animations \u2192 Only for loading states
91848
+ - Center-aligned multi-line body text \u2192 Hard to read`;
91849
+ var responseFormat = `Output as JSON with files array containing:
91850
+ 1. **manifest.json** - Component manifest (JSON) containing:
91851
+ - editorElement: full editor element configuration (selector, displayName, archetype, layout, cssProperties, data, elements, behaviors)
91852
+ 2. **component.tsx** - React component implementation
91853
+ 3. **style.css** - CSS styles
91854
+ 4. **types.ts** - TypeScript type definitions
91855
+
91856
+ Each file: { path: string, content: string, operation: "insert" }
91857
+
91858
+ ### manifest.json Structure Example:
91859
+ \`\`\`json
91860
+ {
91861
+ "editorElement": {
91862
+ "selector": ".component-name",
91863
+ "displayName": "Component Name",
91864
+ "archetype": "Container",
91865
+ "layout": { ... },
91866
+ "cssProperties": { ... },
91867
+ "elements": { ... }
91868
+ }
91869
+ }
91870
+ \`\`\`
91871
+
91872
+ **NEVER ask questions or clarifications, when in doubt make assumptions.**`;
91873
+ var assetGuidelines = `### Image Asset Requirements
91874
+ **Format**:
91875
+ \`\`\`
91876
+ <imageUrlName>
91877
+ { "description": "...", "width": number, "height": number }
91878
+ </imageUrlName>
91879
+ \`\`\`
91880
+
91881
+ **Rules**:
91882
+ - Import as named export from \`'./assets/defaultImages'\`
91883
+ - XML tag name matches imported variable name
91884
+ - Width/height: multiples of 64, between 128-2048px
91885
+ - NEVER use external URLs
91886
+
91887
+ **Example**:
91888
+ \`\`\`tsx
91889
+ import { heroImage } from './assets/defaultImages'
91890
+ ;<img src={heroImage} alt="Hero" />
91891
+ \`\`\`
91892
+
91893
+ \`\`\`
91894
+ <heroImage>
91895
+ { "description": "Modern cityscape at sunset with glass buildings reflecting golden light", "width": 1920, "height": 1088 }
91896
+ </heroImage>
91897
+ \`\`\``;
91898
+ var hardConstraints = `- Return ONLY a JSON object with files array (no prose, no markdown)
91899
+ - Each file: { path, content, operation } where operation is "insert" for new files
91900
+ - Do NOT add dependencies; do NOT use @wix/design-system or @wix/wix-ui-icons-common
91901
+ - Do NOT invent types/modules/props; use only what exists in the scaffold and standard libs
91902
+ - NEVER ask questions or clarifications, when in doubt make assumptions`;
91378
91903
  exports2.siteComponentInstructions = {
91379
91904
  role: siteComponentRole,
91380
- implementationGuidelines: siteComponentImplementationGuidelines
91905
+ coreDocumentation,
91906
+ dataTypes: dataTypesDocumentation,
91907
+ cssProperties: cssPropertiesDocumentation,
91908
+ editorElement: editorElementDocumentation,
91909
+ layout: layoutDocumentation,
91910
+ elements: elementsDocumentation,
91911
+ props: propsDocumentation,
91912
+ componentElementsGuidelines,
91913
+ manifestGuidelines: componentManifestGuidelines,
91914
+ reactGuidelines: componentReactGuidelines,
91915
+ cssGuidelines: componentCssGuidelines,
91916
+ designGuidelines,
91917
+ assetGuidelines,
91918
+ responseFormat,
91919
+ hardConstraints,
91920
+ typescriptQualityGuidelines: typescript_quality_guidelines_1.typescriptQualityGuidelines
91381
91921
  };
91382
91922
  }
91383
91923
  });
@@ -91397,7 +91937,7 @@ var require_site_component_prompt = __commonJS({
91397
91937
  apiDocumentation,
91398
91938
  useData,
91399
91939
  useIteration
91400
- }).withRole(site_component_instructions_1.siteComponentInstructions.role).withImplementationGuidelines(site_component_instructions_1.siteComponentInstructions.implementationGuidelines);
91940
+ }).withRole(site_component_instructions_1.siteComponentInstructions.role).withSection("core_documentation", site_component_instructions_1.siteComponentInstructions.coreDocumentation).withSection("data_types", site_component_instructions_1.siteComponentInstructions.dataTypes).withSection("css_properties", site_component_instructions_1.siteComponentInstructions.cssProperties).withSection("editor_element", site_component_instructions_1.siteComponentInstructions.editorElement).withSection("layout", site_component_instructions_1.siteComponentInstructions.layout).withSection("elements", site_component_instructions_1.siteComponentInstructions.elements).withSection("props", site_component_instructions_1.siteComponentInstructions.props).withSection("component_elements_guidelines", site_component_instructions_1.siteComponentInstructions.componentElementsGuidelines).withSection("manifest_guidelines", site_component_instructions_1.siteComponentInstructions.manifestGuidelines).withSection("react_guidelines", site_component_instructions_1.siteComponentInstructions.reactGuidelines).withSection("css_guidelines", site_component_instructions_1.siteComponentInstructions.cssGuidelines).withSection("design_guidelines", site_component_instructions_1.siteComponentInstructions.designGuidelines).withSection("asset_guidelines", site_component_instructions_1.siteComponentInstructions.assetGuidelines).withSection("response_format", site_component_instructions_1.siteComponentInstructions.responseFormat).withSection("hard_constraints", site_component_instructions_1.siteComponentInstructions.hardConstraints).withImplementationGuidelines(site_component_instructions_1.siteComponentInstructions.typescriptQualityGuidelines);
91401
91941
  };
91402
91942
  var siteComponentCorePrompt = () => {
91403
91943
  return createCoreBuilder({
@@ -105183,14 +105723,12 @@ var require_extensionGenerators = __commonJS({
105183
105723
  }
105184
105724
  case types_1.ExtensionType.SITE_COMPONENT: {
105185
105725
  const name = extension.name || "My Site Component";
105186
- const extensionConfig = this.createSiteComponentData(name, scaffoldDir, id);
105187
- return writeExtensionFile({
105726
+ return writeSiteComponentExtensionFile({
105188
105727
  outputPath,
105189
105728
  name,
105190
- builderMethodName: "siteComponent",
105191
- extensionConfig,
105192
105729
  extensionType: extension.type,
105193
- scaffoldDir
105730
+ scaffoldDir,
105731
+ id
105194
105732
  });
105195
105733
  }
105196
105734
  case types_1.ExtensionType.SITE_WIDGET: {
@@ -105315,24 +105853,6 @@ var require_extensionGenerators = __commonJS({
105315
105853
  height: { defaultHeight: 500 }
105316
105854
  };
105317
105855
  }
105318
- static createSiteComponentData(name, scaffoldDir, id) {
105319
- const kebabCaseComponentName = (0, ditto_scaffolding_2.toKebabCase)(name);
105320
- const componentPath = getScaffoldPath(scaffoldDir, "component.tsx");
105321
- return {
105322
- id,
105323
- description: name,
105324
- type: `platform.builder.${id}`,
105325
- editorElement: {
105326
- displayName: name,
105327
- selector: kebabCaseComponentName
105328
- },
105329
- resources: {
105330
- client: {
105331
- componentUrl: componentPath
105332
- }
105333
- }
105334
- };
105335
- }
105336
105856
  static createEmbeddedScriptData(id, name, scaffoldDir, placement, scriptType) {
105337
105857
  const source = getScaffoldPath(scaffoldDir, "embedded.html");
105338
105858
  return {
@@ -105356,25 +105876,59 @@ var require_extensionGenerators = __commonJS({
105356
105876
  function getScaffoldPath(scaffoldDir, file) {
105357
105877
  return "./" + path_1.default.join(scaffoldDir, file).replace(/^src\//, "");
105358
105878
  }
105359
- function writeExtensionFile({ outputPath, name, builderMethodName, extensionConfig, extensionType, scaffoldDir }) {
105879
+ function validateAndSanitizeName(name) {
105360
105880
  const sanitizedName = name.replace(/[^a-zA-Z0-9\s-_]/g, "").trim();
105361
105881
  if (!sanitizedName) {
105362
105882
  throw new ditto_codegen_types_12.ExtensionGenerationError(`Invalid extension name: "${name}"`, {
105363
105883
  extensionName: name
105364
105884
  });
105365
105885
  }
105886
+ return sanitizedName;
105887
+ }
105888
+ function resolveAndValidateScaffoldPath(outputPath, scaffoldDir) {
105366
105889
  const absoluteScaffoldPath = path_1.default.isAbsolute(scaffoldDir) ? scaffoldDir : path_1.default.resolve(outputPath, scaffoldDir);
105367
- const filePath = path_1.default.join(absoluteScaffoldPath, "extensions.ts");
105368
- const relativePath = path_1.default.relative(outputPath, filePath);
105369
- const normalizedFilePath = path_1.default.resolve(filePath);
105890
+ const normalizedScaffoldPath = path_1.default.resolve(absoluteScaffoldPath);
105370
105891
  const normalizedOutputPath = path_1.default.resolve(outputPath);
105371
- if (!normalizedFilePath.startsWith(normalizedOutputPath)) {
105372
- throw new ditto_codegen_types_12.ExtensionGenerationError(`Attempted to write extension file outside output path: ${filePath}`, { filePath });
105892
+ if (!normalizedScaffoldPath.startsWith(normalizedOutputPath)) {
105893
+ throw new ditto_codegen_types_12.ExtensionGenerationError(`Attempted to write files outside output path: ${absoluteScaffoldPath}`, { filePath: absoluteScaffoldPath });
105373
105894
  }
105374
- const tsContent = generateExtensionTsContent(builderMethodName, extensionConfig, extensionType, name);
105375
- fs_extra_1.default.outputFileSync(filePath, tsContent);
105895
+ return absoluteScaffoldPath;
105896
+ }
105897
+ function writeExtensionsFile(outputPath, absoluteScaffoldPath, content) {
105898
+ const extensionsFilePath = path_1.default.join(absoluteScaffoldPath, "extensions.ts");
105899
+ const relativePath = path_1.default.relative(outputPath, extensionsFilePath);
105900
+ fs_extra_1.default.outputFileSync(extensionsFilePath, content);
105376
105901
  return relativePath;
105377
105902
  }
105903
+ function writeExtensionFile({ outputPath, name, builderMethodName, extensionConfig, extensionType, scaffoldDir }) {
105904
+ validateAndSanitizeName(name);
105905
+ const absoluteScaffoldPath = resolveAndValidateScaffoldPath(outputPath, scaffoldDir);
105906
+ const tsContent = generateExtensionTsContent(builderMethodName, extensionConfig, extensionType, name);
105907
+ return writeExtensionsFile(outputPath, absoluteScaffoldPath, tsContent);
105908
+ }
105909
+ function writeSiteComponentExtensionFile({ outputPath, name, extensionType, scaffoldDir, id }) {
105910
+ validateAndSanitizeName(name);
105911
+ const absoluteScaffoldPath = resolveAndValidateScaffoldPath(outputPath, scaffoldDir);
105912
+ const componentPath = getScaffoldPath(scaffoldDir, "component.tsx");
105913
+ const extensionName = generateUniqueExtensionName(extensionType, name);
105914
+ const tsContent = `import { extensions } from '@wix/astro/builders';
105915
+ import manifest from './manifest.json';
105916
+
105917
+ export const ${extensionName} = extensions.siteComponent({
105918
+ ...manifest,
105919
+ id: '${id}',
105920
+ description: '${name}',
105921
+ type: 'platform.builder.${id}',
105922
+ resources: {
105923
+ client: {
105924
+ component: '${componentPath}',
105925
+ componentUrl: '${componentPath}',
105926
+ },
105927
+ },
105928
+ });
105929
+ `;
105930
+ return writeExtensionsFile(outputPath, absoluteScaffoldPath, tsContent);
105931
+ }
105378
105932
  function generateExtensionTsContent(builderMethodName, extensionConfig, extensionType, name) {
105379
105933
  const extensionName = generateUniqueExtensionName(extensionType, name);
105380
105934
  const configString = (0, naturalJsonStringify_1.naturalJsonStringify)(extensionConfig);