@webstudio-is/react-sdk 0.0.1-c87cdba.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js ADDED
@@ -0,0 +1,1834 @@
1
+ // src/remix.ts
2
+ var getRemixSegment = (segment) => {
3
+ if (segment === "*") {
4
+ return "$";
5
+ }
6
+ const match = segment.match(/^:(?<name>\w+)(?<modifier>\*|\?)?$/);
7
+ const name = match?.groups?.name;
8
+ const modifier = match?.groups?.modifier;
9
+ if (name) {
10
+ if (modifier === "*") {
11
+ return "$";
12
+ }
13
+ if (modifier === "?") {
14
+ return `($${name})`;
15
+ }
16
+ return `$${name}`;
17
+ }
18
+ return `[${segment}]`;
19
+ };
20
+ var generateRemixRoute = (pathname) => {
21
+ if (pathname.startsWith("/")) {
22
+ pathname = pathname.slice(1);
23
+ }
24
+ if (pathname === "") {
25
+ return `_index`;
26
+ }
27
+ const base = pathname.split("/").map(getRemixSegment).join(".");
28
+ const tail = pathname.endsWith("*") ? "" : "._index";
29
+ return `${base}${tail}`;
30
+ };
31
+ var generateRemixParams = (pathname) => {
32
+ const name = pathname.match(/:(?<name>\w+)\*$/)?.groups?.name;
33
+ let generated = "";
34
+ generated += `type Params = Record<string, string | undefined>;
35
+ `;
36
+ generated += `export const getRemixParams = ({ ...params }: Params): Params => {
37
+ `;
38
+ if (name) {
39
+ generated += ` params["${name}"] = params["*"]
40
+ `;
41
+ generated += ` delete params["*"]
42
+ `;
43
+ }
44
+ if (pathname.endsWith("/*")) {
45
+ generated += ` params[0] = params["*"]
46
+ `;
47
+ generated += ` delete params["*"]
48
+ `;
49
+ }
50
+ generated += ` return params
51
+ `;
52
+ generated += `}
53
+ `;
54
+ return generated;
55
+ };
56
+
57
+ // src/css/global-rules.ts
58
+ import { getFontFaces } from "@webstudio-is/fonts";
59
+ var addGlobalRules = (sheet, { assets, assetBaseUrl }) => {
60
+ const fontAssets = [];
61
+ for (const asset of assets.values()) {
62
+ if (asset.type === "font") {
63
+ fontAssets.push(asset);
64
+ }
65
+ }
66
+ const fontFaces = getFontFaces(fontAssets, { assetBaseUrl });
67
+ for (const fontFace of fontFaces) {
68
+ sheet.addFontFaceRule(fontFace);
69
+ }
70
+ };
71
+
72
+ // src/css/css.ts
73
+ import {
74
+ createRegularStyleSheet,
75
+ generateAtomic
76
+ } from "@webstudio-is/css-engine";
77
+ import {
78
+ ROOT_INSTANCE_ID,
79
+ createScope,
80
+ parseComponentName
81
+ } from "@webstudio-is/sdk";
82
+
83
+ // src/core-components.ts
84
+ import {
85
+ ContentBlockIcon,
86
+ ListViewIcon,
87
+ PaintBrushIcon,
88
+ SettingsIcon,
89
+ AddTemplateInstanceIcon
90
+ } from "@webstudio-is/icons/svg";
91
+ import { html } from "@webstudio-is/sdk/normalize.css";
92
+ var rootComponent = "ws:root";
93
+ var rootMeta = {
94
+ category: "hidden",
95
+ type: "container",
96
+ label: "Global Root",
97
+ icon: SettingsIcon,
98
+ presetStyle: {
99
+ html
100
+ }
101
+ };
102
+ var rootPropsMeta = {
103
+ props: {}
104
+ };
105
+ var portalComponent = "Slot";
106
+ var collectionComponent = "ws:collection";
107
+ var collectionMeta = {
108
+ category: "data",
109
+ order: 2,
110
+ type: "container",
111
+ label: "Collection",
112
+ icon: ListViewIcon,
113
+ stylable: false,
114
+ template: [
115
+ {
116
+ type: "instance",
117
+ component: collectionComponent,
118
+ props: [
119
+ {
120
+ name: "data",
121
+ type: "json",
122
+ value: [
123
+ "Collection Item 1",
124
+ "Collection Item 2",
125
+ "Collection Item 3"
126
+ ]
127
+ },
128
+ {
129
+ name: "item",
130
+ type: "parameter",
131
+ variableName: "collectionItem",
132
+ variableAlias: "Collection Item"
133
+ }
134
+ ],
135
+ children: [
136
+ {
137
+ type: "instance",
138
+ component: "Box",
139
+ children: [
140
+ {
141
+ type: "instance",
142
+ component: "Text",
143
+ children: [{ type: "expression", value: "collectionItem" }]
144
+ }
145
+ ]
146
+ }
147
+ ]
148
+ }
149
+ ]
150
+ };
151
+ var collectionPropsMeta = {
152
+ props: {
153
+ data: {
154
+ required: true,
155
+ control: "json",
156
+ type: "json"
157
+ }
158
+ },
159
+ initialProps: ["data"]
160
+ };
161
+ var descendantComponent = "ws:descendant";
162
+ var descendantMeta = {
163
+ category: "internal",
164
+ type: "control",
165
+ label: "Descendant",
166
+ icon: PaintBrushIcon,
167
+ constraints: {
168
+ relation: "parent",
169
+ component: { $in: ["HtmlEmbed", "MarkdownEmbed"] }
170
+ }
171
+ };
172
+ var descendantPropsMeta = {
173
+ props: {
174
+ selector: {
175
+ required: true,
176
+ type: "string",
177
+ control: "select",
178
+ options: [
179
+ " p",
180
+ " h1",
181
+ " h2",
182
+ " h3",
183
+ " h4",
184
+ " h5",
185
+ " h6",
186
+ " :where(strong, b)",
187
+ " :where(em, i)",
188
+ " a",
189
+ " img",
190
+ " blockquote",
191
+ " code",
192
+ " :where(ul, ol)",
193
+ " li",
194
+ " hr"
195
+ ]
196
+ }
197
+ },
198
+ initialProps: ["selector"]
199
+ };
200
+ var blockComponent = "ws:block";
201
+ var blockTemplateComponent = "ws:block-template";
202
+ var blockTemplateMeta = {
203
+ category: "hidden",
204
+ type: "container",
205
+ icon: AddTemplateInstanceIcon,
206
+ stylable: false,
207
+ constraints: {
208
+ relation: "parent",
209
+ component: { $eq: blockComponent }
210
+ }
211
+ };
212
+ var blockTemplatePropsMeta = {
213
+ props: {},
214
+ initialProps: []
215
+ };
216
+ var blockMeta = {
217
+ category: "typography",
218
+ type: "container",
219
+ label: "Content Block",
220
+ icon: ContentBlockIcon,
221
+ constraints: [
222
+ {
223
+ relation: "ancestor",
224
+ component: { $nin: [collectionComponent, blockComponent] }
225
+ },
226
+ {
227
+ relation: "child",
228
+ component: { $eq: blockTemplateComponent }
229
+ }
230
+ ],
231
+ stylable: false,
232
+ template: [
233
+ {
234
+ type: "instance",
235
+ component: blockComponent,
236
+ props: [],
237
+ children: [
238
+ {
239
+ component: blockTemplateComponent,
240
+ type: "instance",
241
+ label: "Templates",
242
+ children: [
243
+ {
244
+ component: "Paragraph",
245
+ type: "instance",
246
+ children: []
247
+ },
248
+ {
249
+ component: "Heading",
250
+ type: "instance",
251
+ label: "Heading 1",
252
+ props: [
253
+ {
254
+ name: "tag",
255
+ type: "string",
256
+ value: "h1"
257
+ }
258
+ ],
259
+ children: []
260
+ },
261
+ {
262
+ component: "Heading",
263
+ type: "instance",
264
+ label: "Heading 2",
265
+ props: [
266
+ {
267
+ name: "tag",
268
+ type: "string",
269
+ value: "h2"
270
+ }
271
+ ],
272
+ children: []
273
+ },
274
+ {
275
+ component: "Heading",
276
+ type: "instance",
277
+ label: "Heading 3",
278
+ props: [
279
+ {
280
+ name: "tag",
281
+ type: "string",
282
+ value: "h3"
283
+ }
284
+ ],
285
+ children: []
286
+ },
287
+ {
288
+ component: "Heading",
289
+ type: "instance",
290
+ label: "Heading 4",
291
+ props: [
292
+ {
293
+ name: "tag",
294
+ type: "string",
295
+ value: "h4"
296
+ }
297
+ ],
298
+ children: []
299
+ },
300
+ {
301
+ component: "Heading",
302
+ type: "instance",
303
+ label: "Heading 5",
304
+ props: [
305
+ {
306
+ name: "tag",
307
+ type: "string",
308
+ value: "h5"
309
+ }
310
+ ],
311
+ children: []
312
+ },
313
+ {
314
+ component: "Heading",
315
+ type: "instance",
316
+ label: "Heading 6",
317
+ props: [
318
+ {
319
+ name: "tag",
320
+ type: "string",
321
+ value: "h6"
322
+ }
323
+ ],
324
+ children: []
325
+ },
326
+ {
327
+ component: "List",
328
+ type: "instance",
329
+ label: "List (Unordered)",
330
+ children: [
331
+ {
332
+ component: "ListItem",
333
+ type: "instance",
334
+ children: []
335
+ }
336
+ ]
337
+ },
338
+ {
339
+ component: "List",
340
+ type: "instance",
341
+ label: "List (Ordered)",
342
+ props: [
343
+ {
344
+ name: "ordered",
345
+ type: "boolean",
346
+ value: true
347
+ }
348
+ ],
349
+ children: [
350
+ {
351
+ component: "ListItem",
352
+ type: "instance",
353
+ children: []
354
+ }
355
+ ]
356
+ },
357
+ {
358
+ component: "Link",
359
+ type: "instance",
360
+ children: []
361
+ },
362
+ {
363
+ component: "Image",
364
+ type: "instance",
365
+ styles: [
366
+ {
367
+ property: "marginRight",
368
+ value: {
369
+ type: "keyword",
370
+ value: "auto"
371
+ }
372
+ },
373
+ {
374
+ property: "marginLeft",
375
+ value: {
376
+ type: "keyword",
377
+ value: "auto"
378
+ }
379
+ },
380
+ {
381
+ property: "width",
382
+ value: {
383
+ type: "unit",
384
+ unit: "%",
385
+ value: 100
386
+ }
387
+ },
388
+ {
389
+ property: "height",
390
+ value: {
391
+ type: "keyword",
392
+ value: "auto"
393
+ }
394
+ }
395
+ ],
396
+ children: []
397
+ },
398
+ {
399
+ component: "Separator",
400
+ type: "instance",
401
+ children: []
402
+ },
403
+ {
404
+ component: "Blockquote",
405
+ type: "instance",
406
+ children: []
407
+ },
408
+ {
409
+ component: "HtmlEmbed",
410
+ type: "instance",
411
+ children: []
412
+ },
413
+ {
414
+ component: "CodeText",
415
+ type: "instance",
416
+ children: []
417
+ }
418
+ ]
419
+ },
420
+ {
421
+ type: "instance",
422
+ component: "Paragraph",
423
+ children: [
424
+ {
425
+ type: "text",
426
+ value: "The Content Block component designates regions on the page where pre-styled instances can be inserted in "
427
+ },
428
+ {
429
+ type: "instance",
430
+ component: "RichTextLink",
431
+ children: [
432
+ {
433
+ type: "text",
434
+ value: "Content mode"
435
+ }
436
+ ],
437
+ props: [
438
+ {
439
+ type: "string",
440
+ name: "href",
441
+ value: "https://wstd.us/content-block"
442
+ }
443
+ ]
444
+ },
445
+ {
446
+ type: "text",
447
+ value: "."
448
+ }
449
+ ]
450
+ },
451
+ {
452
+ type: "instance",
453
+ component: "List",
454
+ children: [
455
+ {
456
+ type: "instance",
457
+ component: "ListItem",
458
+ children: [
459
+ {
460
+ type: "text",
461
+ value: "In Content mode, you can edit any direct child instances that were pre-added to the Content Block, as well as add new instances predefined in Templates."
462
+ }
463
+ ]
464
+ },
465
+ {
466
+ type: "instance",
467
+ component: "ListItem",
468
+ children: [
469
+ {
470
+ type: "text",
471
+ value: "To predefine instances for insertion in Content mode, switch to Design mode and add them to the Templates container."
472
+ }
473
+ ]
474
+ },
475
+ {
476
+ type: "instance",
477
+ component: "ListItem",
478
+ children: [
479
+ {
480
+ type: "text",
481
+ value: "To insert predefined instances in Content mode, click the + button while hovering over the Content Block on the canvas and choose an instance from the list."
482
+ }
483
+ ]
484
+ }
485
+ ]
486
+ }
487
+ ]
488
+ }
489
+ ]
490
+ };
491
+ var blockPropsMeta = {
492
+ props: {},
493
+ initialProps: []
494
+ };
495
+ var coreMetas = {
496
+ [rootComponent]: rootMeta,
497
+ [collectionComponent]: collectionMeta,
498
+ [descendantComponent]: descendantMeta,
499
+ [blockComponent]: blockMeta,
500
+ [blockTemplateComponent]: blockTemplateMeta
501
+ };
502
+ var corePropsMetas = {
503
+ [rootComponent]: rootPropsMeta,
504
+ [collectionComponent]: collectionPropsMeta,
505
+ [descendantComponent]: descendantPropsMeta,
506
+ [blockComponent]: blockPropsMeta,
507
+ [blockTemplateComponent]: blockTemplatePropsMeta
508
+ };
509
+ var isCoreComponent = (component) => component === rootComponent || component === collectionComponent || component === descendantComponent || component === blockComponent || component === blockTemplateComponent;
510
+
511
+ // src/css/css.ts
512
+ import { kebabCase } from "change-case";
513
+ var createImageValueTransformer = (assets, { assetBaseUrl }) => (styleValue) => {
514
+ if (styleValue.type === "image" && styleValue.value.type === "asset") {
515
+ const asset = assets.get(styleValue.value.value);
516
+ if (asset === void 0) {
517
+ return { type: "keyword", value: "none" };
518
+ }
519
+ const url = `${assetBaseUrl}${asset.name}`;
520
+ return {
521
+ type: "image",
522
+ value: {
523
+ type: "url",
524
+ url
525
+ },
526
+ hidden: styleValue.hidden
527
+ };
528
+ }
529
+ };
530
+ var normalizeClassName = (name) => kebabCase(name);
531
+ var generateCss = ({
532
+ assets,
533
+ instances,
534
+ props,
535
+ breakpoints,
536
+ styles,
537
+ styleSourceSelections,
538
+ componentMetas,
539
+ assetBaseUrl,
540
+ atomic
541
+ }) => {
542
+ const globalSheet = createRegularStyleSheet({ name: "ssr" });
543
+ const sheet = createRegularStyleSheet({ name: "ssr" });
544
+ addGlobalRules(globalSheet, { assets, assetBaseUrl });
545
+ globalSheet.addMediaRule("presets");
546
+ const presetClasses = /* @__PURE__ */ new Map();
547
+ const scope = createScope([], normalizeClassName, "-");
548
+ for (const [component, meta] of componentMetas) {
549
+ const [_namespace, componentName] = parseComponentName(component);
550
+ const className = `w-${scope.getName(component, meta.label ?? componentName)}`;
551
+ const presetStyle = Object.entries(meta.presetStyle ?? {});
552
+ if (presetStyle.length > 0) {
553
+ presetClasses.set(component, className);
554
+ }
555
+ for (const [tag, styles2] of presetStyle) {
556
+ const selector = component === rootComponent ? ":root" : `:where(${tag}.${className})`;
557
+ const rule = globalSheet.addNestingRule(selector);
558
+ for (const declaration of styles2) {
559
+ rule.setDeclaration({
560
+ breakpoint: "presets",
561
+ selector: declaration.state ?? "",
562
+ property: declaration.property,
563
+ value: declaration.value
564
+ });
565
+ }
566
+ }
567
+ }
568
+ for (const breakpoint of breakpoints.values()) {
569
+ sheet.addMediaRule(breakpoint.id, breakpoint);
570
+ }
571
+ const imageValueTransformer = createImageValueTransformer(assets, {
572
+ assetBaseUrl
573
+ });
574
+ sheet.setTransformer(imageValueTransformer);
575
+ for (const styleDecl of styles.values()) {
576
+ const rule = sheet.addMixinRule(styleDecl.styleSourceId);
577
+ rule.setDeclaration({
578
+ breakpoint: styleDecl.breakpointId,
579
+ selector: styleDecl.state ?? "",
580
+ property: styleDecl.property,
581
+ value: styleDecl.value
582
+ });
583
+ }
584
+ const classes = /* @__PURE__ */ new Map();
585
+ const parentIdByInstanceId = /* @__PURE__ */ new Map();
586
+ for (const instance of instances.values()) {
587
+ const presetClass = presetClasses.get(instance.component);
588
+ if (presetClass) {
589
+ classes.set(instance.id, [presetClass]);
590
+ }
591
+ for (const child of instance.children) {
592
+ if (child.type === "id") {
593
+ parentIdByInstanceId.set(child.value, instance.id);
594
+ }
595
+ }
596
+ }
597
+ const descendantSelectorByInstanceId = /* @__PURE__ */ new Map();
598
+ for (const prop of props.values()) {
599
+ if (prop.name === "selector" && prop.type === "string") {
600
+ descendantSelectorByInstanceId.set(prop.instanceId, prop.value);
601
+ }
602
+ }
603
+ const instanceByRule = /* @__PURE__ */ new Map();
604
+ for (const selection of styleSourceSelections.values()) {
605
+ let { instanceId } = selection;
606
+ const { values } = selection;
607
+ if (instanceId === ROOT_INSTANCE_ID) {
608
+ const rule2 = sheet.addNestingRule(`:root`);
609
+ rule2.applyMixins(values);
610
+ continue;
611
+ }
612
+ let descendantSuffix = "";
613
+ const instance = instances.get(instanceId);
614
+ if (instance?.component === descendantComponent) {
615
+ const parentId = parentIdByInstanceId.get(instanceId);
616
+ const descendantSelector = descendantSelectorByInstanceId.get(instanceId);
617
+ if (parentId && descendantSelector) {
618
+ descendantSuffix = descendantSelector;
619
+ instanceId = parentId;
620
+ }
621
+ }
622
+ const meta = instance ? componentMetas.get(instance.component) : void 0;
623
+ const baseName = instance?.label ?? meta?.label ?? instance?.component ?? instanceId;
624
+ const className = `w-${scope.getName(instanceId, baseName)}`;
625
+ if (atomic === false) {
626
+ let classList = classes.get(instanceId);
627
+ if (classList === void 0) {
628
+ classList = [];
629
+ classes.set(instanceId, classList);
630
+ }
631
+ classList.push(className);
632
+ }
633
+ const rule = sheet.addNestingRule(`.${className}`, descendantSuffix);
634
+ rule.applyMixins(values);
635
+ instanceByRule.set(rule, instanceId);
636
+ }
637
+ if (atomic) {
638
+ const { cssText } = generateAtomic(sheet, {
639
+ getKey: (rule) => instanceByRule.get(rule),
640
+ transformValue: imageValueTransformer,
641
+ classes
642
+ });
643
+ return { cssText: `${globalSheet.cssText}
644
+ ${cssText}`, classes };
645
+ }
646
+ return {
647
+ cssText: `${globalSheet.cssText}
648
+ ${sheet.cssText}`,
649
+ classes
650
+ };
651
+ };
652
+
653
+ // src/props.ts
654
+ import {
655
+ getPagePath,
656
+ findPageByIdOrPath
657
+ } from "@webstudio-is/sdk";
658
+ var normalizeProps = ({
659
+ props,
660
+ assetBaseUrl,
661
+ assets,
662
+ uploadingImageAssets,
663
+ pages,
664
+ source
665
+ }) => {
666
+ const newProps = [];
667
+ for (const prop of props) {
668
+ if (prop.type === "asset") {
669
+ const assetId = prop.value;
670
+ const asset = assets.get(assetId) ?? uploadingImageAssets.find((asset2) => asset2.id === assetId);
671
+ if (asset === void 0) {
672
+ continue;
673
+ }
674
+ const propBase = {
675
+ id: prop.id,
676
+ name: prop.name,
677
+ required: prop.required,
678
+ instanceId: prop.instanceId
679
+ };
680
+ if (prop.name === "width" && asset.type === "image") {
681
+ newProps.push({
682
+ ...propBase,
683
+ type: "number",
684
+ value: asset.meta.width
685
+ });
686
+ continue;
687
+ }
688
+ if (prop.name === "height" && asset.type === "image") {
689
+ newProps.push({
690
+ ...propBase,
691
+ type: "number",
692
+ value: asset.meta.height
693
+ });
694
+ continue;
695
+ }
696
+ newProps.push({
697
+ ...propBase,
698
+ type: "string",
699
+ value: `${assetBaseUrl}${asset.name}`
700
+ });
701
+ if (source === "canvas") {
702
+ newProps.push({
703
+ id: `${prop.instanceId}-${asset.id}-assetId`,
704
+ name: "$webstudio$canvasOnly$assetId",
705
+ required: false,
706
+ instanceId: prop.instanceId,
707
+ type: "string",
708
+ value: asset.id
709
+ });
710
+ }
711
+ continue;
712
+ }
713
+ if (prop.type === "page") {
714
+ let idProp;
715
+ const pageId = typeof prop.value === "string" ? prop.value : prop.value.pageId;
716
+ const page = findPageByIdOrPath(pageId, pages);
717
+ if (page === void 0) {
718
+ continue;
719
+ }
720
+ if (typeof prop.value !== "string") {
721
+ const { instanceId } = prop.value;
722
+ idProp = props.find(
723
+ (prop2) => prop2.instanceId === instanceId && prop2.name === "id"
724
+ );
725
+ }
726
+ const path = getPagePath(page.id, pages);
727
+ const url = new URL(path, "https://any-valid.url");
728
+ let value = url.pathname;
729
+ if (idProp?.type === "string") {
730
+ const hash = idProp.value;
731
+ url.hash = encodeURIComponent(hash);
732
+ value = `${url.pathname}${url.hash}`;
733
+ }
734
+ newProps.push({
735
+ id: prop.id,
736
+ name: prop.name,
737
+ required: prop.required,
738
+ instanceId: prop.instanceId,
739
+ type: "string",
740
+ value
741
+ });
742
+ continue;
743
+ }
744
+ newProps.push(prop);
745
+ }
746
+ return newProps;
747
+ };
748
+ var idAttribute = "data-ws-id";
749
+ var selectorIdAttribute = "data-ws-selector";
750
+ var componentAttribute = "data-ws-component";
751
+ var showAttribute = "data-ws-show";
752
+ var indexAttribute = "data-ws-index";
753
+ var collapsedAttribute = "data-ws-collapsed";
754
+ var textContentAttribute = "data-ws-text-content";
755
+ var editablePlaceholderVariable = "--data-ws-editable-placeholder";
756
+ var editingPlaceholderVariable = "--data-ws-editing-placeholder";
757
+ var attributeNameStartChar = "A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
758
+ var attributeNameChar = attributeNameStartChar + ":\\-0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
759
+ var validAttributeNameRegex = new RegExp(
760
+ // eslint-disable-next-line no-misleading-character-class
761
+ "^[" + attributeNameStartChar + "][" + attributeNameChar + "]*$"
762
+ );
763
+ var illegalAttributeNameCache = /* @__PURE__ */ new Map();
764
+ var validatedAttributeNameCache = /* @__PURE__ */ new Map();
765
+ var isAttributeNameSafe = (attributeName) => {
766
+ if (validatedAttributeNameCache.has(attributeName)) {
767
+ return true;
768
+ }
769
+ if (illegalAttributeNameCache.has(attributeName)) {
770
+ return false;
771
+ }
772
+ if (validAttributeNameRegex.test(attributeName)) {
773
+ validatedAttributeNameCache.set(attributeName, true);
774
+ return true;
775
+ }
776
+ illegalAttributeNameCache.set(attributeName, true);
777
+ return false;
778
+ };
779
+
780
+ // src/prop-meta.ts
781
+ import { z } from "zod";
782
+ var common = {
783
+ label: z.string().optional(),
784
+ description: z.string().optional(),
785
+ required: z.boolean()
786
+ };
787
+ var Number = z.object({
788
+ ...common,
789
+ control: z.literal("number"),
790
+ type: z.literal("number"),
791
+ defaultValue: z.number().optional()
792
+ });
793
+ var Range = z.object({
794
+ ...common,
795
+ control: z.literal("range"),
796
+ type: z.literal("number"),
797
+ defaultValue: z.number().optional()
798
+ });
799
+ var Text = z.object({
800
+ ...common,
801
+ control: z.literal("text"),
802
+ type: z.literal("string"),
803
+ defaultValue: z.string().optional(),
804
+ /**
805
+ * The number of rows in <textarea>. If set to 0 an <input> will be used instead.
806
+ * In line with Storybook team's plan: https://github.com/storybookjs/storybook/issues/21100
807
+ */
808
+ rows: z.number().optional()
809
+ });
810
+ var Code = z.object({
811
+ ...common,
812
+ control: z.literal("code"),
813
+ type: z.literal("string"),
814
+ language: z.union([z.literal("html"), z.literal("markdown")]),
815
+ defaultValue: z.string().optional()
816
+ });
817
+ var CodeText = z.object({
818
+ ...common,
819
+ control: z.literal("codetext"),
820
+ type: z.literal("string"),
821
+ defaultValue: z.string().optional()
822
+ });
823
+ var Color = z.object({
824
+ ...common,
825
+ control: z.literal("color"),
826
+ type: z.literal("string"),
827
+ defaultValue: z.string().optional()
828
+ });
829
+ var Boolean = z.object({
830
+ ...common,
831
+ control: z.literal("boolean"),
832
+ type: z.literal("boolean"),
833
+ defaultValue: z.boolean().optional()
834
+ });
835
+ var Radio = z.object({
836
+ ...common,
837
+ control: z.literal("radio"),
838
+ type: z.literal("string"),
839
+ defaultValue: z.string().optional(),
840
+ options: z.array(z.string())
841
+ });
842
+ var InlineRadio = z.object({
843
+ ...common,
844
+ control: z.literal("inline-radio"),
845
+ type: z.literal("string"),
846
+ defaultValue: z.string().optional(),
847
+ options: z.array(z.string())
848
+ });
849
+ var Select = z.object({
850
+ ...common,
851
+ control: z.literal("select"),
852
+ type: z.literal("string"),
853
+ defaultValue: z.string().optional(),
854
+ options: z.array(z.string())
855
+ });
856
+ var Check = z.object({
857
+ ...common,
858
+ control: z.literal("check"),
859
+ type: z.literal("string[]"),
860
+ defaultValue: z.array(z.string()).optional(),
861
+ options: z.array(z.string())
862
+ });
863
+ var InlineCheck = z.object({
864
+ ...common,
865
+ control: z.literal("inline-check"),
866
+ type: z.literal("string[]"),
867
+ defaultValue: z.array(z.string()).optional(),
868
+ options: z.array(z.string())
869
+ });
870
+ var MultiSelect = z.object({
871
+ ...common,
872
+ control: z.literal("multi-select"),
873
+ type: z.literal("string[]"),
874
+ defaultValue: z.array(z.string()).optional(),
875
+ options: z.array(z.string())
876
+ });
877
+ var File = z.object({
878
+ ...common,
879
+ control: z.literal("file"),
880
+ type: z.literal("string"),
881
+ defaultValue: z.string().optional(),
882
+ /** https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept */
883
+ accept: z.string().optional()
884
+ });
885
+ var Url = z.object({
886
+ ...common,
887
+ control: z.literal("url"),
888
+ type: z.literal("string"),
889
+ defaultValue: z.string().optional()
890
+ });
891
+ var Json = z.object({
892
+ ...common,
893
+ control: z.literal("json"),
894
+ type: z.literal("json"),
895
+ defaultValue: z.unknown().optional()
896
+ });
897
+ var Date = z.object({
898
+ ...common,
899
+ control: z.literal("date"),
900
+ // @todo not sure what type should be here
901
+ // (we don't support Date yet, added for completeness)
902
+ type: z.literal("string"),
903
+ defaultValue: z.string().optional()
904
+ });
905
+ var Action = z.object({
906
+ ...common,
907
+ control: z.literal("action"),
908
+ type: z.literal("action"),
909
+ defaultValue: z.undefined().optional()
910
+ });
911
+ var TextContent = z.object({
912
+ ...common,
913
+ control: z.literal("textContent"),
914
+ type: z.literal("string"),
915
+ defaultValue: z.string().optional()
916
+ });
917
+ var PropMeta = z.union([
918
+ Number,
919
+ Range,
920
+ Text,
921
+ Code,
922
+ CodeText,
923
+ Color,
924
+ Boolean,
925
+ Radio,
926
+ InlineRadio,
927
+ Select,
928
+ MultiSelect,
929
+ Check,
930
+ InlineCheck,
931
+ File,
932
+ Url,
933
+ Json,
934
+ Date,
935
+ Action,
936
+ TextContent
937
+ ]);
938
+
939
+ // src/components/component-meta.ts
940
+ import { z as z3 } from "zod";
941
+ import { Matchers } from "@webstudio-is/sdk";
942
+
943
+ // src/embed-template.ts
944
+ import { z as z2 } from "zod";
945
+ import { nanoid } from "nanoid";
946
+ import {
947
+ encodeDataSourceVariable,
948
+ transpileExpression
949
+ } from "@webstudio-is/sdk";
950
+ import { StyleValue } from "@webstudio-is/css-engine";
951
+ var EmbedTemplateText = z2.object({
952
+ type: z2.literal("text"),
953
+ value: z2.string(),
954
+ placeholder: z2.boolean().optional()
955
+ });
956
+ var EmbedTemplateExpression = z2.object({
957
+ type: z2.literal("expression"),
958
+ value: z2.string()
959
+ });
960
+ var EmbedTemplateVariable = z2.object({
961
+ alias: z2.optional(z2.string()),
962
+ initialValue: z2.unknown()
963
+ });
964
+ var EmbedTemplateProp = z2.union([
965
+ z2.object({
966
+ type: z2.literal("number"),
967
+ name: z2.string(),
968
+ value: z2.number()
969
+ }),
970
+ z2.object({
971
+ type: z2.literal("string"),
972
+ name: z2.string(),
973
+ value: z2.string()
974
+ }),
975
+ z2.object({
976
+ type: z2.literal("boolean"),
977
+ name: z2.string(),
978
+ value: z2.boolean()
979
+ }),
980
+ z2.object({
981
+ type: z2.literal("string[]"),
982
+ name: z2.string(),
983
+ value: z2.array(z2.string())
984
+ }),
985
+ z2.object({
986
+ type: z2.literal("json"),
987
+ name: z2.string(),
988
+ value: z2.unknown()
989
+ }),
990
+ z2.object({
991
+ type: z2.literal("expression"),
992
+ name: z2.string(),
993
+ code: z2.string()
994
+ }),
995
+ z2.object({
996
+ type: z2.literal("parameter"),
997
+ name: z2.string(),
998
+ variableName: z2.string(),
999
+ variableAlias: z2.optional(z2.string())
1000
+ }),
1001
+ z2.object({
1002
+ type: z2.literal("action"),
1003
+ name: z2.string(),
1004
+ value: z2.array(
1005
+ z2.object({
1006
+ type: z2.literal("execute"),
1007
+ args: z2.optional(z2.array(z2.string())),
1008
+ code: z2.string()
1009
+ })
1010
+ )
1011
+ })
1012
+ ]);
1013
+ var EmbedTemplateStyleDeclRaw = z2.object({
1014
+ // State selector, e.g. :hover
1015
+ state: z2.optional(z2.string()),
1016
+ property: z2.string(),
1017
+ value: StyleValue
1018
+ });
1019
+ var EmbedTemplateStyleDecl = EmbedTemplateStyleDeclRaw;
1020
+ var EmbedTemplateInstance = z2.lazy(
1021
+ () => z2.object({
1022
+ type: z2.literal("instance"),
1023
+ component: z2.string(),
1024
+ label: z2.optional(z2.string()),
1025
+ variables: z2.optional(z2.record(z2.string(), EmbedTemplateVariable)),
1026
+ props: z2.optional(z2.array(EmbedTemplateProp)),
1027
+ styles: z2.optional(z2.array(EmbedTemplateStyleDecl)),
1028
+ children: WsEmbedTemplate
1029
+ })
1030
+ );
1031
+ var WsEmbedTemplate = z2.lazy(
1032
+ () => z2.array(
1033
+ z2.union([EmbedTemplateInstance, EmbedTemplateText, EmbedTemplateExpression])
1034
+ )
1035
+ );
1036
+ var getVariablValue = (value) => {
1037
+ if (typeof value === "string") {
1038
+ return { type: "string", value };
1039
+ }
1040
+ if (typeof value === "number") {
1041
+ return { type: "number", value };
1042
+ }
1043
+ if (typeof value === "boolean") {
1044
+ return { type: "boolean", value };
1045
+ }
1046
+ if (Array.isArray(value)) {
1047
+ return { type: "string[]", value };
1048
+ }
1049
+ return { type: "json", value };
1050
+ };
1051
+ var createInstancesFromTemplate = (treeTemplate, instances, props, dataSourceByRef, styleSourceSelections, styleSources, styles, metas, defaultBreakpointId, generateId) => {
1052
+ const parentChildren = [];
1053
+ for (const item of treeTemplate) {
1054
+ if (item.type === "instance") {
1055
+ const instanceId = generateId();
1056
+ if (item.variables) {
1057
+ for (const [name, variable] of Object.entries(item.variables)) {
1058
+ if (dataSourceByRef.has(name)) {
1059
+ throw Error(`${name} data source already defined`);
1060
+ }
1061
+ dataSourceByRef.set(name, {
1062
+ type: "variable",
1063
+ id: generateId(),
1064
+ scopeInstanceId: instanceId,
1065
+ name: variable.alias ?? name,
1066
+ value: getVariablValue(variable.initialValue)
1067
+ });
1068
+ }
1069
+ }
1070
+ if (item.props) {
1071
+ for (const prop of item.props) {
1072
+ const propId = generateId();
1073
+ if (prop.type === "expression") {
1074
+ props.push({
1075
+ id: propId,
1076
+ instanceId,
1077
+ name: prop.name,
1078
+ type: "expression",
1079
+ // replace all references with variable names
1080
+ value: transpileExpression({
1081
+ expression: prop.code,
1082
+ replaceVariable: (ref) => {
1083
+ const id = dataSourceByRef.get(ref)?.id ?? ref;
1084
+ return encodeDataSourceVariable(id);
1085
+ }
1086
+ })
1087
+ });
1088
+ continue;
1089
+ }
1090
+ if (prop.type === "action") {
1091
+ props.push({
1092
+ id: propId,
1093
+ instanceId,
1094
+ type: "action",
1095
+ name: prop.name,
1096
+ value: prop.value.map((value) => {
1097
+ const args = value.args ?? [];
1098
+ return {
1099
+ type: "execute",
1100
+ args,
1101
+ // replace all references with variable names
1102
+ code: transpileExpression({
1103
+ expression: value.code,
1104
+ replaceVariable: (ref) => {
1105
+ if (args.includes(ref)) {
1106
+ return;
1107
+ }
1108
+ const id = dataSourceByRef.get(ref)?.id ?? ref;
1109
+ return encodeDataSourceVariable(id);
1110
+ }
1111
+ })
1112
+ };
1113
+ })
1114
+ });
1115
+ continue;
1116
+ }
1117
+ if (prop.type === "parameter") {
1118
+ const dataSourceId = generateId();
1119
+ dataSourceByRef.set(prop.variableName, {
1120
+ type: "parameter",
1121
+ id: dataSourceId,
1122
+ scopeInstanceId: instanceId,
1123
+ name: prop.variableAlias ?? prop.variableName
1124
+ });
1125
+ props.push({
1126
+ id: propId,
1127
+ instanceId,
1128
+ name: prop.name,
1129
+ type: "parameter",
1130
+ // replace variable reference with variable id
1131
+ value: dataSourceId
1132
+ });
1133
+ continue;
1134
+ }
1135
+ props.push({ id: propId, instanceId, ...prop });
1136
+ }
1137
+ }
1138
+ const styleSourceIds = [];
1139
+ if (item.styles) {
1140
+ const styleSourceId = generateId();
1141
+ styleSources.push({
1142
+ type: "local",
1143
+ id: styleSourceId
1144
+ });
1145
+ styleSourceIds.push(styleSourceId);
1146
+ for (const styleDecl of item.styles) {
1147
+ styles.push({
1148
+ breakpointId: defaultBreakpointId,
1149
+ styleSourceId,
1150
+ state: styleDecl.state,
1151
+ property: styleDecl.property,
1152
+ value: styleDecl.value
1153
+ });
1154
+ }
1155
+ }
1156
+ if (styleSourceIds.length > 0) {
1157
+ styleSourceSelections.push({
1158
+ instanceId,
1159
+ values: styleSourceIds
1160
+ });
1161
+ }
1162
+ const instance = {
1163
+ type: "instance",
1164
+ id: instanceId,
1165
+ label: item.label,
1166
+ component: item.component,
1167
+ children: []
1168
+ };
1169
+ instances.push(instance);
1170
+ instance.children = createInstancesFromTemplate(
1171
+ item.children,
1172
+ instances,
1173
+ props,
1174
+ dataSourceByRef,
1175
+ styleSourceSelections,
1176
+ styleSources,
1177
+ styles,
1178
+ metas,
1179
+ defaultBreakpointId,
1180
+ generateId
1181
+ );
1182
+ parentChildren.push({
1183
+ type: "id",
1184
+ value: instanceId
1185
+ });
1186
+ }
1187
+ if (item.type === "text") {
1188
+ parentChildren.push({
1189
+ type: "text",
1190
+ value: item.value,
1191
+ placeholder: item.placeholder
1192
+ });
1193
+ }
1194
+ if (item.type === "expression") {
1195
+ parentChildren.push({
1196
+ type: "expression",
1197
+ // replace all references with variable names
1198
+ value: transpileExpression({
1199
+ expression: item.value,
1200
+ replaceVariable: (ref) => {
1201
+ const id = dataSourceByRef.get(ref)?.id ?? ref;
1202
+ return encodeDataSourceVariable(id);
1203
+ }
1204
+ })
1205
+ });
1206
+ }
1207
+ }
1208
+ return parentChildren;
1209
+ };
1210
+ var generateDataFromEmbedTemplate = (treeTemplate, metas, generateId = nanoid) => {
1211
+ const instances = [];
1212
+ const props = [];
1213
+ const dataSourceByRef = /* @__PURE__ */ new Map();
1214
+ const styleSourceSelections = [];
1215
+ const styleSources = [];
1216
+ const styles = [];
1217
+ const baseBreakpointId = generateId();
1218
+ const children = createInstancesFromTemplate(
1219
+ treeTemplate,
1220
+ instances,
1221
+ props,
1222
+ dataSourceByRef,
1223
+ styleSourceSelections,
1224
+ styleSources,
1225
+ styles,
1226
+ metas,
1227
+ baseBreakpointId,
1228
+ generateId
1229
+ );
1230
+ const breakpoints = [];
1231
+ if (styles.length > 0) {
1232
+ breakpoints.push({
1233
+ id: baseBreakpointId,
1234
+ label: ""
1235
+ });
1236
+ }
1237
+ return {
1238
+ children,
1239
+ instances,
1240
+ props,
1241
+ dataSources: Array.from(dataSourceByRef.values()),
1242
+ styleSourceSelections,
1243
+ styleSources,
1244
+ styles,
1245
+ breakpoints,
1246
+ assets: [],
1247
+ resources: []
1248
+ };
1249
+ };
1250
+ var namespaceEmbedTemplateComponents = (template, namespace, components) => {
1251
+ return template.map((item) => {
1252
+ if (item.type === "text") {
1253
+ return item;
1254
+ }
1255
+ if (item.type === "expression") {
1256
+ return item;
1257
+ }
1258
+ if (item.type === "instance") {
1259
+ const prefix = components.has(item.component) ? `${namespace}:` : "";
1260
+ return {
1261
+ ...item,
1262
+ component: `${prefix}${item.component}`,
1263
+ children: namespaceEmbedTemplateComponents(
1264
+ item.children,
1265
+ namespace,
1266
+ components
1267
+ )
1268
+ };
1269
+ }
1270
+ item;
1271
+ throw Error("Impossible case");
1272
+ });
1273
+ };
1274
+ var namespaceMatcher = (namespace, matcher) => {
1275
+ const newMatcher = structuredClone(matcher);
1276
+ if (newMatcher.component?.$eq) {
1277
+ newMatcher.component.$eq = `${namespace}:${newMatcher.component.$eq}`;
1278
+ }
1279
+ if (newMatcher.component?.$neq) {
1280
+ newMatcher.component.$neq = `${namespace}:${newMatcher.component.$neq}`;
1281
+ }
1282
+ if (newMatcher.component?.$in) {
1283
+ newMatcher.component.$in = newMatcher.component.$in.map(
1284
+ (component) => `${namespace}:${component}`
1285
+ );
1286
+ }
1287
+ if (newMatcher.component?.$nin) {
1288
+ newMatcher.component.$nin = newMatcher.component.$nin.map(
1289
+ (component) => `${namespace}:${component}`
1290
+ );
1291
+ }
1292
+ return newMatcher;
1293
+ };
1294
+ var namespaceMeta = (meta, namespace, components) => {
1295
+ const newMeta = { ...meta };
1296
+ if (newMeta.constraints) {
1297
+ if (Array.isArray(newMeta.constraints)) {
1298
+ newMeta.constraints = newMeta.constraints.map(
1299
+ (matcher) => namespaceMatcher(namespace, matcher)
1300
+ );
1301
+ } else {
1302
+ newMeta.constraints = namespaceMatcher(namespace, newMeta.constraints);
1303
+ }
1304
+ }
1305
+ if (newMeta.indexWithinAncestor) {
1306
+ newMeta.indexWithinAncestor = components.has(newMeta.indexWithinAncestor) ? `${namespace}:${newMeta.indexWithinAncestor}` : newMeta.indexWithinAncestor;
1307
+ }
1308
+ if (newMeta.template) {
1309
+ newMeta.template = namespaceEmbedTemplateComponents(
1310
+ newMeta.template,
1311
+ namespace,
1312
+ components
1313
+ );
1314
+ }
1315
+ return newMeta;
1316
+ };
1317
+
1318
+ // src/components/component-meta.ts
1319
+ var WsComponentPropsMeta = z3.object({
1320
+ props: z3.record(PropMeta),
1321
+ // Props that will be always visible in properties panel.
1322
+ initialProps: z3.array(z3.string()).optional()
1323
+ });
1324
+ var componentCategories = [
1325
+ "general",
1326
+ "typography",
1327
+ "media",
1328
+ "data",
1329
+ "forms",
1330
+ "localization",
1331
+ "radix",
1332
+ "xml",
1333
+ "hidden",
1334
+ "internal"
1335
+ ];
1336
+ var stateCategories = ["states", "component-states"];
1337
+ var ComponentState = z3.object({
1338
+ category: z3.enum(stateCategories).optional(),
1339
+ selector: z3.string(),
1340
+ label: z3.string()
1341
+ });
1342
+ var defaultStates = [
1343
+ { selector: ":hover", label: "Hover" },
1344
+ { selector: ":active", label: "Active" },
1345
+ { selector: ":focus", label: "Focus" },
1346
+ { selector: ":focus-visible", label: "Focus Visible" },
1347
+ { selector: ":focus-within", label: "Focus Within" }
1348
+ ];
1349
+ var WsComponentMeta = z3.object({
1350
+ category: z3.enum(componentCategories).optional(),
1351
+ // container - can accept other components with dnd or be edited as text
1352
+ // control - usually form controls like inputs, without children
1353
+ // embed - images, videos or other embeddable components, without children
1354
+ // rich-text-child - formatted text fragment, not listed in components list
1355
+ type: z3.enum(["container", "control", "embed", "rich-text-child"]),
1356
+ constraints: Matchers.optional(),
1357
+ // when this field is specified component receives
1358
+ // prop with index of same components withiin specified ancestor
1359
+ // important to automatically enumerate collections without
1360
+ // naming every item manually
1361
+ indexWithinAncestor: z3.optional(z3.string()),
1362
+ stylable: z3.optional(z3.boolean()),
1363
+ label: z3.optional(z3.string()),
1364
+ description: z3.string().optional(),
1365
+ icon: z3.string(),
1366
+ presetStyle: z3.optional(
1367
+ z3.record(z3.string(), z3.array(EmbedTemplateStyleDecl))
1368
+ ),
1369
+ states: z3.optional(z3.array(ComponentState)),
1370
+ template: z3.optional(WsEmbedTemplate),
1371
+ order: z3.number().optional()
1372
+ });
1373
+
1374
+ // src/instance-utils.ts
1375
+ var getIndexesWithinAncestors = (metas, instances, rootIds) => {
1376
+ const ancestors = /* @__PURE__ */ new Set();
1377
+ for (const meta of metas.values()) {
1378
+ if (meta.indexWithinAncestor !== void 0) {
1379
+ ancestors.add(meta.indexWithinAncestor);
1380
+ }
1381
+ }
1382
+ const indexes = /* @__PURE__ */ new Map();
1383
+ const traverseInstances = (instances2, instanceId, latestIndexes2 = /* @__PURE__ */ new Map()) => {
1384
+ const instance = instances2.get(instanceId);
1385
+ if (instance === void 0) {
1386
+ return;
1387
+ }
1388
+ const meta = metas.get(instance.component);
1389
+ if (meta === void 0) {
1390
+ return;
1391
+ }
1392
+ if (ancestors.has(instance.component)) {
1393
+ latestIndexes2 = new Map(latestIndexes2);
1394
+ latestIndexes2.set(instance.component, /* @__PURE__ */ new Map());
1395
+ }
1396
+ if (meta.indexWithinAncestor !== void 0) {
1397
+ const ancestorIndexes = latestIndexes2.get(meta.indexWithinAncestor);
1398
+ if (ancestorIndexes !== void 0) {
1399
+ let index = ancestorIndexes.get(instance.component) ?? -1;
1400
+ index += 1;
1401
+ ancestorIndexes.set(instance.component, index);
1402
+ indexes.set(instance.id, index);
1403
+ }
1404
+ }
1405
+ for (const child of instance.children) {
1406
+ if (child.type === "id") {
1407
+ traverseInstances(instances2, child.value, latestIndexes2);
1408
+ }
1409
+ }
1410
+ };
1411
+ const latestIndexes = /* @__PURE__ */ new Map();
1412
+ for (const instanceId of rootIds) {
1413
+ traverseInstances(instances, instanceId, latestIndexes);
1414
+ }
1415
+ return indexes;
1416
+ };
1417
+
1418
+ // src/component-generator.ts
1419
+ import {
1420
+ parseComponentName as parseComponentName2,
1421
+ generateExpression,
1422
+ decodeDataSourceVariable,
1423
+ transpileExpression as transpileExpression2
1424
+ } from "@webstudio-is/sdk";
1425
+ var generateAction = ({
1426
+ scope,
1427
+ prop,
1428
+ dataSources,
1429
+ usedDataSources
1430
+ }) => {
1431
+ const setters = /* @__PURE__ */ new Set();
1432
+ let args = [];
1433
+ let assignersCode = "";
1434
+ for (const value of prop.value) {
1435
+ args = value.args;
1436
+ assignersCode += transpileExpression2({
1437
+ expression: value.code,
1438
+ executable: true,
1439
+ replaceVariable: (identifier, assignee) => {
1440
+ if (args?.includes(identifier)) {
1441
+ return;
1442
+ }
1443
+ const depId = decodeDataSourceVariable(identifier);
1444
+ const dep = depId ? dataSources.get(depId) : void 0;
1445
+ if (dep) {
1446
+ usedDataSources.set(dep.id, dep);
1447
+ if (assignee) {
1448
+ setters.add(dep);
1449
+ }
1450
+ const valueName = scope.getName(dep.id, dep.name);
1451
+ return valueName;
1452
+ }
1453
+ console.error(`Unknown dependency "${identifier}"`);
1454
+ }
1455
+ });
1456
+ assignersCode += `
1457
+ `;
1458
+ }
1459
+ let settersCode = "";
1460
+ for (const dataSource of setters) {
1461
+ const valueName = scope.getName(dataSource.id, dataSource.name);
1462
+ const setterName = scope.getName(
1463
+ `set$${dataSource.id}`,
1464
+ `set$${dataSource.name}`
1465
+ );
1466
+ settersCode += `${setterName}(${valueName})
1467
+ `;
1468
+ }
1469
+ const argsList = args.map((arg) => `${arg}: any`).join(", ");
1470
+ let generated = "";
1471
+ generated += `(${argsList}) => {
1472
+ `;
1473
+ generated += assignersCode;
1474
+ generated += settersCode;
1475
+ generated += `}`;
1476
+ return generated;
1477
+ };
1478
+ var generatePropValue = ({
1479
+ scope,
1480
+ prop,
1481
+ dataSources,
1482
+ usedDataSources
1483
+ }) => {
1484
+ if (prop.type === "asset" || prop.type === "page") {
1485
+ return;
1486
+ }
1487
+ if (prop.type === "string" || prop.type === "number" || prop.type === "boolean" || prop.type === "string[]" || prop.type === "json") {
1488
+ return JSON.stringify(prop.value);
1489
+ }
1490
+ if (prop.type === "parameter") {
1491
+ const dataSource = dataSources.get(prop.value);
1492
+ if (dataSource === void 0) {
1493
+ return;
1494
+ }
1495
+ usedDataSources.set(dataSource.id, dataSource);
1496
+ return scope.getName(dataSource.id, dataSource.name);
1497
+ }
1498
+ if (prop.type === "expression") {
1499
+ return generateExpression({
1500
+ expression: prop.value,
1501
+ dataSources,
1502
+ usedDataSources,
1503
+ scope
1504
+ });
1505
+ }
1506
+ if (prop.type === "action") {
1507
+ return generateAction({ scope, prop, dataSources, usedDataSources });
1508
+ }
1509
+ if (prop.type === "resource") {
1510
+ return JSON.stringify(scope.getName(prop.value, prop.name));
1511
+ }
1512
+ prop;
1513
+ };
1514
+ var generateJsxElement = ({
1515
+ context = "jsx",
1516
+ scope,
1517
+ instance,
1518
+ props,
1519
+ dataSources,
1520
+ usedDataSources,
1521
+ indexesWithinAncestors,
1522
+ children,
1523
+ classesMap
1524
+ }) => {
1525
+ if (instance.component === descendantComponent) {
1526
+ return "";
1527
+ }
1528
+ let generatedProps = "";
1529
+ const index = indexesWithinAncestors.get(instance.id);
1530
+ if (index !== void 0) {
1531
+ generatedProps += `
1532
+ ${indexAttribute}="${index}"`;
1533
+ }
1534
+ let conditionValue;
1535
+ let collectionDataValue;
1536
+ let collectionItemValue;
1537
+ const classMapArray = classesMap?.get(instance.id);
1538
+ const classes = classMapArray !== void 0 ? [JSON.stringify(classMapArray.join(" "))] : [];
1539
+ for (const prop of props.values()) {
1540
+ if (prop.instanceId !== instance.id) {
1541
+ continue;
1542
+ }
1543
+ const propValue = generatePropValue({
1544
+ scope,
1545
+ prop,
1546
+ dataSources,
1547
+ usedDataSources
1548
+ });
1549
+ if (isAttributeNameSafe(prop.name) === false) {
1550
+ continue;
1551
+ }
1552
+ if (prop.name === showAttribute) {
1553
+ if (propValue === "true") {
1554
+ continue;
1555
+ }
1556
+ if (propValue === "false") {
1557
+ return "";
1558
+ }
1559
+ conditionValue = propValue;
1560
+ continue;
1561
+ }
1562
+ if (instance.component === collectionComponent) {
1563
+ if (prop.name === "data") {
1564
+ collectionDataValue = propValue;
1565
+ }
1566
+ if (prop.name === "item") {
1567
+ collectionItemValue = propValue;
1568
+ }
1569
+ continue;
1570
+ }
1571
+ if (prop.name === "className" && propValue !== void 0) {
1572
+ classes.push(propValue);
1573
+ continue;
1574
+ }
1575
+ if (propValue !== void 0) {
1576
+ generatedProps += `
1577
+ ${prop.name}={${propValue}}`;
1578
+ }
1579
+ }
1580
+ if (classes.length !== 0) {
1581
+ generatedProps += `
1582
+ className={${classes.join(` + " " + `)}}`;
1583
+ }
1584
+ let generatedElement = "";
1585
+ if (instance.component === blockTemplateComponent) {
1586
+ return "";
1587
+ }
1588
+ if (instance.component === collectionComponent) {
1589
+ if (collectionDataValue === void 0 || collectionItemValue === void 0) {
1590
+ return "";
1591
+ }
1592
+ const indexVariable = scope.getName(`${instance.id}-index`, "index");
1593
+ generatedElement += `{${collectionDataValue}?.map((${collectionItemValue}: any, ${indexVariable}: number) =>
1594
+ `;
1595
+ generatedElement += `<Fragment key={${indexVariable}}>
1596
+ `;
1597
+ generatedElement += children;
1598
+ generatedElement += `</Fragment>
1599
+ `;
1600
+ generatedElement += `)}
1601
+ `;
1602
+ } else if (instance.component === blockComponent) {
1603
+ generatedElement += children;
1604
+ } else {
1605
+ const [_namespace, shortName] = parseComponentName2(instance.component);
1606
+ const componentVariable = scope.getName(instance.component, shortName);
1607
+ if (instance.children.length === 0) {
1608
+ generatedElement += `<${componentVariable}${generatedProps} />
1609
+ `;
1610
+ } else {
1611
+ generatedElement += `<${componentVariable}${generatedProps}>
1612
+ `;
1613
+ generatedElement += children;
1614
+ generatedElement += `</${componentVariable}>
1615
+ `;
1616
+ }
1617
+ }
1618
+ if (conditionValue) {
1619
+ let conditionalElement = "";
1620
+ let before = "";
1621
+ let after = "";
1622
+ if (context === "jsx") {
1623
+ before = "{";
1624
+ after = "}";
1625
+ }
1626
+ conditionalElement += `${before}(${conditionValue}) &&
1627
+ `;
1628
+ if (instance.component === collectionComponent) {
1629
+ conditionalElement += "<>\n";
1630
+ conditionalElement += generatedElement;
1631
+ conditionalElement += "</>\n";
1632
+ } else {
1633
+ conditionalElement += generatedElement;
1634
+ }
1635
+ conditionalElement += `${after}
1636
+ `;
1637
+ return conditionalElement;
1638
+ }
1639
+ return generatedElement;
1640
+ };
1641
+ var generateJsxChildren = ({
1642
+ scope,
1643
+ children,
1644
+ instances,
1645
+ props,
1646
+ dataSources,
1647
+ usedDataSources,
1648
+ indexesWithinAncestors,
1649
+ classesMap,
1650
+ excludePlaceholders
1651
+ }) => {
1652
+ let generatedChildren = "";
1653
+ for (const child of children) {
1654
+ if (child.type === "text") {
1655
+ if (excludePlaceholders && child.placeholder === true) {
1656
+ continue;
1657
+ }
1658
+ generatedChildren += child.value.split("\n").map((line) => `{${JSON.stringify(line)}}
1659
+ `).join(`<br />
1660
+ `);
1661
+ continue;
1662
+ }
1663
+ if (child.type === "expression") {
1664
+ const expression = generateExpression({
1665
+ expression: child.value,
1666
+ dataSources,
1667
+ usedDataSources,
1668
+ scope
1669
+ });
1670
+ generatedChildren = `{${expression}}
1671
+ `;
1672
+ continue;
1673
+ }
1674
+ if (child.type === "id") {
1675
+ const instanceId = child.value;
1676
+ const instance = instances.get(instanceId);
1677
+ if (instance === void 0) {
1678
+ continue;
1679
+ }
1680
+ generatedChildren += generateJsxElement({
1681
+ context: "jsx",
1682
+ scope,
1683
+ instance,
1684
+ props,
1685
+ dataSources,
1686
+ usedDataSources,
1687
+ indexesWithinAncestors,
1688
+ classesMap,
1689
+ children: generateJsxChildren({
1690
+ classesMap,
1691
+ scope,
1692
+ children: instance.children,
1693
+ instances,
1694
+ props,
1695
+ dataSources,
1696
+ usedDataSources,
1697
+ indexesWithinAncestors,
1698
+ excludePlaceholders
1699
+ })
1700
+ });
1701
+ continue;
1702
+ }
1703
+ child;
1704
+ }
1705
+ return generatedChildren;
1706
+ };
1707
+ var generateWebstudioComponent = ({
1708
+ scope,
1709
+ name,
1710
+ rootInstanceId,
1711
+ parameters,
1712
+ instances,
1713
+ props,
1714
+ dataSources,
1715
+ indexesWithinAncestors,
1716
+ classesMap
1717
+ }) => {
1718
+ const instance = instances.get(rootInstanceId);
1719
+ if (instance === void 0) {
1720
+ return "";
1721
+ }
1722
+ const usedDataSources = /* @__PURE__ */ new Map();
1723
+ const generatedJsx = generateJsxElement({
1724
+ context: "expression",
1725
+ scope,
1726
+ instance,
1727
+ props,
1728
+ dataSources,
1729
+ usedDataSources,
1730
+ indexesWithinAncestors,
1731
+ classesMap,
1732
+ children: generateJsxChildren({
1733
+ scope,
1734
+ children: instance.children,
1735
+ instances,
1736
+ props,
1737
+ dataSources,
1738
+ usedDataSources,
1739
+ indexesWithinAncestors,
1740
+ classesMap
1741
+ })
1742
+ });
1743
+ let generatedProps = "";
1744
+ if (parameters.length > 0) {
1745
+ let generatedPropsValue = "{ ";
1746
+ let generatedPropsType = "{ ";
1747
+ for (const parameter of parameters) {
1748
+ const dataSource = usedDataSources.get(parameter.value);
1749
+ if (dataSource) {
1750
+ const valueName = scope.getName(dataSource.id, dataSource.name);
1751
+ generatedPropsValue += `${parameter.name}: ${valueName}, `;
1752
+ }
1753
+ generatedPropsType += `${parameter.name}: any; `;
1754
+ }
1755
+ generatedPropsValue += `}`;
1756
+ generatedPropsType += `}`;
1757
+ generatedProps = `${generatedPropsValue}: ${generatedPropsType}`;
1758
+ }
1759
+ let generatedDataSources = "";
1760
+ for (const dataSource of usedDataSources.values()) {
1761
+ if (dataSource.type === "variable") {
1762
+ const valueName = scope.getName(dataSource.id, dataSource.name);
1763
+ const setterName = scope.getName(
1764
+ `set$${dataSource.id}`,
1765
+ `set$${dataSource.name}`
1766
+ );
1767
+ const initialValue = dataSource.value.value;
1768
+ const initialValueString = JSON.stringify(initialValue);
1769
+ generatedDataSources += `let [${valueName}, ${setterName}] = useVariableState<any>(${initialValueString})
1770
+ `;
1771
+ }
1772
+ if (dataSource.type === "resource") {
1773
+ const valueName = scope.getName(dataSource.id, dataSource.name);
1774
+ const resourceName = scope.getName(
1775
+ dataSource.resourceId,
1776
+ dataSource.name
1777
+ );
1778
+ const resourceNameString = JSON.stringify(resourceName);
1779
+ generatedDataSources += `let ${valueName} = useResource(${resourceNameString})
1780
+ `;
1781
+ }
1782
+ }
1783
+ let generatedComponent = "";
1784
+ generatedComponent += `const ${name} = (${generatedProps}) => {
1785
+ `;
1786
+ generatedComponent += `${generatedDataSources}`;
1787
+ generatedComponent += `return ${generatedJsx}`;
1788
+ generatedComponent += `}
1789
+ `;
1790
+ return generatedComponent;
1791
+ };
1792
+ export {
1793
+ EmbedTemplateInstance,
1794
+ EmbedTemplateProp,
1795
+ EmbedTemplateStyleDecl,
1796
+ PropMeta,
1797
+ WsComponentMeta,
1798
+ WsEmbedTemplate,
1799
+ addGlobalRules,
1800
+ blockComponent,
1801
+ blockTemplateComponent,
1802
+ blockTemplateMeta,
1803
+ collapsedAttribute,
1804
+ collectionComponent,
1805
+ componentAttribute,
1806
+ componentCategories,
1807
+ coreMetas,
1808
+ corePropsMetas,
1809
+ createImageValueTransformer,
1810
+ defaultStates,
1811
+ descendantComponent,
1812
+ editablePlaceholderVariable,
1813
+ editingPlaceholderVariable,
1814
+ generateCss,
1815
+ generateDataFromEmbedTemplate,
1816
+ generateJsxChildren,
1817
+ generateJsxElement,
1818
+ generateRemixParams,
1819
+ generateRemixRoute,
1820
+ generateWebstudioComponent,
1821
+ getIndexesWithinAncestors,
1822
+ idAttribute,
1823
+ indexAttribute,
1824
+ isAttributeNameSafe,
1825
+ isCoreComponent,
1826
+ namespaceMeta,
1827
+ normalizeProps,
1828
+ portalComponent,
1829
+ rootComponent,
1830
+ selectorIdAttribute,
1831
+ showAttribute,
1832
+ stateCategories,
1833
+ textContentAttribute
1834
+ };