webstudio 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/cli.js +193 -44
- package/package.json +15 -15
- package/templates/cloudflare/package.json +1 -1
- package/templates/defaults/app/redirect-url.ts +21 -0
- package/templates/defaults/app/route-templates/html.tsx +24 -10
- package/templates/defaults/app/route-templates/redirect.tsx +4 -3
- package/templates/defaults/package.json +8 -8
- package/templates/react-router/app/redirect-url.ts +21 -0
- package/templates/react-router/app/route-templates/html.tsx +24 -10
- package/templates/react-router/app/route-templates/redirect.tsx +4 -3
- package/templates/react-router/package.json +8 -8
- package/templates/react-router-cloudflare/package.json +1 -1
- package/templates/ssg/app/route-templates/html/+Page.tsx +34 -11
- package/templates/ssg/package.json +6 -6
- package/templates/ssg/renderer/+onRenderClient.tsx +3 -2
- package/templates/ssg/public/favicon.ico +0 -0
package/lib/cli.js
CHANGED
|
@@ -374,7 +374,7 @@ const getApiCompatibilityPayload = (value) => {
|
|
|
374
374
|
return findPayload(value, /* @__PURE__ */ new WeakSet());
|
|
375
375
|
};
|
|
376
376
|
const name = "webstudio";
|
|
377
|
-
const version = "0.
|
|
377
|
+
const version = "0.269.0";
|
|
378
378
|
const description = "Webstudio CLI";
|
|
379
379
|
const author = "Webstudio <github@webstudio.is>";
|
|
380
380
|
const homepage = "https://webstudio.is";
|
|
@@ -4207,6 +4207,14 @@ var Page = z.object({
|
|
|
4207
4207
|
...commonPageFields,
|
|
4208
4208
|
path: z.union([HomePagePath, PagePath])
|
|
4209
4209
|
});
|
|
4210
|
+
var PageTemplate = z.object({
|
|
4211
|
+
id: PageId,
|
|
4212
|
+
name: PageName,
|
|
4213
|
+
title: PageTitle,
|
|
4214
|
+
rootInstanceId: z.string(),
|
|
4215
|
+
systemDataSourceId: z.string().optional(),
|
|
4216
|
+
meta: commonPageFields.meta
|
|
4217
|
+
});
|
|
4210
4218
|
var ProjectMeta = z.object({
|
|
4211
4219
|
// All fields are optional to ensure consistency and allow for the addition of new fields without requiring migration
|
|
4212
4220
|
siteName: z.string().optional(),
|
|
@@ -4239,6 +4247,7 @@ var Pages = z.object({
|
|
|
4239
4247
|
homePageId: PageId,
|
|
4240
4248
|
rootFolderId: FolderId,
|
|
4241
4249
|
pages: z.map(PageId, Page),
|
|
4250
|
+
pageTemplates: z.map(PageId, PageTemplate).optional(),
|
|
4242
4251
|
folders: z.map(FolderId, Folder).refine((folders) => folders.size > 0, "Folders can't be empty")
|
|
4243
4252
|
}).superRefine((pages, context) => {
|
|
4244
4253
|
const homePage = pages.pages.get(pages.homePageId);
|
|
@@ -4280,6 +4289,22 @@ var Pages = z.object({
|
|
|
4280
4289
|
});
|
|
4281
4290
|
}
|
|
4282
4291
|
}
|
|
4292
|
+
for (const [templateId, template] of pages.pageTemplates ?? []) {
|
|
4293
|
+
if (template.id !== templateId) {
|
|
4294
|
+
context.addIssue({
|
|
4295
|
+
code: z.ZodIssueCode.custom,
|
|
4296
|
+
path: ["pageTemplates", templateId, "id"],
|
|
4297
|
+
message: "Page template id must match its record key"
|
|
4298
|
+
});
|
|
4299
|
+
}
|
|
4300
|
+
if (pages.pages.has(templateId)) {
|
|
4301
|
+
context.addIssue({
|
|
4302
|
+
code: z.ZodIssueCode.custom,
|
|
4303
|
+
path: ["pageTemplates", templateId, "id"],
|
|
4304
|
+
message: "Page template id must not match an existing page id"
|
|
4305
|
+
});
|
|
4306
|
+
}
|
|
4307
|
+
}
|
|
4283
4308
|
for (const [folderId, folder] of pages.folders) {
|
|
4284
4309
|
if (folder.id !== folderId) {
|
|
4285
4310
|
context.addIssue({
|
|
@@ -4923,6 +4948,13 @@ var Select = z.object({
|
|
|
4923
4948
|
defaultValue: z.string().optional(),
|
|
4924
4949
|
options: z.array(z.string())
|
|
4925
4950
|
});
|
|
4951
|
+
var TimeZone = z.object({
|
|
4952
|
+
...common,
|
|
4953
|
+
control: z.literal("timeZone"),
|
|
4954
|
+
type: z.literal("string"),
|
|
4955
|
+
defaultValue: z.string().optional(),
|
|
4956
|
+
options: z.array(z.string())
|
|
4957
|
+
});
|
|
4926
4958
|
var Check = z.object({
|
|
4927
4959
|
...common,
|
|
4928
4960
|
control: z.literal("check"),
|
|
@@ -5003,6 +5035,7 @@ var PropMeta = z.union([
|
|
|
5003
5035
|
Radio,
|
|
5004
5036
|
InlineRadio,
|
|
5005
5037
|
Select,
|
|
5038
|
+
TimeZone,
|
|
5006
5039
|
MultiSelect,
|
|
5007
5040
|
Check,
|
|
5008
5041
|
InlineCheck,
|
|
@@ -5906,6 +5939,29 @@ var parseComponentName = (componentName) => {
|
|
|
5906
5939
|
}
|
|
5907
5940
|
return [namespace, name2];
|
|
5908
5941
|
};
|
|
5942
|
+
var getHtmlTagsFromProps = (props) => {
|
|
5943
|
+
const tags2 = /* @__PURE__ */ new Map();
|
|
5944
|
+
for (const prop of props.values()) {
|
|
5945
|
+
if (prop.type === "string" && prop.name === "tag") {
|
|
5946
|
+
tags2.set(prop.instanceId, prop.value);
|
|
5947
|
+
}
|
|
5948
|
+
}
|
|
5949
|
+
return tags2;
|
|
5950
|
+
};
|
|
5951
|
+
var getHtmlTagFromInstance = ({
|
|
5952
|
+
instance: instance2,
|
|
5953
|
+
metas,
|
|
5954
|
+
props,
|
|
5955
|
+
htmlTagsByInstanceId
|
|
5956
|
+
}) => {
|
|
5957
|
+
if (instance2.component === "XmlNode") {
|
|
5958
|
+
return;
|
|
5959
|
+
}
|
|
5960
|
+
const meta = metas.get(instance2.component);
|
|
5961
|
+
const metaTag = Object.keys((meta == null ? void 0 : meta.presetStyle) ?? {}).at(0);
|
|
5962
|
+
const propTag = (htmlTagsByInstanceId == null ? void 0 : htmlTagsByInstanceId.get(instance2.id)) ?? getHtmlTagsFromProps(props).get(instance2.id);
|
|
5963
|
+
return instance2.tag ?? propTag ?? metaTag;
|
|
5964
|
+
};
|
|
5909
5965
|
var getIndexesWithinAncestors = (metas, instances, rootIds) => {
|
|
5910
5966
|
const ancestors = /* @__PURE__ */ new Set();
|
|
5911
5967
|
for (const meta of metas.values()) {
|
|
@@ -5958,6 +6014,24 @@ var systemParameter = {
|
|
|
5958
6014
|
type: "parameter",
|
|
5959
6015
|
name: "system"
|
|
5960
6016
|
};
|
|
6017
|
+
var walkAssignmentTarget = (node, visitor) => {
|
|
6018
|
+
var _a2, _b2, _c2, _d2;
|
|
6019
|
+
if (node.type === "Identifier") {
|
|
6020
|
+
(_a2 = visitor.Identifier) == null ? void 0 : _a2.call(visitor, node, "binding");
|
|
6021
|
+
return;
|
|
6022
|
+
}
|
|
6023
|
+
if (node.type === "MemberExpression") {
|
|
6024
|
+
(_b2 = visitor.MemberExpression) == null ? void 0 : _b2.call(visitor, node);
|
|
6025
|
+
const { object } = node;
|
|
6026
|
+
if (object.type === "Identifier") {
|
|
6027
|
+
(_c2 = visitor.Identifier) == null ? void 0 : _c2.call(visitor, object, "memberObject");
|
|
6028
|
+
} else if (object.type === "MemberExpression") {
|
|
6029
|
+
walkAssignmentTarget(object, visitor);
|
|
6030
|
+
}
|
|
6031
|
+
return;
|
|
6032
|
+
}
|
|
6033
|
+
(_d2 = visitor.UnsupportedPattern) == null ? void 0 : _d2.call(visitor, node);
|
|
6034
|
+
};
|
|
5961
6035
|
var stringMethodReturnKindByName = /* @__PURE__ */ new Map([
|
|
5962
6036
|
["toLowerCase", "string"],
|
|
5963
6037
|
["replace", "string"],
|
|
@@ -5995,17 +6069,44 @@ var transpileExpression = ({
|
|
|
5995
6069
|
const message = error.message;
|
|
5996
6070
|
throw Error(`${message} in ${JSON.stringify(expression)}`);
|
|
5997
6071
|
}
|
|
6072
|
+
const assignmentTargetMemberRanges = [];
|
|
6073
|
+
if (executable) {
|
|
6074
|
+
simple(root, {
|
|
6075
|
+
AssignmentExpression(node) {
|
|
6076
|
+
walkAssignmentTarget(node.left, {
|
|
6077
|
+
MemberExpression(node2) {
|
|
6078
|
+
assignmentTargetMemberRanges.push([node2.start, node2.end]);
|
|
6079
|
+
}
|
|
6080
|
+
});
|
|
6081
|
+
}
|
|
6082
|
+
});
|
|
6083
|
+
}
|
|
5998
6084
|
const replacements = [];
|
|
6085
|
+
const replacementIndexByRange = /* @__PURE__ */ new Map();
|
|
6086
|
+
const addReplacement = (start, end, fragment, { replaceExisting = false } = {}) => {
|
|
6087
|
+
const range = `${start}:${end}`;
|
|
6088
|
+
const existingIndex = replacementIndexByRange.get(range);
|
|
6089
|
+
if (existingIndex !== void 0) {
|
|
6090
|
+
if (replaceExisting) {
|
|
6091
|
+
replacements[existingIndex] = [start, end, fragment];
|
|
6092
|
+
}
|
|
6093
|
+
return;
|
|
6094
|
+
}
|
|
6095
|
+
replacementIndexByRange.set(range, replacements.length);
|
|
6096
|
+
replacements.push([start, end, fragment]);
|
|
6097
|
+
};
|
|
5999
6098
|
const replaceIdentifier = (node, assignee) => {
|
|
6000
6099
|
const newName = replaceVariable == null ? void 0 : replaceVariable(node.name, assignee);
|
|
6001
6100
|
if (newName) {
|
|
6002
|
-
|
|
6101
|
+
addReplacement(node.start, node.end, newName, {
|
|
6102
|
+
replaceExisting: assignee
|
|
6103
|
+
});
|
|
6003
6104
|
}
|
|
6004
6105
|
};
|
|
6005
6106
|
simple(root, {
|
|
6006
6107
|
Identifier: (node) => replaceIdentifier(node, false),
|
|
6007
6108
|
AssignmentExpression(node) {
|
|
6008
|
-
|
|
6109
|
+
walkAssignmentTarget(node.left, {
|
|
6009
6110
|
Identifier: (node2) => replaceIdentifier(node2, true)
|
|
6010
6111
|
});
|
|
6011
6112
|
},
|
|
@@ -6013,13 +6114,18 @@ var transpileExpression = ({
|
|
|
6013
6114
|
if (executable === false || node.optional) {
|
|
6014
6115
|
return;
|
|
6015
6116
|
}
|
|
6117
|
+
if (assignmentTargetMemberRanges.some(
|
|
6118
|
+
([start, end]) => start === node.start && end === node.end
|
|
6119
|
+
)) {
|
|
6120
|
+
return;
|
|
6121
|
+
}
|
|
6016
6122
|
if (node.computed === false) {
|
|
6017
6123
|
const dotIndex = expression.indexOf(".", node.object.end);
|
|
6018
|
-
|
|
6124
|
+
addReplacement(dotIndex, dotIndex, "?");
|
|
6019
6125
|
}
|
|
6020
6126
|
if (node.computed === true) {
|
|
6021
6127
|
const dotIndex = expression.indexOf("[", node.object.end);
|
|
6022
|
-
|
|
6128
|
+
addReplacement(dotIndex, dotIndex, "?.");
|
|
6023
6129
|
}
|
|
6024
6130
|
},
|
|
6025
6131
|
CallExpression(node) {
|
|
@@ -6029,7 +6135,7 @@ var transpileExpression = ({
|
|
|
6029
6135
|
if (node.callee.type === "MemberExpression") {
|
|
6030
6136
|
const openParenIndex = expression.indexOf("(", node.callee.end);
|
|
6031
6137
|
if (openParenIndex !== -1) {
|
|
6032
|
-
|
|
6138
|
+
addReplacement(openParenIndex, openParenIndex, "?.");
|
|
6033
6139
|
}
|
|
6034
6140
|
}
|
|
6035
6141
|
}
|
|
@@ -6103,14 +6209,21 @@ var getHomePage = (pages) => {
|
|
|
6103
6209
|
}
|
|
6104
6210
|
return homePage;
|
|
6105
6211
|
};
|
|
6106
|
-
|
|
6212
|
+
function findPageByIdOrPath(idOrPath, pages, options = {}) {
|
|
6213
|
+
var _a2;
|
|
6107
6214
|
if (idOrPath === "" || idOrPath === "/" || idOrPath === pages.homePageId) {
|
|
6108
6215
|
return getHomePage(pages);
|
|
6109
6216
|
}
|
|
6110
|
-
|
|
6217
|
+
const found = getAllPages(pages).find(
|
|
6111
6218
|
(page) => page.id === idOrPath || getPagePath(page.id, pages) === idOrPath
|
|
6112
6219
|
);
|
|
6113
|
-
|
|
6220
|
+
if (found) {
|
|
6221
|
+
return found;
|
|
6222
|
+
}
|
|
6223
|
+
if (options.includeTemplates) {
|
|
6224
|
+
return (_a2 = pages.pageTemplates) == null ? void 0 : _a2.get(idOrPath);
|
|
6225
|
+
}
|
|
6226
|
+
}
|
|
6114
6227
|
var getPagePath = (id, pages) => {
|
|
6115
6228
|
const foldersMap = /* @__PURE__ */ new Map();
|
|
6116
6229
|
const childParentMap = /* @__PURE__ */ new Map();
|
|
@@ -6576,22 +6689,19 @@ var generateCss = ({
|
|
|
6576
6689
|
const scope = createScope([], normalizeClassName, "-");
|
|
6577
6690
|
const tagsByComponent = /* @__PURE__ */ new Map();
|
|
6578
6691
|
tagsByComponent.set(rootComponent, /* @__PURE__ */ new Set(["html"]));
|
|
6579
|
-
const
|
|
6580
|
-
for (const prop of props.values()) {
|
|
6581
|
-
if (prop.type === "string" && prop.name === "tag") {
|
|
6582
|
-
tagByInstanceId.set(prop.instanceId, prop.value);
|
|
6583
|
-
}
|
|
6584
|
-
}
|
|
6692
|
+
const htmlTagsByInstanceId = getHtmlTagsFromProps(props);
|
|
6585
6693
|
for (const instance2 of instances.values()) {
|
|
6586
|
-
const propTag = tagByInstanceId.get(instance2.id);
|
|
6587
|
-
const meta = componentMetas.get(instance2.component);
|
|
6588
|
-
const metaTag = Object.keys((meta == null ? void 0 : meta.presetStyle) ?? {}).at(0);
|
|
6589
6694
|
let componentTags = tagsByComponent.get(instance2.component);
|
|
6590
6695
|
if (componentTags === void 0) {
|
|
6591
6696
|
componentTags = /* @__PURE__ */ new Set();
|
|
6592
6697
|
tagsByComponent.set(instance2.component, componentTags);
|
|
6593
6698
|
}
|
|
6594
|
-
const tag =
|
|
6699
|
+
const tag = getHtmlTagFromInstance({
|
|
6700
|
+
instance: instance2,
|
|
6701
|
+
metas: componentMetas,
|
|
6702
|
+
props,
|
|
6703
|
+
htmlTagsByInstanceId
|
|
6704
|
+
});
|
|
6595
6705
|
if (tag) {
|
|
6596
6706
|
componentTags.add(tag);
|
|
6597
6707
|
}
|
|
@@ -7293,7 +7403,7 @@ var generateJsxChildren = ({
|
|
|
7293
7403
|
usedDataSources,
|
|
7294
7404
|
scope
|
|
7295
7405
|
});
|
|
7296
|
-
generatedChildren = `{${expression}}
|
|
7406
|
+
generatedChildren = `{renderText(${expression})}
|
|
7297
7407
|
`;
|
|
7298
7408
|
continue;
|
|
7299
7409
|
}
|
|
@@ -7474,11 +7584,12 @@ var migratePages = (pages) => {
|
|
|
7474
7584
|
if (isSerializedPages(pages) && pages.pages instanceof Map && pages.folders instanceof Map) {
|
|
7475
7585
|
const currentPages = pages;
|
|
7476
7586
|
const result = Pages.safeParse(currentPages);
|
|
7477
|
-
if (result.success) {
|
|
7587
|
+
if (result.success && currentPages.pageTemplates !== void 0) {
|
|
7478
7588
|
return currentPages;
|
|
7479
7589
|
}
|
|
7480
7590
|
return {
|
|
7481
7591
|
...currentPages,
|
|
7592
|
+
pageTemplates: currentPages.pageTemplates ?? /* @__PURE__ */ new Map(),
|
|
7482
7593
|
folders: removeOrphanFolderChildren(
|
|
7483
7594
|
currentPages.pages,
|
|
7484
7595
|
currentPages.folders
|
|
@@ -7495,6 +7606,7 @@ var migratePages = (pages) => {
|
|
|
7495
7606
|
homePageId: pages.homePageId,
|
|
7496
7607
|
rootFolderId: pages.rootFolderId,
|
|
7497
7608
|
pages: nextPages2,
|
|
7609
|
+
pageTemplates: pages.pageTemplates === void 0 ? /* @__PURE__ */ new Map() : toMap(pages.pageTemplates),
|
|
7498
7610
|
folders: removeOrphanFolderChildren(nextPages2, nextFolders2)
|
|
7499
7611
|
};
|
|
7500
7612
|
}
|
|
@@ -7551,6 +7663,7 @@ var migratePages = (pages) => {
|
|
|
7551
7663
|
homePageId: homePage.id,
|
|
7552
7664
|
rootFolderId: rootFolder.id,
|
|
7553
7665
|
pages: nextPages,
|
|
7666
|
+
pageTemplates: /* @__PURE__ */ new Map(),
|
|
7554
7667
|
folders: nextFolders
|
|
7555
7668
|
};
|
|
7556
7669
|
};
|
|
@@ -8012,7 +8125,7 @@ const g$3 = {
|
|
|
8012
8125
|
const t$f = {
|
|
8013
8126
|
tag: { required: false, control: "text", type: "string" }
|
|
8014
8127
|
};
|
|
8015
|
-
const n$
|
|
8128
|
+
const n$7 = {
|
|
8016
8129
|
icon: TextIcon,
|
|
8017
8130
|
presetStyle: {
|
|
8018
8131
|
div: [
|
|
@@ -8208,14 +8321,14 @@ const c$4 = {
|
|
|
8208
8321
|
}
|
|
8209
8322
|
};
|
|
8210
8323
|
const o$v = {};
|
|
8211
|
-
const r$
|
|
8324
|
+
const r$c = {
|
|
8212
8325
|
form: [
|
|
8213
8326
|
...form,
|
|
8214
8327
|
{ property: "min-height", value: { type: "unit", unit: "px", value: 20 } }
|
|
8215
8328
|
]
|
|
8216
8329
|
}, p$4 = {
|
|
8217
8330
|
label: "Form",
|
|
8218
|
-
presetStyle: r$
|
|
8331
|
+
presetStyle: r$c,
|
|
8219
8332
|
initialProps: ["id", "class", "action"],
|
|
8220
8333
|
props: o$v
|
|
8221
8334
|
};
|
|
@@ -8229,7 +8342,7 @@ const e$o = {
|
|
|
8229
8342
|
},
|
|
8230
8343
|
quality: { required: false, control: "number", type: "number" }
|
|
8231
8344
|
};
|
|
8232
|
-
const r$
|
|
8345
|
+
const r$b = {
|
|
8233
8346
|
img: [
|
|
8234
8347
|
...img,
|
|
8235
8348
|
// Otherwise on new image insert onto canvas it can overfit screen size multiple times
|
|
@@ -8254,7 +8367,7 @@ const r$c = {
|
|
|
8254
8367
|
}, i$7 = {
|
|
8255
8368
|
category: "media",
|
|
8256
8369
|
description: "Add an image asset to the page. Webstudio automatically converts images to WebP or AVIF format and makes them responsive for best performance.",
|
|
8257
|
-
presetStyle: r$
|
|
8370
|
+
presetStyle: r$b,
|
|
8258
8371
|
order: 0,
|
|
8259
8372
|
initialProps: [
|
|
8260
8373
|
"id",
|
|
@@ -8345,7 +8458,7 @@ const e$n = {
|
|
|
8345
8458
|
value: { type: "rgb", r: 226, g: 226, b: 226, alpha: 1 }
|
|
8346
8459
|
}
|
|
8347
8460
|
]
|
|
8348
|
-
}, r$
|
|
8461
|
+
}, r$a = {
|
|
8349
8462
|
presetStyle: e$n,
|
|
8350
8463
|
initialProps: ["id", "class", "cite"],
|
|
8351
8464
|
props: o$u
|
|
@@ -8532,7 +8645,7 @@ const e$k = {
|
|
|
8532
8645
|
description: "Value of the form control"
|
|
8533
8646
|
}
|
|
8534
8647
|
};
|
|
8535
|
-
const r$
|
|
8648
|
+
const r$9 = {
|
|
8536
8649
|
input: [
|
|
8537
8650
|
...radio,
|
|
8538
8651
|
{
|
|
@@ -8543,7 +8656,7 @@ const r$a = {
|
|
|
8543
8656
|
}, m$7 = {
|
|
8544
8657
|
label: "Radio",
|
|
8545
8658
|
icon: RadioCheckedIcon,
|
|
8546
|
-
presetStyle: r$
|
|
8659
|
+
presetStyle: r$9,
|
|
8547
8660
|
initialProps: ["id", "class", "name", "value", "required", "checked"],
|
|
8548
8661
|
props: e$k
|
|
8549
8662
|
};
|
|
@@ -9307,15 +9420,22 @@ const e$d = {
|
|
|
9307
9420
|
defaultValue: "medium",
|
|
9308
9421
|
options: ["full", "long", "medium", "short", "none"]
|
|
9309
9422
|
},
|
|
9423
|
+
datetime: {
|
|
9424
|
+
required: false,
|
|
9425
|
+
control: "text",
|
|
9426
|
+
type: "string",
|
|
9427
|
+
defaultValue: "dateTime attribute is not set",
|
|
9428
|
+
description: "Machine-readable value"
|
|
9429
|
+
},
|
|
9310
9430
|
format: {
|
|
9311
9431
|
description: `Custom format template. Overrides Date Style and Time Style.
|
|
9312
9432
|
|
|
9313
9433
|
Tokens: YYYY/YY (year), MMMM/MMM/MM/M (month), DDDD/DDD/DD/D (day), HH/H (hours), mm/m (minutes), ss/s (seconds)
|
|
9314
9434
|
|
|
9315
9435
|
Examples:
|
|
9316
|
-
"YYYY-MM-DD" → 2025-11-03
|
|
9317
|
-
"DDDD, MMMM D" → Monday, November 3
|
|
9318
|
-
"DDD, D. MMM YYYY" → Mon, 3. Nov 2025
|
|
9436
|
+
- "YYYY-MM-DD" → 2025-11-03
|
|
9437
|
+
- "DDDD, MMMM D" → Monday, November 3
|
|
9438
|
+
- "DDD, D. MMM YYYY" → Mon, 3. Nov 2025
|
|
9319
9439
|
|
|
9320
9440
|
Day and month names use the selected language.`,
|
|
9321
9441
|
required: false,
|
|
@@ -9407,9 +9527,19 @@ Day and month names use the selected language.`,
|
|
|
9407
9527
|
type: "string",
|
|
9408
9528
|
defaultValue: "none",
|
|
9409
9529
|
options: ["full", "long", "medium", "short", "none"]
|
|
9530
|
+
},
|
|
9531
|
+
timeZone: {
|
|
9532
|
+
description: `Time zone used to format the date.
|
|
9533
|
+
|
|
9534
|
+
Use "UTC" for deterministic UTC output, "visitor" to use the browser time
|
|
9535
|
+
zone after hydration, or an IANA time zone like "Europe/Berlin".`,
|
|
9536
|
+
required: false,
|
|
9537
|
+
control: "text",
|
|
9538
|
+
type: "string",
|
|
9539
|
+
defaultValue: "UTC"
|
|
9410
9540
|
}
|
|
9411
9541
|
};
|
|
9412
|
-
const
|
|
9542
|
+
const n$6 = {
|
|
9413
9543
|
category: "localization",
|
|
9414
9544
|
description: "Converts machine-readable date and time to a human-readable format.",
|
|
9415
9545
|
contentModel: {
|
|
@@ -9425,6 +9555,7 @@ const r$9 = {
|
|
|
9425
9555
|
"country",
|
|
9426
9556
|
"dateStyle",
|
|
9427
9557
|
"timeStyle",
|
|
9558
|
+
"timeZone",
|
|
9428
9559
|
"format"
|
|
9429
9560
|
],
|
|
9430
9561
|
props: {
|
|
@@ -9451,6 +9582,15 @@ const r$9 = {
|
|
|
9451
9582
|
...e$d.timeStyle,
|
|
9452
9583
|
contentMode: true
|
|
9453
9584
|
},
|
|
9585
|
+
timeZone: {
|
|
9586
|
+
required: false,
|
|
9587
|
+
control: "timeZone",
|
|
9588
|
+
type: "string",
|
|
9589
|
+
defaultValue: "UTC",
|
|
9590
|
+
options: ["UTC", "visitor"],
|
|
9591
|
+
description: 'Timezone used to display the date. Use "visitor" to display each visitor’s browser timezone after the page loads, or select/type an IANA timezone like "Europe/Berlin".',
|
|
9592
|
+
contentMode: true
|
|
9593
|
+
},
|
|
9454
9594
|
format: {
|
|
9455
9595
|
...e$d.format,
|
|
9456
9596
|
contentMode: true
|
|
@@ -9605,7 +9745,7 @@ const n$5 = {
|
|
|
9605
9745
|
};
|
|
9606
9746
|
const baseComponentMetas = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
9607
9747
|
__proto__: null,
|
|
9608
|
-
Blockquote: r$
|
|
9748
|
+
Blockquote: r$a,
|
|
9609
9749
|
Body: i$9,
|
|
9610
9750
|
Bold: p$6,
|
|
9611
9751
|
Box: g$3,
|
|
@@ -9639,9 +9779,9 @@ const baseComponentMetas = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.
|
|
|
9639
9779
|
Span: e$s,
|
|
9640
9780
|
Subscript: s$3,
|
|
9641
9781
|
Superscript: o$z,
|
|
9642
|
-
Text: n$
|
|
9782
|
+
Text: n$7,
|
|
9643
9783
|
Textarea: l$4,
|
|
9644
|
-
Time:
|
|
9784
|
+
Time: n$6,
|
|
9645
9785
|
Video: n$5,
|
|
9646
9786
|
Vimeo: s$2,
|
|
9647
9787
|
VimeoPlayButton: c$2,
|
|
@@ -10246,7 +10386,15 @@ const e$5 = {
|
|
|
10246
10386
|
type: "string",
|
|
10247
10387
|
description: "Current value of the element"
|
|
10248
10388
|
}
|
|
10249
|
-
}, t$2 = {},
|
|
10389
|
+
}, t$2 = {}, n$2 = {}, r$3 = {
|
|
10390
|
+
forceMount: {
|
|
10391
|
+
description: "Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries or keeping content available in the DOM.",
|
|
10392
|
+
required: false,
|
|
10393
|
+
control: "boolean",
|
|
10394
|
+
type: "boolean",
|
|
10395
|
+
defaultValue: true
|
|
10396
|
+
}
|
|
10397
|
+
};
|
|
10250
10398
|
const C$1 = {
|
|
10251
10399
|
icon: AccordionIcon,
|
|
10252
10400
|
contentModel: {
|
|
@@ -10313,7 +10461,7 @@ const C$1 = {
|
|
|
10313
10461
|
presetStyle: {
|
|
10314
10462
|
button: [button, b$2].flat()
|
|
10315
10463
|
},
|
|
10316
|
-
props:
|
|
10464
|
+
props: n$2
|
|
10317
10465
|
}, H = {
|
|
10318
10466
|
label: "Item Content",
|
|
10319
10467
|
icon: ContentIcon,
|
|
@@ -10328,7 +10476,7 @@ const C$1 = {
|
|
|
10328
10476
|
presetStyle: {
|
|
10329
10477
|
div
|
|
10330
10478
|
},
|
|
10331
|
-
props:
|
|
10479
|
+
props: r$3
|
|
10332
10480
|
};
|
|
10333
10481
|
const e$4 = {
|
|
10334
10482
|
defaultValue: { required: false, control: "text", type: "string" },
|
|
@@ -10927,7 +11075,7 @@ const createFramework$2 = async () => {
|
|
|
10927
11075
|
"utf8"
|
|
10928
11076
|
);
|
|
10929
11077
|
await rm(routeTemplatesDir, { recursive: true, force: true });
|
|
10930
|
-
const base = "@webstudio-is/sdk-components-react";
|
|
11078
|
+
const base = "@webstudio-is/sdk-components-react/components";
|
|
10931
11079
|
const remix = "@webstudio-is/sdk-components-react-remix";
|
|
10932
11080
|
const reactRadix = "@webstudio-is/sdk-components-react-radix";
|
|
10933
11081
|
const animation = "@webstudio-is/sdk-components-animation";
|
|
@@ -11018,7 +11166,7 @@ const createFramework$1 = async () => {
|
|
|
11018
11166
|
"utf8"
|
|
11019
11167
|
);
|
|
11020
11168
|
await rm(routeTemplatesDir, { recursive: true, force: true });
|
|
11021
|
-
const base = "@webstudio-is/sdk-components-react";
|
|
11169
|
+
const base = "@webstudio-is/sdk-components-react/components";
|
|
11022
11170
|
const reactRouter = "@webstudio-is/sdk-components-react-router";
|
|
11023
11171
|
const reactRadix = "@webstudio-is/sdk-components-react-radix";
|
|
11024
11172
|
const animation = "@webstudio-is/sdk-components-animation";
|
|
@@ -11107,7 +11255,7 @@ const createFramework = async () => {
|
|
|
11107
11255
|
"utf8"
|
|
11108
11256
|
);
|
|
11109
11257
|
await rm(routeTemplatesDir, { recursive: true, force: true });
|
|
11110
|
-
const base = "@webstudio-is/sdk-components-react";
|
|
11258
|
+
const base = "@webstudio-is/sdk-components-react/components";
|
|
11111
11259
|
const reactRadix = "@webstudio-is/sdk-components-react-radix";
|
|
11112
11260
|
const animation = "@webstudio-is/sdk-components-animation";
|
|
11113
11261
|
const components = {};
|
|
@@ -11130,7 +11278,8 @@ const createFramework = async () => {
|
|
|
11130
11278
|
tags: {
|
|
11131
11279
|
textarea: `${base}:Textarea`,
|
|
11132
11280
|
input: `${base}:Input`,
|
|
11133
|
-
select: `${base}:Select
|
|
11281
|
+
select: `${base}:Select`,
|
|
11282
|
+
a: `${base}:Link`
|
|
11134
11283
|
},
|
|
11135
11284
|
html: ({ pagePath }) => {
|
|
11136
11285
|
if (isPathnamePattern(pagePath)) {
|
|
@@ -11568,7 +11717,7 @@ Please check webstudio --help for more details`
|
|
|
11568
11717
|
|
|
11569
11718
|
|
|
11570
11719
|
import { Fragment, useState } from "react";
|
|
11571
|
-
import { useResource, useVariableState } from "@webstudio-is/react-sdk/runtime";
|
|
11720
|
+
import { renderText, useResource, useVariableState } from "@webstudio-is/react-sdk/runtime";
|
|
11572
11721
|
${importsString}
|
|
11573
11722
|
|
|
11574
11723
|
export const projectId = "${siteData.build.projectId}";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webstudio",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.269.0",
|
|
4
4
|
"description": "Webstudio CLI",
|
|
5
5
|
"author": "Webstudio <github@webstudio.is>",
|
|
6
6
|
"homepage": "https://webstudio.is",
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"warn-once": "^0.1.1",
|
|
44
44
|
"yargs": "^17.7.2",
|
|
45
45
|
"zod": "^3.24.2",
|
|
46
|
-
"@webstudio-is/
|
|
47
|
-
"@webstudio-is/
|
|
46
|
+
"@webstudio-is/project-migrations": "0.269.0",
|
|
47
|
+
"@webstudio-is/trpc-interface": "0.269.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@cloudflare/vite-plugin": "^1.1.0",
|
|
@@ -74,18 +74,18 @@
|
|
|
74
74
|
"vite": "^6.3.4",
|
|
75
75
|
"vitest": "^3.1.2",
|
|
76
76
|
"wrangler": "^3.63.2",
|
|
77
|
-
"@webstudio-is/
|
|
78
|
-
"@webstudio-is/
|
|
79
|
-
"@webstudio-is/
|
|
80
|
-
"@webstudio-is/
|
|
81
|
-
"@webstudio-is/
|
|
82
|
-
"@webstudio-is/sdk
|
|
83
|
-
"@webstudio-is/sdk-components-react
|
|
84
|
-
"@webstudio-is/sdk-components-react-
|
|
85
|
-
"@webstudio-is/sdk-components-react-
|
|
86
|
-
"@webstudio-is/sdk-components-react": "0.
|
|
87
|
-
"@webstudio-is/
|
|
88
|
-
"@webstudio-is/
|
|
77
|
+
"@webstudio-is/http-client": "0.269.0",
|
|
78
|
+
"@webstudio-is/image": "0.269.0",
|
|
79
|
+
"@webstudio-is/react-sdk": "0.269.0",
|
|
80
|
+
"@webstudio-is/sdk-components-animation": "0.269.0",
|
|
81
|
+
"@webstudio-is/css-engine": "0.269.0",
|
|
82
|
+
"@webstudio-is/sdk": "0.269.0",
|
|
83
|
+
"@webstudio-is/sdk-components-react": "0.269.0",
|
|
84
|
+
"@webstudio-is/sdk-components-react-radix": "0.269.0",
|
|
85
|
+
"@webstudio-is/sdk-components-react-remix": "0.269.0",
|
|
86
|
+
"@webstudio-is/sdk-components-react-router": "0.269.0",
|
|
87
|
+
"@webstudio-is/tsconfig": "1.0.7",
|
|
88
|
+
"@webstudio-is/wsauth": "0.269.0"
|
|
89
89
|
},
|
|
90
90
|
"scripts": {
|
|
91
91
|
"typecheck": "tsgo --noEmit",
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createPath, generatePath, parsePath } from "@remix-run/react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Expands route params in local redirect targets.
|
|
5
|
+
* External and protocol-relative URLs are returned unchanged because route params
|
|
6
|
+
* only apply to app paths.
|
|
7
|
+
*/
|
|
8
|
+
export const generateRedirectUrl = (
|
|
9
|
+
url: string,
|
|
10
|
+
params: Record<string, string | undefined>
|
|
11
|
+
) => {
|
|
12
|
+
if (url.startsWith("/") === false || url.startsWith("//")) {
|
|
13
|
+
return url;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const path = parsePath(url);
|
|
17
|
+
return createPath({
|
|
18
|
+
...path,
|
|
19
|
+
pathname: generatePath(path.pathname ?? "/", params),
|
|
20
|
+
});
|
|
21
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ComponentProps, memo, useMemo } from "react";
|
|
1
2
|
import {
|
|
2
3
|
type ServerRuntimeMetaFunction as MetaFunction,
|
|
3
4
|
type LinksFunction,
|
|
@@ -328,20 +329,33 @@ export const action = async ({
|
|
|
328
329
|
}
|
|
329
330
|
};
|
|
330
331
|
|
|
332
|
+
const PageBoundary = memo(
|
|
333
|
+
({ url, system }: ComponentProps<typeof Page> & { url: string }) => {
|
|
334
|
+
// Use the URL as the key to force scripts in HTML Embed to reload on dynamic pages
|
|
335
|
+
return <Page key={url} system={system} />;
|
|
336
|
+
},
|
|
337
|
+
// React Router can rerender the current route while the next route loaders are
|
|
338
|
+
// still pending. Keep the generated page out of that pending-navigation render
|
|
339
|
+
// path, but let URL changes remount it.
|
|
340
|
+
(prevProps, nextProps) => prevProps.url === nextProps.url
|
|
341
|
+
);
|
|
342
|
+
|
|
331
343
|
const Outlet = () => {
|
|
332
344
|
const { system, resources, url, pageMeta, host } =
|
|
333
345
|
useLoaderData<typeof loader>();
|
|
346
|
+
const sdkContext = useMemo(
|
|
347
|
+
() => ({
|
|
348
|
+
...constants,
|
|
349
|
+
resources,
|
|
350
|
+
breakpoints,
|
|
351
|
+
onError: console.error,
|
|
352
|
+
}),
|
|
353
|
+
[resources]
|
|
354
|
+
);
|
|
355
|
+
|
|
334
356
|
return (
|
|
335
|
-
<ReactSdkContext.Provider
|
|
336
|
-
|
|
337
|
-
...constants,
|
|
338
|
-
resources,
|
|
339
|
-
breakpoints,
|
|
340
|
-
onError: console.error,
|
|
341
|
-
}}
|
|
342
|
-
>
|
|
343
|
-
{/* Use the URL as the key to force scripts in HTML Embed to reload on dynamic pages */}
|
|
344
|
-
<Page key={url} system={system} />
|
|
357
|
+
<ReactSdkContext.Provider value={sdkContext}>
|
|
358
|
+
<PageBoundary url={url} system={system} />
|
|
345
359
|
<PageSettingsMeta
|
|
346
360
|
url={url}
|
|
347
361
|
pageMeta={pageMeta}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { redirect } from "@remix-run/server-runtime";
|
|
1
|
+
import { type LoaderFunctionArgs, redirect } from "@remix-run/server-runtime";
|
|
2
|
+
import { generateRedirectUrl } from "../redirect-url";
|
|
2
3
|
import { url, status } from "__REDIRECT__";
|
|
3
4
|
|
|
4
|
-
export const loader = () => {
|
|
5
|
-
return redirect(url, status);
|
|
5
|
+
export const loader = (arg: LoaderFunctionArgs) => {
|
|
6
|
+
return redirect(generateRedirectUrl(url, arg.params), status);
|
|
6
7
|
};
|
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
"@remix-run/node": "2.16.5",
|
|
12
12
|
"@remix-run/react": "2.16.5",
|
|
13
13
|
"@remix-run/server-runtime": "2.16.5",
|
|
14
|
-
"@webstudio-is/image": "0.
|
|
15
|
-
"@webstudio-is/react-sdk": "0.
|
|
16
|
-
"@webstudio-is/sdk": "0.
|
|
17
|
-
"@webstudio-is/sdk-components-react": "0.
|
|
18
|
-
"@webstudio-is/sdk-components-animation": "0.
|
|
19
|
-
"@webstudio-is/sdk-components-react-radix": "0.
|
|
20
|
-
"@webstudio-is/sdk-components-react-remix": "0.
|
|
21
|
-
"@webstudio-is/wsauth": "0.
|
|
14
|
+
"@webstudio-is/image": "0.269.0",
|
|
15
|
+
"@webstudio-is/react-sdk": "0.269.0",
|
|
16
|
+
"@webstudio-is/sdk": "0.269.0",
|
|
17
|
+
"@webstudio-is/sdk-components-react": "0.269.0",
|
|
18
|
+
"@webstudio-is/sdk-components-animation": "0.269.0",
|
|
19
|
+
"@webstudio-is/sdk-components-react-radix": "0.269.0",
|
|
20
|
+
"@webstudio-is/sdk-components-react-remix": "0.269.0",
|
|
21
|
+
"@webstudio-is/wsauth": "0.269.0",
|
|
22
22
|
"isbot": "^5.1.25",
|
|
23
23
|
"react": "18.3.0-canary-14898b6a9-20240318",
|
|
24
24
|
"react-dom": "18.3.0-canary-14898b6a9-20240318"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createPath, generatePath, parsePath } from "react-router";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Expands route params in local redirect targets.
|
|
5
|
+
* External and protocol-relative URLs are returned unchanged because route params
|
|
6
|
+
* only apply to app paths.
|
|
7
|
+
*/
|
|
8
|
+
export const generateRedirectUrl = (
|
|
9
|
+
url: string,
|
|
10
|
+
params: Record<string, string | undefined>
|
|
11
|
+
) => {
|
|
12
|
+
if (url.startsWith("/") === false || url.startsWith("//")) {
|
|
13
|
+
return url;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const path = parsePath(url);
|
|
17
|
+
return createPath({
|
|
18
|
+
...path,
|
|
19
|
+
pathname: generatePath(path.pathname ?? "/", params),
|
|
20
|
+
});
|
|
21
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ComponentProps, memo, useMemo } from "react";
|
|
1
2
|
import {
|
|
2
3
|
type MetaFunction,
|
|
3
4
|
type LinksFunction,
|
|
@@ -327,20 +328,33 @@ export const action = async ({
|
|
|
327
328
|
}
|
|
328
329
|
};
|
|
329
330
|
|
|
331
|
+
const PageBoundary = memo(
|
|
332
|
+
({ url, system }: ComponentProps<typeof Page> & { url: string }) => {
|
|
333
|
+
// Use the URL as the key to force scripts in HTML Embed to reload on dynamic pages
|
|
334
|
+
return <Page key={url} system={system} />;
|
|
335
|
+
},
|
|
336
|
+
// React Router can rerender the current route while the next route loaders are
|
|
337
|
+
// still pending. Keep the generated page out of that pending-navigation render
|
|
338
|
+
// path, but let URL changes remount it.
|
|
339
|
+
(prevProps, nextProps) => prevProps.url === nextProps.url
|
|
340
|
+
);
|
|
341
|
+
|
|
330
342
|
const Outlet = () => {
|
|
331
343
|
const { system, resources, url, pageMeta, host } =
|
|
332
344
|
useLoaderData<typeof loader>();
|
|
345
|
+
const sdkContext = useMemo(
|
|
346
|
+
() => ({
|
|
347
|
+
...constants,
|
|
348
|
+
resources,
|
|
349
|
+
breakpoints,
|
|
350
|
+
onError: console.error,
|
|
351
|
+
}),
|
|
352
|
+
[resources]
|
|
353
|
+
);
|
|
354
|
+
|
|
333
355
|
return (
|
|
334
|
-
<ReactSdkContext.Provider
|
|
335
|
-
|
|
336
|
-
...constants,
|
|
337
|
-
resources,
|
|
338
|
-
breakpoints,
|
|
339
|
-
onError: console.error,
|
|
340
|
-
}}
|
|
341
|
-
>
|
|
342
|
-
{/* Use the URL as the key to force scripts in HTML Embed to reload on dynamic pages */}
|
|
343
|
-
<Page key={url} system={system} />
|
|
356
|
+
<ReactSdkContext.Provider value={sdkContext}>
|
|
357
|
+
<PageBoundary url={url} system={system} />
|
|
344
358
|
<PageSettingsMeta
|
|
345
359
|
url={url}
|
|
346
360
|
pageMeta={pageMeta}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { redirect } from "react-router";
|
|
1
|
+
import { type LoaderFunctionArgs, redirect } from "react-router";
|
|
2
|
+
import { generateRedirectUrl } from "../redirect-url";
|
|
2
3
|
import { url, status } from "__REDIRECT__";
|
|
3
4
|
|
|
4
|
-
export const loader = () => {
|
|
5
|
-
throw redirect(url, status);
|
|
5
|
+
export const loader = (arg: LoaderFunctionArgs) => {
|
|
6
|
+
throw redirect(generateRedirectUrl(url, arg.params), status);
|
|
6
7
|
};
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@react-router/dev": "^7.5.3",
|
|
12
12
|
"@react-router/fs-routes": "^7.5.3",
|
|
13
|
-
"@webstudio-is/image": "0.
|
|
14
|
-
"@webstudio-is/react-sdk": "0.
|
|
15
|
-
"@webstudio-is/sdk": "0.
|
|
16
|
-
"@webstudio-is/sdk-components-animation": "0.
|
|
17
|
-
"@webstudio-is/sdk-components-react-radix": "0.
|
|
18
|
-
"@webstudio-is/sdk-components-react-router": "0.
|
|
19
|
-
"@webstudio-is/sdk-components-react": "0.
|
|
20
|
-
"@webstudio-is/wsauth": "0.
|
|
13
|
+
"@webstudio-is/image": "0.269.0",
|
|
14
|
+
"@webstudio-is/react-sdk": "0.269.0",
|
|
15
|
+
"@webstudio-is/sdk": "0.269.0",
|
|
16
|
+
"@webstudio-is/sdk-components-animation": "0.269.0",
|
|
17
|
+
"@webstudio-is/sdk-components-react-radix": "0.269.0",
|
|
18
|
+
"@webstudio-is/sdk-components-react-router": "0.269.0",
|
|
19
|
+
"@webstudio-is/sdk-components-react": "0.269.0",
|
|
20
|
+
"@webstudio-is/wsauth": "0.269.0",
|
|
21
21
|
"isbot": "^5.1.25",
|
|
22
22
|
"react": "18.3.0-canary-14898b6a9-20240318",
|
|
23
23
|
"react-dom": "18.3.0-canary-14898b6a9-20240318",
|
|
@@ -1,26 +1,49 @@
|
|
|
1
|
+
import { type ComponentProps, memo, useMemo } from "react";
|
|
1
2
|
import type { PageContext } from "vike/types";
|
|
2
3
|
import {
|
|
3
4
|
PageSettingsMeta,
|
|
4
5
|
PageSettingsTitle,
|
|
5
6
|
ReactSdkContext,
|
|
6
7
|
} from "@webstudio-is/react-sdk/runtime";
|
|
8
|
+
import { LinkCurrentUrlContext } from "@webstudio-is/sdk-components-react";
|
|
7
9
|
import { assetBaseUrl, imageLoader } from "__CONSTANTS__";
|
|
8
10
|
import { Page, breakpoints, siteName } from "__CLIENT__";
|
|
9
11
|
|
|
12
|
+
const getPageKey = (url: string) => {
|
|
13
|
+
const { origin, pathname, search } = new URL(url);
|
|
14
|
+
return `${origin}${pathname}${search}`;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const PageBoundary = memo(
|
|
18
|
+
({ pageKey, system }: ComponentProps<typeof Page> & { pageKey: string }) => {
|
|
19
|
+
// Use the URL as the key to force scripts in HTML Embed to reload on dynamic pages
|
|
20
|
+
return <Page key={pageKey} system={system} />;
|
|
21
|
+
},
|
|
22
|
+
// Vike can rerender the current page during client-side navigation and
|
|
23
|
+
// hash-only URL updates. Keep the generated page out of that render path,
|
|
24
|
+
// but let actual page URL changes remount it.
|
|
25
|
+
(prevProps, nextProps) => prevProps.pageKey === nextProps.pageKey
|
|
26
|
+
);
|
|
27
|
+
|
|
10
28
|
const PageComponent = ({ data }: { data: PageContext["data"] }) => {
|
|
11
29
|
const { system, resources, url, pageMeta } = data;
|
|
30
|
+
const pageKey = getPageKey(url);
|
|
31
|
+
const sdkContext = useMemo(
|
|
32
|
+
() => ({
|
|
33
|
+
imageLoader,
|
|
34
|
+
assetBaseUrl,
|
|
35
|
+
resources,
|
|
36
|
+
breakpoints,
|
|
37
|
+
onError: console.error,
|
|
38
|
+
}),
|
|
39
|
+
[resources]
|
|
40
|
+
);
|
|
41
|
+
|
|
12
42
|
return (
|
|
13
|
-
<ReactSdkContext.Provider
|
|
14
|
-
value={
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
resources,
|
|
18
|
-
breakpoints,
|
|
19
|
-
onError: console.error,
|
|
20
|
-
}}
|
|
21
|
-
>
|
|
22
|
-
{/* Use the URL as the key to force scripts in HTML Embed to reload on dynamic pages */}
|
|
23
|
-
<Page key={url} system={system} />
|
|
43
|
+
<ReactSdkContext.Provider value={sdkContext}>
|
|
44
|
+
<LinkCurrentUrlContext.Provider value={url}>
|
|
45
|
+
<PageBoundary pageKey={pageKey} system={system} />
|
|
46
|
+
</LinkCurrentUrlContext.Provider>
|
|
24
47
|
<PageSettingsMeta
|
|
25
48
|
url={url}
|
|
26
49
|
pageMeta={pageMeta}
|
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
"typecheck": "tsgo --noEmit"
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@webstudio-is/image": "0.
|
|
12
|
-
"@webstudio-is/react-sdk": "0.
|
|
13
|
-
"@webstudio-is/sdk": "0.
|
|
14
|
-
"@webstudio-is/sdk-components-react": "0.
|
|
15
|
-
"@webstudio-is/sdk-components-animation": "0.
|
|
16
|
-
"@webstudio-is/sdk-components-react-radix": "0.
|
|
11
|
+
"@webstudio-is/image": "0.269.0",
|
|
12
|
+
"@webstudio-is/react-sdk": "0.269.0",
|
|
13
|
+
"@webstudio-is/sdk": "0.269.0",
|
|
14
|
+
"@webstudio-is/sdk-components-react": "0.269.0",
|
|
15
|
+
"@webstudio-is/sdk-components-animation": "0.269.0",
|
|
16
|
+
"@webstudio-is/sdk-components-react-radix": "0.269.0",
|
|
17
17
|
"react": "18.3.0-canary-14898b6a9-20240318",
|
|
18
18
|
"react-dom": "18.3.0-canary-14898b6a9-20240318",
|
|
19
19
|
"vike": "^0.4.229"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Root,
|
|
1
|
+
import { type Root, hydrateRoot } from "react-dom/client";
|
|
2
2
|
import type { OnRenderClientSync } from "vike/types";
|
|
3
3
|
|
|
4
4
|
let root: Root;
|
|
@@ -19,7 +19,8 @@ export const onRenderClient: OnRenderClientSync = (pageContext) => {
|
|
|
19
19
|
</>
|
|
20
20
|
);
|
|
21
21
|
if (root === undefined) {
|
|
22
|
-
root =
|
|
22
|
+
root = hydrateRoot(document.documentElement, htmlContent);
|
|
23
|
+
return;
|
|
23
24
|
}
|
|
24
25
|
document.documentElement.lang = lang;
|
|
25
26
|
root.render(htmlContent);
|
|
Binary file
|