@webstudio-is/sdk 0.268.0 → 0.269.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
@@ -163,6 +163,14 @@ var Page = z2.object({
163
163
  ...commonPageFields,
164
164
  path: z2.union([HomePagePath, PagePath])
165
165
  });
166
+ var PageTemplate = z2.object({
167
+ id: PageId,
168
+ name: PageName,
169
+ title: PageTitle,
170
+ rootInstanceId: z2.string(),
171
+ systemDataSourceId: z2.string().optional(),
172
+ meta: commonPageFields.meta
173
+ });
166
174
  var ProjectMeta = z2.object({
167
175
  // All fields are optional to ensure consistency and allow for the addition of new fields without requiring migration
168
176
  siteName: z2.string().optional(),
@@ -195,6 +203,7 @@ var Pages = z2.object({
195
203
  homePageId: PageId,
196
204
  rootFolderId: FolderId,
197
205
  pages: z2.map(PageId, Page),
206
+ pageTemplates: z2.map(PageId, PageTemplate).optional(),
198
207
  folders: z2.map(FolderId, Folder).refine((folders) => folders.size > 0, "Folders can't be empty")
199
208
  }).superRefine((pages, context) => {
200
209
  const homePage = pages.pages.get(pages.homePageId);
@@ -236,6 +245,22 @@ var Pages = z2.object({
236
245
  });
237
246
  }
238
247
  }
248
+ for (const [templateId, template] of pages.pageTemplates ?? []) {
249
+ if (template.id !== templateId) {
250
+ context.addIssue({
251
+ code: z2.ZodIssueCode.custom,
252
+ path: ["pageTemplates", templateId, "id"],
253
+ message: "Page template id must match its record key"
254
+ });
255
+ }
256
+ if (pages.pages.has(templateId)) {
257
+ context.addIssue({
258
+ code: z2.ZodIssueCode.custom,
259
+ path: ["pageTemplates", templateId, "id"],
260
+ message: "Page template id must not match an existing page id"
261
+ });
262
+ }
263
+ }
239
264
  for (const [folderId, folder] of pages.folders) {
240
265
  if (folder.id !== folderId) {
241
266
  context.addIssue({
@@ -928,6 +953,13 @@ var Select = z14.object({
928
953
  defaultValue: z14.string().optional(),
929
954
  options: z14.array(z14.string())
930
955
  });
956
+ var TimeZone = z14.object({
957
+ ...common,
958
+ control: z14.literal("timeZone"),
959
+ type: z14.literal("string"),
960
+ defaultValue: z14.string().optional(),
961
+ options: z14.array(z14.string())
962
+ });
931
963
  var Check = z14.object({
932
964
  ...common,
933
965
  control: z14.literal("check"),
@@ -1008,6 +1040,7 @@ var PropMeta = z14.union([
1008
1040
  Radio,
1009
1041
  InlineRadio,
1010
1042
  Select,
1043
+ TimeZone,
1011
1044
  MultiSelect,
1012
1045
  Check,
1013
1046
  InlineCheck,
@@ -2086,6 +2119,29 @@ var parseComponentName = (componentName) => {
2086
2119
  }
2087
2120
  return [namespace, name];
2088
2121
  };
2122
+ var getHtmlTagsFromProps = (props) => {
2123
+ const tags2 = /* @__PURE__ */ new Map();
2124
+ for (const prop of props.values()) {
2125
+ if (prop.type === "string" && prop.name === "tag") {
2126
+ tags2.set(prop.instanceId, prop.value);
2127
+ }
2128
+ }
2129
+ return tags2;
2130
+ };
2131
+ var getHtmlTagFromInstance = ({
2132
+ instance,
2133
+ metas,
2134
+ props,
2135
+ htmlTagsByInstanceId
2136
+ }) => {
2137
+ if (instance.component === "XmlNode") {
2138
+ return;
2139
+ }
2140
+ const meta = metas.get(instance.component);
2141
+ const metaTag = Object.keys(meta?.presetStyle ?? {}).at(0);
2142
+ const propTag = htmlTagsByInstanceId?.get(instance.id) ?? getHtmlTagsFromProps(props).get(instance.id);
2143
+ return instance.tag ?? propTag ?? metaTag;
2144
+ };
2089
2145
  var getIndexesWithinAncestors = (metas, instances, rootIds) => {
2090
2146
  const ancestors = /* @__PURE__ */ new Set();
2091
2147
  for (const meta of metas.values()) {
@@ -2145,6 +2201,23 @@ var systemParameter = {
2145
2201
  type: "parameter",
2146
2202
  name: "system"
2147
2203
  };
2204
+ var walkAssignmentTarget = (node, visitor) => {
2205
+ if (node.type === "Identifier") {
2206
+ visitor.Identifier?.(node, "binding");
2207
+ return;
2208
+ }
2209
+ if (node.type === "MemberExpression") {
2210
+ visitor.MemberExpression?.(node);
2211
+ const { object } = node;
2212
+ if (object.type === "Identifier") {
2213
+ visitor.Identifier?.(object, "memberObject");
2214
+ } else if (object.type === "MemberExpression") {
2215
+ walkAssignmentTarget(object, visitor);
2216
+ }
2217
+ return;
2218
+ }
2219
+ visitor.UnsupportedPattern?.(node);
2220
+ };
2148
2221
  var stringMethodReturnKindByName = /* @__PURE__ */ new Map([
2149
2222
  ["toLowerCase", "string"],
2150
2223
  ["replace", "string"],
@@ -2361,15 +2434,21 @@ var lintExpression = ({
2361
2434
  addMessage("Assignment is supported only inside actions")(node);
2362
2435
  return;
2363
2436
  }
2364
- simple(node.left, {
2365
- Identifier(node2) {
2437
+ walkAssignmentTarget(node.left, {
2438
+ Identifier(node2, kind) {
2439
+ if (kind !== "binding") {
2440
+ return;
2441
+ }
2366
2442
  if (availableVariables.has(node2.name) === false) {
2367
2443
  addMessage(
2368
2444
  `"${node2.name}" is not defined in the scope`,
2369
2445
  "warning"
2370
2446
  )(node2);
2371
2447
  }
2372
- }
2448
+ },
2449
+ UnsupportedPattern: addMessage(
2450
+ "Destructuring assignment is not supported"
2451
+ )
2373
2452
  });
2374
2453
  },
2375
2454
  // parser forbids to yield inside module
@@ -2467,7 +2546,7 @@ var getExpressionIdentifiers = (expression) => {
2467
2546
  simple(root, {
2468
2547
  Identifier: (node) => identifiers2.add(node.name),
2469
2548
  AssignmentExpression(node) {
2470
- simple(node.left, {
2549
+ walkAssignmentTarget(node.left, {
2471
2550
  Identifier: (node2) => identifiers2.add(node2.name)
2472
2551
  });
2473
2552
  }
@@ -2488,17 +2567,44 @@ var transpileExpression = ({
2488
2567
  const message = error.message;
2489
2568
  throw Error(`${message} in ${JSON.stringify(expression)}`);
2490
2569
  }
2570
+ const assignmentTargetMemberRanges = [];
2571
+ if (executable) {
2572
+ simple(root, {
2573
+ AssignmentExpression(node) {
2574
+ walkAssignmentTarget(node.left, {
2575
+ MemberExpression(node2) {
2576
+ assignmentTargetMemberRanges.push([node2.start, node2.end]);
2577
+ }
2578
+ });
2579
+ }
2580
+ });
2581
+ }
2491
2582
  const replacements = [];
2583
+ const replacementIndexByRange = /* @__PURE__ */ new Map();
2584
+ const addReplacement = (start, end, fragment, { replaceExisting = false } = {}) => {
2585
+ const range = `${start}:${end}`;
2586
+ const existingIndex = replacementIndexByRange.get(range);
2587
+ if (existingIndex !== void 0) {
2588
+ if (replaceExisting) {
2589
+ replacements[existingIndex] = [start, end, fragment];
2590
+ }
2591
+ return;
2592
+ }
2593
+ replacementIndexByRange.set(range, replacements.length);
2594
+ replacements.push([start, end, fragment]);
2595
+ };
2492
2596
  const replaceIdentifier = (node, assignee) => {
2493
2597
  const newName = replaceVariable?.(node.name, assignee);
2494
2598
  if (newName) {
2495
- replacements.push([node.start, node.end, newName]);
2599
+ addReplacement(node.start, node.end, newName, {
2600
+ replaceExisting: assignee
2601
+ });
2496
2602
  }
2497
2603
  };
2498
2604
  simple(root, {
2499
2605
  Identifier: (node) => replaceIdentifier(node, false),
2500
2606
  AssignmentExpression(node) {
2501
- simple(node.left, {
2607
+ walkAssignmentTarget(node.left, {
2502
2608
  Identifier: (node2) => replaceIdentifier(node2, true)
2503
2609
  });
2504
2610
  },
@@ -2506,13 +2612,18 @@ var transpileExpression = ({
2506
2612
  if (executable === false || node.optional) {
2507
2613
  return;
2508
2614
  }
2615
+ if (assignmentTargetMemberRanges.some(
2616
+ ([start, end]) => start === node.start && end === node.end
2617
+ )) {
2618
+ return;
2619
+ }
2509
2620
  if (node.computed === false) {
2510
2621
  const dotIndex = expression.indexOf(".", node.object.end);
2511
- replacements.push([dotIndex, dotIndex, "?"]);
2622
+ addReplacement(dotIndex, dotIndex, "?");
2512
2623
  }
2513
2624
  if (node.computed === true) {
2514
2625
  const dotIndex = expression.indexOf("[", node.object.end);
2515
- replacements.push([dotIndex, dotIndex, "?."]);
2626
+ addReplacement(dotIndex, dotIndex, "?.");
2516
2627
  }
2517
2628
  },
2518
2629
  CallExpression(node) {
@@ -2522,7 +2633,7 @@ var transpileExpression = ({
2522
2633
  if (node.callee.type === "MemberExpression") {
2523
2634
  const openParenIndex = expression.indexOf("(", node.callee.end);
2524
2635
  if (openParenIndex !== -1) {
2525
- replacements.push([openParenIndex, openParenIndex, "?."]);
2636
+ addReplacement(openParenIndex, openParenIndex, "?.");
2526
2637
  }
2527
2638
  }
2528
2639
  }
@@ -2646,6 +2757,8 @@ var isAbsoluteUrl = (href) => {
2646
2757
 
2647
2758
  // src/page-utils.ts
2648
2759
  var ROOT_FOLDER_ID = "root";
2760
+ var isPage = (page) => page !== void 0 && "path" in page;
2761
+ var isPageTemplate = (page) => page !== void 0 && !("path" in page);
2649
2762
  var isRootFolder = ({ id }) => id === ROOT_FOLDER_ID;
2650
2763
  var getPageById = (pages, pageId) => {
2651
2764
  return pages.pages.get(pageId);
@@ -2666,14 +2779,20 @@ var getHomePage = (pages) => {
2666
2779
  }
2667
2780
  return homePage;
2668
2781
  };
2669
- var findPageByIdOrPath = (idOrPath, pages) => {
2782
+ function findPageByIdOrPath(idOrPath, pages, options = {}) {
2670
2783
  if (idOrPath === "" || idOrPath === "/" || idOrPath === pages.homePageId) {
2671
2784
  return getHomePage(pages);
2672
2785
  }
2673
- return getAllPages(pages).find(
2786
+ const found = getAllPages(pages).find(
2674
2787
  (page) => page.id === idOrPath || getPagePath(page.id, pages) === idOrPath
2675
2788
  );
2676
- };
2789
+ if (found) {
2790
+ return found;
2791
+ }
2792
+ if (options.includeTemplates) {
2793
+ return pages.pageTemplates?.get(idOrPath);
2794
+ }
2795
+ }
2677
2796
  var findParentFolderByChildId = (id, folders) => {
2678
2797
  const folderList = folders instanceof Map ? folders.values() : folders;
2679
2798
  for (const folder of folderList) {
@@ -3099,6 +3218,29 @@ var generatePageMeta = ({
3099
3218
  return generated;
3100
3219
  };
3101
3220
 
3221
+ // src/link-utils.ts
3222
+ var isInternalHref = (href, assetBaseUrl) => /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i.test(href) === false && (assetBaseUrl !== "" && href.startsWith("/") && href.startsWith(assetBaseUrl)) === false;
3223
+ var resolveLocalLinkUrl = (href, location, resolvedPath) => {
3224
+ if (href === "") {
3225
+ return {
3226
+ pathname: location.pathname,
3227
+ search: location.search,
3228
+ hash: ""
3229
+ };
3230
+ }
3231
+ if (href.startsWith("#")) {
3232
+ return {
3233
+ pathname: location.pathname,
3234
+ search: location.search,
3235
+ hash: href === "#" ? "" : href
3236
+ };
3237
+ }
3238
+ return resolvedPath;
3239
+ };
3240
+ var isLocalLinkActive = (current, target) => {
3241
+ return current.pathname === target.pathname && current.search === target.search && current.hash === target.hash;
3242
+ };
3243
+
3102
3244
  // src/css.ts
3103
3245
  import { kebabCase } from "change-case";
3104
3246
  import {
@@ -3160,22 +3302,19 @@ var generateCss = ({
3160
3302
  const scope = createScope([], normalizeClassName, "-");
3161
3303
  const tagsByComponent = /* @__PURE__ */ new Map();
3162
3304
  tagsByComponent.set(rootComponent, /* @__PURE__ */ new Set(["html"]));
3163
- const tagByInstanceId = /* @__PURE__ */ new Map();
3164
- for (const prop of props.values()) {
3165
- if (prop.type === "string" && prop.name === "tag") {
3166
- tagByInstanceId.set(prop.instanceId, prop.value);
3167
- }
3168
- }
3305
+ const htmlTagsByInstanceId = getHtmlTagsFromProps(props);
3169
3306
  for (const instance of instances.values()) {
3170
- const propTag = tagByInstanceId.get(instance.id);
3171
- const meta = componentMetas.get(instance.component);
3172
- const metaTag = Object.keys(meta?.presetStyle ?? {}).at(0);
3173
3307
  let componentTags = tagsByComponent.get(instance.component);
3174
3308
  if (componentTags === void 0) {
3175
3309
  componentTags = /* @__PURE__ */ new Set();
3176
3310
  tagsByComponent.set(instance.component, componentTags);
3177
3311
  }
3178
- const tag = instance.tag ?? propTag ?? metaTag;
3312
+ const tag = getHtmlTagFromInstance({
3313
+ instance,
3314
+ metas: componentMetas,
3315
+ props,
3316
+ htmlTagsByInstanceId
3317
+ });
3179
3318
  if (tag) {
3180
3319
  componentTags.add(tag);
3181
3320
  }
@@ -3338,6 +3477,7 @@ export {
3338
3477
  PageName,
3339
3478
  PagePath,
3340
3479
  PageRedirect,
3480
+ PageTemplate,
3341
3481
  PageTitle,
3342
3482
  Pages,
3343
3483
  PresetStyleDecl,
@@ -3409,6 +3549,8 @@ export {
3409
3549
  getExpressionValueKind,
3410
3550
  getFolderById,
3411
3551
  getHomePage,
3552
+ getHtmlTagFromInstance,
3553
+ getHtmlTagsFromProps,
3412
3554
  getIndexesWithinAncestors,
3413
3555
  getMimeTypeByExtension,
3414
3556
  getMimeTypeByFilename,
@@ -3423,7 +3565,11 @@ export {
3423
3565
  isAllowedMimeCategory,
3424
3566
  isComponentDetachable,
3425
3567
  isCoreComponent,
3568
+ isInternalHref,
3426
3569
  isLiteralExpression,
3570
+ isLocalLinkActive,
3571
+ isPage,
3572
+ isPageTemplate,
3427
3573
  isPathnamePattern,
3428
3574
  isRootFolder,
3429
3575
  lintExpression,
@@ -3433,6 +3579,7 @@ export {
3433
3579
  portalComponent,
3434
3580
  rangeUnitValueSchema,
3435
3581
  replaceFormActionsWithResources,
3582
+ resolveLocalLinkUrl,
3436
3583
  rootComponent,
3437
3584
  scrollAnimationSchema,
3438
3585
  systemParameter,
@@ -0,0 +1,27 @@
1
+ // src/link-utils.ts
2
+ var isInternalHref = (href, assetBaseUrl) => /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i.test(href) === false && (assetBaseUrl !== "" && href.startsWith("/") && href.startsWith(assetBaseUrl)) === false;
3
+ var resolveLocalLinkUrl = (href, location, resolvedPath) => {
4
+ if (href === "") {
5
+ return {
6
+ pathname: location.pathname,
7
+ search: location.search,
8
+ hash: ""
9
+ };
10
+ }
11
+ if (href.startsWith("#")) {
12
+ return {
13
+ pathname: location.pathname,
14
+ search: location.search,
15
+ hash: href === "#" ? "" : href
16
+ };
17
+ }
18
+ return resolvedPath;
19
+ };
20
+ var isLocalLinkActive = (current, target) => {
21
+ return current.pathname === target.pathname && current.search === target.search && current.hash === target.hash;
22
+ };
23
+ export {
24
+ isInternalHref,
25
+ isLocalLinkActive,
26
+ resolveLocalLinkUrl
27
+ };
@@ -21,6 +21,7 @@ export * from "./expression";
21
21
  export * from "./resources-generator";
22
22
  export * from "./page-meta-generator";
23
23
  export * from "./url-pattern";
24
+ export * from "./link-utils";
24
25
  export * from "./css";
25
26
  export * from "./__generated__/tags";
26
27
  export type { AnimationAction, AnimationActionScroll, AnimationActionView, AnimationKeyframe, KeyframeStyles, RangeUnit, RangeUnitValue, ScrollNamedRange, ScrollRangeValue, ViewNamedRange, ViewRangeValue, ScrollAnimation, ViewAnimation, InsetUnitValue, DurationUnitValue, IterationsUnitValue, TimeUnit, } from "./schema/animation-schema";
@@ -1,8 +1,16 @@
1
1
  import type { WsComponentMeta } from "./schema/component-meta";
2
2
  import type { Instance, Instances } from "./schema/instances";
3
+ import type { Props } from "./schema/props";
3
4
  export declare const ROOT_INSTANCE_ID = ":root";
4
5
  export declare const findTreeInstanceIds: (instances: Instances, rootInstanceId: Instance["id"]) => Set<string>;
5
6
  export declare const findTreeInstanceIdsExcludingSlotDescendants: (instances: Instances, rootInstanceId: Instance["id"]) => Set<string>;
6
7
  export declare const parseComponentName: (componentName: string) => readonly [string | undefined, string];
8
+ export declare const getHtmlTagsFromProps: (props: Props) => Map<string, string>;
9
+ export declare const getHtmlTagFromInstance: ({ instance, metas, props, htmlTagsByInstanceId, }: {
10
+ instance: Instance;
11
+ metas: Map<Instance["component"], WsComponentMeta>;
12
+ props: Props;
13
+ htmlTagsByInstanceId?: Map<Instance["id"], string>;
14
+ }) => string | undefined;
7
15
  export type IndexesWithinAncestors = Map<Instance["id"], number>;
8
16
  export declare const getIndexesWithinAncestors: (metas: Map<Instance["component"], WsComponentMeta>, instances: Instances, rootIds: Instance["id"][]) => IndexesWithinAncestors;
@@ -0,0 +1,19 @@
1
+ export type UrlParts = {
2
+ pathname: string;
3
+ search: string;
4
+ hash: string;
5
+ };
6
+ export declare const isInternalHref: (href: string, assetBaseUrl: string) => boolean;
7
+ /**
8
+ * React Router resolves href="" and hash-only hrefs without preserving the
9
+ * concrete browser URL shape Webstudio uses for :local-link-like matching.
10
+ * Normalize those cases before comparing so current-link state follows anchor
11
+ * URL semantics instead of route-only semantics.
12
+ */
13
+ export declare const resolveLocalLinkUrl: (href: string, location: UrlParts, resolvedPath: UrlParts) => UrlParts;
14
+ /**
15
+ * Webstudio's local link styles target the concrete URL, not just the matched
16
+ * route. This intentionally preserves the old NavLink end/exact behavior while
17
+ * also requiring query string and fragment equality.
18
+ */
19
+ export declare const isLocalLinkActive: (current: UrlParts, target: UrlParts) => boolean;
@@ -1,5 +1,16 @@
1
- import type { Folder, Page, Pages } from "./schema/pages";
1
+ import type { Folder, Page, PageTemplate, Pages } from "./schema/pages";
2
2
  export declare const ROOT_FOLDER_ID = "root";
3
+ /**
4
+ * Narrows Page | PageTemplate to Page.
5
+ * Templates have no `path` field; pages always do.
6
+ */
7
+ export declare const isPage: (page: Page | PageTemplate | undefined) => page is Page;
8
+ /**
9
+ * Narrows Page | PageTemplate to PageTemplate.
10
+ */
11
+ export declare const isPageTemplate: (page: Page | PageTemplate | undefined) => page is PageTemplate & {
12
+ path?: never;
13
+ };
3
14
  /**
4
15
  * Returns true if folder is the root folder.
5
16
  */
@@ -12,9 +23,17 @@ export declare const getAllPages: (pages: Pages) => Page[];
12
23
  export declare const getAllFolders: (pages: Pages) => Folder[];
13
24
  export declare const getHomePage: (pages: Pages) => Page;
14
25
  /**
15
- * Find a page by id or path.
26
+ * Find a page by id or path. Pass { includeTemplates: true } to also search
27
+ * pageTemplates (builder-only call sites: canvas awareness, selected-page
28
+ * computation). Without the flag the return type is `Page | undefined` so
29
+ * existing call sites are unaffected.
16
30
  */
17
- export declare const findPageByIdOrPath: (idOrPath: string, pages: Pages) => Page | undefined;
31
+ export declare function findPageByIdOrPath(idOrPath: string, pages: Pages, options: {
32
+ includeTemplates: true;
33
+ }): Page | PageTemplate | undefined;
34
+ export declare function findPageByIdOrPath(idOrPath: string, pages: Pages, options?: {
35
+ includeTemplates?: false;
36
+ }): Page | undefined;
18
37
  /**
19
38
  * Find a folder that has has that id in the children.
20
39
  */
@@ -10493,6 +10493,33 @@ export declare const WsComponentMeta: z.ZodObject<{
10493
10493
  label?: string | undefined;
10494
10494
  defaultValue?: string | undefined;
10495
10495
  contentMode?: boolean | undefined;
10496
+ }>, z.ZodObject<{
10497
+ control: z.ZodLiteral<"timeZone">;
10498
+ type: z.ZodLiteral<"string">;
10499
+ defaultValue: z.ZodOptional<z.ZodString>;
10500
+ options: z.ZodArray<z.ZodString, "many">;
10501
+ label: z.ZodOptional<z.ZodString>;
10502
+ description: z.ZodOptional<z.ZodString>;
10503
+ required: z.ZodBoolean;
10504
+ contentMode: z.ZodOptional<z.ZodBoolean>;
10505
+ }, "strip", z.ZodTypeAny, {
10506
+ options: string[];
10507
+ type: "string";
10508
+ required: boolean;
10509
+ control: "timeZone";
10510
+ description?: string | undefined;
10511
+ label?: string | undefined;
10512
+ defaultValue?: string | undefined;
10513
+ contentMode?: boolean | undefined;
10514
+ }, {
10515
+ options: string[];
10516
+ type: "string";
10517
+ required: boolean;
10518
+ control: "timeZone";
10519
+ description?: string | undefined;
10520
+ label?: string | undefined;
10521
+ defaultValue?: string | undefined;
10522
+ contentMode?: boolean | undefined;
10496
10523
  }>, z.ZodObject<{
10497
10524
  control: z.ZodLiteral<"multi-select">;
10498
10525
  type: z.ZodLiteral<"string[]">;
@@ -10853,6 +10880,15 @@ export declare const WsComponentMeta: z.ZodObject<{
10853
10880
  label?: string | undefined;
10854
10881
  defaultValue?: string | undefined;
10855
10882
  contentMode?: boolean | undefined;
10883
+ } | {
10884
+ options: string[];
10885
+ type: "string";
10886
+ required: boolean;
10887
+ control: "timeZone";
10888
+ description?: string | undefined;
10889
+ label?: string | undefined;
10890
+ defaultValue?: string | undefined;
10891
+ contentMode?: boolean | undefined;
10856
10892
  } | {
10857
10893
  options: string[];
10858
10894
  type: "string[]";
@@ -11663,6 +11699,15 @@ export declare const WsComponentMeta: z.ZodObject<{
11663
11699
  label?: string | undefined;
11664
11700
  defaultValue?: string | undefined;
11665
11701
  contentMode?: boolean | undefined;
11702
+ } | {
11703
+ options: string[];
11704
+ type: "string";
11705
+ required: boolean;
11706
+ control: "timeZone";
11707
+ description?: string | undefined;
11708
+ label?: string | undefined;
11709
+ defaultValue?: string | undefined;
11710
+ contentMode?: boolean | undefined;
11666
11711
  } | {
11667
11712
  options: string[];
11668
11713
  type: "string[]";
@@ -298,6 +298,195 @@ declare const Page: z.ZodObject<{
298
298
  thumbnailAssetId?: string | undefined;
299
299
  } | undefined;
300
300
  }>;
301
+ export declare const PageTemplate: z.ZodObject<{
302
+ id: z.ZodString;
303
+ name: z.ZodEffects<z.ZodString, string, string>;
304
+ title: z.ZodEffects<z.ZodString, string, string>;
305
+ rootInstanceId: z.ZodString;
306
+ systemDataSourceId: z.ZodOptional<z.ZodString>;
307
+ meta: z.ZodObject<{
308
+ description: z.ZodOptional<z.ZodString>;
309
+ title: z.ZodOptional<z.ZodString>;
310
+ excludePageFromSearch: z.ZodOptional<z.ZodString>;
311
+ language: z.ZodOptional<z.ZodString>;
312
+ socialImageAssetId: z.ZodOptional<z.ZodString>;
313
+ socialImageUrl: z.ZodOptional<z.ZodString>;
314
+ status: z.ZodOptional<z.ZodString>;
315
+ redirect: z.ZodOptional<z.ZodString>;
316
+ documentType: z.ZodOptional<z.ZodEnum<["html", "xml", "text"]>>;
317
+ content: z.ZodOptional<z.ZodString>;
318
+ auth: z.ZodOptional<z.ZodUnion<[z.ZodEffects<z.ZodObject<{
319
+ login: z.ZodString;
320
+ password: z.ZodString;
321
+ method: z.ZodLiteral<"basic">;
322
+ }, "strip", z.ZodTypeAny, {
323
+ login: string;
324
+ password: string;
325
+ method: "basic";
326
+ }, {
327
+ login: string;
328
+ password: string;
329
+ method: "basic";
330
+ }>, {
331
+ login: string;
332
+ password: string;
333
+ method: "basic";
334
+ }, {
335
+ login: string;
336
+ password: string;
337
+ method: "basic";
338
+ }>, z.ZodEffects<z.ZodEffects<z.ZodObject<{
339
+ login: z.ZodString;
340
+ password: z.ZodString;
341
+ type: z.ZodLiteral<"basic">;
342
+ }, "strip", z.ZodTypeAny, {
343
+ type: "basic";
344
+ login: string;
345
+ password: string;
346
+ }, {
347
+ type: "basic";
348
+ login: string;
349
+ password: string;
350
+ }>, {
351
+ type: "basic";
352
+ login: string;
353
+ password: string;
354
+ }, {
355
+ type: "basic";
356
+ login: string;
357
+ password: string;
358
+ }>, {
359
+ method: "basic";
360
+ login: string;
361
+ password: string;
362
+ }, {
363
+ type: "basic";
364
+ login: string;
365
+ password: string;
366
+ }>]>>;
367
+ custom: z.ZodOptional<z.ZodArray<z.ZodObject<{
368
+ property: z.ZodString;
369
+ content: z.ZodString;
370
+ }, "strip", z.ZodTypeAny, {
371
+ content: string;
372
+ property: string;
373
+ }, {
374
+ content: string;
375
+ property: string;
376
+ }>, "many">>;
377
+ }, "strip", z.ZodTypeAny, {
378
+ status?: string | undefined;
379
+ custom?: {
380
+ content: string;
381
+ property: string;
382
+ }[] | undefined;
383
+ description?: string | undefined;
384
+ auth?: {
385
+ login: string;
386
+ password: string;
387
+ method: "basic";
388
+ } | {
389
+ method: "basic";
390
+ login: string;
391
+ password: string;
392
+ } | undefined;
393
+ content?: string | undefined;
394
+ title?: string | undefined;
395
+ excludePageFromSearch?: string | undefined;
396
+ language?: string | undefined;
397
+ socialImageAssetId?: string | undefined;
398
+ socialImageUrl?: string | undefined;
399
+ redirect?: string | undefined;
400
+ documentType?: "html" | "xml" | "text" | undefined;
401
+ }, {
402
+ status?: string | undefined;
403
+ custom?: {
404
+ content: string;
405
+ property: string;
406
+ }[] | undefined;
407
+ description?: string | undefined;
408
+ auth?: {
409
+ login: string;
410
+ password: string;
411
+ method: "basic";
412
+ } | {
413
+ type: "basic";
414
+ login: string;
415
+ password: string;
416
+ } | undefined;
417
+ content?: string | undefined;
418
+ title?: string | undefined;
419
+ excludePageFromSearch?: string | undefined;
420
+ language?: string | undefined;
421
+ socialImageAssetId?: string | undefined;
422
+ socialImageUrl?: string | undefined;
423
+ redirect?: string | undefined;
424
+ documentType?: "html" | "xml" | "text" | undefined;
425
+ }>;
426
+ }, "strip", z.ZodTypeAny, {
427
+ name: string;
428
+ meta: {
429
+ status?: string | undefined;
430
+ custom?: {
431
+ content: string;
432
+ property: string;
433
+ }[] | undefined;
434
+ description?: string | undefined;
435
+ auth?: {
436
+ login: string;
437
+ password: string;
438
+ method: "basic";
439
+ } | {
440
+ method: "basic";
441
+ login: string;
442
+ password: string;
443
+ } | undefined;
444
+ content?: string | undefined;
445
+ title?: string | undefined;
446
+ excludePageFromSearch?: string | undefined;
447
+ language?: string | undefined;
448
+ socialImageAssetId?: string | undefined;
449
+ socialImageUrl?: string | undefined;
450
+ redirect?: string | undefined;
451
+ documentType?: "html" | "xml" | "text" | undefined;
452
+ };
453
+ id: string;
454
+ title: string;
455
+ rootInstanceId: string;
456
+ systemDataSourceId?: string | undefined;
457
+ }, {
458
+ name: string;
459
+ meta: {
460
+ status?: string | undefined;
461
+ custom?: {
462
+ content: string;
463
+ property: string;
464
+ }[] | undefined;
465
+ description?: string | undefined;
466
+ auth?: {
467
+ login: string;
468
+ password: string;
469
+ method: "basic";
470
+ } | {
471
+ type: "basic";
472
+ login: string;
473
+ password: string;
474
+ } | undefined;
475
+ content?: string | undefined;
476
+ title?: string | undefined;
477
+ excludePageFromSearch?: string | undefined;
478
+ language?: string | undefined;
479
+ socialImageAssetId?: string | undefined;
480
+ socialImageUrl?: string | undefined;
481
+ redirect?: string | undefined;
482
+ documentType?: "html" | "xml" | "text" | undefined;
483
+ };
484
+ id: string;
485
+ title: string;
486
+ rootInstanceId: string;
487
+ systemDataSourceId?: string | undefined;
488
+ }>;
489
+ export type PageTemplate = z.infer<typeof PageTemplate>;
301
490
  declare const ProjectMeta: z.ZodObject<{
302
491
  siteName: z.ZodOptional<z.ZodString>;
303
492
  contactEmail: z.ZodOptional<z.ZodString>;
@@ -601,6 +790,194 @@ export declare const Pages: z.ZodEffects<z.ZodObject<{
601
790
  thumbnailAssetId?: string | undefined;
602
791
  } | undefined;
603
792
  }>>;
793
+ pageTemplates: z.ZodOptional<z.ZodMap<z.ZodString, z.ZodObject<{
794
+ id: z.ZodString;
795
+ name: z.ZodEffects<z.ZodString, string, string>;
796
+ title: z.ZodEffects<z.ZodString, string, string>;
797
+ rootInstanceId: z.ZodString;
798
+ systemDataSourceId: z.ZodOptional<z.ZodString>;
799
+ meta: z.ZodObject<{
800
+ description: z.ZodOptional<z.ZodString>;
801
+ title: z.ZodOptional<z.ZodString>;
802
+ excludePageFromSearch: z.ZodOptional<z.ZodString>;
803
+ language: z.ZodOptional<z.ZodString>;
804
+ socialImageAssetId: z.ZodOptional<z.ZodString>;
805
+ socialImageUrl: z.ZodOptional<z.ZodString>;
806
+ status: z.ZodOptional<z.ZodString>;
807
+ redirect: z.ZodOptional<z.ZodString>;
808
+ documentType: z.ZodOptional<z.ZodEnum<["html", "xml", "text"]>>;
809
+ content: z.ZodOptional<z.ZodString>;
810
+ auth: z.ZodOptional<z.ZodUnion<[z.ZodEffects<z.ZodObject<{
811
+ login: z.ZodString;
812
+ password: z.ZodString;
813
+ method: z.ZodLiteral<"basic">;
814
+ }, "strip", z.ZodTypeAny, {
815
+ login: string;
816
+ password: string;
817
+ method: "basic";
818
+ }, {
819
+ login: string;
820
+ password: string;
821
+ method: "basic";
822
+ }>, {
823
+ login: string;
824
+ password: string;
825
+ method: "basic";
826
+ }, {
827
+ login: string;
828
+ password: string;
829
+ method: "basic";
830
+ }>, z.ZodEffects<z.ZodEffects<z.ZodObject<{
831
+ login: z.ZodString;
832
+ password: z.ZodString;
833
+ type: z.ZodLiteral<"basic">;
834
+ }, "strip", z.ZodTypeAny, {
835
+ type: "basic";
836
+ login: string;
837
+ password: string;
838
+ }, {
839
+ type: "basic";
840
+ login: string;
841
+ password: string;
842
+ }>, {
843
+ type: "basic";
844
+ login: string;
845
+ password: string;
846
+ }, {
847
+ type: "basic";
848
+ login: string;
849
+ password: string;
850
+ }>, {
851
+ method: "basic";
852
+ login: string;
853
+ password: string;
854
+ }, {
855
+ type: "basic";
856
+ login: string;
857
+ password: string;
858
+ }>]>>;
859
+ custom: z.ZodOptional<z.ZodArray<z.ZodObject<{
860
+ property: z.ZodString;
861
+ content: z.ZodString;
862
+ }, "strip", z.ZodTypeAny, {
863
+ content: string;
864
+ property: string;
865
+ }, {
866
+ content: string;
867
+ property: string;
868
+ }>, "many">>;
869
+ }, "strip", z.ZodTypeAny, {
870
+ status?: string | undefined;
871
+ custom?: {
872
+ content: string;
873
+ property: string;
874
+ }[] | undefined;
875
+ description?: string | undefined;
876
+ auth?: {
877
+ login: string;
878
+ password: string;
879
+ method: "basic";
880
+ } | {
881
+ method: "basic";
882
+ login: string;
883
+ password: string;
884
+ } | undefined;
885
+ content?: string | undefined;
886
+ title?: string | undefined;
887
+ excludePageFromSearch?: string | undefined;
888
+ language?: string | undefined;
889
+ socialImageAssetId?: string | undefined;
890
+ socialImageUrl?: string | undefined;
891
+ redirect?: string | undefined;
892
+ documentType?: "html" | "xml" | "text" | undefined;
893
+ }, {
894
+ status?: string | undefined;
895
+ custom?: {
896
+ content: string;
897
+ property: string;
898
+ }[] | undefined;
899
+ description?: string | undefined;
900
+ auth?: {
901
+ login: string;
902
+ password: string;
903
+ method: "basic";
904
+ } | {
905
+ type: "basic";
906
+ login: string;
907
+ password: string;
908
+ } | undefined;
909
+ content?: string | undefined;
910
+ title?: string | undefined;
911
+ excludePageFromSearch?: string | undefined;
912
+ language?: string | undefined;
913
+ socialImageAssetId?: string | undefined;
914
+ socialImageUrl?: string | undefined;
915
+ redirect?: string | undefined;
916
+ documentType?: "html" | "xml" | "text" | undefined;
917
+ }>;
918
+ }, "strip", z.ZodTypeAny, {
919
+ name: string;
920
+ meta: {
921
+ status?: string | undefined;
922
+ custom?: {
923
+ content: string;
924
+ property: string;
925
+ }[] | undefined;
926
+ description?: string | undefined;
927
+ auth?: {
928
+ login: string;
929
+ password: string;
930
+ method: "basic";
931
+ } | {
932
+ method: "basic";
933
+ login: string;
934
+ password: string;
935
+ } | undefined;
936
+ content?: string | undefined;
937
+ title?: string | undefined;
938
+ excludePageFromSearch?: string | undefined;
939
+ language?: string | undefined;
940
+ socialImageAssetId?: string | undefined;
941
+ socialImageUrl?: string | undefined;
942
+ redirect?: string | undefined;
943
+ documentType?: "html" | "xml" | "text" | undefined;
944
+ };
945
+ id: string;
946
+ title: string;
947
+ rootInstanceId: string;
948
+ systemDataSourceId?: string | undefined;
949
+ }, {
950
+ name: string;
951
+ meta: {
952
+ status?: string | undefined;
953
+ custom?: {
954
+ content: string;
955
+ property: string;
956
+ }[] | undefined;
957
+ description?: string | undefined;
958
+ auth?: {
959
+ login: string;
960
+ password: string;
961
+ method: "basic";
962
+ } | {
963
+ type: "basic";
964
+ login: string;
965
+ password: string;
966
+ } | undefined;
967
+ content?: string | undefined;
968
+ title?: string | undefined;
969
+ excludePageFromSearch?: string | undefined;
970
+ language?: string | undefined;
971
+ socialImageAssetId?: string | undefined;
972
+ socialImageUrl?: string | undefined;
973
+ redirect?: string | undefined;
974
+ documentType?: "html" | "xml" | "text" | undefined;
975
+ };
976
+ id: string;
977
+ title: string;
978
+ rootInstanceId: string;
979
+ systemDataSourceId?: string | undefined;
980
+ }>>>;
604
981
  folders: z.ZodEffects<z.ZodMap<z.ZodString, z.ZodObject<{
605
982
  id: z.ZodString;
606
983
  name: z.ZodEffects<z.ZodString, string, string>;
@@ -690,6 +1067,38 @@ export declare const Pages: z.ZodEffects<z.ZodObject<{
690
1067
  new: string;
691
1068
  status?: "301" | "302" | undefined;
692
1069
  }[] | undefined;
1070
+ pageTemplates?: Map<string, {
1071
+ name: string;
1072
+ meta: {
1073
+ status?: string | undefined;
1074
+ custom?: {
1075
+ content: string;
1076
+ property: string;
1077
+ }[] | undefined;
1078
+ description?: string | undefined;
1079
+ auth?: {
1080
+ login: string;
1081
+ password: string;
1082
+ method: "basic";
1083
+ } | {
1084
+ method: "basic";
1085
+ login: string;
1086
+ password: string;
1087
+ } | undefined;
1088
+ content?: string | undefined;
1089
+ title?: string | undefined;
1090
+ excludePageFromSearch?: string | undefined;
1091
+ language?: string | undefined;
1092
+ socialImageAssetId?: string | undefined;
1093
+ socialImageUrl?: string | undefined;
1094
+ redirect?: string | undefined;
1095
+ documentType?: "html" | "xml" | "text" | undefined;
1096
+ };
1097
+ id: string;
1098
+ title: string;
1099
+ rootInstanceId: string;
1100
+ systemDataSourceId?: string | undefined;
1101
+ }> | undefined;
693
1102
  }, {
694
1103
  pages: Map<string, {
695
1104
  path: string;
@@ -753,6 +1162,38 @@ export declare const Pages: z.ZodEffects<z.ZodObject<{
753
1162
  new: string;
754
1163
  status?: "301" | "302" | undefined;
755
1164
  }[] | undefined;
1165
+ pageTemplates?: Map<string, {
1166
+ name: string;
1167
+ meta: {
1168
+ status?: string | undefined;
1169
+ custom?: {
1170
+ content: string;
1171
+ property: string;
1172
+ }[] | undefined;
1173
+ description?: string | undefined;
1174
+ auth?: {
1175
+ login: string;
1176
+ password: string;
1177
+ method: "basic";
1178
+ } | {
1179
+ type: "basic";
1180
+ login: string;
1181
+ password: string;
1182
+ } | undefined;
1183
+ content?: string | undefined;
1184
+ title?: string | undefined;
1185
+ excludePageFromSearch?: string | undefined;
1186
+ language?: string | undefined;
1187
+ socialImageAssetId?: string | undefined;
1188
+ socialImageUrl?: string | undefined;
1189
+ redirect?: string | undefined;
1190
+ documentType?: "html" | "xml" | "text" | undefined;
1191
+ };
1192
+ id: string;
1193
+ title: string;
1194
+ rootInstanceId: string;
1195
+ systemDataSourceId?: string | undefined;
1196
+ }> | undefined;
756
1197
  }>, {
757
1198
  pages: Map<string, {
758
1199
  path: string;
@@ -816,6 +1257,38 @@ export declare const Pages: z.ZodEffects<z.ZodObject<{
816
1257
  new: string;
817
1258
  status?: "301" | "302" | undefined;
818
1259
  }[] | undefined;
1260
+ pageTemplates?: Map<string, {
1261
+ name: string;
1262
+ meta: {
1263
+ status?: string | undefined;
1264
+ custom?: {
1265
+ content: string;
1266
+ property: string;
1267
+ }[] | undefined;
1268
+ description?: string | undefined;
1269
+ auth?: {
1270
+ login: string;
1271
+ password: string;
1272
+ method: "basic";
1273
+ } | {
1274
+ method: "basic";
1275
+ login: string;
1276
+ password: string;
1277
+ } | undefined;
1278
+ content?: string | undefined;
1279
+ title?: string | undefined;
1280
+ excludePageFromSearch?: string | undefined;
1281
+ language?: string | undefined;
1282
+ socialImageAssetId?: string | undefined;
1283
+ socialImageUrl?: string | undefined;
1284
+ redirect?: string | undefined;
1285
+ documentType?: "html" | "xml" | "text" | undefined;
1286
+ };
1287
+ id: string;
1288
+ title: string;
1289
+ rootInstanceId: string;
1290
+ systemDataSourceId?: string | undefined;
1291
+ }> | undefined;
819
1292
  }, {
820
1293
  pages: Map<string, {
821
1294
  path: string;
@@ -879,6 +1352,38 @@ export declare const Pages: z.ZodEffects<z.ZodObject<{
879
1352
  new: string;
880
1353
  status?: "301" | "302" | undefined;
881
1354
  }[] | undefined;
1355
+ pageTemplates?: Map<string, {
1356
+ name: string;
1357
+ meta: {
1358
+ status?: string | undefined;
1359
+ custom?: {
1360
+ content: string;
1361
+ property: string;
1362
+ }[] | undefined;
1363
+ description?: string | undefined;
1364
+ auth?: {
1365
+ login: string;
1366
+ password: string;
1367
+ method: "basic";
1368
+ } | {
1369
+ type: "basic";
1370
+ login: string;
1371
+ password: string;
1372
+ } | undefined;
1373
+ content?: string | undefined;
1374
+ title?: string | undefined;
1375
+ excludePageFromSearch?: string | undefined;
1376
+ language?: string | undefined;
1377
+ socialImageAssetId?: string | undefined;
1378
+ socialImageUrl?: string | undefined;
1379
+ redirect?: string | undefined;
1380
+ documentType?: "html" | "xml" | "text" | undefined;
1381
+ };
1382
+ id: string;
1383
+ title: string;
1384
+ rootInstanceId: string;
1385
+ systemDataSourceId?: string | undefined;
1386
+ }> | undefined;
882
1387
  }>;
883
1388
  export type Pages = z.infer<typeof Pages>;
884
1389
  export {};
@@ -309,6 +309,33 @@ export declare const PropMeta: z.ZodUnion<[z.ZodObject<{
309
309
  label?: string | undefined;
310
310
  defaultValue?: string | undefined;
311
311
  contentMode?: boolean | undefined;
312
+ }>, z.ZodObject<{
313
+ control: z.ZodLiteral<"timeZone">;
314
+ type: z.ZodLiteral<"string">;
315
+ defaultValue: z.ZodOptional<z.ZodString>;
316
+ options: z.ZodArray<z.ZodString, "many">;
317
+ label: z.ZodOptional<z.ZodString>;
318
+ description: z.ZodOptional<z.ZodString>;
319
+ required: z.ZodBoolean;
320
+ contentMode: z.ZodOptional<z.ZodBoolean>;
321
+ }, "strip", z.ZodTypeAny, {
322
+ options: string[];
323
+ type: "string";
324
+ required: boolean;
325
+ control: "timeZone";
326
+ description?: string | undefined;
327
+ label?: string | undefined;
328
+ defaultValue?: string | undefined;
329
+ contentMode?: boolean | undefined;
330
+ }, {
331
+ options: string[];
332
+ type: "string";
333
+ required: boolean;
334
+ control: "timeZone";
335
+ description?: string | undefined;
336
+ label?: string | undefined;
337
+ defaultValue?: string | undefined;
338
+ contentMode?: boolean | undefined;
312
339
  }>, z.ZodObject<{
313
340
  control: z.ZodLiteral<"multi-select">;
314
341
  type: z.ZodLiteral<"string[]">;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webstudio-is/sdk",
3
- "version": "0.268.0",
3
+ "version": "0.269.0",
4
4
  "description": "Webstudio project data schema",
5
5
  "author": "Webstudio <github@webstudio.is>",
6
6
  "homepage": "https://webstudio.is",
@@ -18,6 +18,11 @@
18
18
  "types": "./lib/types/runtime.d.ts",
19
19
  "import": "./lib/runtime.js"
20
20
  },
21
+ "./link-utils": {
22
+ "webstudio": "./src/link-utils.ts",
23
+ "types": "./lib/types/link-utils.d.ts",
24
+ "import": "./lib/link-utils.js"
25
+ },
21
26
  "./normalize.css": {
22
27
  "webstudio": "./src/__generated__/normalize.css.ts",
23
28
  "types": "./lib/types/__generated__/normalize.css.d.ts",
@@ -46,23 +51,23 @@
46
51
  "type-fest": "^4.37.0",
47
52
  "warn-once": "^0.1.1",
48
53
  "zod": "^3.24.2",
49
- "@webstudio-is/css-engine": "0.268.0",
50
- "@webstudio-is/icons": "0.268.0",
51
- "@webstudio-is/wsauth": "0.268.0",
52
- "@webstudio-is/fonts": "0.268.0"
54
+ "@webstudio-is/css-engine": "0.269.0",
55
+ "@webstudio-is/fonts": "0.269.0",
56
+ "@webstudio-is/icons": "0.269.0",
57
+ "@webstudio-is/wsauth": "0.269.0"
53
58
  },
54
59
  "devDependencies": {
55
60
  "html-tags": "^4.0.0",
56
61
  "vitest": "^3.1.2",
57
- "@webstudio-is/css-data": "0.268.0",
58
- "@webstudio-is/template": "0.268.0",
62
+ "@webstudio-is/template": "0.269.0",
63
+ "@webstudio-is/css-data": "0.269.0",
59
64
  "@webstudio-is/tsconfig": "1.0.7"
60
65
  },
61
66
  "scripts": {
62
67
  "typecheck": "tsgo --noEmit -p tsconfig.typecheck.json",
63
68
  "test": "vitest run",
64
69
  "build:normalize.css": "tsx --conditions=webstudio ./scripts/normalize.css.ts && prettier --write src/__generated__/normalize.css.ts",
65
- "build": "rm -rf lib && esbuild src/index.ts src/runtime.ts src/__generated__/normalize.css.ts src/core-templates.tsx --outdir=lib --bundle --format=esm --packages=external",
70
+ "build": "rm -rf lib && esbuild src/index.ts src/runtime.ts src/link-utils.ts src/__generated__/normalize.css.ts src/core-templates.tsx --outdir=lib --bundle --format=esm --packages=external",
66
71
  "dts": "tsc --project tsconfig.dts.json"
67
72
  }
68
73
  }