@webstudio-is/react-sdk 0.185.0 → 0.191.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 CHANGED
@@ -82,9 +82,11 @@ import {
82
82
 
83
83
  // src/core-components.ts
84
84
  import {
85
+ EditIcon,
85
86
  ListViewIcon,
86
87
  PaintBrushIcon,
87
- EmbedIcon
88
+ SettingsIcon,
89
+ AddTemplateInstanceIcon
88
90
  } from "@webstudio-is/icons/svg";
89
91
  import { html } from "@webstudio-is/sdk/normalize.css";
90
92
  var rootComponent = "ws:root";
@@ -92,7 +94,7 @@ var rootMeta = {
92
94
  category: "hidden",
93
95
  type: "container",
94
96
  label: "Global Root",
95
- icon: EmbedIcon,
97
+ icon: SettingsIcon,
96
98
  presetStyle: {
97
99
  html
98
100
  }
@@ -192,17 +194,183 @@ var descendantPropsMeta = {
192
194
  },
193
195
  initialProps: ["selector"]
194
196
  };
197
+ var blockTemplateComponent = "ws:block-template";
198
+ var blockTemplateMeta = {
199
+ category: "hidden",
200
+ detachable: false,
201
+ type: "container",
202
+ icon: AddTemplateInstanceIcon,
203
+ stylable: false
204
+ };
205
+ var blockTemplatePropsMeta = {
206
+ props: {},
207
+ initialProps: []
208
+ };
209
+ var blockComponent = "ws:block";
210
+ var blockMeta = {
211
+ category: "data",
212
+ order: 2,
213
+ type: "container",
214
+ label: "Content Block",
215
+ icon: EditIcon,
216
+ constraints: {
217
+ relation: "ancestor",
218
+ component: { $neq: collectionComponent }
219
+ },
220
+ stylable: false,
221
+ template: [
222
+ {
223
+ type: "instance",
224
+ component: blockComponent,
225
+ props: [],
226
+ children: [
227
+ {
228
+ type: "instance",
229
+ label: "Templates",
230
+ component: blockTemplateComponent,
231
+ children: [
232
+ {
233
+ type: "instance",
234
+ component: "Paragraph",
235
+ children: [
236
+ {
237
+ type: "text",
238
+ value: "Paragraph text you can edit",
239
+ placeholder: true
240
+ }
241
+ ]
242
+ },
243
+ {
244
+ type: "instance",
245
+ component: "List",
246
+ children: [
247
+ {
248
+ type: "instance",
249
+ component: "ListItem",
250
+ children: [
251
+ {
252
+ type: "text",
253
+ value: "List Item text you can edit",
254
+ placeholder: true
255
+ }
256
+ ]
257
+ },
258
+ {
259
+ type: "instance",
260
+ component: "ListItem",
261
+ children: [
262
+ {
263
+ type: "text",
264
+ value: "List Item text you can edit",
265
+ placeholder: true
266
+ }
267
+ ]
268
+ },
269
+ {
270
+ type: "instance",
271
+ component: "ListItem",
272
+ children: [
273
+ {
274
+ type: "text",
275
+ value: "List Item text you can edit",
276
+ placeholder: true
277
+ }
278
+ ]
279
+ }
280
+ ]
281
+ }
282
+ ]
283
+ },
284
+ {
285
+ type: "instance",
286
+ component: "Paragraph",
287
+ children: [
288
+ {
289
+ type: "text",
290
+ value: "The Content Block component designates regions on the page where pre-styled instances can be inserted in "
291
+ },
292
+ {
293
+ type: "instance",
294
+ component: "RichTextLink",
295
+ children: [
296
+ {
297
+ type: "text",
298
+ value: "Content mode"
299
+ }
300
+ ],
301
+ props: [
302
+ {
303
+ type: "string",
304
+ name: "href",
305
+ value: "https://wstd.us/content-block"
306
+ }
307
+ ]
308
+ },
309
+ {
310
+ type: "text",
311
+ value: "."
312
+ }
313
+ ]
314
+ },
315
+ {
316
+ type: "instance",
317
+ component: "List",
318
+ children: [
319
+ {
320
+ type: "instance",
321
+ component: "ListItem",
322
+ children: [
323
+ {
324
+ type: "text",
325
+ 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."
326
+ }
327
+ ]
328
+ },
329
+ {
330
+ type: "instance",
331
+ component: "ListItem",
332
+ children: [
333
+ {
334
+ type: "text",
335
+ value: "To predefine instances for insertion in Content mode, switch to Design mode and add them to the Templates container."
336
+ }
337
+ ]
338
+ },
339
+ {
340
+ type: "instance",
341
+ component: "ListItem",
342
+ children: [
343
+ {
344
+ type: "text",
345
+ 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."
346
+ }
347
+ ]
348
+ }
349
+ ]
350
+ }
351
+ ]
352
+ }
353
+ ]
354
+ };
355
+ var blockPropsMeta = {
356
+ props: {},
357
+ initialProps: []
358
+ };
195
359
  var coreMetas = {
196
360
  [rootComponent]: rootMeta,
197
361
  [collectionComponent]: collectionMeta,
198
- [descendantComponent]: descendantMeta
362
+ [descendantComponent]: descendantMeta,
363
+ [blockComponent]: blockMeta,
364
+ [blockTemplateComponent]: blockTemplateMeta
199
365
  };
200
366
  var corePropsMetas = {
201
367
  [rootComponent]: rootPropsMeta,
202
368
  [collectionComponent]: collectionPropsMeta,
203
- [descendantComponent]: descendantPropsMeta
369
+ [descendantComponent]: descendantPropsMeta,
370
+ [blockComponent]: blockPropsMeta,
371
+ [blockTemplateComponent]: blockTemplatePropsMeta
204
372
  };
205
- var isCoreComponent = (component) => component === rootComponent || component === collectionComponent || component === descendantComponent;
373
+ var isCoreComponent = (component) => component === rootComponent || component === collectionComponent || component === descendantComponent || component === blockComponent || component === blockTemplateComponent;
206
374
 
207
375
  // src/css/css.ts
208
376
  import { kebabCase } from "change-case";
@@ -346,120 +514,6 @@ ${sheet.cssText}`,
346
514
  };
347
515
  };
348
516
 
349
- // src/tree/create-elements-tree.tsx
350
- import {
351
- Fragment
352
- } from "react";
353
-
354
- // src/context.tsx
355
- import { createContext, useContext, useMemo } from "react";
356
- import { createJsonStringifyProxy, isPlainObject } from "@webstudio-is/sdk";
357
- var ReactSdkContext = createContext({
358
- assetBaseUrl: "/",
359
- imageBaseUrl: "/",
360
- imageLoader: ({ src }) => src,
361
- resources: {}
362
- });
363
-
364
- // src/tree/create-elements-tree.tsx
365
- import { jsx, jsxs } from "react/jsx-runtime";
366
- var createElementsTree = ({
367
- renderer,
368
- assetBaseUrl,
369
- imageBaseUrl,
370
- imageLoader,
371
- instances,
372
- rootInstanceId,
373
- Component,
374
- components
375
- }) => {
376
- const rootInstance = instances.get(rootInstanceId);
377
- if (rootInstance === void 0) {
378
- return null;
379
- }
380
- const rootInstanceSelector = [rootInstanceId];
381
- const root = createInstanceElement({
382
- Component,
383
- instance: rootInstance,
384
- instanceSelector: rootInstanceSelector,
385
- components
386
- });
387
- return /* @__PURE__ */ jsx(
388
- ReactSdkContext.Provider,
389
- {
390
- value: {
391
- renderer,
392
- imageLoader,
393
- assetBaseUrl,
394
- imageBaseUrl,
395
- resources: {}
396
- },
397
- children: root
398
- }
399
- );
400
- };
401
- var renderText = (text) => {
402
- const lines = text.split("\n");
403
- return lines.map((line, index) => /* @__PURE__ */ jsxs(Fragment, { children: [
404
- line,
405
- index < lines.length - 1 && /* @__PURE__ */ jsx("br", {})
406
- ] }, index));
407
- };
408
- var createInstanceChildrenElements = ({
409
- instances,
410
- instanceSelector,
411
- children,
412
- Component,
413
- components
414
- }) => {
415
- const elements = [];
416
- for (const child of children) {
417
- if (child.type === "text") {
418
- elements.push(renderText(child.value));
419
- continue;
420
- }
421
- if (child.type === "expression") {
422
- continue;
423
- }
424
- if (child.type === "id") {
425
- const childInstance = instances.get(child.value);
426
- if (childInstance === void 0) {
427
- continue;
428
- }
429
- const childInstanceSelector = [child.value, ...instanceSelector];
430
- const element = createInstanceElement({
431
- instance: childInstance,
432
- instanceSelector: childInstanceSelector,
433
- Component,
434
- components
435
- });
436
- elements.push(element);
437
- continue;
438
- }
439
- child;
440
- }
441
- if (elements.length === 0) {
442
- return;
443
- }
444
- return elements;
445
- };
446
- var createInstanceElement = ({
447
- Component,
448
- instance,
449
- instanceSelector,
450
- components
451
- }) => {
452
- return /* @__PURE__ */ jsx(
453
- Component,
454
- {
455
- instance,
456
- instanceSelector,
457
- components
458
- },
459
- instance.id
460
- );
461
- };
462
-
463
517
  // src/props.ts
464
518
  import {
465
519
  getPagePath,
@@ -746,6 +800,7 @@ var PropMeta = z.union([
746
800
 
747
801
  // src/components/component-meta.ts
748
802
  import { z as z3 } from "zod";
803
+ import { Matchers } from "@webstudio-is/sdk";
749
804
 
750
805
  // src/embed-template.ts
751
806
  import { z as z2 } from "zod";
@@ -1099,6 +1154,26 @@ var namespaceEmbedTemplateComponents = (template, namespace, components) => {
1099
1154
  throw Error("Impossible case");
1100
1155
  });
1101
1156
  };
1157
+ var namespaceMatcher = (namespace, matcher) => {
1158
+ const newMatcher = structuredClone(matcher);
1159
+ if (newMatcher.component?.$eq) {
1160
+ newMatcher.component.$eq = `${namespace}:${newMatcher.component.$eq}`;
1161
+ }
1162
+ if (newMatcher.component?.$neq) {
1163
+ newMatcher.component.$neq = `${namespace}:${newMatcher.component.$neq}`;
1164
+ }
1165
+ if (newMatcher.component?.$in) {
1166
+ newMatcher.component.$in = newMatcher.component.$in.map(
1167
+ (component) => `${namespace}:${component}`
1168
+ );
1169
+ }
1170
+ if (newMatcher.component?.$nin) {
1171
+ newMatcher.component.$nin = newMatcher.component.$nin.map(
1172
+ (component) => `${namespace}:${component}`
1173
+ );
1174
+ }
1175
+ return newMatcher;
1176
+ };
1102
1177
  var namespaceMeta = (meta, namespace, components) => {
1103
1178
  const newMeta = { ...meta };
1104
1179
  if (newMeta.requiredAncestors) {
@@ -1111,6 +1186,15 @@ var namespaceMeta = (meta, namespace, components) => {
1111
1186
  (component) => components.has(component) ? `${namespace}:${component}` : component
1112
1187
  );
1113
1188
  }
1189
+ if (newMeta.constraints) {
1190
+ if (Array.isArray(newMeta.constraints)) {
1191
+ newMeta.constraints = newMeta.constraints.map(
1192
+ (matcher) => namespaceMatcher(namespace, matcher)
1193
+ );
1194
+ } else {
1195
+ newMeta.constraints = namespaceMatcher(namespace, newMeta.constraints);
1196
+ }
1197
+ }
1114
1198
  if (newMeta.indexWithinAncestor) {
1115
1199
  newMeta.indexWithinAncestor = components.has(newMeta.indexWithinAncestor) ? `${namespace}:${newMeta.indexWithinAncestor}` : newMeta.indexWithinAncestor;
1116
1200
  }
@@ -1167,6 +1251,7 @@ var WsComponentMeta = z3.object({
1167
1251
  type: z3.enum(["container", "control", "embed", "rich-text-child"]),
1168
1252
  requiredAncestors: z3.optional(z3.array(z3.string())),
1169
1253
  invalidAncestors: z3.optional(z3.array(z3.string())),
1254
+ constraints: Matchers.optional(),
1170
1255
  // when this field is specified component receives
1171
1256
  // prop with index of same components withiin specified ancestor
1172
1257
  // important to automatically enumerate collections without
@@ -1400,6 +1485,9 @@ ${prop.name}={${propValue}}`;
1400
1485
  className={${classes.join(` + " " + `)}}`;
1401
1486
  }
1402
1487
  let generatedElement = "";
1488
+ if (instance.component === blockTemplateComponent) {
1489
+ return "";
1490
+ }
1403
1491
  if (instance.component === collectionComponent) {
1404
1492
  if (collectionDataValue === void 0 || collectionItemValue === void 0) {
1405
1493
  return "";
@@ -1414,6 +1502,8 @@ className={${classes.join(` + " " + `)}}`;
1414
1502
  `;
1415
1503
  generatedElement += `)}
1416
1504
  `;
1505
+ } else if (instance.component === blockComponent) {
1506
+ generatedElement += children;
1417
1507
  } else {
1418
1508
  const [_namespace, shortName] = parseComponentName2(instance.component);
1419
1509
  const componentVariable = scope.getName(instance.component, shortName);
@@ -1610,15 +1700,16 @@ export {
1610
1700
  WsComponentMeta,
1611
1701
  WsEmbedTemplate,
1612
1702
  addGlobalRules,
1703
+ blockComponent,
1704
+ blockTemplateComponent,
1705
+ blockTemplateMeta,
1613
1706
  collapsedAttribute,
1614
1707
  collectionComponent,
1615
1708
  componentAttribute,
1616
1709
  componentCategories,
1617
1710
  coreMetas,
1618
1711
  corePropsMetas,
1619
- createElementsTree,
1620
1712
  createImageValueTransformer,
1621
- createInstanceChildrenElements,
1622
1713
  defaultStates,
1623
1714
  descendantComponent,
1624
1715
  generateCss,
package/lib/runtime.js CHANGED
@@ -1,6 +1,9 @@
1
1
  // src/context.tsx
2
2
  import { createContext, useContext, useMemo } from "react";
3
- import { createJsonStringifyProxy, isPlainObject } from "@webstudio-is/sdk";
3
+ import {
4
+ createJsonStringifyProxy,
5
+ isPlainObject
6
+ } from "@webstudio-is/sdk/runtime";
4
7
  var ReactSdkContext = createContext({
5
8
  assetBaseUrl: "/",
6
9
  imageBaseUrl: "/",
@@ -29,19 +32,13 @@ var getClosestInstance = (instancePath, currentInstance, closestComponent) => {
29
32
  }
30
33
  }
31
34
  };
32
- var getInstanceSelectorById = (instanceSelector, instanceId) => {
33
- const index = instanceSelector.findIndex(
34
- (selector) => selector === instanceId
35
- );
36
- if (index === -1) {
37
- return [];
38
- }
39
- return instanceSelector.slice(index);
40
- };
41
35
 
42
36
  // src/variable-state.tsx
43
- import { createJsonStringifyProxy as createJsonStringifyProxy2, isPlainObject as isPlainObject2 } from "@webstudio-is/sdk";
44
37
  import { useState, useMemo as useMemo2 } from "react";
38
+ import {
39
+ createJsonStringifyProxy as createJsonStringifyProxy2,
40
+ isPlainObject as isPlainObject2
41
+ } from "@webstudio-is/sdk/runtime";
45
42
  var useVariableState = (initialState) => {
46
43
  const [state, setState] = useState(initialState);
47
44
  const value = useMemo2(
@@ -59,7 +56,6 @@ export {
59
56
  ReactSdkContext,
60
57
  getClosestInstance,
61
58
  getIndexWithinAncestorFromComponentProps,
62
- getInstanceSelectorById,
63
59
  useResource,
64
60
  useVariableState
65
61
  };