@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.
- package/dist/examples-apps/react-builder/component.tsx +117 -0
- package/dist/examples-apps/react-builder/components/Badge.tsx +14 -0
- package/dist/examples-apps/react-builder/components/Button.tsx +31 -0
- package/dist/examples-apps/react-builder/components/Counter.tsx +14 -0
- package/dist/examples-apps/react-builder/components/FeaturedImage.tsx +31 -0
- package/dist/examples-apps/react-builder/components/SocialLinks.tsx +61 -0
- package/dist/examples-apps/react-builder/components/Subtitle.tsx +11 -0
- package/dist/examples-apps/react-builder/components/Tags.tsx +25 -0
- package/dist/examples-apps/react-builder/components/Title.tsx +11 -0
- package/dist/examples-apps/react-builder/components/index.ts +8 -0
- package/dist/examples-apps/react-builder/manifest.json +325 -0
- package/dist/examples-apps/react-builder/style.css +197 -0
- package/dist/examples-apps/react-builder/types.ts +68 -0
- package/dist/out.js +615 -61
- package/dist/wix-cli-templates/src/site/components/my-component/component.tsx +8 -5
- package/dist/wix-cli-templates/src/site/components/my-component/manifest.json +14 -0
- package/dist/wix-cli-templates/src/site/components/my-component/{styles.module.css → style.css} +1 -1
- package/package.json +2 -2
- package/dist/examples-apps/inventory-countdown/.nvmrc +0 -1
- package/dist/examples-apps/inventory-countdown/README.md +0 -21
- package/dist/examples-apps/inventory-countdown/package-lock.json +0 -7457
- package/dist/examples-apps/inventory-countdown/package.json +0 -33
- package/dist/examples-apps/inventory-countdown/src/assets/stock-counter/site-plugin-logo.svg +0 -27
- package/dist/examples-apps/inventory-countdown/src/env.d.ts +0 -4
- package/dist/examples-apps/inventory-countdown/src/site/plugins/custom-elements/stock-counter/consts.ts +0 -1
- package/dist/examples-apps/inventory-countdown/src/site/plugins/custom-elements/stock-counter/panel.tsx +0 -81
- package/dist/examples-apps/inventory-countdown/src/site/plugins/custom-elements/stock-counter/plugin.json +0 -24
- package/dist/examples-apps/inventory-countdown/src/site/plugins/custom-elements/stock-counter/plugin.module.css +0 -4
- package/dist/examples-apps/inventory-countdown/src/site/plugins/custom-elements/stock-counter/plugin.tsx +0 -132
- package/dist/examples-apps/inventory-countdown/tsconfig.json +0 -8
- 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
|
-
|
|
75697
|
-
path: "
|
|
75698
|
-
description: "A
|
|
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
|
-
"
|
|
75702
|
-
"
|
|
75703
|
-
"
|
|
75704
|
-
"
|
|
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.
|
|
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
|
|
91356
|
-
|
|
91357
|
-
|
|
91358
|
-
|
|
91359
|
-
|
|
91360
|
-
|
|
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
|
-
|
|
91363
|
-
|
|
91364
|
-
|
|
91365
|
-
|
|
91366
|
-
|
|
91367
|
-
|
|
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
|
-
|
|
91370
|
-
|
|
91371
|
-
|
|
91372
|
-
|
|
91373
|
-
|
|
91374
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
|
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
|
|
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 (!
|
|
105372
|
-
throw new ditto_codegen_types_12.ExtensionGenerationError(`Attempted to write
|
|
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
|
-
|
|
105375
|
-
|
|
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);
|