@popcraft/cli 0.13.2 → 0.15.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/dist/popcraft.mjs +1170 -238
- package/package.json +2 -2
package/dist/popcraft.mjs
CHANGED
|
@@ -32,9 +32,9 @@ var __commonJS = (cb, mod) => function __require2() {
|
|
|
32
32
|
throw mod = 0, e;
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
|
-
var __export = (target2,
|
|
36
|
-
for (var name2 in
|
|
37
|
-
__defProp(target2, name2, { get:
|
|
35
|
+
var __export = (target2, all4) => {
|
|
36
|
+
for (var name2 in all4)
|
|
37
|
+
__defProp(target2, name2, { get: all4[name2], enumerable: true });
|
|
38
38
|
};
|
|
39
39
|
var __copyProps = (to, from2, except, desc2) => {
|
|
40
40
|
if (from2 && typeof from2 === "object" || typeof from2 === "function") {
|
|
@@ -456,9 +456,9 @@ var init_groups = __esm({
|
|
|
456
456
|
label: "Web",
|
|
457
457
|
hint: "Pages and sections at every breakpoint",
|
|
458
458
|
home: ["WEB", "KIT"],
|
|
459
|
-
types: [t("web", "Pages", "WEB"), t("components", "Components", "WEB")],
|
|
459
|
+
types: [t("web", "Pages", "WEB"), t("storefront", "Storefronts", "WEB"), t("components", "Components", "WEB")],
|
|
460
460
|
presets: ids((p2) => p2.category === "WEB" && !p2.id.startsWith("lottie-")),
|
|
461
|
-
keywords: ["website", "landing", "site", "ui kit"]
|
|
461
|
+
keywords: ["website", "landing", "site", "ui kit", "ecommerce", "shop", "store"]
|
|
462
462
|
},
|
|
463
463
|
{
|
|
464
464
|
id: "app",
|
|
@@ -1186,7 +1186,7 @@ function operations(spec = openapi) {
|
|
|
1186
1186
|
}
|
|
1187
1187
|
async function call(target2, method, path, opts = {}) {
|
|
1188
1188
|
const qs = new URLSearchParams(opts.query ?? {}).toString();
|
|
1189
|
-
const headers = { "user-agent": `popcraft-cli/${"0.
|
|
1189
|
+
const headers = { "user-agent": `popcraft-cli/${"0.15.0"}`, ...opts.headers };
|
|
1190
1190
|
if (target2.token) headers.authorization = `Bearer ${target2.token}`;
|
|
1191
1191
|
if (opts.contentType) headers["content-type"] = opts.contentType;
|
|
1192
1192
|
try {
|
|
@@ -1460,10 +1460,10 @@ function forgetToken(url4) {
|
|
|
1460
1460
|
} catch {
|
|
1461
1461
|
return false;
|
|
1462
1462
|
}
|
|
1463
|
-
const
|
|
1464
|
-
if (!(url4 in
|
|
1465
|
-
delete
|
|
1466
|
-
if (Object.keys(
|
|
1463
|
+
const all4 = readCredentials();
|
|
1464
|
+
if (!(url4 in all4)) return false;
|
|
1465
|
+
delete all4[url4];
|
|
1466
|
+
if (Object.keys(all4).length) writeCredentials(all4);
|
|
1467
1467
|
else rmSync(credentialsPath(), { force: true });
|
|
1468
1468
|
return true;
|
|
1469
1469
|
}
|
|
@@ -5928,7 +5928,7 @@ var init_types = __esm({
|
|
|
5928
5928
|
"lib/document/types.ts"() {
|
|
5929
5929
|
"use strict";
|
|
5930
5930
|
CONTROL_KINDS = ["FORM", "INPUT", "TEXTAREA", "SELECT", "CHECKBOX", "RADIO", "BUTTON"];
|
|
5931
|
-
INPUT_TYPES = ["text", "email", "number", "tel", "url", "search", "date", "password"];
|
|
5931
|
+
INPUT_TYPES = ["text", "email", "number", "tel", "url", "search", "date", "password", "hidden"];
|
|
5932
5932
|
FIELD_TYPES = ["TEXT", "RICH_TEXT", "NUMBER", "BOOLEAN", "DATE", "COLOR", "MEDIA", "URL", "SLUG", "OPTION"];
|
|
5933
5933
|
SEMANTIC_TAGS = ["div", "section", "header", "footer", "nav", "main", "aside", "article", "ul", "ol", "li", "h1", "h2", "h3", "h4", "h5", "h6", "p", "span", "button", "figure", "label"];
|
|
5934
5934
|
INTERACTION_TRIGGERS = ["ON_CLICK", "ON_HOVER", "ON_PRESS", "ON_DRAG", "MOUSE_ENTER", "MOUSE_LEAVE", "AFTER_TIMEOUT", "KEY_DOWN", "ON_SCROLL"];
|
|
@@ -29073,10 +29073,10 @@ function paramsFromFlags(spec, flags) {
|
|
|
29073
29073
|
if (!RESERVED.has(name2)) unknown2.push(name2);
|
|
29074
29074
|
continue;
|
|
29075
29075
|
}
|
|
29076
|
-
const
|
|
29077
|
-
const last3 =
|
|
29076
|
+
const all4 = Array.isArray(value3) ? value3 : [value3];
|
|
29077
|
+
const last3 = all4[all4.length - 1];
|
|
29078
29078
|
if (f2.type === "array") {
|
|
29079
|
-
const list2 =
|
|
29079
|
+
const list2 = all4.flatMap((v) => {
|
|
29080
29080
|
if (typeof v === "string" && v.trim().startsWith("[")) {
|
|
29081
29081
|
try {
|
|
29082
29082
|
return JSON.parse(v);
|
|
@@ -29504,8 +29504,8 @@ function parseNumberSkeleton(tokens) {
|
|
|
29504
29504
|
result = {
|
|
29505
29505
|
...result,
|
|
29506
29506
|
notation: "scientific",
|
|
29507
|
-
...token.options.reduce((
|
|
29508
|
-
...
|
|
29507
|
+
...token.options.reduce((all4, opt) => ({
|
|
29508
|
+
...all4,
|
|
29509
29509
|
...parseNotationOptions(opt)
|
|
29510
29510
|
}), {})
|
|
29511
29511
|
};
|
|
@@ -29514,8 +29514,8 @@ function parseNumberSkeleton(tokens) {
|
|
|
29514
29514
|
result = {
|
|
29515
29515
|
...result,
|
|
29516
29516
|
notation: "engineering",
|
|
29517
|
-
...token.options.reduce((
|
|
29518
|
-
...
|
|
29517
|
+
...token.options.reduce((all4, opt) => ({
|
|
29518
|
+
...all4,
|
|
29519
29519
|
...parseNotationOptions(opt)
|
|
29520
29520
|
}), {})
|
|
29521
29521
|
};
|
|
@@ -31663,11 +31663,11 @@ var init_icu_messageformat_parser = __esm({
|
|
|
31663
31663
|
// node_modules/.pnpm/intl-messageformat@12.1.2/node_modules/intl-messageformat/index.js
|
|
31664
31664
|
function mergeLiteral(parts) {
|
|
31665
31665
|
if (parts.length < 2) return parts;
|
|
31666
|
-
return parts.reduce((
|
|
31667
|
-
const lastPart =
|
|
31668
|
-
if (!lastPart || lastPart.type !== 0 || part.type !== 0)
|
|
31666
|
+
return parts.reduce((all4, part) => {
|
|
31667
|
+
const lastPart = all4[all4.length - 1];
|
|
31668
|
+
if (!lastPart || lastPart.type !== 0 || part.type !== 0) all4.push(part);
|
|
31669
31669
|
else lastPart.value += part.value;
|
|
31670
|
-
return
|
|
31670
|
+
return all4;
|
|
31671
31671
|
}, []);
|
|
31672
31672
|
}
|
|
31673
31673
|
function isFormatXMLElementFn(el) {
|
|
@@ -31780,20 +31780,20 @@ function mergeConfig(c1, c2) {
|
|
|
31780
31780
|
return {
|
|
31781
31781
|
...c1,
|
|
31782
31782
|
...c2,
|
|
31783
|
-
...Object.keys(c1).reduce((
|
|
31784
|
-
|
|
31783
|
+
...Object.keys(c1).reduce((all4, k2) => {
|
|
31784
|
+
all4[k2] = {
|
|
31785
31785
|
...c1[k2],
|
|
31786
31786
|
...c2[k2]
|
|
31787
31787
|
};
|
|
31788
|
-
return
|
|
31788
|
+
return all4;
|
|
31789
31789
|
}, {})
|
|
31790
31790
|
};
|
|
31791
31791
|
}
|
|
31792
31792
|
function mergeConfigs(defaultConfig, configs) {
|
|
31793
31793
|
if (!configs) return defaultConfig;
|
|
31794
|
-
return Object.keys(defaultConfig).reduce((
|
|
31795
|
-
|
|
31796
|
-
return
|
|
31794
|
+
return Object.keys(defaultConfig).reduce((all4, k2) => {
|
|
31795
|
+
all4[k2] = mergeConfig(defaultConfig[k2], configs[k2]);
|
|
31796
|
+
return all4;
|
|
31797
31797
|
}, { ...defaultConfig });
|
|
31798
31798
|
}
|
|
31799
31799
|
function createFastMemoizeCache(store6) {
|
|
@@ -31868,10 +31868,10 @@ var init_intl_messageformat = __esm({
|
|
|
31868
31868
|
this.format = ((values3) => {
|
|
31869
31869
|
const parts = this.formatToParts(values3);
|
|
31870
31870
|
if (parts.length === 1) return parts[0].value;
|
|
31871
|
-
const result = parts.reduce((
|
|
31872
|
-
if (!
|
|
31873
|
-
else
|
|
31874
|
-
return
|
|
31871
|
+
const result = parts.reduce((all4, part) => {
|
|
31872
|
+
if (!all4.length || part.type !== 0 || typeof all4[all4.length - 1] !== "string") all4.push(part.value);
|
|
31873
|
+
else all4[all4.length - 1] += part.value;
|
|
31874
|
+
return all4;
|
|
31875
31875
|
}, []);
|
|
31876
31876
|
if (result.length <= 1) return result[0] || "";
|
|
31877
31877
|
return result;
|
|
@@ -32502,6 +32502,7 @@ var init_en2 = __esm({
|
|
|
32502
32502
|
"collections.no": "No",
|
|
32503
32503
|
"collections.noRecords": "No records yet. Add one, or import a CSV.",
|
|
32504
32504
|
"collections.noRepeat": "Does not repeat",
|
|
32505
|
+
"collections.offset": "Skip first",
|
|
32505
32506
|
"collections.onePage": "One page",
|
|
32506
32507
|
"collections.open": "{count, plural, =0 {Collections} one {Collections (#)} other {Collections (#)}}",
|
|
32507
32508
|
"collections.ownOrder": "In the collection\u2019s order",
|
|
@@ -32510,10 +32511,18 @@ var init_en2 = __esm({
|
|
|
32510
32511
|
"collections.perVisitorHint": "On the published site, a signed-in visitor sees and adds only their own records, kept in the site's database. The records here are samples the design is drawn with.",
|
|
32511
32512
|
"collections.repeat": "Repeat its content for",
|
|
32512
32513
|
"collections.repeatHint": "{count, plural, one {Shows # record on the page. The canvas shows the first.} other {Shows # records on the page. The canvas shows the first.}}",
|
|
32514
|
+
"collections.schema.commerce.cart": "The cart's totals",
|
|
32515
|
+
"collections.schema.commerce.cartLine": "The cart's lines",
|
|
32516
|
+
"collections.schema.commerce.collection": "Store categories",
|
|
32517
|
+
"collections.schema.commerce.menu": "The store's menu",
|
|
32518
|
+
"collections.schema.commerce.product": "Store products",
|
|
32513
32519
|
"collections.shared": "They all see each other's",
|
|
32514
32520
|
"collections.sharedHint": "Every signed-in visitor sees everyone's records, each with who added it. A visitor changes and deletes only their own.",
|
|
32515
32521
|
"collections.sortBy": "Sort by",
|
|
32516
32522
|
"collections.sortedBy": "Sorted by {name}",
|
|
32523
|
+
"collections.standsFor": "Stands for",
|
|
32524
|
+
"collections.standsForHint": "What the records are in a storefront: its fields become the store's, and exported as storefront components a list of it is a prop the store fills",
|
|
32525
|
+
"collections.standsForNothing": "Records of your own",
|
|
32517
32526
|
"collections.title": "Collections",
|
|
32518
32527
|
"collections.tokenHint": "Type this in a text to say the field",
|
|
32519
32528
|
"collections.yes": "Yes",
|
|
@@ -32542,12 +32551,16 @@ var init_en2 = __esm({
|
|
|
32542
32551
|
"command:export.pdf": "Export as PDF",
|
|
32543
32552
|
"command:export.pngSequence": "Export animation as PNG sequence",
|
|
32544
32553
|
"command:export.pptx": "Export as PowerPoint (.pptx)",
|
|
32554
|
+
"command:export.storefront": "Export storefront\u2026",
|
|
32555
|
+
"command:export.storefront#next-commerce": "Export storefront as Next.js Commerce components",
|
|
32556
|
+
"command:export.storefront#shopify-theme": "Export storefront as a Shopify theme",
|
|
32545
32557
|
"command:export.web": "Export as web code\u2026",
|
|
32546
32558
|
"command:export.webm": "Export animation as WebM",
|
|
32547
32559
|
"command:file.duplicate": "Duplicate file",
|
|
32548
32560
|
"command:generate.video": "Generate video",
|
|
32549
32561
|
"command:history.redo": "Redo",
|
|
32550
32562
|
"command:history.undo": "Undo",
|
|
32563
|
+
"command:integration.pullProducts": "Draw with my store's products",
|
|
32551
32564
|
"command:media.download": "Download",
|
|
32552
32565
|
"command:motion.addAudio": "Add audio",
|
|
32553
32566
|
"command:motion.applyPreset": "Animate",
|
|
@@ -32898,17 +32911,23 @@ var init_en2 = __esm({
|
|
|
32898
32911
|
"controlFields.required": "Required",
|
|
32899
32912
|
"controlFields.reset": "Clears the form",
|
|
32900
32913
|
"controlFields.sending": "Sending it",
|
|
32914
|
+
"controlFields.sendingAddToCart": "Adds the product to the cart",
|
|
32901
32915
|
"controlFields.sendingChangePassword": "Changes the visitor's password",
|
|
32916
|
+
"controlFields.sendingCheckout": "Goes to checkout",
|
|
32902
32917
|
"controlFields.sendingDelete": "Deletes its record",
|
|
32903
32918
|
"controlFields.sendingDeleteAccount": "Deletes the visitor's account",
|
|
32904
32919
|
"controlFields.sendingForgotPassword": "Emails a password reset link",
|
|
32920
|
+
"controlFields.sendingRemoveCartLine": "Removes a line from the cart",
|
|
32905
32921
|
"controlFields.sendingResetPassword": "Sets a new password from a reset link",
|
|
32906
32922
|
"controlFields.sendingSaves": "Saves what was entered",
|
|
32923
|
+
"controlFields.sendingSearch": "Searches the store",
|
|
32907
32924
|
"controlFields.sendingSignIn": "Signs the visitor in",
|
|
32908
32925
|
"controlFields.sendingSignOut": "Signs the visitor out",
|
|
32909
32926
|
"controlFields.sendingSignUp": "Creates an account",
|
|
32927
|
+
"controlFields.sendingStore": "Storefront",
|
|
32910
32928
|
"controlFields.sendingUpdate": "Changes its record",
|
|
32911
32929
|
"controlFields.sendingUpdateAccount": "Changes the visitor's name",
|
|
32930
|
+
"controlFields.sendingUpdateCartLine": "Changes a cart line's quantity",
|
|
32912
32931
|
"controlFields.stayHere": "Stay on the page",
|
|
32913
32932
|
"controlFields.submit": "Sends the form",
|
|
32914
32933
|
"controlFields.turnOn": "Turn on {name}",
|
|
@@ -33789,6 +33808,7 @@ var init_en2 = __esm({
|
|
|
33789
33808
|
"integrationsDialog.adminsOnly": "Only owners and admins of this team connect and disconnect accounts.",
|
|
33790
33809
|
"integrationsDialog.cancel": "Cancel",
|
|
33791
33810
|
"integrationsDialog.capabilityAuth": "Sign-in",
|
|
33811
|
+
"integrationsDialog.capabilityCommerce": "Store",
|
|
33792
33812
|
"integrationsDialog.capabilityDatabase": "Database",
|
|
33793
33813
|
"integrationsDialog.capabilityDeploy": "Hosting",
|
|
33794
33814
|
"integrationsDialog.capabilityRepo": "Code",
|
|
@@ -35680,6 +35700,7 @@ var init_en2 = __esm({
|
|
|
35680
35700
|
"taskCluster.starting": "starting\u2026",
|
|
35681
35701
|
"taskCluster.subagent": "subagent",
|
|
35682
35702
|
"templateGallery.animated": "Animated",
|
|
35703
|
+
"templateGallery.exportsAsStorefront": "Exports as a storefront: {store}",
|
|
35683
35704
|
"templateGallery.featured": "Featured",
|
|
35684
35705
|
"templateGallery.featuredTitle": "Featured by PopCraft: shown first",
|
|
35685
35706
|
"templateGallery.lottie": "Lottie",
|
|
@@ -35738,6 +35759,7 @@ var init_en2 = __esm({
|
|
|
35738
35759
|
"templateType:resume": "Resume",
|
|
35739
35760
|
"templateType:social": "Social",
|
|
35740
35761
|
"templateType:sticker": "Sticker",
|
|
35762
|
+
"templateType:storefront": "Storefronts",
|
|
35741
35763
|
"templateType:text-gif": "Text GIF",
|
|
35742
35764
|
"templateType:web": "Pages",
|
|
35743
35765
|
"textAnimatorPanel.afterTheFigureK": "After the figure (%, k, +\u2026)",
|
|
@@ -92127,6 +92149,39 @@ var init_editability = __esm({
|
|
|
92127
92149
|
}
|
|
92128
92150
|
});
|
|
92129
92151
|
|
|
92152
|
+
// lib/server/media-types.ts
|
|
92153
|
+
function sniffMime(bytes2, fallback2) {
|
|
92154
|
+
if (bytes2[0] === 137 && bytes2[1] === 80) return "image/png";
|
|
92155
|
+
if (bytes2[0] === 255 && bytes2[1] === 216) return "image/jpeg";
|
|
92156
|
+
if (ascii(bytes2, 0, "RIFF") && ascii(bytes2, 8, "WAVE")) return "audio/wav";
|
|
92157
|
+
if (bytes2[0] === 82 && bytes2[1] === 73 && bytes2[8] === 87) return "image/webp";
|
|
92158
|
+
if (ascii(bytes2, 0, "GIF8")) return "image/gif";
|
|
92159
|
+
if (ascii(bytes2, 4, "ftyp")) {
|
|
92160
|
+
const brand = String.fromCharCode(...bytes2.subarray(8, 12));
|
|
92161
|
+
if (brand === "avif" || brand === "avis") return "image/avif";
|
|
92162
|
+
if (brand === "qt ") return "video/quicktime";
|
|
92163
|
+
return "video/mp4";
|
|
92164
|
+
}
|
|
92165
|
+
if (bytes2[0] === 26 && bytes2[1] === 69 && bytes2[2] === 223 && bytes2[3] === 163) return "video/webm";
|
|
92166
|
+
if (ascii(bytes2, 0, "OggS")) return "audio/ogg";
|
|
92167
|
+
if (ascii(bytes2, 0, "ID3") || bytes2[0] === 255 && (bytes2[1] & 230) === 226) return "audio/mpeg";
|
|
92168
|
+
const head2 = new TextDecoder().decode(bytes2.slice(0, 512)).trimStart().toLowerCase();
|
|
92169
|
+
if (head2.startsWith("<svg") || head2.startsWith("<?xml") && head2.includes("<svg")) return "image/svg+xml";
|
|
92170
|
+
return fallback2;
|
|
92171
|
+
}
|
|
92172
|
+
var MAX_MEDIA_BYTES, ascii;
|
|
92173
|
+
var init_media_types = __esm({
|
|
92174
|
+
"lib/server/media-types.ts"() {
|
|
92175
|
+
"use strict";
|
|
92176
|
+
MAX_MEDIA_BYTES = 100 * 1024 * 1024;
|
|
92177
|
+
ascii = (bytes2, at3, s) => {
|
|
92178
|
+
if (bytes2.length < at3 + s.length) return false;
|
|
92179
|
+
for (let i2 = 0; i2 < s.length; i2++) if (bytes2[at3 + i2] !== s.charCodeAt(i2)) return false;
|
|
92180
|
+
return true;
|
|
92181
|
+
};
|
|
92182
|
+
}
|
|
92183
|
+
});
|
|
92184
|
+
|
|
92130
92185
|
// packages/cli/src/shims/idb-keyval.ts
|
|
92131
92186
|
import { mkdirSync as mkdirSync2, readFileSync as readFileSync5, readdirSync, rmSync as rmSync2, writeFileSync as writeFileSync2, existsSync as existsSync3 } from "node:fs";
|
|
92132
92187
|
import { join as join2 } from "node:path";
|
|
@@ -92565,7 +92620,8 @@ async function mediaToDataUrl(ref3) {
|
|
|
92565
92620
|
const bytes2 = new Uint8Array(await blob.arrayBuffer());
|
|
92566
92621
|
let bin = "";
|
|
92567
92622
|
for (let i2 = 0; i2 < bytes2.length; i2 += 32768) bin += String.fromCharCode(...bytes2.subarray(i2, i2 + 32768));
|
|
92568
|
-
|
|
92623
|
+
const type = blob.type && blob.type !== "application/octet-stream" ? blob.type : sniffMime(bytes2, "application/octet-stream");
|
|
92624
|
+
return `data:${type};base64,${btoa(bin)}`;
|
|
92569
92625
|
}
|
|
92570
92626
|
function mapNodeImageUrls(node2, fn) {
|
|
92571
92627
|
let out = null;
|
|
@@ -92688,6 +92744,7 @@ var key2, peaksKey, objectUrls, sourceKey, remoteResolver, MEDIA_FETCH_TIMEOUT_M
|
|
|
92688
92744
|
var init_media_store = __esm({
|
|
92689
92745
|
"lib/storage/media-store.ts"() {
|
|
92690
92746
|
"use strict";
|
|
92747
|
+
init_media_types();
|
|
92691
92748
|
init_idb();
|
|
92692
92749
|
init_media_hash();
|
|
92693
92750
|
init_types2();
|
|
@@ -96009,8 +96066,8 @@ function setOnsetMarkers(comp, times2) {
|
|
|
96009
96066
|
return bare;
|
|
96010
96067
|
}
|
|
96011
96068
|
function cutToBeat(comp, opts = {}) {
|
|
96012
|
-
const
|
|
96013
|
-
const beats = onsetTimes(comp).filter((_, k2) => k2 %
|
|
96069
|
+
const every3 = Math.max(1, Math.round(opts.every ?? 1)), minScene = Math.max(1, opts.minScene ?? 250);
|
|
96070
|
+
const beats = onsetTimes(comp).filter((_, k2) => k2 % every3 === 0);
|
|
96014
96071
|
const cuts = [];
|
|
96015
96072
|
let out = comp, last3 = -Infinity;
|
|
96016
96073
|
for (let i2 = 0; i2 + 1 < out.clips.length; i2++) {
|
|
@@ -97170,9 +97227,9 @@ function applyActions(sm, values3, actions) {
|
|
|
97170
97227
|
return { values: out, fired };
|
|
97171
97228
|
}
|
|
97172
97229
|
function nextTransition(sm, run4, fired) {
|
|
97173
|
-
const
|
|
97174
|
-
const own2 =
|
|
97175
|
-
const any4 =
|
|
97230
|
+
const all4 = sortedValues(sm.transitions);
|
|
97231
|
+
const own2 = all4.filter((t3) => t3.from === run4.state);
|
|
97232
|
+
const any4 = all4.filter((t3) => t3.from === ANY_STATE && t3.to !== run4.state);
|
|
97176
97233
|
for (const t3 of [...own2, ...any4]) {
|
|
97177
97234
|
if (!sm.states[t3.to]) continue;
|
|
97178
97235
|
if ((t3.guards ?? []).every((g) => guardHolds(sm, g, run4.values, fired))) return t3;
|
|
@@ -239981,8 +240038,8 @@ function googleCssUrl(family, italic, weight, withAxes = true, wghtRange = "100.
|
|
|
239981
240038
|
return `https://fonts.googleapis.com/css2?family=${fam}:${tags}@${tuple2}&display=swap`;
|
|
239982
240039
|
}
|
|
239983
240040
|
function pickWoff2FromCss(css, italic) {
|
|
239984
|
-
const blocks = css.split("@font-face").slice(1).map((b, i2,
|
|
239985
|
-
const prev = i2 === 0 ? css.split("@font-face")[0] :
|
|
240041
|
+
const blocks = css.split("@font-face").slice(1).map((b, i2, all4) => {
|
|
240042
|
+
const prev = i2 === 0 ? css.split("@font-face")[0] : all4[i2 - 1];
|
|
239986
240043
|
const subset = /\/\*\s*([\w-]+)\s*\*\/\s*$/.exec(prev)?.[1] ?? "";
|
|
239987
240044
|
return { body: b, subset };
|
|
239988
240045
|
});
|
|
@@ -248378,11 +248435,11 @@ function createPixelSlice(set4, get4) {
|
|
|
248378
248435
|
const n = l?.parentId ? node2(l.parentId) : null;
|
|
248379
248436
|
if (!l || !n) return;
|
|
248380
248437
|
const fid = n.frames[clampFrame(n, frameIndex)].id;
|
|
248381
|
-
const
|
|
248382
|
-
const ids2 = frameIdsOf(l) ??
|
|
248438
|
+
const all4 = n.frames.map((f2) => f2.id);
|
|
248439
|
+
const ids2 = frameIdsOf(l) ?? all4;
|
|
248383
248440
|
let next2 = ids2.includes(fid) ? ids2.filter((x2) => x2 !== fid) : [...ids2, fid];
|
|
248384
|
-
next2 =
|
|
248385
|
-
commitDoc(updateNode(doc2, layerId2, { pixelFrameIds: next2.length ===
|
|
248441
|
+
next2 = all4.filter((x2) => next2.includes(x2));
|
|
248442
|
+
commitDoc(updateNode(doc2, layerId2, { pixelFrameIds: next2.length === all4.length ? void 0 : next2 }), "Layer frames");
|
|
248386
248443
|
},
|
|
248387
248444
|
/** Show a layer in every frame. */
|
|
248388
248445
|
pixelShowLayerInAllFrames: (layerId2) => {
|
|
@@ -248444,9 +248501,9 @@ function createPixelSlice(set4, get4) {
|
|
|
248444
248501
|
const count2 = n.pixelWidth * n.pixelHeight;
|
|
248445
248502
|
let palette2 = n.palette;
|
|
248446
248503
|
if (mode === "INDEXED" && palette2.length < 2) {
|
|
248447
|
-
const
|
|
248448
|
-
n.frames.forEach((_, i2) =>
|
|
248449
|
-
palette2 = extractPalette(
|
|
248504
|
+
const all4 = new Uint32Array(count2 * n.frames.length);
|
|
248505
|
+
n.frames.forEach((_, i2) => all4.set(frameRGBA(n, i2), i2 * count2));
|
|
248506
|
+
palette2 = extractPalette(all4, 256).map(packedToHex);
|
|
248450
248507
|
}
|
|
248451
248508
|
const conv = (b64, cellCount) => encodeCels(convertCels(decodeCels(b64, cellCount), n.colorMode, mode, n.palette, palette2, n.transparentIndex));
|
|
248452
248509
|
const patch = { colorMode: mode, palette: palette2 };
|
|
@@ -250007,6 +250064,7 @@ __export(apply_exports2, {
|
|
|
250007
250064
|
insertFragment: () => insertFragment,
|
|
250008
250065
|
insertRootGroups: () => insertRootGroups,
|
|
250009
250066
|
insertRoots: () => insertRoots,
|
|
250067
|
+
ownBox: () => ownBox,
|
|
250010
250068
|
variantOf: () => variantOf
|
|
250011
250069
|
});
|
|
250012
250070
|
function freshIdMap(t3) {
|
|
@@ -250076,10 +250134,10 @@ function insertRoots(doc2, t3, rootIds, parentId, ox, oy) {
|
|
|
250076
250134
|
}
|
|
250077
250135
|
function insertRootGroups(doc2, t3, groups, parentId) {
|
|
250078
250136
|
const map2 = freshIdMap(t3);
|
|
250079
|
-
const
|
|
250080
|
-
let document2 = mergeLibraryNodes(mergeRecords(doc2, t3, map2, new Set(
|
|
250137
|
+
const all4 = groups.flatMap((g) => g.rootIds);
|
|
250138
|
+
let document2 = mergeLibraryNodes(mergeRecords(doc2, t3, map2, new Set(all4)), t3);
|
|
250081
250139
|
for (const g of groups) for (const rid of g.rootIds) document2 = addTree(document2, t3, map2, rid, parentId, g.ox, g.oy);
|
|
250082
|
-
return { document: document2, rootIds:
|
|
250140
|
+
return { document: document2, rootIds: all4.map((r) => map2.get(r)) };
|
|
250083
250141
|
}
|
|
250084
250142
|
function documentFromTemplate(t3, name2 = t3.meta.name, sizeId) {
|
|
250085
250143
|
const chosen = variantOf(t3, sizeId);
|
|
@@ -250111,7 +250169,7 @@ function documentFromTemplate(t3, name2 = t3.meta.name, sizeId) {
|
|
|
250111
250169
|
});
|
|
250112
250170
|
return document2;
|
|
250113
250171
|
}
|
|
250114
|
-
var variantOf;
|
|
250172
|
+
var variantOf, ownBox;
|
|
250115
250173
|
var init_apply2 = __esm({
|
|
250116
250174
|
"lib/templates/apply.ts"() {
|
|
250117
250175
|
"use strict";
|
|
@@ -250121,6 +250179,7 @@ var init_apply2 = __esm({
|
|
|
250121
250179
|
init_page_presets();
|
|
250122
250180
|
init_print_pages();
|
|
250123
250181
|
variantOf = (t3, sizeId) => sizeId && t3.payload.variants.find((v) => v.sizeId === sizeId) || t3.payload.variants[0];
|
|
250182
|
+
ownBox = (t3, root2) => t3.meta.kind === "PRESENTATION" || t3.meta.kind === "WEB" && root2.height > root2.width * 1.5;
|
|
250124
250183
|
}
|
|
250125
250184
|
});
|
|
250126
250185
|
|
|
@@ -251022,39 +251081,6 @@ var init_collapse_duplicates = __esm({
|
|
|
251022
251081
|
}
|
|
251023
251082
|
});
|
|
251024
251083
|
|
|
251025
|
-
// lib/server/media-types.ts
|
|
251026
|
-
function sniffMime(bytes2, fallback2) {
|
|
251027
|
-
if (bytes2[0] === 137 && bytes2[1] === 80) return "image/png";
|
|
251028
|
-
if (bytes2[0] === 255 && bytes2[1] === 216) return "image/jpeg";
|
|
251029
|
-
if (ascii(bytes2, 0, "RIFF") && ascii(bytes2, 8, "WAVE")) return "audio/wav";
|
|
251030
|
-
if (bytes2[0] === 82 && bytes2[1] === 73 && bytes2[8] === 87) return "image/webp";
|
|
251031
|
-
if (ascii(bytes2, 0, "GIF8")) return "image/gif";
|
|
251032
|
-
if (ascii(bytes2, 4, "ftyp")) {
|
|
251033
|
-
const brand = String.fromCharCode(...bytes2.subarray(8, 12));
|
|
251034
|
-
if (brand === "avif" || brand === "avis") return "image/avif";
|
|
251035
|
-
if (brand === "qt ") return "video/quicktime";
|
|
251036
|
-
return "video/mp4";
|
|
251037
|
-
}
|
|
251038
|
-
if (bytes2[0] === 26 && bytes2[1] === 69 && bytes2[2] === 223 && bytes2[3] === 163) return "video/webm";
|
|
251039
|
-
if (ascii(bytes2, 0, "OggS")) return "audio/ogg";
|
|
251040
|
-
if (ascii(bytes2, 0, "ID3") || bytes2[0] === 255 && (bytes2[1] & 230) === 226) return "audio/mpeg";
|
|
251041
|
-
const head2 = new TextDecoder().decode(bytes2.slice(0, 512)).trimStart().toLowerCase();
|
|
251042
|
-
if (head2.startsWith("<svg") || head2.startsWith("<?xml") && head2.includes("<svg")) return "image/svg+xml";
|
|
251043
|
-
return fallback2;
|
|
251044
|
-
}
|
|
251045
|
-
var MAX_MEDIA_BYTES, ascii;
|
|
251046
|
-
var init_media_types = __esm({
|
|
251047
|
-
"lib/server/media-types.ts"() {
|
|
251048
|
-
"use strict";
|
|
251049
|
-
MAX_MEDIA_BYTES = 100 * 1024 * 1024;
|
|
251050
|
-
ascii = (bytes2, at3, s) => {
|
|
251051
|
-
if (bytes2.length < at3 + s.length) return false;
|
|
251052
|
-
for (let i2 = 0; i2 < s.length; i2++) if (bytes2[at3 + i2] !== s.charCodeAt(i2)) return false;
|
|
251053
|
-
return true;
|
|
251054
|
-
};
|
|
251055
|
-
}
|
|
251056
|
-
});
|
|
251057
|
-
|
|
251058
251084
|
// lib/storage/document-library.ts
|
|
251059
251085
|
var document_library_exports = {};
|
|
251060
251086
|
__export(document_library_exports, {
|
|
@@ -251595,7 +251621,7 @@ function editCounter(node2, patch) {
|
|
|
251595
251621
|
let motion = node2.motion;
|
|
251596
251622
|
const track2 = motion?.tracks[COUNTER_PATH];
|
|
251597
251623
|
if (track2?.keys.length && (patch.from !== void 0 || patch.to !== void 0)) {
|
|
251598
|
-
const keys4 = track2.keys.map((k2, i2,
|
|
251624
|
+
const keys4 = track2.keys.map((k2, i2, all4) => i2 === 0 && patch.from !== void 0 ? { ...k2, v: next2.from } : i2 === all4.length - 1 && patch.to !== void 0 ? { ...k2, v: next2.to } : k2);
|
|
251599
251625
|
motion = withTrack(motion, COUNTER_PATH, { ...track2, keys: keys4 });
|
|
251600
251626
|
}
|
|
251601
251627
|
return { ...withCounter(node2, next2), motion };
|
|
@@ -254192,10 +254218,12 @@ function createMotionSlice(set4, get4) {
|
|
|
254192
254218
|
transport: DEFAULT_TRANSPORT,
|
|
254193
254219
|
motionGesture: null,
|
|
254194
254220
|
keySelection: [],
|
|
254195
|
-
setMotionTarget: (target2) => {
|
|
254221
|
+
setMotionTarget: (target2, at3 = "start") => {
|
|
254196
254222
|
const tr = get4().transport;
|
|
254197
254223
|
if (sameTarget(tr.target, target2)) return;
|
|
254198
|
-
|
|
254224
|
+
const fid = at3 === "end" ? targetFrameId(target2) : null;
|
|
254225
|
+
const time4 = fid ? Math.max(0, timelineDuration(get4().document.nodes, fid) - 1) : 0;
|
|
254226
|
+
set4({ transport: { ...tr, target: target2, time: time4, playing: false, playAnchor: null, fps: fpsOf(target2, tr.fps) }, keySelection: [] });
|
|
254199
254227
|
},
|
|
254200
254228
|
editComposition: (id3, fn, description) => {
|
|
254201
254229
|
const s = get4();
|
|
@@ -254467,9 +254495,9 @@ function breakpointsOf(doc2) {
|
|
|
254467
254495
|
return [base, ...rest];
|
|
254468
254496
|
}
|
|
254469
254497
|
function chain2(doc2, id3) {
|
|
254470
|
-
const
|
|
254471
|
-
const at3 =
|
|
254472
|
-
return at3 > 0 ?
|
|
254498
|
+
const all4 = breakpointsOf(doc2);
|
|
254499
|
+
const at3 = all4.findIndex((b) => b.id === id3);
|
|
254500
|
+
return at3 > 0 ? all4.slice(1, at3 + 1) : [];
|
|
254473
254501
|
}
|
|
254474
254502
|
function overridesAt(node2, doc2, id3) {
|
|
254475
254503
|
if (!node2.responsive) return null;
|
|
@@ -254741,6 +254769,35 @@ var init_contract = __esm({
|
|
|
254741
254769
|
});
|
|
254742
254770
|
|
|
254743
254771
|
// lib/document/collections.ts
|
|
254772
|
+
var collections_exports = {};
|
|
254773
|
+
__export(collections_exports, {
|
|
254774
|
+
COLLECTION_LIMITS: () => COLLECTION_LIMITS,
|
|
254775
|
+
ITEM_RECORD: () => ITEM_RECORD,
|
|
254776
|
+
copyRecord: () => copyRecord,
|
|
254777
|
+
copySuffix: () => copySuffix,
|
|
254778
|
+
exprData: () => exprData,
|
|
254779
|
+
fieldKey: () => fieldKey,
|
|
254780
|
+
fieldText: () => fieldText,
|
|
254781
|
+
hasItemToken: () => hasItemToken,
|
|
254782
|
+
itemMark: () => itemMark,
|
|
254783
|
+
itemMarks: () => itemMarks,
|
|
254784
|
+
itemNode: () => itemNode,
|
|
254785
|
+
itemScope: () => itemScope,
|
|
254786
|
+
itemText: () => itemText,
|
|
254787
|
+
itemValues: () => itemValues,
|
|
254788
|
+
layerId: () => layerId,
|
|
254789
|
+
recordSlugs: () => recordSlugs,
|
|
254790
|
+
recordsIn: () => recordsIn,
|
|
254791
|
+
removeCollection: () => removeCollection,
|
|
254792
|
+
removeRecords: () => removeRecords,
|
|
254793
|
+
repeatRecords: () => repeatRecords,
|
|
254794
|
+
setCollection: () => setCollection,
|
|
254795
|
+
shownRecordOf: () => shownRecordOf,
|
|
254796
|
+
slugify: () => slugify2,
|
|
254797
|
+
templateRecord: () => templateRecord,
|
|
254798
|
+
upsertRecords: () => upsertRecords,
|
|
254799
|
+
withData: () => withData
|
|
254800
|
+
});
|
|
254744
254801
|
function recordsIn(doc2, collectionId) {
|
|
254745
254802
|
const c2 = doc2.collections?.[collectionId];
|
|
254746
254803
|
if (!c2) return [];
|
|
@@ -255998,6 +256055,7 @@ function activeTeamWorkspaceId() {
|
|
|
255998
256055
|
var STORAGE_KEY2, useHyperyTeam, useTeamPrompt;
|
|
255999
256056
|
var init_team = __esm({
|
|
256000
256057
|
"lib/client/cloud/team.ts"() {
|
|
256058
|
+
"use strict";
|
|
256001
256059
|
init_esm();
|
|
256002
256060
|
init_api4();
|
|
256003
256061
|
init_session();
|
|
@@ -265427,12 +265485,12 @@ var init_client = __esm({
|
|
|
265427
265485
|
|
|
265428
265486
|
// lib/collab/private.ts
|
|
265429
265487
|
function privateNodeIds(nodes, userId) {
|
|
265430
|
-
const
|
|
265431
|
-
if (!userId) return
|
|
265488
|
+
const all4 = allPrivateIds(nodes);
|
|
265489
|
+
if (!userId) return all4;
|
|
265432
265490
|
if (nodes === privateIdsFor && userId === privateIdsOwner) return privateIdsCache;
|
|
265433
265491
|
privateIdsFor = nodes;
|
|
265434
265492
|
privateIdsOwner = userId;
|
|
265435
|
-
privateIdsCache =
|
|
265493
|
+
privateIdsCache = all4.filter((id3) => nodes[id3].privateTo === userId);
|
|
265436
265494
|
return privateIdsCache;
|
|
265437
265495
|
}
|
|
265438
265496
|
function withoutPrivate(doc2) {
|
|
@@ -266147,7 +266205,7 @@ var init_vocabulary = __esm({
|
|
|
266147
266205
|
TEMPLATE_CATEGORIES = Object.fromEntries(
|
|
266148
266206
|
["SOCIAL", "PRESENTATION", "WEB", "APP", "EMAIL", "BOARD", "CANVAS", "PRINT"].map((kind) => [kind, typesForKind(kind).map((t3) => t3.id)])
|
|
266149
266207
|
);
|
|
266150
|
-
FACET_KEYS = ["animated", "durationMs", "fps", "platforms", "formats", "useCases", "lottie", "threeD", "featured", "pinned"];
|
|
266208
|
+
FACET_KEYS = ["animated", "durationMs", "fps", "platforms", "formats", "useCases", "lottie", "threeD", "storefronts", "featured", "pinned"];
|
|
266151
266209
|
}
|
|
266152
266210
|
});
|
|
266153
266211
|
|
|
@@ -266213,9 +266271,9 @@ var require_gifenc = __commonJS({
|
|
|
266213
266271
|
"node_modules/.pnpm/gifenc@1.0.3/node_modules/gifenc/dist/gifenc.js"(exports) {
|
|
266214
266272
|
var __defProp2 = Object.defineProperty;
|
|
266215
266273
|
var __markAsModule = (target2) => __defProp2(target2, "__esModule", { value: true });
|
|
266216
|
-
var __export2 = (target2,
|
|
266217
|
-
for (var name2 in
|
|
266218
|
-
__defProp2(target2, name2, { get:
|
|
266274
|
+
var __export2 = (target2, all4) => {
|
|
266275
|
+
for (var name2 in all4)
|
|
266276
|
+
__defProp2(target2, name2, { get: all4[name2], enumerable: true });
|
|
266219
266277
|
};
|
|
266220
266278
|
__markAsModule(exports);
|
|
266221
266279
|
__export2(exports, {
|
|
@@ -290428,7 +290486,7 @@ var init_input_track = __esm({
|
|
|
290428
290486
|
sortBy: queryA?.sortBy || queryB?.sortBy ? (track2) => {
|
|
290429
290487
|
const resultA = queryA?.sortBy?.(track2) ?? [];
|
|
290430
290488
|
const resultB = queryB?.sortBy?.(track2) ?? [];
|
|
290431
|
-
const
|
|
290489
|
+
const join13 = (resultA2, resultB2) => {
|
|
290432
290490
|
return [
|
|
290433
290491
|
...Array.isArray(resultA2) ? resultA2 : [resultA2],
|
|
290434
290492
|
...Array.isArray(resultB2) ? resultB2 : [resultB2]
|
|
@@ -290436,10 +290494,10 @@ var init_input_track = __esm({
|
|
|
290436
290494
|
};
|
|
290437
290495
|
if (isThenable(resultA) || isThenable(resultB)) {
|
|
290438
290496
|
return Promise.all([resultA, resultB]).then(([resultA2, resultB2]) => {
|
|
290439
|
-
return
|
|
290497
|
+
return join13(resultA2, resultB2);
|
|
290440
290498
|
});
|
|
290441
290499
|
} else {
|
|
290442
|
-
return
|
|
290500
|
+
return join13(resultA, resultB);
|
|
290443
290501
|
}
|
|
290444
290502
|
} : void 0
|
|
290445
290503
|
};
|
|
@@ -303263,7 +303321,7 @@ function thumbnailRegion(t3, sizeId) {
|
|
|
303263
303321
|
const sheets = v.rootIds.filter((id3) => !nodes[id3]?.print?.isMaster);
|
|
303264
303322
|
const root2 = nodes[sheets[0] ?? v.rootIds[0]];
|
|
303265
303323
|
const x2 = root2?.x ?? 0, y = root2?.y ?? 0;
|
|
303266
|
-
const box2 =
|
|
303324
|
+
const box2 = root2 && ownBox(t3, root2) ? { width: root2.width, height: root2.height } : { width: v.width, height: v.height };
|
|
303267
303325
|
return { minX: x2, minY: y, maxX: x2 + box2.width, maxY: y + box2.height };
|
|
303268
303326
|
}
|
|
303269
303327
|
function flattenOnWhite(px5) {
|
|
@@ -304583,7 +304641,6 @@ function downloadBlob(blob, filename) {
|
|
|
304583
304641
|
}
|
|
304584
304642
|
var init_download = __esm({
|
|
304585
304643
|
"lib/io/download.ts"() {
|
|
304586
|
-
"use strict";
|
|
304587
304644
|
}
|
|
304588
304645
|
});
|
|
304589
304646
|
|
|
@@ -304801,7 +304858,6 @@ function creditLine(c2) {
|
|
|
304801
304858
|
var MAX_PHOTO_PAGE, MAX_PHOTO_QUERY, UUID, isPhotoId, photoImagePath;
|
|
304802
304859
|
var init_stock = __esm({
|
|
304803
304860
|
"lib/photos/stock.ts"() {
|
|
304804
|
-
"use strict";
|
|
304805
304861
|
MAX_PHOTO_PAGE = 12;
|
|
304806
304862
|
MAX_PHOTO_QUERY = 200;
|
|
304807
304863
|
UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -307476,8 +307532,8 @@ function lineItems(node2, ctx2, acc) {
|
|
|
307476
307532
|
const items = [];
|
|
307477
307533
|
if (visual) {
|
|
307478
307534
|
const cmds = visual.map((p2, i2) => ({ op: i2 ? "L" : "M", x: p2.x, y: p2.y }));
|
|
307479
|
-
const
|
|
307480
|
-
items.push({ t: "path", cmds, fillRule: "nonzero", fills: [], strokes: [...
|
|
307535
|
+
const all4 = (strokes.length ? strokes : [stroke3]).map(toIRStroke).filter((s) => !!s);
|
|
307536
|
+
items.push({ t: "path", cmds, fillRule: "nonzero", fills: [], strokes: [...all4].reverse() });
|
|
307481
307537
|
}
|
|
307482
307538
|
const headAlpha = strokeAlpha(stroke3);
|
|
307483
307539
|
const head2 = (type, tip, angle2) => {
|
|
@@ -309814,6 +309870,7 @@ async function exportSettingFile(renderer, node2, setting, doc2, styles) {
|
|
|
309814
309870
|
var MIME, DEFAULT_EXPORT, exportSettingsOf;
|
|
309815
309871
|
var init_export = __esm({
|
|
309816
309872
|
"lib/io/export.ts"() {
|
|
309873
|
+
"use strict";
|
|
309817
309874
|
init_download();
|
|
309818
309875
|
init_scene_graph();
|
|
309819
309876
|
init_codecs();
|
|
@@ -309905,6 +309962,7 @@ async function selectionReferenceImages(doc2, selection, opts = {}) {
|
|
|
309905
309962
|
var FIT_QUALITIES, FIT_SCALES, blobToDataUrl;
|
|
309906
309963
|
var init_reference_images = __esm({
|
|
309907
309964
|
"lib/ai/reference-images.ts"() {
|
|
309965
|
+
"use strict";
|
|
309908
309966
|
init_export();
|
|
309909
309967
|
init_selection_bounds();
|
|
309910
309968
|
init_renderer_registry();
|
|
@@ -314584,6 +314642,27 @@ var init_vector = __esm({
|
|
|
314584
314642
|
}
|
|
314585
314643
|
});
|
|
314586
314644
|
|
|
314645
|
+
// lib/io/web/project/storefront-targets.ts
|
|
314646
|
+
var STOREFRONT_TARGET_INFO, STOREFRONT_TARGET_IDS;
|
|
314647
|
+
var init_storefront_targets = __esm({
|
|
314648
|
+
"lib/io/web/project/storefront-targets.ts"() {
|
|
314649
|
+
"use strict";
|
|
314650
|
+
STOREFRONT_TARGET_INFO = {
|
|
314651
|
+
"next-commerce": {
|
|
314652
|
+
label: "Next.js Commerce components",
|
|
314653
|
+
short: "Next.js Commerce",
|
|
314654
|
+
description: "React components a Next.js Commerce store renders with its own Shopify data and server actions."
|
|
314655
|
+
},
|
|
314656
|
+
"shopify-theme": {
|
|
314657
|
+
label: "Shopify theme",
|
|
314658
|
+
short: "Shopify",
|
|
314659
|
+
description: "An Online Store 2.0 theme to upload in Shopify: Online Store \u203A Themes \u203A Add theme \u203A Upload zip file."
|
|
314660
|
+
}
|
|
314661
|
+
};
|
|
314662
|
+
STOREFRONT_TARGET_IDS = Object.keys(STOREFRONT_TARGET_INFO);
|
|
314663
|
+
}
|
|
314664
|
+
});
|
|
314665
|
+
|
|
314587
314666
|
// lib/motion/video-edit.ts
|
|
314588
314667
|
function clipOr(doc2, id3, frameId) {
|
|
314589
314668
|
const c2 = videoClipOf(doc2.nodes, id3, frameId, timelineDuration(doc2.nodes, frameId));
|
|
@@ -314818,8 +314897,8 @@ function splitAudioClip(holder, clipId, at3) {
|
|
|
314818
314897
|
return { holder: withAudio(made.composition, placeAudio(placeAudio(others, left), right)), id: made.id };
|
|
314819
314898
|
}
|
|
314820
314899
|
function crossfadeAudio(holder, aId, bId, ms2, sourceMs) {
|
|
314821
|
-
const
|
|
314822
|
-
let a =
|
|
314900
|
+
const all4 = holder.audio ?? [];
|
|
314901
|
+
let a = all4.find((c2) => c2.id === aId), b = all4.find((c2) => c2.id === bId);
|
|
314823
314902
|
if (!a || !b || a.id === b.id) throw new Error("Pick two different audio clips to crossfade.");
|
|
314824
314903
|
if (b.start < a.start) [a, b] = [b, a];
|
|
314825
314904
|
const d = Math.max(1, Math.round(ms2));
|
|
@@ -315670,17 +315749,17 @@ function exactKeys(src, grid, samples, present2) {
|
|
|
315670
315749
|
}
|
|
315671
315750
|
const b = keys4[j + 1];
|
|
315672
315751
|
const eases = moving.map((d) => cpOf(d, j));
|
|
315673
|
-
const
|
|
315752
|
+
const all4 = (kind) => eases.every((e) => e.kind === kind);
|
|
315674
315753
|
const cps = (sel) => src.dims.map((s, d) => s ? sel(eases[moving.indexOf(d)]) : LINEAR_CP);
|
|
315675
|
-
if (
|
|
315754
|
+
if (all4("hold")) {
|
|
315676
315755
|
push2(a.t, keyValue(j), "hold");
|
|
315677
315756
|
continue;
|
|
315678
315757
|
}
|
|
315679
|
-
if (
|
|
315758
|
+
if (all4("curve")) {
|
|
315680
315759
|
push2(a.t, keyValue(j), cps((e) => e.kind === "curve" ? e.cp : LINEAR_CP));
|
|
315681
315760
|
continue;
|
|
315682
315761
|
}
|
|
315683
|
-
if (
|
|
315762
|
+
if (all4("halves")) {
|
|
315684
315763
|
const va = keyValue(j), vb = keyValue(j + 1);
|
|
315685
315764
|
push2(a.t, va, cps((e) => e.kind === "halves" ? e.first : LINEAR_CP));
|
|
315686
315765
|
push2((a.t + b.t) / 2, va.map((v, d) => (v + vb[d]) / 2), cps((e) => e.kind === "halves" ? e.second : LINEAR_CP));
|
|
@@ -315869,12 +315948,12 @@ function uniqueName(name2, taken) {
|
|
|
315869
315948
|
function lottieMarkers(timeline, range3) {
|
|
315870
315949
|
const markers = [];
|
|
315871
315950
|
const names = /* @__PURE__ */ new Map();
|
|
315872
|
-
const
|
|
315951
|
+
const all4 = [...timeline?.markers ?? []].sort((a, b) => a.t - b.t);
|
|
315873
315952
|
const taken = /* @__PURE__ */ new Set();
|
|
315874
315953
|
const frames = (ms2) => (ms2 - range3.start) * range3.fps / 1e3;
|
|
315875
|
-
|
|
315954
|
+
all4.forEach((m, i2) => {
|
|
315876
315955
|
if (m.t < range3.start || m.t > range3.end) return;
|
|
315877
|
-
const next2 =
|
|
315956
|
+
const next2 = all4.find((n) => n.t > m.t && n.kind !== "pause")?.t ?? range3.end;
|
|
315878
315957
|
const cm = uniqueName(m.label || `Marker ${i2 + 1}`, taken);
|
|
315879
315958
|
names.set(m.id, cm);
|
|
315880
315959
|
markers.push({ tm: frames(m.t), cm, dr: Math.max(0, frames(Math.min(next2, range3.end)) - frames(m.t)) });
|
|
@@ -317976,7 +318055,8 @@ var init_naming = __esm({
|
|
|
317976
318055
|
"use strict";
|
|
317977
318056
|
classNameFor = (node2) => {
|
|
317978
318057
|
const base = (node2.name || node2.type).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "node";
|
|
317979
|
-
|
|
318058
|
+
const id3 = node2.id.includes("~__pcitem__") ? node2.id.split("~")[0] : node2.id;
|
|
318059
|
+
return `${base}-${id3.replace(/[^a-zA-Z0-9]/g, "").slice(-6)}`;
|
|
317980
318060
|
};
|
|
317981
318061
|
componentName = (name2) => (name2.replace(/[^a-zA-Z0-9]/g, "") || "Node").replace(/^[0-9]/, "N$&");
|
|
317982
318062
|
fileBase = (name2) => (name2 || "export").replace(/[^a-zA-Z0-9-_]+/g, "-").replace(/^-|-$/g, "") || "export";
|
|
@@ -317989,11 +318069,11 @@ function codeSyntaxFor(v, platform4) {
|
|
|
317989
318069
|
if (explicit) return explicit;
|
|
317990
318070
|
const parts = v.name.split("/").map((p2) => p2.trim()).filter(Boolean);
|
|
317991
318071
|
if (platform4 === "WEB") return `--${parts.join("-").toLowerCase().replace(/[^a-z0-9-]+/g, "-")}`;
|
|
317992
|
-
const
|
|
318072
|
+
const camel4 = parts.map((p2, i2) => {
|
|
317993
318073
|
const w = p2.replace(/[^A-Za-z0-9]+/g, " ").trim().split(/\s+/);
|
|
317994
318074
|
return w.map((x2, j) => i2 === 0 && j === 0 ? x2.toLowerCase() : x2[0].toUpperCase() + x2.slice(1).toLowerCase()).join("");
|
|
317995
318075
|
}).join("");
|
|
317996
|
-
return platform4 === "iOS" ? `Tokens.${
|
|
318076
|
+
return platform4 === "iOS" ? `Tokens.${camel4}` : `Tokens.${camel4}`;
|
|
317997
318077
|
}
|
|
317998
318078
|
var init_dev_mode = __esm({
|
|
317999
318079
|
"lib/document/dev-mode.ts"() {
|
|
@@ -318130,10 +318210,12 @@ function serializeHTML(tree, opts = {}) {
|
|
|
318130
318210
|
}
|
|
318131
318211
|
} else {
|
|
318132
318212
|
const cls = classNameFor(node2);
|
|
318213
|
+
const own2 = Object.fromEntries(Object.entries(style).filter(([, v]) => v.includes("{{")));
|
|
318214
|
+
const shared = Object.fromEntries(Object.entries(style).filter(([, v]) => !v.includes("{{")));
|
|
318133
318215
|
rules.push(`.${cls} {
|
|
318134
|
-
${styleMapToCSSText(
|
|
318216
|
+
${styleMapToCSSText(shared, " ")}
|
|
318135
318217
|
}`);
|
|
318136
|
-
attrs = ` class="${cls}"`;
|
|
318218
|
+
attrs = ` class="${cls}"${Object.keys(own2).length ? ` style="${styleMapToInline(own2)}"` : ""}`;
|
|
318137
318219
|
if (el.keyframes) {
|
|
318138
318220
|
if (!keyframes.includes(el.keyframes)) keyframes.push(el.keyframes);
|
|
318139
318221
|
attrs += " data-motion-child";
|
|
@@ -318143,7 +318225,8 @@ ${styleMapToCSSText(style, " ")}
|
|
|
318143
318225
|
triggered = true;
|
|
318144
318226
|
}
|
|
318145
318227
|
}
|
|
318146
|
-
|
|
318228
|
+
const sends = node2.action ? opts.form?.(node2) : null;
|
|
318229
|
+
for (const [k2, v] of Object.entries({ ...el.attrs, ...sends?.attrs })) attrs += ` ${k2}="${escapeHTML(v)}"`;
|
|
318147
318230
|
attrs += imageRoleAttrs(node2);
|
|
318148
318231
|
if (opts.ids) attrs += ` data-pc-id="${escapeHTML(node2.id)}"`;
|
|
318149
318232
|
if (machine && isRoot) attrs += ' data-sm-root=""';
|
|
@@ -318158,17 +318241,30 @@ ${indent}` : escapeHTML(el.input.value ?? "");
|
|
|
318158
318241
|
const check2 = el.check ? `
|
|
318159
318242
|
${indent} <input${Object.entries(el.check.attrs).map(([k2, v]) => ` ${k2}="${escapeHTML(v)}"`).join("")} style="${CHECK_STYLE}" />` : "";
|
|
318160
318243
|
if (el.html !== void 0) return `${indent}<${tag}${attrs}>${el.html}</${tag}>`;
|
|
318244
|
+
const words = el.runs ? el.runs.map(runMarkup).join("") : el.text !== void 0 ? escapeHTML(el.text) : null;
|
|
318245
|
+
if (words !== null && !el.picture && !node2.children.length && !node2.repeat && !check2 && !sends?.fields) return `${indent}<${tag}${attrs}>${words}</${tag}>`;
|
|
318161
318246
|
const inner = [
|
|
318162
318247
|
el.runs ? `
|
|
318163
318248
|
${indent} ${el.runs.map(runMarkup).join("")}` : el.text !== void 0 ? `
|
|
318164
318249
|
${indent} ${escapeHTML(el.text)}` : "",
|
|
318165
318250
|
pictureMarkup(node2, el.picture, indent),
|
|
318166
|
-
...
|
|
318167
|
-
${
|
|
318251
|
+
...sends?.fields ? [`
|
|
318252
|
+
${indent} ${sends.fields}`] : [],
|
|
318253
|
+
...listed(node2, depth2),
|
|
318168
318254
|
check2
|
|
318169
318255
|
].join("");
|
|
318170
318256
|
return inner ? `${indent}<${tag}${attrs}>${inner}
|
|
318171
318257
|
${indent}</${tag}>` : `${indent}<${tag}${attrs}></${tag}>`;
|
|
318258
|
+
};
|
|
318259
|
+
const listed = (node2, depth2) => {
|
|
318260
|
+
const loop = node2.repeat && opts.lists?.(node2);
|
|
318261
|
+
if (!loop || !node2.repeat) return node2.children.map((c2) => `
|
|
318262
|
+
${emit8(c2, depth2 + 1, false)}`);
|
|
318263
|
+
const indent = " ".repeat(depth2 + 1);
|
|
318264
|
+
return [`
|
|
318265
|
+
${indent}${loop.open}`, ...node2.repeat.template.map((c2) => `
|
|
318266
|
+
${emit8(c2, depth2 + 2, false)}`), `
|
|
318267
|
+
${indent}${loop.close}`];
|
|
318172
318268
|
};
|
|
318173
318269
|
const body = emit8(tree.root, opts.document ? 2 : 0, true);
|
|
318174
318270
|
const fonts = opts.document ? fontsHref(tree) : null;
|
|
@@ -318398,6 +318494,7 @@ var init_tailwind = __esm({
|
|
|
318398
318494
|
// lib/io/web/react.ts
|
|
318399
318495
|
function serializeReact(tree, opts = {}) {
|
|
318400
318496
|
const tailwind = opts.styling === "tailwind";
|
|
318497
|
+
const reader = opts.itemReader ?? "itemWords";
|
|
318401
318498
|
const spec = interactiveSpec(tree);
|
|
318402
318499
|
const machine = tree.stateMachine ?? null;
|
|
318403
318500
|
const listened = machineLayers(machine);
|
|
@@ -318434,10 +318531,10 @@ ${pad}</>`;
|
|
|
318434
318531
|
const fonted = opts.fontFamily && el.style["font-family"] ? { ...el.style, "font-family": opts.fontFamily(el.style["font-family"]) } : el.style;
|
|
318435
318532
|
const style = node2.hidden && !bound?.visible && !el.pc ? { ...fonted, display: "none" } : fonted;
|
|
318436
318533
|
if (el.keyframes && !keyframes.includes(el.keyframes)) keyframes.push(el.keyframes);
|
|
318437
|
-
let attrs = tailwind && !el.pc ? ` className="${tailwindFor(style)}"` : ` style={{ ${[...styleMapToJSX(style).filter(([p2]) => !bound?.style[p2]).map(([p2, v]) => `${JSON.stringify(p2).replace(/^"([A-Za-z_$][\w$]*)"$/, "$1")}: '${v}'`), ...Object.entries(bound?.style ?? {}).map(([p2, e]) => `${p2}: ${e}`)].join(", ")} }${Object.keys(style).some((k2) => k2.startsWith("--")) ? " as CSSProperties" : ""}}`;
|
|
318438
|
-
if (isRoot && (spec || machine || triggeredIn(node2))) attrs = ` ref={root}${attrs}`;
|
|
318439
318534
|
const inItem = node2.id.includes(`~${ITEM_RECORD}`);
|
|
318440
|
-
|
|
318535
|
+
let attrs = tailwind && !el.pc ? ` className="${tailwindFor(style)}"` : ` style={{ ${[...styleMapToJSX(style).filter(([p2]) => !bound?.style[p2]).map(([p2, v]) => `${JSON.stringify(p2).replace(/^"([A-Za-z_$][\w$]*)"$/, "$1")}: ${inItem ? itemStyle(v, reader) : `'${v}'`}`), ...Object.entries(bound?.style ?? {}).map(([p2, e]) => `${p2}: ${e}`)].join(", ")} }${Object.keys(style).some((k2) => k2.startsWith("--")) ? " as CSSProperties" : ""}}`;
|
|
318536
|
+
if (isRoot && (spec || machine || triggeredIn(node2))) attrs = ` ref={root}${attrs}`;
|
|
318537
|
+
for (const [k2, v] of Object.entries(el.attrs)) attrs += inItem ? itemAttr(k2, v, reader) : jsxAttr(k2, v);
|
|
318441
318538
|
if (opts.ids) attrs += inItem ? ` data-pc-id={${JSON.stringify(node2.id.split(`~${ITEM_RECORD}`)[0] + "~")} + item.id${node2.id.split(`~${ITEM_RECORD}`)[1] ? ` + ${JSON.stringify(node2.id.split(`~${ITEM_RECORD}`)[1])}` : ""}}` : ` data-pc-id=${JSON.stringify(node2.id)}`;
|
|
318442
318539
|
const host = node2.id.includes("::") ? layerId(node2.id).split("::")[0] : void 0;
|
|
318443
318540
|
const changeTo = (id3, target2) => {
|
|
@@ -318447,6 +318544,8 @@ ${pad}</>`;
|
|
|
318447
318544
|
const handlers = opts.behaviour?.events(node2.id, { variant: chosen && layerId(node2.id) === chosen.instance ? node2.variant : void 0, changeTo }) ?? {};
|
|
318448
318545
|
for (const [event, handler] of Object.entries(handlers)) attrs += ` ${event}={${inItem ? handler.split(ITEM_ID).join("item.id") : handler}}`;
|
|
318449
318546
|
if (handlers.onClick && !NATIVELY_INTERACTIVE.has(tag)) attrs += ` role="button" tabIndex={0} onKeyDown={e => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); e.currentTarget.click() } }}`;
|
|
318547
|
+
const sends = node2.action ? opts.formAction?.(node2) : null;
|
|
318548
|
+
if (sends) attrs += ` action={${sends}}`;
|
|
318450
318549
|
if (el.keyframes) attrs += ' data-motion-child=""';
|
|
318451
318550
|
if (el.motionTrigger) {
|
|
318452
318551
|
attrs += ` data-motion="${el.motionTrigger}"`;
|
|
@@ -318455,7 +318554,7 @@ ${pad}</>`;
|
|
|
318455
318554
|
if (el.pc) attrs += ` data-pc="${el.pc.uid}" data-layer=${JSON.stringify(el.pc.layer)}`;
|
|
318456
318555
|
if (el.sm) attrs += ` data-sm=${JSON.stringify(el.sm)}`;
|
|
318457
318556
|
if (el.input?.tag === "input") return `${pad}<input${attrs} />`;
|
|
318458
|
-
const fieldValue = (v) => inItem ? itemAttr("value", v) : ` defaultValue=${JSON.stringify(v)}`;
|
|
318557
|
+
const fieldValue = (v) => inItem ? itemAttr("value", v, reader) : ` defaultValue=${JSON.stringify(v)}`;
|
|
318459
318558
|
if (el.input?.tag === "textarea") return `${pad}<textarea${attrs}${el.input.value ? fieldValue(el.input.value) : ""} />`;
|
|
318460
318559
|
if (el.input) return `${pad}<select${attrs}${el.input.value ? fieldValue(el.input.value) : ""}>
|
|
318461
318560
|
${(el.input.options ?? []).map((o) => `${pad} <option value=${JSON.stringify(o.value)}>${jsxText(o.label)}</option>`).join("\n")}
|
|
@@ -318466,14 +318565,15 @@ ${pad}</select>`;
|
|
|
318466
318565
|
if (drawn2) inner.push(`${pad} ${drawn2}`);
|
|
318467
318566
|
if (el.runs) inner.push(...el.runs.map((run4) => {
|
|
318468
318567
|
const style2 = Object.keys(run4.style).length ? ` style={{ ${styleMapToJSX(run4.style).map(([p2, v]) => `${p2}: '${v}'`).join(", ")} }}` : "";
|
|
318469
|
-
const words = inItem ? itemJsx(run4.text) : jsxText(run4.text);
|
|
318568
|
+
const words = inItem ? itemJsx(run4.text, reader) : jsxText(run4.text);
|
|
318470
318569
|
if (run4.link) return `${pad} <a href=${JSON.stringify(run4.link)}${style2}>${words}</a>`;
|
|
318471
318570
|
return style2 ? `${pad} <span${style2}>${words}</span>` : `${pad} ${words}`;
|
|
318472
318571
|
}));
|
|
318473
318572
|
else if (bound?.text) inner.push(`${pad} {${bound.text}}`);
|
|
318474
|
-
else if (el.text !== void 0) inner.push(`${pad} ${inItem ? itemJsx(el.text) : jsxText(el.text)}`);
|
|
318573
|
+
else if (el.text !== void 0) inner.push(`${pad} ${inItem ? itemJsx(el.text, reader) : jsxText(el.text)}`);
|
|
318475
318574
|
const picture2 = el.picture;
|
|
318476
318575
|
if (picture2?.kind === "svg") inner.push(`${pad} <span dangerouslySetInnerHTML={{ __html: ${JSON.stringify(labelSVG(picture2.svg, node2))} }} />`);
|
|
318576
|
+
else if (picture2?.kind === "img" && inItem && itemMarks(picture2.src)) inner.push(`${pad} <img${itemAttr("src", picture2.src, reader)} width={${Math.round(node2.width)}} height={${Math.round(node2.height)}} alt=${JSON.stringify(altFor(node2))} style={{ objectFit: 'cover' }} />`);
|
|
318477
318577
|
else if (picture2?.kind === "img") inner.push(`${pad} ${opts.image ? opts.image({ src: picture2.src, width: node2.width, height: node2.height, alt: altFor(node2) }) : `<img src="${picture2.src}" width={${node2.width}} height={${node2.height}} alt=${JSON.stringify(altFor(node2))} />`}`);
|
|
318478
318578
|
else if (picture2) inner.push(`${pad} {/* ${picture2.reason}: render this node to ${picture2.format.toUpperCase()} */}`);
|
|
318479
318579
|
const live2 = node2.island ? opts.island?.(node2) : null;
|
|
@@ -318511,7 +318611,7 @@ ${drawn}
|
|
|
318511
318611
|
const live = !!spec || !!machine || triggered;
|
|
318512
318612
|
const prelude = [...opts.prelude ?? [], ...states].map((l) => ` ${l}
|
|
318513
318613
|
`).join("");
|
|
318514
|
-
if (!live && !keyframes.length && !body.includes(" as CSSProperties}")) return `export function ${name2}() {
|
|
318614
|
+
if (!live && !keyframes.length && !body.includes(" as CSSProperties}")) return `export function ${name2}(${opts.props ?? ""}) {
|
|
318515
318615
|
${prelude} return (
|
|
318516
318616
|
${body}
|
|
318517
318617
|
)
|
|
@@ -318544,7 +318644,7 @@ ${body}
|
|
|
318544
318644
|
" return () => { io.disconnect(); el.removeEventListener('click', click); el.removeEventListener('mouseover', hover) }",
|
|
318545
318645
|
" }, [])"
|
|
318546
318646
|
);
|
|
318547
|
-
return `${head2.join("\n")}export function ${name2}() {
|
|
318647
|
+
return `${head2.join("\n")}export function ${name2}(${opts.props ?? ""}) {
|
|
318548
318648
|
${prelude}${effects.join("\n")}${effects.length ? "\n" : ""} return (
|
|
318549
318649
|
${body}
|
|
318550
318650
|
)
|
|
@@ -318555,7 +318655,7 @@ function elementType(node2) {
|
|
|
318555
318655
|
const known = { div: "HTMLDivElement", section: "HTMLElement", main: "HTMLElement", header: "HTMLElement", footer: "HTMLElement", nav: "HTMLElement", article: "HTMLElement", aside: "HTMLElement", form: "HTMLFormElement", a: "HTMLAnchorElement", button: "HTMLButtonElement", ul: "HTMLUListElement", li: "HTMLLIElement" };
|
|
318556
318656
|
return known[tag] ?? "HTMLElement";
|
|
318557
318657
|
}
|
|
318558
|
-
var jsxText, template, JSX_ATTR, NATIVELY_INTERACTIVE, BOOLEAN_ATTR, jsxAttr, itemJsx, itemAttr, ITEM_ID;
|
|
318658
|
+
var jsxText, template, JSX_ATTR, NATIVELY_INTERACTIVE, BOOLEAN_ATTR, jsxAttr, itemJsx, itemAttr, itemStyle, ITEM_ID;
|
|
318559
318659
|
var init_react2 = __esm({
|
|
318560
318660
|
"lib/io/web/react.ts"() {
|
|
318561
318661
|
"use strict";
|
|
@@ -318574,33 +318674,173 @@ var init_react2 = __esm({
|
|
|
318574
318674
|
NATIVELY_INTERACTIVE = /* @__PURE__ */ new Set(["a", "button", "input", "select", "textarea", "summary", "label"]);
|
|
318575
318675
|
BOOLEAN_ATTR = /* @__PURE__ */ new Set(["required", "checked", "disabled", "multiple", "readonly", "autofocus", "novalidate", "selected", "hidden", "open"]);
|
|
318576
318676
|
jsxAttr = (k2, v) => BOOLEAN_ATTR.has(k2) ? v === "false" ? "" : ` ${JSX_ATTR[k2] ?? k2}` : ` ${JSX_ATTR[k2] ?? k2}=${JSON.stringify(v)}`;
|
|
318577
|
-
itemJsx = (s) => {
|
|
318677
|
+
itemJsx = (s, reader = "itemWords") => {
|
|
318578
318678
|
const parts = itemMarks(s);
|
|
318579
318679
|
if (!parts) return jsxText(s);
|
|
318580
|
-
return `{${parts.map((p2) => typeof p2 === "string" ? JSON.stringify(p2) :
|
|
318680
|
+
return `{${parts.map((p2) => typeof p2 === "string" ? JSON.stringify(p2) : `${reader}(item, ${JSON.stringify(p2.key)})`).join(" + ")}}`;
|
|
318581
318681
|
};
|
|
318582
|
-
itemAttr = (k2, v) => {
|
|
318682
|
+
itemAttr = (k2, v, reader = "itemWords") => {
|
|
318583
318683
|
const parts = itemMarks(v);
|
|
318584
318684
|
if (!parts || BOOLEAN_ATTR.has(k2)) return jsxAttr(k2, v);
|
|
318585
|
-
return ` ${JSX_ATTR[k2] ?? k2}={${parts.map((p2) => typeof p2 === "string" ? JSON.stringify(p2) :
|
|
318685
|
+
return ` ${JSX_ATTR[k2] ?? k2}={${parts.map((p2) => typeof p2 === "string" ? JSON.stringify(p2) : `${reader}(item, ${JSON.stringify(p2.key)})`).join(" + ")}}`;
|
|
318686
|
+
};
|
|
318687
|
+
itemStyle = (v, reader) => {
|
|
318688
|
+
const parts = itemMarks(v);
|
|
318689
|
+
if (!parts) return `'${v}'`;
|
|
318690
|
+
return parts.map((p2) => typeof p2 === "string" ? JSON.stringify(p2.replace(/\\'/g, "'")) : `${reader}(item, ${JSON.stringify(p2.key)})`).join(" + ");
|
|
318586
318691
|
};
|
|
318587
318692
|
ITEM_ID = JSON.stringify(ITEM_RECORD);
|
|
318588
318693
|
}
|
|
318589
318694
|
});
|
|
318590
318695
|
|
|
318696
|
+
// packages/runtime/src/commerce.ts
|
|
318697
|
+
var commerce_exports = {};
|
|
318698
|
+
__export(commerce_exports, {
|
|
318699
|
+
COMMERCE_ACTIONS: () => COMMERCE_ACTIONS,
|
|
318700
|
+
COMMERCE_ACTION_PROP: () => COMMERCE_ACTION_PROP,
|
|
318701
|
+
COMMERCE_FIELDS: () => COMMERCE_FIELDS,
|
|
318702
|
+
COMMERCE_PROP: () => COMMERCE_PROP,
|
|
318703
|
+
COMMERCE_SCHEMAS: () => COMMERCE_SCHEMAS,
|
|
318704
|
+
commerceItem: () => commerceItem,
|
|
318705
|
+
commerceWords: () => commerceWords,
|
|
318706
|
+
formatMoney: () => formatMoney,
|
|
318707
|
+
isCommerceAction: () => isCommerceAction
|
|
318708
|
+
});
|
|
318709
|
+
function formatMoney(m, locale = "en-US") {
|
|
318710
|
+
if (!m) return "";
|
|
318711
|
+
try {
|
|
318712
|
+
return new Intl.NumberFormat(locale, { style: "currency", currency: m.currencyCode, currencyDisplay: "narrowSymbol" }).format(Number(m.amount));
|
|
318713
|
+
} catch {
|
|
318714
|
+
return `${m.amount} ${m.currencyCode}`;
|
|
318715
|
+
}
|
|
318716
|
+
}
|
|
318717
|
+
function commerceItem(schema, value3) {
|
|
318718
|
+
switch (schema) {
|
|
318719
|
+
case "commerce.product": {
|
|
318720
|
+
const p2 = value3;
|
|
318721
|
+
return { id: p2.id, values: {
|
|
318722
|
+
title: p2.title,
|
|
318723
|
+
handle: p2.handle,
|
|
318724
|
+
url: `/product/${p2.handle}`,
|
|
318725
|
+
description: p2.description,
|
|
318726
|
+
price: formatMoney(p2.priceRange?.minVariantPrice),
|
|
318727
|
+
max_price: formatMoney(p2.priceRange?.maxVariantPrice),
|
|
318728
|
+
image: p2.featuredImage?.url ?? "",
|
|
318729
|
+
image_alt: p2.featuredImage?.altText || p2.title,
|
|
318730
|
+
available: !!p2.availableForSale,
|
|
318731
|
+
variant_id: p2.variants?.find((v) => v.availableForSale)?.id ?? p2.variants?.[0]?.id ?? "",
|
|
318732
|
+
tags: (p2.tags ?? []).join(", ")
|
|
318733
|
+
} };
|
|
318734
|
+
}
|
|
318735
|
+
case "commerce.collection": {
|
|
318736
|
+
const c2 = value3;
|
|
318737
|
+
return { id: c2.handle || "all", values: { title: c2.title, handle: c2.handle, url: c2.path, description: c2.description } };
|
|
318738
|
+
}
|
|
318739
|
+
case "commerce.cart": {
|
|
318740
|
+
const c2 = value3;
|
|
318741
|
+
return { id: c2.id ?? "cart", values: {
|
|
318742
|
+
count: c2.totalQuantity,
|
|
318743
|
+
subtotal: formatMoney(c2.cost?.subtotalAmount),
|
|
318744
|
+
taxes: formatMoney(c2.cost?.totalTaxAmount),
|
|
318745
|
+
total: formatMoney(c2.cost?.totalAmount),
|
|
318746
|
+
checkout_url: c2.checkoutUrl
|
|
318747
|
+
} };
|
|
318748
|
+
}
|
|
318749
|
+
case "commerce.cartLine": {
|
|
318750
|
+
const l = value3;
|
|
318751
|
+
const m = l.merchandise;
|
|
318752
|
+
return { id: l.id ?? m.id, values: {
|
|
318753
|
+
title: m.product.title,
|
|
318754
|
+
variant: m.title === "Default Title" ? "" : m.title,
|
|
318755
|
+
url: `/product/${m.product.handle}`,
|
|
318756
|
+
image: m.product.featuredImage?.url ?? "",
|
|
318757
|
+
quantity: l.quantity,
|
|
318758
|
+
price: formatMoney(l.cost?.totalAmount),
|
|
318759
|
+
merchandise_id: m.id
|
|
318760
|
+
} };
|
|
318761
|
+
}
|
|
318762
|
+
case "commerce.menu": {
|
|
318763
|
+
const m = value3;
|
|
318764
|
+
return { id: m.path, values: { title: m.title, url: m.path } };
|
|
318765
|
+
}
|
|
318766
|
+
}
|
|
318767
|
+
}
|
|
318768
|
+
function commerceWords(item, key5) {
|
|
318769
|
+
if (key5 === "id") return item.id;
|
|
318770
|
+
const v = item.values[key5];
|
|
318771
|
+
return typeof v === "boolean" ? v ? "Yes" : "No" : v === void 0 ? "" : String(v);
|
|
318772
|
+
}
|
|
318773
|
+
var COMMERCE_SCHEMAS, COMMERCE_FIELDS, COMMERCE_PROP, COMMERCE_ACTIONS, COMMERCE_ACTION_PROP, isCommerceAction;
|
|
318774
|
+
var init_commerce = __esm({
|
|
318775
|
+
"packages/runtime/src/commerce.ts"() {
|
|
318776
|
+
"use strict";
|
|
318777
|
+
COMMERCE_SCHEMAS = ["commerce.product", "commerce.collection", "commerce.cart", "commerce.cartLine", "commerce.menu"];
|
|
318778
|
+
COMMERCE_FIELDS = {
|
|
318779
|
+
"commerce.product": [
|
|
318780
|
+
{ name: "Title", type: "TEXT" },
|
|
318781
|
+
{ name: "Handle", type: "TEXT" },
|
|
318782
|
+
{ name: "URL", type: "URL" },
|
|
318783
|
+
{ name: "Description", type: "TEXT" },
|
|
318784
|
+
{ name: "Price", type: "TEXT" },
|
|
318785
|
+
{ name: "Max price", type: "TEXT" },
|
|
318786
|
+
{ name: "Image", type: "MEDIA" },
|
|
318787
|
+
{ name: "Image alt", type: "TEXT" },
|
|
318788
|
+
{ name: "Available", type: "BOOLEAN" },
|
|
318789
|
+
{ name: "Variant ID", type: "TEXT" },
|
|
318790
|
+
{ name: "Tags", type: "TEXT" }
|
|
318791
|
+
],
|
|
318792
|
+
"commerce.collection": [{ name: "Title", type: "TEXT" }, { name: "Handle", type: "TEXT" }, { name: "URL", type: "URL" }, { name: "Description", type: "TEXT" }],
|
|
318793
|
+
"commerce.cart": [
|
|
318794
|
+
{ name: "Count", type: "NUMBER" },
|
|
318795
|
+
{ name: "Subtotal", type: "TEXT" },
|
|
318796
|
+
{ name: "Taxes", type: "TEXT" },
|
|
318797
|
+
{ name: "Total", type: "TEXT" },
|
|
318798
|
+
{ name: "Checkout URL", type: "URL" }
|
|
318799
|
+
],
|
|
318800
|
+
"commerce.cartLine": [
|
|
318801
|
+
{ name: "Title", type: "TEXT" },
|
|
318802
|
+
{ name: "Variant", type: "TEXT" },
|
|
318803
|
+
{ name: "URL", type: "URL" },
|
|
318804
|
+
{ name: "Image", type: "MEDIA" },
|
|
318805
|
+
{ name: "Quantity", type: "NUMBER" },
|
|
318806
|
+
{ name: "Price", type: "TEXT" },
|
|
318807
|
+
{ name: "Merchandise ID", type: "TEXT" }
|
|
318808
|
+
],
|
|
318809
|
+
"commerce.menu": [{ name: "Title", type: "TEXT" }, { name: "URL", type: "URL" }]
|
|
318810
|
+
};
|
|
318811
|
+
COMMERCE_PROP = {
|
|
318812
|
+
"commerce.product": { name: "products", type: "Product" },
|
|
318813
|
+
"commerce.collection": { name: "collections", type: "Collection" },
|
|
318814
|
+
"commerce.cart": { name: "cart", type: "Cart", one: true },
|
|
318815
|
+
"commerce.cartLine": { name: "lines", type: "CartItem" },
|
|
318816
|
+
"commerce.menu": { name: "menu", type: "Menu" }
|
|
318817
|
+
};
|
|
318818
|
+
COMMERCE_ACTIONS = ["addToCart", "updateCartLine", "removeCartLine", "checkout", "search"];
|
|
318819
|
+
COMMERCE_ACTION_PROP = {
|
|
318820
|
+
addToCart: "onAddToCart",
|
|
318821
|
+
updateCartLine: "onUpdateCartLine",
|
|
318822
|
+
removeCartLine: "onRemoveCartLine",
|
|
318823
|
+
checkout: "onCheckout",
|
|
318824
|
+
search: "onSearch"
|
|
318825
|
+
};
|
|
318826
|
+
isCommerceAction = (a) => typeof a === "string" && COMMERCE_ACTIONS.includes(a);
|
|
318827
|
+
}
|
|
318828
|
+
});
|
|
318829
|
+
|
|
318591
318830
|
// lib/sites/auth.ts
|
|
318592
318831
|
function usesSignIn(doc2) {
|
|
318593
318832
|
if (Object.values(doc2.collections ?? {}).some((c2) => c2.perVisitor)) return true;
|
|
318594
318833
|
if (Object.values(doc2.variables ?? {}).some((v) => v.name.startsWith("user/"))) return true;
|
|
318595
318834
|
return Object.values(doc2.nodes).some((n) => {
|
|
318596
318835
|
const o = n;
|
|
318597
|
-
return !!o.route?.access || !!o.control?.formAction && o.control.formAction !== "deleteRecord" && o.control.formAction !== "updateRecord";
|
|
318836
|
+
return !!o.route?.access || !!o.control?.formAction && o.control.formAction !== "deleteRecord" && o.control.formAction !== "updateRecord" && !isCommerceAction(o.control.formAction);
|
|
318598
318837
|
});
|
|
318599
318838
|
}
|
|
318600
318839
|
var init_auth = __esm({
|
|
318601
318840
|
"lib/sites/auth.ts"() {
|
|
318602
318841
|
"use strict";
|
|
318603
318842
|
init_contract();
|
|
318843
|
+
init_commerce();
|
|
318604
318844
|
}
|
|
318605
318845
|
});
|
|
318606
318846
|
|
|
@@ -319282,7 +319522,7 @@ var init_package = __esm({
|
|
|
319282
319522
|
"packages/runtime/package.json"() {
|
|
319283
319523
|
package_default = {
|
|
319284
319524
|
name: "@popcraft/runtime",
|
|
319285
|
-
version: "0.
|
|
319525
|
+
version: "0.15.0",
|
|
319286
319526
|
description: "What code exported from PopCraft shares: the meaning of expressions (operators and functions) and, as it grows, the parts of a design's behaviour that are common code rather than generated React.",
|
|
319287
319527
|
license: "MIT",
|
|
319288
319528
|
homepage: "https://popcraft.app/docs/exporting/nextjs",
|
|
@@ -319298,6 +319538,10 @@ var init_package = __esm({
|
|
|
319298
319538
|
types: "./dist/index.d.ts",
|
|
319299
319539
|
import: "./dist/index.js"
|
|
319300
319540
|
},
|
|
319541
|
+
"./commerce": {
|
|
319542
|
+
types: "./dist/commerce.d.ts",
|
|
319543
|
+
import: "./dist/commerce.js"
|
|
319544
|
+
},
|
|
319301
319545
|
"./server": {
|
|
319302
319546
|
types: "./dist/server/index.d.ts",
|
|
319303
319547
|
import: "./dist/server.js"
|
|
@@ -319877,10 +320121,11 @@ function cleanPath(raw) {
|
|
|
319877
320121
|
function routesOf(screens) {
|
|
319878
320122
|
const taken = /* @__PURE__ */ new Set();
|
|
319879
320123
|
const own2 = /* @__PURE__ */ new Map();
|
|
320124
|
+
const claim2 = (s, path) => s.route?.collectionId ? `${path}/*` : path;
|
|
319880
320125
|
for (const s of screens) {
|
|
319881
320126
|
const path = s.route?.path ? cleanPath(s.route.path) : null;
|
|
319882
|
-
if (path && !taken.has(path)) {
|
|
319883
|
-
taken.add(path);
|
|
320127
|
+
if (path && !taken.has(claim2(s, path))) {
|
|
320128
|
+
taken.add(claim2(s, path));
|
|
319884
320129
|
own2.set(s.id, path);
|
|
319885
320130
|
}
|
|
319886
320131
|
}
|
|
@@ -320395,6 +320640,7 @@ function buildPlainTree(doc2, nodeId2, opts = {}, start2, hooks = {}) {
|
|
|
320395
320640
|
const anchored = anchorTargets(doc2);
|
|
320396
320641
|
const pageItem = () => {
|
|
320397
320642
|
const c2 = opts.item && doc2.collections?.[opts.item.collectionId];
|
|
320643
|
+
if (c2 && opts.item.recordId === ITEM_RECORD) return { collection: c2, record: templateRecord(c2), suffix: `~${ITEM_RECORD}` };
|
|
320398
320644
|
const r = opts.item && doc2.records?.[opts.item.recordId];
|
|
320399
320645
|
return c2 && r ? { collection: c2, record: r, suffix: "" } : null;
|
|
320400
320646
|
};
|
|
@@ -320408,6 +320654,8 @@ function buildPlainTree(doc2, nodeId2, opts = {}, start2, hooks = {}) {
|
|
|
320408
320654
|
const base = opts.routes?.[filled2.frameId];
|
|
320409
320655
|
const of = dest?.route?.collectionId;
|
|
320410
320656
|
if (of && base !== void 0) {
|
|
320657
|
+
const slugField = it?.record.id === ITEM_RECORD && it.collection.id === of ? it.collection.fields.find((f2) => f2.id === it.collection.slugFieldId) ?? it.collection.fields.find((f2) => f2.type === "SLUG" || f2.type === "TEXT") : void 0;
|
|
320658
|
+
if (slugField) return { link: filled2, href: `${base === "/" ? "" : base}/${itemMark(fieldKey(slugField.name))}`, screen: filled2.frameId };
|
|
320411
320659
|
const slugs = recordSlugs(doc2, of);
|
|
320412
320660
|
const rec = it?.collection.id === of ? it.record.id : slugs.keys().next().value;
|
|
320413
320661
|
const slug3 = rec ? slugs.get(rec) : void 0;
|
|
@@ -320415,6 +320663,7 @@ function buildPlainTree(doc2, nodeId2, opts = {}, start2, hooks = {}) {
|
|
|
320415
320663
|
}
|
|
320416
320664
|
return { link: filled2, href: base ?? null, screen: filled2.frameId };
|
|
320417
320665
|
}
|
|
320666
|
+
if (filled2.kind === "url" && it?.record.id === ITEM_RECORD && itemMarks(filled2.url)) return { link: filled2, href: filled2.url.trim() };
|
|
320418
320667
|
return { link: filled2, href: hrefOf(filled2, doc2.nodes, opts.routes) };
|
|
320419
320668
|
};
|
|
320420
320669
|
const fields = /* @__PURE__ */ new Map();
|
|
@@ -320494,8 +320743,10 @@ function buildPlainTree(doc2, nodeId2, opts = {}, start2, hooks = {}) {
|
|
|
320494
320743
|
const control = node2.control;
|
|
320495
320744
|
if (control) {
|
|
320496
320745
|
const named = control.name ? { name: control.name } : {};
|
|
320497
|
-
if (control.kind === "FORM")
|
|
320498
|
-
|
|
320746
|
+
if (control.kind === "FORM") {
|
|
320747
|
+
web.tag = "form";
|
|
320748
|
+
if (isCommerceAction(control.formAction)) web.action = control.formAction;
|
|
320749
|
+
} else if (control.kind === "BUTTON") {
|
|
320499
320750
|
web.tag = "button";
|
|
320500
320751
|
web.attrs = { ...web.attrs, type: control.buttonType ?? "submit", ...named, ...control.name && control.value !== void 0 ? { value: item && hasItemToken(control.value) ? itemText(control.value, item.collection, item.record) : control.value } : {} };
|
|
320501
320752
|
} else if (control.kind === "CHECKBOX" || control.kind === "RADIO") {
|
|
@@ -320624,7 +320875,7 @@ function buildPlainTree(doc2, nodeId2, opts = {}, start2, hooks = {}) {
|
|
|
320624
320875
|
if (built) web.children.push(built);
|
|
320625
320876
|
}
|
|
320626
320877
|
}
|
|
320627
|
-
if (collection.perVisitor && !outerItem) {
|
|
320878
|
+
if (collection.perVisitor && !outerItem || collection.schema && opts.listTemplates) {
|
|
320628
320879
|
item = { collection, record: templateRecord(collection), suffix: `~${ITEM_RECORD}` };
|
|
320629
320880
|
const template2 = [];
|
|
320630
320881
|
for (const child of childrenOf(node2, doc2.nodes)) {
|
|
@@ -320683,6 +320934,7 @@ var init_tree = __esm({
|
|
|
320683
320934
|
init_variables();
|
|
320684
320935
|
init_scene3d();
|
|
320685
320936
|
init_semantics();
|
|
320937
|
+
init_commerce();
|
|
320686
320938
|
init_collections();
|
|
320687
320939
|
init_props();
|
|
320688
320940
|
init_native_registry();
|
|
@@ -333927,9 +334179,9 @@ var require_sourcemap_codec_umd = __commonJS({
|
|
|
333927
334179
|
var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
|
|
333928
334180
|
var __getOwnPropNames2 = Object.getOwnPropertyNames;
|
|
333929
334181
|
var __hasOwnProp2 = Object.prototype.hasOwnProperty;
|
|
333930
|
-
var __export2 = (target2,
|
|
333931
|
-
for (var name2 in
|
|
333932
|
-
__defProp2(target2, name2, { get:
|
|
334182
|
+
var __export2 = (target2, all4) => {
|
|
334183
|
+
for (var name2 in all4)
|
|
334184
|
+
__defProp2(target2, name2, { get: all4[name2], enumerable: true });
|
|
333933
334185
|
};
|
|
333934
334186
|
var __copyProps2 = (to, from2, except, desc2) => {
|
|
333935
334187
|
if (from2 && typeof from2 === "object" || typeof from2 === "function") {
|
|
@@ -334614,9 +334866,9 @@ var require_trace_mapping_umd = __commonJS({
|
|
|
334614
334866
|
var __commonJS2 = (cb, mod) => function __require2() {
|
|
334615
334867
|
return mod || (0, cb[__getOwnPropNames2(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
334616
334868
|
};
|
|
334617
|
-
var __export2 = (target2,
|
|
334618
|
-
for (var name2 in
|
|
334619
|
-
__defProp2(target2, name2, { get:
|
|
334869
|
+
var __export2 = (target2, all4) => {
|
|
334870
|
+
for (var name2 in all4)
|
|
334871
|
+
__defProp2(target2, name2, { get: all4[name2], enumerable: true });
|
|
334620
334872
|
};
|
|
334621
334873
|
var __copyProps2 = (to, from2, except, desc2) => {
|
|
334622
334874
|
if (from2 && typeof from2 === "object" || typeof from2 === "function") {
|
|
@@ -335098,7 +335350,7 @@ var require_trace_mapping_umd = __commonJS({
|
|
|
335098
335350
|
}
|
|
335099
335351
|
return result;
|
|
335100
335352
|
}
|
|
335101
|
-
function generatedPosition(map2, source3, line, column, bias,
|
|
335353
|
+
function generatedPosition(map2, source3, line, column, bias, all4) {
|
|
335102
335354
|
var _a4, _b2;
|
|
335103
335355
|
line--;
|
|
335104
335356
|
if (line < 0) throw new Error(LINE_GTR_ZERO);
|
|
@@ -335106,13 +335358,13 @@ var require_trace_mapping_umd = __commonJS({
|
|
|
335106
335358
|
const { sources, resolvedSources } = map2;
|
|
335107
335359
|
let sourceIndex2 = sources.indexOf(source3);
|
|
335108
335360
|
if (sourceIndex2 === -1) sourceIndex2 = resolvedSources.indexOf(source3);
|
|
335109
|
-
if (sourceIndex2 === -1) return
|
|
335361
|
+
if (sourceIndex2 === -1) return all4 ? [] : GMapping(null, null);
|
|
335110
335362
|
const bySourceMemos = (_a4 = cast(map2))._bySourceMemos || (_a4._bySourceMemos = sources.map(memoizedState));
|
|
335111
335363
|
const generated = (_b2 = cast(map2))._bySources || (_b2._bySources = buildBySources(decodedMappings(map2), bySourceMemos));
|
|
335112
335364
|
const segments = generated[sourceIndex2][line];
|
|
335113
|
-
if (segments == null) return
|
|
335365
|
+
if (segments == null) return all4 ? [] : GMapping(null, null);
|
|
335114
335366
|
const memo5 = bySourceMemos[sourceIndex2];
|
|
335115
|
-
if (
|
|
335367
|
+
if (all4) return sliceGeneratedPositions(segments, memo5, line, column, bias);
|
|
335116
335368
|
const index2 = traceSegmentInternal(segments, memo5, line, column, bias);
|
|
335117
335369
|
if (index2 === -1) return GMapping(null, null);
|
|
335118
335370
|
const segment = segments[index2];
|
|
@@ -335154,9 +335406,9 @@ var require_gen_mapping_umd = __commonJS({
|
|
|
335154
335406
|
var __commonJS2 = (cb, mod) => function __require2() {
|
|
335155
335407
|
return mod || (0, cb[__getOwnPropNames2(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
335156
335408
|
};
|
|
335157
|
-
var __export2 = (target2,
|
|
335158
|
-
for (var name2 in
|
|
335159
|
-
__defProp2(target2, name2, { get:
|
|
335409
|
+
var __export2 = (target2, all4) => {
|
|
335410
|
+
for (var name2 in all4)
|
|
335411
|
+
__defProp2(target2, name2, { get: all4[name2], enumerable: true });
|
|
335160
335412
|
};
|
|
335161
335413
|
var __copyProps2 = (to, from2, except, desc2) => {
|
|
335162
335414
|
if (from2 && typeof from2 === "object" || typeof from2 === "function") {
|
|
@@ -345221,8 +345473,8 @@ ${pad})`;
|
|
|
345221
345473
|
return [`${pad}Box(`, `${pad} modifier = ${modifier}`, `${pad}) {`, ...kids, `${pad}}`].join("\n");
|
|
345222
345474
|
};
|
|
345223
345475
|
const body = emit8(tree.root, 1, true);
|
|
345224
|
-
const
|
|
345225
|
-
const uses = (re) => re.test(
|
|
345476
|
+
const all4 = [body, ...parts].join("\n");
|
|
345477
|
+
const uses = (re) => re.test(all4);
|
|
345226
345478
|
const imports3 = [
|
|
345227
345479
|
[/\.background\(/, "androidx.compose.foundation.background"],
|
|
345228
345480
|
[/\.border\(/, "androidx.compose.foundation.border"],
|
|
@@ -345826,6 +346078,429 @@ var init_project = __esm({
|
|
|
345826
346078
|
}
|
|
345827
346079
|
});
|
|
345828
346080
|
|
|
346081
|
+
// lib/io/web/project/components.ts
|
|
346082
|
+
var components_exports = {};
|
|
346083
|
+
__export(components_exports, {
|
|
346084
|
+
componentFiles: () => componentFiles,
|
|
346085
|
+
componentMedia: () => componentMedia,
|
|
346086
|
+
componentScreens: () => componentScreens
|
|
346087
|
+
});
|
|
346088
|
+
function componentScreens(doc2, pageId2 = doc2.pages[0], nodeCap = 2e4) {
|
|
346089
|
+
const screens = screensOf(doc2, pageId2);
|
|
346090
|
+
const build3 = { target: "site", nodeCap, listTemplates: true, routes: Object.fromEntries(routesOf(screens)) };
|
|
346091
|
+
return screens.map((s) => {
|
|
346092
|
+
const of = s.route?.collectionId ? doc2.collections?.[s.route.collectionId] : void 0;
|
|
346093
|
+
const about = of?.schema ? of : void 0;
|
|
346094
|
+
const opts = about ? { ...build3, item: { collectionId: about.id, recordId: ITEM_RECORD } } : build3;
|
|
346095
|
+
const tree = buildPlainTree(doc2, s.id, opts);
|
|
346096
|
+
const media2 = mediaRules(doc2, s.id, tree.root, opts).map((r) => r.replace(/\[data-pc-id="([^"~]+)~[^"]+"\]/g, '[data-pc-id^="$1~"]'));
|
|
346097
|
+
return { id: s.id, name: s.name, tree: media2.length ? { ...tree, rules: [...tree.rules ?? [], ...media2] } : tree, ...about ? { about } : {} };
|
|
346098
|
+
});
|
|
346099
|
+
}
|
|
346100
|
+
function componentMedia(doc2, screens) {
|
|
346101
|
+
const text = JSON.stringify(screens.map((s) => s.tree)) + JSON.stringify(doc2.records ?? {});
|
|
346102
|
+
return [...new Set(text.match(MEDIA_REF2) ?? [])].sort();
|
|
346103
|
+
}
|
|
346104
|
+
function componentFiles(doc2, screens, o = {}) {
|
|
346105
|
+
const dir = (o.dir ?? "components/popcraft").replace(/\/$/, "");
|
|
346106
|
+
const media2 = [];
|
|
346107
|
+
const at3 = /* @__PURE__ */ new Map();
|
|
346108
|
+
for (const [ref3, m] of Object.entries(o.media ?? {})) {
|
|
346109
|
+
const name2 = `${ref3.slice("media://".length)}.${MEDIA_EXT[m.type] ?? "bin"}`;
|
|
346110
|
+
at3.set(ref3, `/popcraft/media/${name2}`);
|
|
346111
|
+
media2.push({ path: `public/popcraft/media/${name2}`, content: m.bytes });
|
|
346112
|
+
}
|
|
346113
|
+
const located = (v) => at3.size ? JSON.parse(JSON.stringify(v).replace(MEDIA_REF2, (ref3) => at3.get(ref3) ?? ref3)) : v;
|
|
346114
|
+
doc2 = { ...doc2, records: located(doc2.records) };
|
|
346115
|
+
const holder = { pages: screens.map((s) => ({ tree: located(s.tree) })) };
|
|
346116
|
+
const pictures = [...externalizeBitmaps(holder).map((f2) => ({ ...f2, path: `public/popcraft/${f2.path}` })), ...media2];
|
|
346117
|
+
const names = /* @__PURE__ */ new Set();
|
|
346118
|
+
const files = [];
|
|
346119
|
+
const index2 = [];
|
|
346120
|
+
screens.forEach((s, i2) => {
|
|
346121
|
+
const tree = { ...holder.pages[i2].tree, root: withAssetBase(holder.pages[i2].tree.root, "/popcraft/") };
|
|
346122
|
+
const base = (componentName(s.name) || "Screen").replace(/(page|screen)?$/i, "Page");
|
|
346123
|
+
let name2 = base;
|
|
346124
|
+
for (let n = 2; names.has(name2); n++) name2 = `${base}${n}`;
|
|
346125
|
+
names.add(name2);
|
|
346126
|
+
const props = [];
|
|
346127
|
+
const types = /* @__PURE__ */ new Set();
|
|
346128
|
+
const samples = [];
|
|
346129
|
+
const prelude = [];
|
|
346130
|
+
const listProp = /* @__PURE__ */ new Map();
|
|
346131
|
+
const propName2 = (base2) => {
|
|
346132
|
+
let p2 = base2;
|
|
346133
|
+
for (let n = 2; props.some((x2) => x2.name === p2) || p2 === "item"; n++) p2 = `${base2}${n}`;
|
|
346134
|
+
return p2;
|
|
346135
|
+
};
|
|
346136
|
+
if (s.about) {
|
|
346137
|
+
const schema = s.about.schema;
|
|
346138
|
+
const p2 = propName2(camel3(singular(COMMERCE_PROP[schema].name)));
|
|
346139
|
+
const type = COMMERCE_PROP[schema].type;
|
|
346140
|
+
types.add(type);
|
|
346141
|
+
props.push({ name: p2, type: `${type}`, doc: `The ${singular(s.about.name).toLowerCase()} this page is about; none: the design's first sample.` });
|
|
346142
|
+
samples.push(sampleConst(`SAMPLE_${p2.toUpperCase()}`, doc2, s.about, 1));
|
|
346143
|
+
prelude.push(`const item = ${p2} ? commerceItem(${JSON.stringify(schema)}, ${p2}) : SAMPLE_${p2.toUpperCase()}`);
|
|
346144
|
+
}
|
|
346145
|
+
for (const n of all3(tree.root)) {
|
|
346146
|
+
const c2 = n.repeat && doc2.collections?.[n.repeat.collectionId];
|
|
346147
|
+
if (!c2?.schema || listProp.has(c2.id)) continue;
|
|
346148
|
+
const { type, one } = COMMERCE_PROP[c2.schema];
|
|
346149
|
+
const p2 = propName2(one ? COMMERCE_PROP[c2.schema].name : camel3(c2.name));
|
|
346150
|
+
types.add(type);
|
|
346151
|
+
listProp.set(c2.id, p2);
|
|
346152
|
+
props.push({ name: p2, type: one ? type : `${type}[]`, doc: `${c2.name}; none: the design's samples.` });
|
|
346153
|
+
samples.push(sampleConst(`SAMPLE_${p2.toUpperCase()}`, doc2, c2));
|
|
346154
|
+
}
|
|
346155
|
+
const actions = [...new Set(all3(tree.root).map((n) => n.action).filter((a) => !!a))];
|
|
346156
|
+
for (const a of actions) props.push({ name: COMMERCE_ACTION_PROP[a], type: "(formData: FormData) => void | Promise<void>", doc: `What sending its ${a} form does (a server action).` });
|
|
346157
|
+
const body = serializeReact(tree, {
|
|
346158
|
+
ids: true,
|
|
346159
|
+
name: name2,
|
|
346160
|
+
styling: o.styling ?? "inline",
|
|
346161
|
+
prelude,
|
|
346162
|
+
itemReader: "commerceWords",
|
|
346163
|
+
props: props.length ? `{ ${props.map((p2) => p2.name).join(", ")} }: ${name2}Props = {}` : "",
|
|
346164
|
+
lists: (r) => {
|
|
346165
|
+
const p2 = listProp.get(r.collectionId);
|
|
346166
|
+
if (!p2) return null;
|
|
346167
|
+
const c2 = doc2.collections[r.collectionId];
|
|
346168
|
+
let out = COMMERCE_PROP[c2.schema].one ? `(${p2} ? [commerceItem(${JSON.stringify(c2.schema)}, ${p2})] : SAMPLE_${p2.toUpperCase()})` : `(${p2} ? ${p2}.map(v => commerceItem(${JSON.stringify(c2.schema)}, v)) : SAMPLE_${p2.toUpperCase()})`;
|
|
346169
|
+
if (r.offset || r.limit) out += `.slice(${r.offset ?? 0}${r.limit ? `, ${(r.offset ?? 0) + r.limit}` : ""})`;
|
|
346170
|
+
return out;
|
|
346171
|
+
},
|
|
346172
|
+
formAction: (n) => n.action ? COMMERCE_ACTION_PROP[n.action] : null
|
|
346173
|
+
});
|
|
346174
|
+
const runtime = [.../\bcommerceItem\(/.test(body) ? ["commerceItem"] : [], .../\bcommerceWords\(/.test(body) ? ["commerceWords"] : [], ...samples.length ? ["type CommerceItem"] : [], ...[...types].sort().map((t3) => `type ${t3}`)];
|
|
346175
|
+
const client = /\buse(Effect|Ref|State)\b/.test(body);
|
|
346176
|
+
const react = /<Fragment\b/.test(body) && !/import \{[^}]*\bFragment\b/.test(body) ? ["import { Fragment } from 'react'"] : [];
|
|
346177
|
+
const content = [
|
|
346178
|
+
...client ? ["'use client'", ""] : [],
|
|
346179
|
+
`// ${s.name}, exported from PopCraft (${doc2.name}) as a component a Next.js Commerce store renders with its own data.`,
|
|
346180
|
+
"// Re-export it from PopCraft rather than editing it here: the design is the source.",
|
|
346181
|
+
"",
|
|
346182
|
+
...react,
|
|
346183
|
+
...runtime.length ? [`import { ${runtime.join(", ")} } from '@popcraft/runtime/commerce'`] : [],
|
|
346184
|
+
"",
|
|
346185
|
+
...props.length ? [`export interface ${name2}Props {`, ...props.map((p2) => ` /** ${p2.doc} */
|
|
346186
|
+
${p2.name}?: ${p2.type}`), "}", ""] : [],
|
|
346187
|
+
...samples,
|
|
346188
|
+
body,
|
|
346189
|
+
""
|
|
346190
|
+
].join("\n");
|
|
346191
|
+
files.push({ path: `${dir}/${name2}.tsx`, content });
|
|
346192
|
+
index2.push(`export { ${name2}${props.length ? `, type ${name2}Props` : ""} } from './${name2}'`);
|
|
346193
|
+
});
|
|
346194
|
+
const tokens = screens.find((sc) => sc.tree.tokens)?.tree.tokens;
|
|
346195
|
+
files.push({ path: `${dir}/popcraft.css`, content: [
|
|
346196
|
+
`/* The variables of ${doc2.name}'s design, exported from PopCraft: what its components' styles name. */`,
|
|
346197
|
+
"*, *::before, *::after { box-sizing: border-box; }",
|
|
346198
|
+
...tokens ? tokensCSS(tokens) : [],
|
|
346199
|
+
""
|
|
346200
|
+
].join("\n") });
|
|
346201
|
+
files.push({ path: `${dir}/index.ts`, content: [`// The components of ${doc2.name}, exported from PopCraft.`, "import './popcraft.css'", "", ...index2, ""].join("\n") });
|
|
346202
|
+
return [...files, ...pictures];
|
|
346203
|
+
}
|
|
346204
|
+
function sampleConst(name2, doc2, c2, one) {
|
|
346205
|
+
const rows = recordsIn(doc2, c2.id).map((r) => ({ id: r.id, values: Object.fromEntries(c2.fields.map((f2) => [fieldKey(f2.name), r.values[f2.id] ?? ""])) }));
|
|
346206
|
+
return one ? `const ${name2}: CommerceItem = ${JSON.stringify(rows[0] ?? { id: "sample", values: {} }, null, 2)}
|
|
346207
|
+
` : `const ${name2}: CommerceItem[] = ${JSON.stringify(rows, null, 2)}
|
|
346208
|
+
`;
|
|
346209
|
+
}
|
|
346210
|
+
var all3, camel3, singular, MEDIA_REF2, MEDIA_EXT;
|
|
346211
|
+
var init_components = __esm({
|
|
346212
|
+
"lib/io/web/project/components.ts"() {
|
|
346213
|
+
init_commerce();
|
|
346214
|
+
init_collections();
|
|
346215
|
+
init_routes();
|
|
346216
|
+
init_naming();
|
|
346217
|
+
init_react2();
|
|
346218
|
+
init_tokens2();
|
|
346219
|
+
init_site();
|
|
346220
|
+
init_tree();
|
|
346221
|
+
init_assets();
|
|
346222
|
+
all3 = (n, out = []) => {
|
|
346223
|
+
out.push(n);
|
|
346224
|
+
n.children.forEach((c2) => all3(c2, out));
|
|
346225
|
+
n.repeat?.template.forEach((c2) => all3(c2, out));
|
|
346226
|
+
return out;
|
|
346227
|
+
};
|
|
346228
|
+
camel3 = (s) => {
|
|
346229
|
+
const w = componentName(s.replace(/[^A-Za-z0-9]+/g, " ").replace(/\b\w/g, (c2) => c2.toUpperCase()));
|
|
346230
|
+
return w.charAt(0).toLowerCase() + w.slice(1);
|
|
346231
|
+
};
|
|
346232
|
+
singular = (s) => s.replace(/ies$/, "y").replace(/s$/, "");
|
|
346233
|
+
MEDIA_REF2 = /media:\/\/[A-Za-z0-9_-]+/g;
|
|
346234
|
+
MEDIA_EXT = { "image/png": "png", "image/jpeg": "jpg", "image/webp": "webp", "image/gif": "gif", "image/avif": "avif", "image/svg+xml": "svg" };
|
|
346235
|
+
}
|
|
346236
|
+
});
|
|
346237
|
+
|
|
346238
|
+
// lib/io/web/project/shopify-theme.ts
|
|
346239
|
+
function kindOf(s, doc2, route2) {
|
|
346240
|
+
if (s.about?.schema === "commerce.product") return "product";
|
|
346241
|
+
if (s.about?.schema === "commerce.collection") return "collection";
|
|
346242
|
+
const nodes = every2(s.tree.root);
|
|
346243
|
+
if (nodes.some((n) => n.action === "search")) return "search";
|
|
346244
|
+
if (nodes.some((n) => n.repeat && doc2.collections?.[n.repeat.collectionId]?.schema === "commerce.cartLine")) return "cart";
|
|
346245
|
+
if (route2 === "/") return "index";
|
|
346246
|
+
return "page";
|
|
346247
|
+
}
|
|
346248
|
+
function liquidNode(node2, schema, v) {
|
|
346249
|
+
const fields = LIQUID[schema](v);
|
|
346250
|
+
const out = boundNode(node2, (key5) => key5 in fields ? `{{ ${fields[key5]} }}` : key5 === "id" ? `{{ ${v}.id }}` : "");
|
|
346251
|
+
const rename = (n) => ({ ...n, ...n.input?.attrs.name === "merchandiseId" ? { input: { ...n.input, attrs: { ...n.input.attrs, name: "id" } } } : {}, children: n.children.map(rename) });
|
|
346252
|
+
return rename(out);
|
|
346253
|
+
}
|
|
346254
|
+
function boundNode(node2, field) {
|
|
346255
|
+
const { children, repeat, variants, ...own2 } = node2;
|
|
346256
|
+
const out = JSON.parse(JSON.stringify(own2).replace(/\u2063([^\u2063]*)\u2063/g, (_m, key5) => field(key5)));
|
|
346257
|
+
const page = new RegExp(`^/[\\w-]+/${field("handle").replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`);
|
|
346258
|
+
const href = (h) => field("handle") && page.test(h) ? field("url") : h;
|
|
346259
|
+
if (out.link?.href) out.link = { ...out.link, href: href(out.link.href) };
|
|
346260
|
+
if (out.attrs?.href) out.attrs = { ...out.attrs, href: href(out.attrs.href) };
|
|
346261
|
+
return { ...out, children: children.map((c2) => boundNode(c2, field)), ...repeat ? { repeat } : {}, ...variants ? { variants } : {} };
|
|
346262
|
+
}
|
|
346263
|
+
function shopifyThemeFiles(doc2, screens, o = {}) {
|
|
346264
|
+
const files = [];
|
|
346265
|
+
const name2 = o.name ?? doc2.name;
|
|
346266
|
+
const asset = /* @__PURE__ */ new Map();
|
|
346267
|
+
for (const [ref3, m] of Object.entries(o.media ?? {})) {
|
|
346268
|
+
const file2 = `popcraft-${ref3.slice("media://".length)}.${MEDIA_EXT2[m.type] ?? "bin"}`;
|
|
346269
|
+
asset.set(ref3, `{{ '${file2}' | asset_url }}`);
|
|
346270
|
+
files.push({ path: `assets/${file2}`, content: m.bytes });
|
|
346271
|
+
}
|
|
346272
|
+
const holder = { pages: screens.map((s) => ({ tree: s.tree })) };
|
|
346273
|
+
for (const f2 of externalizeBitmaps(holder)) {
|
|
346274
|
+
const file2 = `popcraft-${f2.path.replace(/^assets\//, "")}`;
|
|
346275
|
+
files.push({ path: `assets/${file2}`, content: f2.content });
|
|
346276
|
+
}
|
|
346277
|
+
const located = (v) => JSON.parse(JSON.stringify(v).replace(MEDIA_REF3, (ref3) => asset.get(ref3) ?? ref3).replace(/(["'(])assets\/(img-\d+\.\w+)/g, (_m, lead, f2) => `${lead}{{ 'popcraft-${f2}' | asset_url }}`));
|
|
346278
|
+
const schemaOf = (id3) => doc2.collections?.[id3]?.schema;
|
|
346279
|
+
const used = /* @__PURE__ */ new Set();
|
|
346280
|
+
const sections = [];
|
|
346281
|
+
for (const [i2, s] of screens.entries()) {
|
|
346282
|
+
const route2 = doc2.nodes?.[s.id] ? doc2.nodes[s.id].route?.path : void 0;
|
|
346283
|
+
let kind = kindOf(s, doc2, route2 ?? (i2 === 0 ? "/" : void 0));
|
|
346284
|
+
if (kind !== "page" && used.has(kind)) kind = "page";
|
|
346285
|
+
used.add(kind);
|
|
346286
|
+
const slug3 = fileBase(s.name).toLowerCase() || `page-${i2 + 1}`;
|
|
346287
|
+
let tree = located(holder.pages[i2].tree);
|
|
346288
|
+
if (s.about?.schema) tree = { ...tree, root: liquidNode(tree.root, s.about.schema, s.about.schema === "commerce.product" ? "product" : "collection") };
|
|
346289
|
+
const relist = (n) => {
|
|
346290
|
+
const schema = n.repeat && schemaOf(n.repeat.collectionId);
|
|
346291
|
+
const template3 = n.repeat && schema ? n.repeat.template.map((c2) => liquidNode(c2, schema, LOOP_VAR[schema])) : n.repeat?.template;
|
|
346292
|
+
return { ...n, children: n.children.map(relist), ...n.repeat ? { repeat: { ...n.repeat, template: (template3 ?? []).map(relist) } } : {} };
|
|
346293
|
+
};
|
|
346294
|
+
tree = { ...tree, root: relist(tree.root) };
|
|
346295
|
+
const source3 = kind === "collection" ? "collection.products" : kind === "search" ? "pc_results" : "collections.all.products";
|
|
346296
|
+
const html = serializeHTML(tree, {
|
|
346297
|
+
ids: true,
|
|
346298
|
+
lists: (n) => {
|
|
346299
|
+
const schema = n.repeat && schemaOf(n.repeat.collectionId);
|
|
346300
|
+
if (!schema || !n.repeat) return null;
|
|
346301
|
+
const range3 = `${n.repeat.limit ? ` limit: ${n.repeat.limit}` : ""}${n.repeat.offset ? ` offset: ${n.repeat.offset}` : ""}`;
|
|
346302
|
+
switch (schema) {
|
|
346303
|
+
case "commerce.product":
|
|
346304
|
+
return { open: `{% for p in ${source3}${range3} %}`, close: "{% endfor %}" };
|
|
346305
|
+
case "commerce.collection":
|
|
346306
|
+
return { open: `{% for c in collections${range3} %}{% if c.handle == 'all' or c.handle == 'frontpage' %}{% continue %}{% endif %}`, close: "{% endfor %}" };
|
|
346307
|
+
case "commerce.cartLine":
|
|
346308
|
+
return { open: `{% for line in cart.items${range3} %}`, close: "{% endfor %}" };
|
|
346309
|
+
case "commerce.menu":
|
|
346310
|
+
return { open: `{% for link in linklists['main-menu'].links${range3} %}`, close: "{% endfor %}" };
|
|
346311
|
+
case "commerce.cart":
|
|
346312
|
+
return { open: "", close: "" };
|
|
346313
|
+
}
|
|
346314
|
+
},
|
|
346315
|
+
form: (n) => {
|
|
346316
|
+
const f2 = n.action && FORMS[n.action];
|
|
346317
|
+
return f2 ? { attrs: { action: f2.action, method: f2.method, "accept-charset": "UTF-8" }, ...f2.fields ? { fields: f2.fields } : {} } : null;
|
|
346318
|
+
}
|
|
346319
|
+
});
|
|
346320
|
+
const prelude = kind === "search" ? "{%- liquid\n if search.performed\n assign pc_results = search.results | where: 'object_type', 'product'\n else\n assign pc_results = collections.all.products\n endif\n-%}\n" : "";
|
|
346321
|
+
const title = s.name;
|
|
346322
|
+
files.push({ path: `sections/popcraft-${slug3}.liquid`, content: `${prelude}${html}
|
|
346323
|
+
|
|
346324
|
+
{% schema %}
|
|
346325
|
+
${JSON.stringify({ name: `${title} (PopCraft)`, settings: [] }, null, 2)}
|
|
346326
|
+
{% endschema %}
|
|
346327
|
+
` });
|
|
346328
|
+
sections.push({ kind, slug: slug3, title });
|
|
346329
|
+
const template2 = kind === "page" ? `page.${slug3}` : kind;
|
|
346330
|
+
files.push({ path: `templates/${template2}.json`, content: `${JSON.stringify({ sections: { main: { type: `popcraft-${slug3}`, settings: {} } }, order: ["main"] }, null, 2)}
|
|
346331
|
+
` });
|
|
346332
|
+
}
|
|
346333
|
+
const plain2 = (template2, title, body) => {
|
|
346334
|
+
files.push({ path: `sections/popcraft-${template2}.liquid`, content: `<div class="popcraft-plain">
|
|
346335
|
+
${body}
|
|
346336
|
+
</div>
|
|
346337
|
+
|
|
346338
|
+
{% schema %}
|
|
346339
|
+
${JSON.stringify({ name: `${title} (PopCraft)`, settings: [] }, null, 2)}
|
|
346340
|
+
{% endschema %}
|
|
346341
|
+
` });
|
|
346342
|
+
files.push({ path: `templates/${template2}.json`, content: `${JSON.stringify({ sections: { main: { type: `popcraft-${template2}`, settings: {} } }, order: ["main"] }, null, 2)}
|
|
346343
|
+
` });
|
|
346344
|
+
};
|
|
346345
|
+
const need = [
|
|
346346
|
+
["index", "Home", "<h1>{{ shop.name }}</h1>"],
|
|
346347
|
+
["product", "Product", `<h1>{{ product.title }}</h1>
|
|
346348
|
+
<p>{{ product.price | money }}</p>
|
|
346349
|
+
{% form 'product', product %}<input type="hidden" name="id" value="{{ product.selected_or_first_available_variant.id }}"><button type="submit">Add to cart</button>{% endform %}`],
|
|
346350
|
+
["collection", "Collection", '<h1>{{ collection.title }}</h1>\n {% for p in collection.products %}<a href="{{ p.url }}">{{ p.title }} \u2014 {{ p.price | money }}</a>{% endfor %}'],
|
|
346351
|
+
["search", "Search", '<form action="/search"><input name="q" value="{{ search.terms | escape }}"><button>Search</button></form>\n {% for item in search.results %}<a href="{{ item.url }}">{{ item.title }}</a>{% endfor %}'],
|
|
346352
|
+
["cart", "Cart", '<form action="/cart" method="post">{% for line in cart.items %}<p>{{ line.product.title }} \xD7 {{ line.quantity }}</p>{% endfor %}<button name="checkout">Check out</button></form>'],
|
|
346353
|
+
["page", "Page", "<h1>{{ page.title }}</h1>\n {{ page.content }}"],
|
|
346354
|
+
["404", "Not found", '<h1>Page not found</h1>\n <a href="{{ routes.root_url }}">Back to the shop</a>'],
|
|
346355
|
+
["list-collections", "Collections", '{% for c in collections %}<a href="{{ c.url }}">{{ c.title }}</a>{% endfor %}'],
|
|
346356
|
+
["blog", "Blog", '<h1>{{ blog.title }}</h1>\n {% for article in blog.articles %}<a href="{{ article.url }}">{{ article.title }}</a>{% endfor %}'],
|
|
346357
|
+
["article", "Article", "<h1>{{ article.title }}</h1>\n {{ article.content }}"],
|
|
346358
|
+
["password", "Password", `<h1>{{ shop.name }}</h1>
|
|
346359
|
+
<p>Opening soon.</p>
|
|
346360
|
+
{% form 'storefront_password' %}<input type="password" name="password"><button>Enter</button>{% endform %}`]
|
|
346361
|
+
];
|
|
346362
|
+
for (const [template2, title, body] of need) if (!files.some((f2) => f2.path === `templates/${template2}.json`)) plain2(template2, title, body);
|
|
346363
|
+
files.push({ path: "templates/gift_card.liquid", content: "{% layout none %}\n<!doctype html>\n<html><head>{{ content_for_header }}</head><body><h1>{{ gift_card.balance | money }}</h1><p>{{ gift_card.code }}</p></body></html>\n" });
|
|
346364
|
+
const fonts = screens.map((s) => fontsHref(s.tree)).find(Boolean);
|
|
346365
|
+
files.push({ path: "layout/theme.liquid", content: [
|
|
346366
|
+
"<!doctype html>",
|
|
346367
|
+
'<html lang="{{ request.locale.iso_code }}">',
|
|
346368
|
+
"<head>",
|
|
346369
|
+
' <meta charset="utf-8">',
|
|
346370
|
+
' <meta name="viewport" content="width=device-width, initial-scale=1">',
|
|
346371
|
+
" <title>{{ page_title }}{% unless page_title contains shop.name %} \xB7 {{ shop.name }}{% endunless %}</title>",
|
|
346372
|
+
' {% if page_description %}<meta name="description" content="{{ page_description | escape }}">{% endif %}',
|
|
346373
|
+
' <link rel="canonical" href="{{ canonical_url }}">',
|
|
346374
|
+
...fonts ? [` <link rel="stylesheet" href="${fonts}">`] : [],
|
|
346375
|
+
" <style>html, body { margin: 0; } *, *::before, *::after { box-sizing: border-box; } img { display: block; max-width: 100%; } .popcraft-plain { max-width: 960px; margin: 48px auto; padding: 0 20px; font-family: system-ui, sans-serif; }</style>",
|
|
346376
|
+
" {{ content_for_header }}",
|
|
346377
|
+
"</head>",
|
|
346378
|
+
"<body>",
|
|
346379
|
+
" {{ content_for_layout }}",
|
|
346380
|
+
"</body>",
|
|
346381
|
+
"</html>",
|
|
346382
|
+
""
|
|
346383
|
+
].join("\n") });
|
|
346384
|
+
files.push({ path: "config/settings_schema.json", content: `${JSON.stringify([{ name: "theme_info", theme_name: name2, theme_version: "1.0.0", theme_author: "PopCraft", theme_documentation_url: "https://popcraft.app/docs/exporting/commerce", theme_support_url: "https://popcraft.app/docs" }], null, 2)}
|
|
346385
|
+
` });
|
|
346386
|
+
files.push({ path: "config/settings_data.json", content: `${JSON.stringify({ current: {} }, null, 2)}
|
|
346387
|
+
` });
|
|
346388
|
+
files.push({ path: "locales/en.default.json", content: "{}\n" });
|
|
346389
|
+
return files;
|
|
346390
|
+
}
|
|
346391
|
+
var MEDIA_REF3, MEDIA_EXT2, LIQUID, LOOP_VAR, FORMS, every2;
|
|
346392
|
+
var init_shopify_theme = __esm({
|
|
346393
|
+
"lib/io/web/project/shopify-theme.ts"() {
|
|
346394
|
+
"use strict";
|
|
346395
|
+
init_fonts3();
|
|
346396
|
+
init_html();
|
|
346397
|
+
init_naming();
|
|
346398
|
+
init_assets();
|
|
346399
|
+
MEDIA_REF3 = /media:\/\/[A-Za-z0-9_-]+/g;
|
|
346400
|
+
MEDIA_EXT2 = { "image/png": "png", "image/jpeg": "jpg", "image/webp": "webp", "image/gif": "gif", "image/avif": "avif", "image/svg+xml": "svg" };
|
|
346401
|
+
LIQUID = {
|
|
346402
|
+
"commerce.product": (v) => ({
|
|
346403
|
+
title: `${v}.title`,
|
|
346404
|
+
handle: `${v}.handle`,
|
|
346405
|
+
url: `${v}.url`,
|
|
346406
|
+
description: `${v}.description | strip_html | truncatewords: 60`,
|
|
346407
|
+
price: `${v}.price | money`,
|
|
346408
|
+
max_price: `${v}.price_max | money`,
|
|
346409
|
+
image: `${v}.featured_image | image_url: width: 1200`,
|
|
346410
|
+
image_alt: `${v}.featured_image.alt | escape`,
|
|
346411
|
+
available: `${v}.available`,
|
|
346412
|
+
variant_id: `${v}.selected_or_first_available_variant.id`,
|
|
346413
|
+
tags: `${v}.tags | join: ', '`
|
|
346414
|
+
}),
|
|
346415
|
+
"commerce.collection": (v) => ({ title: `${v}.title`, handle: `${v}.handle`, url: `${v}.url`, description: `${v}.description | strip_html` }),
|
|
346416
|
+
"commerce.cartLine": (v) => ({
|
|
346417
|
+
title: `${v}.product.title`,
|
|
346418
|
+
variant: `${v}.variant.title`,
|
|
346419
|
+
url: `${v}.url`,
|
|
346420
|
+
image: `${v}.image | image_url: width: 300`,
|
|
346421
|
+
quantity: `${v}.quantity`,
|
|
346422
|
+
price: `${v}.final_line_price | money`,
|
|
346423
|
+
merchandise_id: `${v}.key`
|
|
346424
|
+
}),
|
|
346425
|
+
"commerce.cart": () => ({ count: "cart.item_count", subtotal: "cart.items_subtotal_price | money", taxes: "'Calculated at checkout'", total: "cart.total_price | money", checkout_url: "routes.cart_url" }),
|
|
346426
|
+
"commerce.menu": (v) => ({ title: `${v}.title`, url: `${v}.url` })
|
|
346427
|
+
};
|
|
346428
|
+
LOOP_VAR = { "commerce.product": "p", "commerce.collection": "c", "commerce.cartLine": "line", "commerce.cart": "cart", "commerce.menu": "link" };
|
|
346429
|
+
FORMS = {
|
|
346430
|
+
addToCart: { action: "/cart/add", method: "post" },
|
|
346431
|
+
updateCartLine: { action: "/cart/change", method: "post" },
|
|
346432
|
+
removeCartLine: { action: "/cart/change", method: "post", fields: '<input type="hidden" name="quantity" value="0" />' },
|
|
346433
|
+
checkout: { action: "/cart", method: "post", fields: '<input type="hidden" name="checkout" value="1" />' },
|
|
346434
|
+
search: { action: "/search", method: "get" }
|
|
346435
|
+
};
|
|
346436
|
+
every2 = (n, out = []) => {
|
|
346437
|
+
out.push(n);
|
|
346438
|
+
n.children.forEach((c2) => every2(c2, out));
|
|
346439
|
+
n.repeat?.template.forEach((c2) => every2(c2, out));
|
|
346440
|
+
return out;
|
|
346441
|
+
};
|
|
346442
|
+
}
|
|
346443
|
+
});
|
|
346444
|
+
|
|
346445
|
+
// lib/io/web/project/storefront.ts
|
|
346446
|
+
var storefront_exports = {};
|
|
346447
|
+
__export(storefront_exports, {
|
|
346448
|
+
STOREFRONT_TARGETS: () => STOREFRONT_TARGETS,
|
|
346449
|
+
STOREFRONT_TARGET_IDS: () => STOREFRONT_TARGET_IDS,
|
|
346450
|
+
storefrontDesign: () => storefrontDesign
|
|
346451
|
+
});
|
|
346452
|
+
function storefrontDesign(doc2, screens) {
|
|
346453
|
+
const named = (id3) => doc2.collections?.[id3];
|
|
346454
|
+
const pages2 = screens.map((s) => {
|
|
346455
|
+
let root2 = s.tree.root;
|
|
346456
|
+
if (s.about) root2 = boundNode(root2, (key5) => `{{page.${key5}}}`);
|
|
346457
|
+
const relist = (n) => ({ ...n, children: n.children.map(relist), ...n.repeat ? { repeat: { ...n.repeat, template: n.repeat.template.map((c2) => relist(boundNode(c2, (key5) => `{{item.${key5}}}`))) } } : {} });
|
|
346458
|
+
const html = serializeHTML({ ...s.tree, root: relist(root2) }, {
|
|
346459
|
+
ids: true,
|
|
346460
|
+
lists: (n) => {
|
|
346461
|
+
const c2 = n.repeat && named(n.repeat.collectionId);
|
|
346462
|
+
if (!c2 || !n.repeat) return null;
|
|
346463
|
+
const range3 = `${n.repeat.limit ? ` limit="${n.repeat.limit}"` : ""}${n.repeat.offset ? ` offset="${n.repeat.offset}"` : ""}`;
|
|
346464
|
+
return { open: `<!-- pc:each list="${c2.name}" schema="${c2.schema ?? ""}" as="item"${range3} -->`, close: "<!-- pc:end -->" };
|
|
346465
|
+
},
|
|
346466
|
+
form: (n) => n.action ? { attrs: { "data-pc-action": n.action } } : null
|
|
346467
|
+
});
|
|
346468
|
+
const route2 = doc2.nodes[s.id]?.route?.path ?? null;
|
|
346469
|
+
return { name: s.name, route: route2, about: s.about?.schema ?? null, html };
|
|
346470
|
+
});
|
|
346471
|
+
const collections = Object.values(doc2.collections ?? {}).map((c2) => ({
|
|
346472
|
+
id: c2.id,
|
|
346473
|
+
name: c2.name,
|
|
346474
|
+
schema: c2.schema ?? null,
|
|
346475
|
+
fields: c2.fields.map((f2) => fieldKey(f2.name)),
|
|
346476
|
+
samples: recordsIn(doc2, c2.id).map((r) => Object.fromEntries(c2.fields.map((f2) => [fieldKey(f2.name), r.values[f2.id] ?? null])))
|
|
346477
|
+
}));
|
|
346478
|
+
return { name: doc2.name, pages: pages2, collections };
|
|
346479
|
+
}
|
|
346480
|
+
var STOREFRONT_TARGETS;
|
|
346481
|
+
var init_storefront = __esm({
|
|
346482
|
+
"lib/io/web/project/storefront.ts"() {
|
|
346483
|
+
init_components();
|
|
346484
|
+
init_shopify_theme();
|
|
346485
|
+
init_collections();
|
|
346486
|
+
init_html();
|
|
346487
|
+
init_storefront_targets();
|
|
346488
|
+
init_storefront_targets();
|
|
346489
|
+
STOREFRONT_TARGETS = {
|
|
346490
|
+
"next-commerce": {
|
|
346491
|
+
id: "next-commerce",
|
|
346492
|
+
...STOREFRONT_TARGET_INFO["next-commerce"],
|
|
346493
|
+
files: (doc2, screens, o) => componentFiles(doc2, screens, { media: o.media, styling: o.styling })
|
|
346494
|
+
},
|
|
346495
|
+
"shopify-theme": {
|
|
346496
|
+
id: "shopify-theme",
|
|
346497
|
+
...STOREFRONT_TARGET_INFO["shopify-theme"],
|
|
346498
|
+
files: (doc2, screens, o) => shopifyThemeFiles(doc2, screens, { media: o.media })
|
|
346499
|
+
}
|
|
346500
|
+
};
|
|
346501
|
+
}
|
|
346502
|
+
});
|
|
346503
|
+
|
|
345829
346504
|
// lib/io/csv.ts
|
|
345830
346505
|
function toCsv(rows, delimiter = ",") {
|
|
345831
346506
|
return rows.map((r) => r.map((c2) => quote3(c2, delimiter)).join(delimiter)).join("\n");
|
|
@@ -346088,11 +346763,12 @@ async function exportSite(doc2, pageId2, packaging, styling = "css") {
|
|
|
346088
346763
|
downloadBlob2(zipFiles2(files.map((f2) => ({ name: f2.path, bytes: bytesOf2(f2) }))), `${base}.zip`);
|
|
346089
346764
|
return { summary: `Exported ${plural2(site.pages.length, "page")} as ${packaging === "next" ? "a Next.js project" : "a static site"} (${base}.zip)`, data: { filename: `${base}.zip`, packaging, pages: site.pages.map((p2) => p2.route), files: files.length } };
|
|
346090
346765
|
}
|
|
346091
|
-
var MAX_INLINE_BYTES, exportSvg, exportNodes, exportPdf, exportCopy, exportPages, exportPptx, animationParams, videoParams, gifParams, lottieParams, animationCommand, TARGET, exportMp4, exportWebm, exportGif, exportPngSequence, exportLottie2, EXPORT_NODE_CAP, exportWeb, exportBoard;
|
|
346766
|
+
var MAX_INLINE_BYTES, exportSvg, exportNodes, exportPdf, exportCopy, exportPages, exportPptx, animationParams, videoParams, gifParams, lottieParams, animationCommand, TARGET, exportMp4, exportWebm, exportGif, exportPngSequence, exportLottie2, EXPORT_NODE_CAP, exportWeb, exportStorefront, exportBoard;
|
|
346092
346767
|
var init_export2 = __esm({
|
|
346093
346768
|
"lib/commands/export.ts"() {
|
|
346094
346769
|
"use strict";
|
|
346095
346770
|
init_zod();
|
|
346771
|
+
init_storefront_targets();
|
|
346096
346772
|
init_errors();
|
|
346097
346773
|
init_types5();
|
|
346098
346774
|
init_ui();
|
|
@@ -346493,6 +347169,58 @@ var init_export2 = __esm({
|
|
|
346493
347169
|
return { summary: `Exported ${node2.name || "layer"} as ${filename}`, data: { filename, format, bytes: markup.length, truncated: tree.truncated } };
|
|
346494
347170
|
}
|
|
346495
347171
|
});
|
|
347172
|
+
exportStorefront = defineCommand({
|
|
347173
|
+
id: "export.storefront",
|
|
347174
|
+
title: "Export storefront",
|
|
347175
|
+
domain: "export",
|
|
347176
|
+
effect: "none",
|
|
347177
|
+
permission: "export",
|
|
347178
|
+
needs: ["canvas"],
|
|
347179
|
+
params: external_exports.object({
|
|
347180
|
+
target: external_exports.enum(STOREFRONT_TARGET_IDS).default("next-commerce").describe("next-commerce: React components a Next.js Commerce store renders with its own data and server actions. shopify-theme: an Online Store 2.0 theme (Liquid) to upload in the store's admin, running on Shopify with its own cart and checkout."),
|
|
347181
|
+
styling: external_exports.enum(["inline", "tailwind"]).optional().describe("next-commerce: style objects (default) or Tailwind CSS v4 classes."),
|
|
347182
|
+
dir: external_exports.string().max(200).optional().describe("next-commerce: where the components go in the store's project (default components/popcraft).")
|
|
347183
|
+
}).strict(),
|
|
347184
|
+
expose: {
|
|
347185
|
+
ui: {
|
|
347186
|
+
label: "Export storefront\u2026",
|
|
347187
|
+
keywords: ["commerce", "shopify", "theme", "liquid", "store", "shop", "next", "react", "components", "export"],
|
|
347188
|
+
variants: [
|
|
347189
|
+
{ id: "next-commerce", label: "Export storefront as Next.js Commerce components", params: { target: "next-commerce" } },
|
|
347190
|
+
{ id: "shopify-theme", label: "Export storefront as a Shopify theme", params: { target: "shopify-theme" } }
|
|
347191
|
+
]
|
|
347192
|
+
},
|
|
347193
|
+
agent: { name: "export_storefront", readOnly: false, description: "Download a storefront design (a page whose lists and pages read collections with a commerce schema) as a store's project, in a zip. target next-commerce: a React component per screen, each list a typed prop of Next.js Commerce's own types, each storefront form (addToCart, updateCartLine, removeCartLine, checkout, search) an action prop for a server action. target shopify-theme: an Online Store 2.0 theme, each screen a section and template (home: index, a page about a product: product, about a category: collection, search, cart), each list a Liquid loop over the store's products, cart or menu, each form posting to Shopify's cart; uploaded in Online Store \u203A Themes. With no store data a Next.js Commerce component draws the design's samples." }
|
|
347194
|
+
},
|
|
347195
|
+
run: async (args2, ctx2) => {
|
|
347196
|
+
const doc2 = ctx2.doc();
|
|
347197
|
+
const [{ componentMedia: componentMedia2, componentScreens: componentScreens2 }, { STOREFRONT_TARGETS: STOREFRONT_TARGETS2 }, { bytesOf: bytesOf2 }, { fileBase: fileBase2, flatten: flatten3, resolveWebAssets: resolveWebAssets2 }, { rendererAssetResolvers: rendererAssetResolvers2 }, { zipFiles: zipFiles2 }, { downloadBlob: downloadBlob2 }, { loadMediaBlob: loadMediaBlob2 }] = await Promise.all([
|
|
347198
|
+
Promise.resolve().then(() => (init_components(), components_exports)),
|
|
347199
|
+
Promise.resolve().then(() => (init_storefront(), storefront_exports)),
|
|
347200
|
+
Promise.resolve().then(() => (init_project(), project_exports)),
|
|
347201
|
+
Promise.resolve().then(() => (init_web(), web_exports)),
|
|
347202
|
+
Promise.resolve().then(() => (init_resolvers(), resolvers_exports)),
|
|
347203
|
+
Promise.resolve().then(() => (init_zip_export(), zip_export_exports)),
|
|
347204
|
+
Promise.resolve().then(() => (init_download(), download_exports)),
|
|
347205
|
+
Promise.resolve().then(() => (init_media_store(), media_store_exports))
|
|
347206
|
+
]);
|
|
347207
|
+
const target2 = STOREFRONT_TARGETS2[args2.target];
|
|
347208
|
+
const screens = componentScreens2(doc2, ctx2.pageId(), EXPORT_NODE_CAP);
|
|
347209
|
+
if (!screens.length) throw new ToolError("This page has no screens: a top-level frame is a page of the store.");
|
|
347210
|
+
const resolvers = rendererAssetResolvers2(doc2);
|
|
347211
|
+
for (const s of screens) if (flatten3(s.tree.root).some((n) => n.asset)) await resolveWebAssets2(s.tree, resolvers);
|
|
347212
|
+
const media2 = {};
|
|
347213
|
+
await Promise.all(componentMedia2(doc2, screens).map(async (ref3) => {
|
|
347214
|
+
const blob = await loadMediaBlob2(ref3).catch(() => null);
|
|
347215
|
+
if (blob) media2[ref3] = { bytes: new Uint8Array(await blob.arrayBuffer()), type: blob.type };
|
|
347216
|
+
}));
|
|
347217
|
+
const files = args2.target === "next-commerce" && args2.dir ? (await Promise.resolve().then(() => (init_components(), components_exports))).componentFiles(doc2, screens, { styling: args2.styling, dir: args2.dir, media: media2 }) : target2.files(doc2, screens, { media: media2, styling: args2.styling });
|
|
347218
|
+
const base = `${fileBase2(doc2.name)}-${args2.target}`;
|
|
347219
|
+
downloadBlob2(zipFiles2(files.map((f2) => ({ name: f2.path, bytes: bytesOf2(f2) }))), `${base}.zip`);
|
|
347220
|
+
const bound = screens.filter((s) => s.about || flatten3(s.tree.root).some((n) => n.repeat && doc2.collections?.[n.repeat.collectionId]?.schema)).length;
|
|
347221
|
+
return { summary: `Exported ${plural2(screens.length, "page")} (${bound} bound to store data) as ${target2.label} (${base}.zip)`, data: { filename: `${base}.zip`, target: args2.target, pages: screens.map((s) => s.name), files: files.length } };
|
|
347222
|
+
}
|
|
347223
|
+
});
|
|
346496
347224
|
exportBoard = defineCommand({
|
|
346497
347225
|
id: "export.board",
|
|
346498
347226
|
title: "Export board",
|
|
@@ -347244,7 +347972,7 @@ function selectedImageTarget(doc2, selection) {
|
|
|
347244
347972
|
}
|
|
347245
347973
|
function withImage(node2, ref3) {
|
|
347246
347974
|
if (node2.type === "IMAGE") return { imageUrl: ref3 };
|
|
347247
|
-
const fills = (node2.fills ?? []).map((p2, i2,
|
|
347975
|
+
const fills = (node2.fills ?? []).map((p2, i2, all4) => p2.type === "IMAGE" && all4.findIndex((q) => q.type === "IMAGE") === i2 ? { ...p2, imageUrl: ref3, imageHash: void 0 } : p2);
|
|
347248
347976
|
return { fills };
|
|
347249
347977
|
}
|
|
347250
347978
|
function importSvgLayers(doc2, pageId2, svg, name2, cx, cy) {
|
|
@@ -348333,9 +349061,9 @@ var init_motion2 = __esm({
|
|
|
348333
349061
|
},
|
|
348334
349062
|
run: (args2, ctx2) => {
|
|
348335
349063
|
const doc2 = ctx2.doc();
|
|
348336
|
-
const
|
|
349064
|
+
const all4 = Object.values(doc2.compositions ?? {});
|
|
348337
349065
|
if (args2.id && !doc2.compositions?.[args2.id]) throw new ToolError(`There is no composition "${args2.id}".`);
|
|
348338
|
-
const list2 = args2.id ? [doc2.compositions[args2.id]] :
|
|
349066
|
+
const list2 = args2.id ? [doc2.compositions[args2.id]] : all4;
|
|
348339
349067
|
const hex10 = (c2) => c2 ? "#" + [c2.r, c2.g, c2.b].map((v) => Math.round(v * 255).toString(16).padStart(2, "0")).join("") : void 0;
|
|
348340
349068
|
const data = list2.map((c2) => ({
|
|
348341
349069
|
id: c2.id,
|
|
@@ -352289,7 +353017,6 @@ function publishSite(key5, files, opts = {}) {
|
|
|
352289
353017
|
var siteStatus, setSiteVersion, renameSite;
|
|
352290
353018
|
var init_sites = __esm({
|
|
352291
353019
|
"lib/client/cloud/sites.ts"() {
|
|
352292
|
-
"use strict";
|
|
352293
353020
|
init_files();
|
|
352294
353021
|
init_upload2();
|
|
352295
353022
|
init_api4();
|
|
@@ -352417,7 +353144,8 @@ __export(integrations_exports, {
|
|
|
352417
353144
|
listWorkspaceIntegrations: () => listWorkspaceIntegrations,
|
|
352418
353145
|
removeDestination: () => removeDestination,
|
|
352419
353146
|
setSignIn: () => setSignIn,
|
|
352420
|
-
siteBackend: () => siteBackend
|
|
353147
|
+
siteBackend: () => siteBackend,
|
|
353148
|
+
storeProducts: () => storeProducts
|
|
352421
353149
|
});
|
|
352422
353150
|
function connectWithOAuth(workspaceId, provider2) {
|
|
352423
353151
|
const popup = window.open("", "popcraft-integration", "popup,width=640,height=760");
|
|
@@ -352450,7 +353178,7 @@ function connectWithOAuth(workspaceId, provider2) {
|
|
|
352450
353178
|
});
|
|
352451
353179
|
});
|
|
352452
353180
|
}
|
|
352453
|
-
var integrationsWorkspaceId, listWorkspaceIntegrations, connectWithToken, disconnect, listResources, createResource, listDestinations, addDestination, removeDestination, deployDestination, siteBackend, attachDatabase, setSignIn, detachDatabase, listSubmissions, listCandidates, createDatabase, createDestination;
|
|
353181
|
+
var integrationsWorkspaceId, listWorkspaceIntegrations, connectWithToken, disconnect, listResources, createResource, listDestinations, addDestination, removeDestination, deployDestination, siteBackend, attachDatabase, setSignIn, detachDatabase, listSubmissions, listCandidates, createDatabase, createDestination, storeProducts;
|
|
352454
353182
|
var init_integrations = __esm({
|
|
352455
353183
|
"lib/client/cloud/integrations.ts"() {
|
|
352456
353184
|
init_api4();
|
|
@@ -352473,6 +353201,7 @@ var init_integrations = __esm({
|
|
|
352473
353201
|
listCandidates = async (workspaceId, capability2) => (await api(`/api/workspaces/${encodeURIComponent(workspaceId)}/integrations/candidates?capability=${capability2}`)).candidates;
|
|
352474
353202
|
createDatabase = (key5, provider2, connectionId) => api(`/api/sites/${key5}/backend`, { method: "PUT", json: { create: true, ...provider2 ? { provider: provider2 } : {}, ...connectionId ? { connectionId } : {} } });
|
|
352475
353203
|
createDestination = async (key5, capability2, provider2, connectionId) => (await api(`/api/sites/${key5}/destinations`, { method: "POST", json: { create: true, capability: capability2, ...provider2 ? { provider: provider2 } : {}, ...connectionId ? { connectionId } : {} } })).destination;
|
|
353204
|
+
storeProducts = async (connectionId, first2) => (await api(`/api/integrations/connections/${encodeURIComponent(connectionId)}/products?first=${first2}`)).products;
|
|
352476
353205
|
}
|
|
352477
353206
|
});
|
|
352478
353207
|
|
|
@@ -353542,11 +354271,11 @@ function allThemes(s) {
|
|
|
353542
354271
|
return map2;
|
|
353543
354272
|
}
|
|
353544
354273
|
function pickableThemes(s) {
|
|
353545
|
-
const
|
|
354274
|
+
const all4 = allThemes(s);
|
|
353546
354275
|
const builtinIds = new Set(BUILTIN_THEMES.map((t3) => t3.id));
|
|
353547
354276
|
return [
|
|
353548
|
-
...PICKABLE_BUILTIN_IDS.map((id3) =>
|
|
353549
|
-
...[...
|
|
354277
|
+
...PICKABLE_BUILTIN_IDS.map((id3) => all4.get(id3)),
|
|
354278
|
+
...[...all4.values()].filter((t3) => !builtinIds.has(t3.id))
|
|
353550
354279
|
];
|
|
353551
354280
|
}
|
|
353552
354281
|
function computeAppliedTheme(s) {
|
|
@@ -353585,15 +354314,15 @@ function usePickableThemes() {
|
|
|
353585
354314
|
const userThemes = useThemeStore((s) => s.userThemes);
|
|
353586
354315
|
const pluginThemes = useThemeStore((s) => s.pluginThemes);
|
|
353587
354316
|
const localThemes = useThemeStore((s) => s.localThemes);
|
|
353588
|
-
return (0,
|
|
354317
|
+
return (0, import_react9.useMemo)(() => pickableThemes({ userThemes, pluginThemes, localThemes }), [userThemes, pluginThemes, localThemes]);
|
|
353589
354318
|
}
|
|
353590
|
-
var
|
|
354319
|
+
var import_react9, IDB_KEY, useThemeStore, cssString, defaultAccent, effectiveAccent;
|
|
353591
354320
|
var init_theme_store = __esm({
|
|
353592
354321
|
"lib/theme/theme-store.ts"() {
|
|
353593
354322
|
init_contrast();
|
|
353594
354323
|
init_idb();
|
|
353595
354324
|
init_esm();
|
|
353596
|
-
|
|
354325
|
+
import_react9 = __toESM(require_react());
|
|
353597
354326
|
init_boot2();
|
|
353598
354327
|
init_builtin();
|
|
353599
354328
|
init_resolve();
|
|
@@ -354987,6 +355716,62 @@ before proposing anything, and recommend the least that covers it.
|
|
|
354987
355716
|
}
|
|
354988
355717
|
});
|
|
354989
355718
|
|
|
355719
|
+
// lib/agent/skills/builtin/storefront.ts
|
|
355720
|
+
var storefront;
|
|
355721
|
+
var init_storefront2 = __esm({
|
|
355722
|
+
"lib/agent/skills/builtin/storefront.ts"() {
|
|
355723
|
+
"use strict";
|
|
355724
|
+
storefront = {
|
|
355725
|
+
id: "storefront",
|
|
355726
|
+
name: "Design a storefront",
|
|
355727
|
+
description: "Bind a shop to a store's data and export it for Next.js Commerce or Shopify.",
|
|
355728
|
+
whenToUse: "the design should sell",
|
|
355729
|
+
tools: ["get_document_outline", "edit_collection", "edit_records", "set_repeat", "set_route", "set_control", "export_storefront", "list_integrations", "open_integrations", "pull_store_products", "ask_user", "manage_todos"],
|
|
355730
|
+
instructions: `# Design a storefront
|
|
355731
|
+
|
|
355732
|
+
PopCraft draws the shop; a Next.js Commerce store runs it. The store keeps Shopify, the cart, checkout and search;
|
|
355733
|
+
the design binds to the store's data through collections with a **commerce schema**, and is exported as React
|
|
355734
|
+
components the store renders with its products and server actions. Starting fresh, the Fieldwork and Kiln templates
|
|
355735
|
+
are whole stores to begin from.
|
|
355736
|
+
|
|
355737
|
+
## Steps
|
|
355738
|
+
|
|
355739
|
+
1. **Read the design.** \`get_document_outline\`: which screens are the store's pages (home, search, a product, the
|
|
355740
|
+
cart), where products are listed, where the cart and its totals are.
|
|
355741
|
+
2. **The data.** \`edit_collection\` with \`schema\` and no fields makes a collection whose fields are the schema's:
|
|
355742
|
+
- \`commerce.product\` for products (title, handle, url, description, price, image, variant_id\u2026)
|
|
355743
|
+
- \`commerce.cartLine\` for the cart's lines, \`commerce.cart\` for its count and totals (one record)
|
|
355744
|
+
- \`commerce.menu\` for the store's menu, \`commerce.collection\` for its categories
|
|
355745
|
+
Add a few real sample records with \`edit_records\`: the canvas is drawn with them. When the user has a Shopify
|
|
355746
|
+
store, draw the design with its real products instead: \`list_integrations\` (capability commerce) for a connected
|
|
355747
|
+
store, then \`pull_store_products\`. You cannot connect a store yourself: say why it helps and \`open_integrations\`.
|
|
355748
|
+
3. **The lists.** \`set_repeat\` on the frame that holds one card, over the collection; the card's texts say
|
|
355749
|
+
\`{{item.title}}\`, \`{{item.price}}\`, and its picture follows \`item_image\`. The cart's totals are a list of one
|
|
355750
|
+
(\`limit: 1\`) over the \`commerce.cart\` collection.
|
|
355751
|
+
4. **A page per product.** \`set_route\` on the product screen with the product collection's id: the route is
|
|
355752
|
+
\`/product\` and each product's page is \`/product/<handle>\`. A card links to that screen.
|
|
355753
|
+
5. **The forms.** \`set_control\` FORM with a storefront \`formAction\`:
|
|
355754
|
+
- \`addToCart\`: needs a hidden INPUT named \`merchandiseId\`, value \`{{item.variant_id}}\`
|
|
355755
|
+
- \`removeCartLine\` or \`updateCartLine\` inside a cart line: \`merchandiseId\` is \`{{item.merchandise_id}}\`
|
|
355756
|
+
- \`checkout\`
|
|
355757
|
+
- \`search\`: a field named \`q\`
|
|
355758
|
+
6. **Export.** \`export_storefront\` writes the store's project, for the store the user runs:
|
|
355759
|
+
- \`target: 'next-commerce'\`: components, a prop per list (\`products\`, \`cartLines\`, \`cart\`, \`menu\`), \`product\` on a
|
|
355760
|
+
product's page, and \`onAddToCart\`, \`onCheckout\`\u2026 for the forms; the store passes its \`lib/shopify\` data and its
|
|
355761
|
+
server actions.
|
|
355762
|
+
- \`target: 'shopify-theme'\`: an Online Store 2.0 theme the user uploads in Shopify (Online Store \u203A Themes), running
|
|
355763
|
+
on Shopify with its own cart and checkout.
|
|
355764
|
+
Say which, and where it goes (/docs/exporting/commerce).
|
|
355765
|
+
|
|
355766
|
+
## Rules
|
|
355767
|
+
|
|
355768
|
+
- Never invent a Shopify connection, an API key or an order flow in the design: the store owns those.
|
|
355769
|
+
- Product copy is real (a material, a size, what it is for), never lorem ipsum.
|
|
355770
|
+
- One schema per collection; two lists of one collection (featured, new) share one prop, each with its own limit.`
|
|
355771
|
+
};
|
|
355772
|
+
}
|
|
355773
|
+
});
|
|
355774
|
+
|
|
354990
355775
|
// lib/agent/skills/builtin/index.ts
|
|
354991
355776
|
var BUILTIN_SKILLS;
|
|
354992
355777
|
var init_builtin2 = __esm({
|
|
@@ -355011,6 +355796,7 @@ var init_builtin2 = __esm({
|
|
|
355011
355796
|
init_design_code();
|
|
355012
355797
|
init_design_review();
|
|
355013
355798
|
init_web_app();
|
|
355799
|
+
init_storefront2();
|
|
355014
355800
|
BUILTIN_SKILLS = [
|
|
355015
355801
|
fillContent,
|
|
355016
355802
|
autoLayout,
|
|
@@ -355030,7 +355816,8 @@ var init_builtin2 = __esm({
|
|
|
355030
355816
|
campaignPack,
|
|
355031
355817
|
designCode,
|
|
355032
355818
|
designReview,
|
|
355033
|
-
webApp
|
|
355819
|
+
webApp,
|
|
355820
|
+
storefront
|
|
355034
355821
|
].map((s) => ({ ...s, source: "builtin" }));
|
|
355035
355822
|
}
|
|
355036
355823
|
});
|
|
@@ -357376,16 +358163,16 @@ var init_api5 = __esm({
|
|
|
357376
358163
|
}
|
|
357377
358164
|
});
|
|
357378
358165
|
|
|
357379
|
-
// node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=
|
|
358166
|
+
// node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=997b73fa0364896bf8afb3420ac81e52de261b88cad7cac3e2e206341916c9a5/node_modules/@popcraft/plugins/dist/generated/runtime.js
|
|
357380
358167
|
var MAIN_RUNTIME, UI_RUNTIME;
|
|
357381
358168
|
var init_runtime4 = __esm({
|
|
357382
|
-
"node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=
|
|
357383
|
-
MAIN_RUNTIME = '"use strict";\n(() => {\n // src/runtime/rpc.ts\n function createRpcClient() {\n let port = null;\n const queue = [];\n const pending = {};\n const listeners = {};\n let nextId = 1;\n function send(msg) {\n if (port) port.postMessage(msg);\n else queue.push(msg);\n }\n function call(method, params) {\n return new Promise((resolve, reject) => {\n const id = nextId++;\n pending[id] = { resolve, reject };\n send({ kind: "rpc", id, method, params });\n });\n }\n function emit(event, data) {\n for (const cb of (listeners[event] || []).slice()) {\n try {\n cb(data);\n } catch (e) {\n console.error(e);\n }\n }\n }\n window.addEventListener("message", (e) => {\n const data = e.data;\n if (e.source !== window.parent || !data || data.type !== "popcraft-plugin-port" || port) return;\n port = e.ports[0];\n port.onmessage = (ev) => {\n const m = ev.data || {};\n if (m.kind === "result" && m.id !== void 0 && pending[m.id]) {\n const p = pending[m.id];\n delete pending[m.id];\n if (m.error) p.reject(new Error(m.error));\n else p.resolve(m.result);\n } else if (m.kind === "event" && m.event) {\n emit(m.event, m.data);\n }\n };\n for (const msg of queue.splice(0)) port.postMessage(msg);\n });\n return {\n call,\n send,\n on(event, cb) {\n (listeners[event] = listeners[event] || []).push(cb);\n },\n off(event, cb) {\n listeners[event] = (listeners[event] || []).filter((x) => x !== cb);\n }\n };\n }\n\n // src/runtime/main.ts\n function clone(v) {\n return v === void 0 ? {} : JSON.parse(JSON.stringify(v));\n }\n function createMainApi(rpc = createRpcClient()) {\n const uiHandlers = [];\n let uiOnMessage = null;\n const uiQueue = [];\n function deliverUI(msg) {\n for (const cb of uiHandlers) {\n try {\n cb(msg);\n } catch (e) {\n console.error(e);\n }\n }\n if (typeof uiOnMessage === "function") {\n try {\n uiOnMessage(msg);\n } catch (e) {\n console.error(e);\n }\n }\n }\n function flushUI() {\n if (uiHandlers.length || typeof uiOnMessage === "function") uiQueue.splice(0).forEach(deliverUI);\n }\n rpc.on("uimessage", (msg) => {\n if (!uiHandlers.length && typeof uiOnMessage !== "function") uiQueue.push(msg);\n else deliverUI(msg);\n });\n let widgetDef = null;\n const widgetQueue = [];\n function renderWidget(state) {\n const handlers = {};\n function walk(el, path) {\n if (!el || typeof el !== "object") return el;\n const out = {};\n for (const k of Object.keys(el)) {\n const v = el[k];\n if (k === "children") {\n out.children = (Array.isArray(v) ? v : [v]).filter((c) => c !== null && c !== void 0 && c !== false).map((c, i) => walk(c, path + "." + i));\n } else if (k === "onClick" && typeof v === "function") {\n handlers[path] = v;\n out.onClick = path;\n } else {\n out[k] = v;\n }\n }\n return out;\n }\n return { tree: walk(widgetDef.render(state), "root"), handlers };\n }\n function initialWidgetState() {\n const s = widgetDef && widgetDef.initialState;\n return clone(typeof s === "function" ? s() : s);\n }\n function commitWidget(nodeId, state) {\n return rpc.call("widgetUpdate", { id: nodeId, state, tree: renderWidget(clone(state)).tree });\n }\n function handleWidgetClick(e) {\n Promise.resolve().then(() => {\n const state = clone(e.state);\n const rendered = renderWidget(state);\n const h = rendered.handlers[e.handler] || widgetDef.handlers && widgetDef.handlers[e.handler];\n if (typeof h !== "function") return;\n return Promise.resolve(h(state, { nodeId: e.nodeId })).then((ret) => commitWidget(e.nodeId, ret === void 0 ? state : ret));\n }).catch((err) => rpc.send({ kind: "error", message: String((err == null ? void 0 : err.message) || err) }));\n }\n rpc.on("widgetclick", (e) => {\n if (widgetDef) handleWidgetClick(e);\n else widgetQueue.push(e);\n });\n const popcraft = {\n /** Which menu command the user picked, or null when the plugin ran some other way. */\n command: null,\n /** Host import mode when launched as an importer, else null. */\n importMode: null,\n /** Pending import file when the host handed one over, else null. */\n importFile: null,\n /** Pending export request when the host started this plugin as an exporter, else null. */\n exportRequest: null,\n getSelection: () => rpc.call("getSelection"),\n setSelection: (ids) => rpc.call("setSelection", { ids }),\n getNode: (id) => rpc.call("getNode", { id }),\n findNodes: (query) => rpc.call("findNodes", query || {}),\n getCurrentPage: () => rpc.call("getCurrentPage"),\n createNode: (type, props) => rpc.call("createNode", { type, props: props || {} }),\n updateNode: (id, props) => rpc.call("updateNode", { id, props }),\n deleteNode: (id) => rpc.call("deleteNode", { id }),\n setText: (id, characters) => rpc.call("setText", { id, characters }),\n setTextPath: (opts) => rpc.call("setTextPath", opts || {}),\n flowTextIntoShape: (opts) => rpc.call("flowTextIntoShape", opts || {}),\n detachText: (opts) => rpc.call("detachText", opts || {}),\n setTextFit: (opts) => rpc.call("setTextFit", opts || {}),\n createPage: (name) => rpc.call("createPage", name != null ? { name: String(name) } : {}),\n setCurrentPage: (pageId) => rpc.call("setCurrentPage", { pageId }),\n createImage: (opts) => rpc.call("createImage", opts || {}),\n createDocument: (opts) => rpc.call("createDocument", opts || {}),\n getImportMode: () => rpc.call("getImportMode"),\n getImportFile: () => rpc.call("getImportFile"),\n getExportRequest: () => rpc.call("getExportRequest"),\n saveExport: (file) => rpc.call("saveExport", file || {}),\n getPresentationAudio: (opts) => rpc.call("getPresentationAudio", opts || {}),\n setPresentationAudioSettings: (opts) => rpc.call("setPresentationAudioSettings", opts || {}),\n setPresentationAudioClip: (opts) => rpc.call("setPresentationAudioClip", opts || {}),\n removePresentationAudioClip: (opts) => rpc.call("removePresentationAudioClip", opts || {}),\n setPresentationTiming: (opts) => rpc.call("setPresentationTiming", opts || {}),\n getPresentationMix: (opts) => rpc.call("getPresentationMix", opts || {}),\n requestPresentationAudio: (opts) => rpc.call("requestPresentationAudio", opts || {}),\n moveNodes: (opts) => rpc.call("moveNodes", opts || {}),\n resizeNodes: (opts) => rpc.call("resizeNodes", opts || {}),\n renameNodes: (opts) => rpc.call("renameNodes", opts || {}),\n reparentNodes: (opts) => rpc.call("reparentNodes", opts || {}),\n duplicateNodes: (opts) => rpc.call("duplicateNodes", opts || {}),\n groupNodes: (opts) => rpc.call("groupNodes", opts || {}),\n ungroupNodes: (opts) => rpc.call("ungroupNodes", opts || {}),\n alignNodes: (opts) => rpc.call("alignNodes", opts || {}),\n distributeNodes: (opts) => rpc.call("distributeNodes", opts || {}),\n flipNodes: (opts) => rpc.call("flipNodes", opts || {}),\n rotateNodes: (opts) => rpc.call("rotateNodes", opts || {}),\n reorderNodes: (opts) => rpc.call("reorderNodes", opts || {}),\n setLocked: (opts) => rpc.call("setLocked", opts || {}),\n setVisible: (opts) => rpc.call("setVisible", opts || {}),\n setAutoLayout: (opts) => rpc.call("setAutoLayout", opts || {}),\n importSvg: (opts) => rpc.call("importSvg", opts || {}),\n measureNodes: (opts) => rpc.call("measureNodes", opts || {}),\n setFills: (opts) => rpc.call("setFills", opts || {}),\n setStrokes: (opts) => rpc.call("setStrokes", opts || {}),\n setEffects: (opts) => rpc.call("setEffects", opts || {}),\n replaceColor: (opts) => rpc.call("replaceColor", opts || {}),\n setTypography: (opts) => rpc.call("setTypography", opts || {}),\n applyStyle: (opts) => rpc.call("applyStyle", opts || {}),\n createComponent: (opts) => rpc.call("createComponent", opts || {}),\n createInstance: (opts) => rpc.call("createInstance", opts || {}),\n renamePage: (opts) => rpc.call("renamePage", opts || {}),\n getDocumentOutline: (opts) => rpc.call("getDocumentOutline", opts || {}),\n setPageSetup: (opts) => rpc.call("setPageSetup", opts || {}),\n setShowAdvance: (opts) => rpc.call("setShowAdvance", opts || {}),\n booleanOperation: (opts) => rpc.call("booleanOperation", opts || {}),\n flattenNodes: (opts) => rpc.call("flattenNodes", opts || {}),\n outlineStroke: (opts) => rpc.call("outlineStroke", opts || {}),\n setMask: (opts) => rpc.call("setMask", opts || {}),\n setMaskType: (opts) => rpc.call("setMaskType", opts || {}),\n shapeBuilder: (opts) => rpc.call("shapeBuilder", opts || {}),\n setKeyframes: (opts) => rpc.call("setKeyframes", opts || {}),\n getAnimation: (opts) => rpc.call("getAnimation", opts || {}),\n getCompositions: (opts) => rpc.call("getCompositions", opts || {}),\n editBehaviours: (opts) => rpc.call("editBehaviours", opts || {}),\n setTimeline: (opts) => rpc.call("setTimeline", opts || {}),\n setLayerTiming: (opts) => rpc.call("setLayerTiming", opts || {}),\n editTextAnimation: (opts) => rpc.call("editTextAnimation", opts || {}),\n edit3DScene: (opts) => rpc.call("edit3DScene", opts || {}),\n setInstancePlayback: (opts) => rpc.call("setInstancePlayback", opts || {}),\n editComponentProperty: (opts) => rpc.call("editComponentProperty", opts || {}),\n setShaderFill: (opts) => rpc.call("setShaderFill", opts || {}),\n createComposition: (opts) => rpc.call("createComposition", opts || {}),\n editComposition: (opts) => rpc.call("editComposition", opts || {}),\n editStateMachine: (opts) => rpc.call("editStateMachine", opts || {}),\n getStateMachine: (opts) => rpc.call("getStateMachine", opts || {}),\n applyMotionPreset: (opts) => rpc.call("applyMotionPreset", opts || {}),\n staggerMotion: (opts) => rpc.call("staggerMotion", opts || {}),\n createMotionComponent: (opts) => rpc.call("createMotionComponent", opts || {}),\n addAudio: (opts) => rpc.call("addAudio", opts || {}),\n editFrameAudio: (opts) => rpc.call("editFrameAudio", opts || {}),\n editVideoClip: (opts) => rpc.call("editVideoClip", opts || {}),\n detectAudioOnsets: (opts) => rpc.call("detectAudioOnsets", opts || {}),\n cutToBeat: (opts) => rpc.call("cutToBeat", opts || {}),\n editPrototype: (opts) => rpc.call("editPrototype", opts || {}),\n importFile: (opts) => rpc.call("importFile", opts || {}),\n usePresentationFallbackAudio: (opts) => rpc.call("usePresentationFallbackAudio", opts || {}),\n getStyles: () => rpc.call("getStyles"),\n createPaintStyle: (name, paints) => rpc.call("createPaintStyle", { name, paints }),\n getVariables: () => rpc.call("getVariables"),\n setVariableValue: (variableId, modeId, value) => rpc.call("setVariableValue", { variableId, modeId, value }),\n exportNode: (id, options) => rpc.call("exportNode", { id, options: options || {} }),\n openExternal: (url) => rpc.call("openExternal", { url }),\n notify: (message, options) => rpc.call("notify", { message: String(message), error: !!(options && options.error) }),\n showUI: (options) => rpc.call("showUI", options || {}),\n hideUI: () => rpc.call("hideUI"),\n /** Ends the run. The optional message is shown as a notification. */\n closePlugin: (message) => rpc.call("closePlugin", { message }),\n storage: {\n get: (key) => rpc.call("storageGet", { key }),\n set: (key, value) => rpc.call("storageSet", { key, value })\n },\n ui: {\n get onmessage() {\n return uiOnMessage;\n },\n set onmessage(cb) {\n uiOnMessage = cb;\n flushUI();\n },\n postMessage: (msg) => rpc.send({ kind: "toUI", data: msg }),\n on: (cb) => {\n uiHandlers.push(cb);\n flushUI();\n }\n },\n widget: {\n register(def) {\n if (!def || typeof def.render !== "function") throw new Error("popcraft.widget.register needs a render(state) function");\n widgetDef = def;\n widgetQueue.splice(0).forEach(handleWidgetClick);\n },\n insert(options) {\n if (!widgetDef) return Promise.reject(new Error("Call popcraft.widget.register first"));\n const o = options || {};\n const state = o.state !== void 0 ? clone(o.state) : initialWidgetState();\n return rpc.call("widgetInsert", { state, tree: renderWidget(state).tree, x: o.x, y: o.y });\n },\n getState: (nodeId) => rpc.call("widgetGet", { id: nodeId }),\n setState(nodeId, state) {\n if (!widgetDef) return Promise.reject(new Error("Call popcraft.widget.register first"));\n return commitWidget(nodeId, clone(state));\n }\n },\n on: (event, cb) => rpc.on(event, cb),\n off: (event, cb) => rpc.off(event, cb)\n };\n rpc.on("init", (data) => {\n var _a, _b, _c;\n popcraft.command = data.command;\n popcraft.exportRequest = (_c = data.exportRequest) != null ? _c : null;\n popcraft.importMode = (_a = data.importMode) != null ? _a : null;\n popcraft.importFile = (_b = data.importFile) != null ? _b : null;\n });\n return popcraft;\n }\n function installMainApi() {\n const rpc = createRpcClient();\n const api = createMainApi(rpc);\n const w = window;\n w.__popcraftRpc = rpc;\n w.popcraft = api;\n w.vizpops = api;\n window.addEventListener("error", (e) => rpc.send({ kind: "error", message: String(e.message || e) }));\n window.addEventListener("unhandledrejection", (e) => rpc.send({ kind: "error", message: String(e.reason && e.reason.message || e.reason) }));\n return api;\n }\n\n // src/runtime/main.entry.ts\n installMainApi();\n})();';
|
|
358169
|
+
"node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=997b73fa0364896bf8afb3420ac81e52de261b88cad7cac3e2e206341916c9a5/node_modules/@popcraft/plugins/dist/generated/runtime.js"() {
|
|
358170
|
+
MAIN_RUNTIME = '"use strict";\n(() => {\n // src/runtime/rpc.ts\n function createRpcClient() {\n let port = null;\n const queue = [];\n const pending = {};\n const listeners = {};\n let nextId = 1;\n function send(msg) {\n if (port) port.postMessage(msg);\n else queue.push(msg);\n }\n function call(method, params) {\n return new Promise((resolve, reject) => {\n const id = nextId++;\n pending[id] = { resolve, reject };\n send({ kind: "rpc", id, method, params });\n });\n }\n function emit(event, data) {\n for (const cb of (listeners[event] || []).slice()) {\n try {\n cb(data);\n } catch (e) {\n console.error(e);\n }\n }\n }\n window.addEventListener("message", (e) => {\n const data = e.data;\n if (e.source !== window.parent || !data || data.type !== "popcraft-plugin-port" || port) return;\n port = e.ports[0];\n port.onmessage = (ev) => {\n const m = ev.data || {};\n if (m.kind === "result" && m.id !== void 0 && pending[m.id]) {\n const p = pending[m.id];\n delete pending[m.id];\n if (m.error) p.reject(new Error(m.error));\n else p.resolve(m.result);\n } else if (m.kind === "event" && m.event) {\n emit(m.event, m.data);\n }\n };\n for (const msg of queue.splice(0)) port.postMessage(msg);\n });\n return {\n call,\n send,\n on(event, cb) {\n (listeners[event] = listeners[event] || []).push(cb);\n },\n off(event, cb) {\n listeners[event] = (listeners[event] || []).filter((x) => x !== cb);\n }\n };\n }\n\n // src/runtime/main.ts\n function clone(v) {\n return v === void 0 ? {} : JSON.parse(JSON.stringify(v));\n }\n function createMainApi(rpc = createRpcClient()) {\n const uiHandlers = [];\n let uiOnMessage = null;\n const uiQueue = [];\n function deliverUI(msg) {\n for (const cb of uiHandlers) {\n try {\n cb(msg);\n } catch (e) {\n console.error(e);\n }\n }\n if (typeof uiOnMessage === "function") {\n try {\n uiOnMessage(msg);\n } catch (e) {\n console.error(e);\n }\n }\n }\n function flushUI() {\n if (uiHandlers.length || typeof uiOnMessage === "function") uiQueue.splice(0).forEach(deliverUI);\n }\n rpc.on("uimessage", (msg) => {\n if (!uiHandlers.length && typeof uiOnMessage !== "function") uiQueue.push(msg);\n else deliverUI(msg);\n });\n let widgetDef = null;\n const widgetQueue = [];\n function renderWidget(state) {\n const handlers = {};\n function walk(el, path) {\n if (!el || typeof el !== "object") return el;\n const out = {};\n for (const k of Object.keys(el)) {\n const v = el[k];\n if (k === "children") {\n out.children = (Array.isArray(v) ? v : [v]).filter((c) => c !== null && c !== void 0 && c !== false).map((c, i) => walk(c, path + "." + i));\n } else if (k === "onClick" && typeof v === "function") {\n handlers[path] = v;\n out.onClick = path;\n } else {\n out[k] = v;\n }\n }\n return out;\n }\n return { tree: walk(widgetDef.render(state), "root"), handlers };\n }\n function initialWidgetState() {\n const s = widgetDef && widgetDef.initialState;\n return clone(typeof s === "function" ? s() : s);\n }\n function commitWidget(nodeId, state) {\n return rpc.call("widgetUpdate", { id: nodeId, state, tree: renderWidget(clone(state)).tree });\n }\n function handleWidgetClick(e) {\n Promise.resolve().then(() => {\n const state = clone(e.state);\n const rendered = renderWidget(state);\n const h = rendered.handlers[e.handler] || widgetDef.handlers && widgetDef.handlers[e.handler];\n if (typeof h !== "function") return;\n return Promise.resolve(h(state, { nodeId: e.nodeId })).then((ret) => commitWidget(e.nodeId, ret === void 0 ? state : ret));\n }).catch((err) => rpc.send({ kind: "error", message: String((err == null ? void 0 : err.message) || err) }));\n }\n rpc.on("widgetclick", (e) => {\n if (widgetDef) handleWidgetClick(e);\n else widgetQueue.push(e);\n });\n const popcraft = {\n /** Which menu command the user picked, or null when the plugin ran some other way. */\n command: null,\n /** Host import mode when launched as an importer, else null. */\n importMode: null,\n /** Pending import file when the host handed one over, else null. */\n importFile: null,\n /** Pending export request when the host started this plugin as an exporter, else null. */\n exportRequest: null,\n getSelection: () => rpc.call("getSelection"),\n setSelection: (ids) => rpc.call("setSelection", { ids }),\n getNode: (id) => rpc.call("getNode", { id }),\n findNodes: (query) => rpc.call("findNodes", query || {}),\n getCurrentPage: () => rpc.call("getCurrentPage"),\n createNode: (type, props) => rpc.call("createNode", { type, props: props || {} }),\n updateNode: (id, props) => rpc.call("updateNode", { id, props }),\n deleteNode: (id) => rpc.call("deleteNode", { id }),\n setText: (id, characters) => rpc.call("setText", { id, characters }),\n setTextPath: (opts) => rpc.call("setTextPath", opts || {}),\n flowTextIntoShape: (opts) => rpc.call("flowTextIntoShape", opts || {}),\n detachText: (opts) => rpc.call("detachText", opts || {}),\n setTextFit: (opts) => rpc.call("setTextFit", opts || {}),\n createPage: (name) => rpc.call("createPage", name != null ? { name: String(name) } : {}),\n setCurrentPage: (pageId) => rpc.call("setCurrentPage", { pageId }),\n createImage: (opts) => rpc.call("createImage", opts || {}),\n createDocument: (opts) => rpc.call("createDocument", opts || {}),\n getImportMode: () => rpc.call("getImportMode"),\n getImportFile: () => rpc.call("getImportFile"),\n getStorefront: () => rpc.call("getStorefront"),\n getExportRequest: () => rpc.call("getExportRequest"),\n saveExport: (file) => rpc.call("saveExport", file || {}),\n getPresentationAudio: (opts) => rpc.call("getPresentationAudio", opts || {}),\n setPresentationAudioSettings: (opts) => rpc.call("setPresentationAudioSettings", opts || {}),\n setPresentationAudioClip: (opts) => rpc.call("setPresentationAudioClip", opts || {}),\n removePresentationAudioClip: (opts) => rpc.call("removePresentationAudioClip", opts || {}),\n setPresentationTiming: (opts) => rpc.call("setPresentationTiming", opts || {}),\n getPresentationMix: (opts) => rpc.call("getPresentationMix", opts || {}),\n requestPresentationAudio: (opts) => rpc.call("requestPresentationAudio", opts || {}),\n moveNodes: (opts) => rpc.call("moveNodes", opts || {}),\n resizeNodes: (opts) => rpc.call("resizeNodes", opts || {}),\n renameNodes: (opts) => rpc.call("renameNodes", opts || {}),\n reparentNodes: (opts) => rpc.call("reparentNodes", opts || {}),\n duplicateNodes: (opts) => rpc.call("duplicateNodes", opts || {}),\n groupNodes: (opts) => rpc.call("groupNodes", opts || {}),\n ungroupNodes: (opts) => rpc.call("ungroupNodes", opts || {}),\n alignNodes: (opts) => rpc.call("alignNodes", opts || {}),\n distributeNodes: (opts) => rpc.call("distributeNodes", opts || {}),\n flipNodes: (opts) => rpc.call("flipNodes", opts || {}),\n rotateNodes: (opts) => rpc.call("rotateNodes", opts || {}),\n reorderNodes: (opts) => rpc.call("reorderNodes", opts || {}),\n setLocked: (opts) => rpc.call("setLocked", opts || {}),\n setVisible: (opts) => rpc.call("setVisible", opts || {}),\n setAutoLayout: (opts) => rpc.call("setAutoLayout", opts || {}),\n importSvg: (opts) => rpc.call("importSvg", opts || {}),\n measureNodes: (opts) => rpc.call("measureNodes", opts || {}),\n setFills: (opts) => rpc.call("setFills", opts || {}),\n setStrokes: (opts) => rpc.call("setStrokes", opts || {}),\n setEffects: (opts) => rpc.call("setEffects", opts || {}),\n replaceColor: (opts) => rpc.call("replaceColor", opts || {}),\n setTypography: (opts) => rpc.call("setTypography", opts || {}),\n applyStyle: (opts) => rpc.call("applyStyle", opts || {}),\n createComponent: (opts) => rpc.call("createComponent", opts || {}),\n createInstance: (opts) => rpc.call("createInstance", opts || {}),\n renamePage: (opts) => rpc.call("renamePage", opts || {}),\n getDocumentOutline: (opts) => rpc.call("getDocumentOutline", opts || {}),\n setPageSetup: (opts) => rpc.call("setPageSetup", opts || {}),\n setShowAdvance: (opts) => rpc.call("setShowAdvance", opts || {}),\n booleanOperation: (opts) => rpc.call("booleanOperation", opts || {}),\n flattenNodes: (opts) => rpc.call("flattenNodes", opts || {}),\n outlineStroke: (opts) => rpc.call("outlineStroke", opts || {}),\n setMask: (opts) => rpc.call("setMask", opts || {}),\n setMaskType: (opts) => rpc.call("setMaskType", opts || {}),\n shapeBuilder: (opts) => rpc.call("shapeBuilder", opts || {}),\n setKeyframes: (opts) => rpc.call("setKeyframes", opts || {}),\n getAnimation: (opts) => rpc.call("getAnimation", opts || {}),\n getCompositions: (opts) => rpc.call("getCompositions", opts || {}),\n editBehaviours: (opts) => rpc.call("editBehaviours", opts || {}),\n setTimeline: (opts) => rpc.call("setTimeline", opts || {}),\n setLayerTiming: (opts) => rpc.call("setLayerTiming", opts || {}),\n editTextAnimation: (opts) => rpc.call("editTextAnimation", opts || {}),\n edit3DScene: (opts) => rpc.call("edit3DScene", opts || {}),\n setInstancePlayback: (opts) => rpc.call("setInstancePlayback", opts || {}),\n editComponentProperty: (opts) => rpc.call("editComponentProperty", opts || {}),\n setShaderFill: (opts) => rpc.call("setShaderFill", opts || {}),\n createComposition: (opts) => rpc.call("createComposition", opts || {}),\n editComposition: (opts) => rpc.call("editComposition", opts || {}),\n editStateMachine: (opts) => rpc.call("editStateMachine", opts || {}),\n getStateMachine: (opts) => rpc.call("getStateMachine", opts || {}),\n applyMotionPreset: (opts) => rpc.call("applyMotionPreset", opts || {}),\n staggerMotion: (opts) => rpc.call("staggerMotion", opts || {}),\n createMotionComponent: (opts) => rpc.call("createMotionComponent", opts || {}),\n addAudio: (opts) => rpc.call("addAudio", opts || {}),\n editFrameAudio: (opts) => rpc.call("editFrameAudio", opts || {}),\n editVideoClip: (opts) => rpc.call("editVideoClip", opts || {}),\n detectAudioOnsets: (opts) => rpc.call("detectAudioOnsets", opts || {}),\n cutToBeat: (opts) => rpc.call("cutToBeat", opts || {}),\n editPrototype: (opts) => rpc.call("editPrototype", opts || {}),\n importFile: (opts) => rpc.call("importFile", opts || {}),\n usePresentationFallbackAudio: (opts) => rpc.call("usePresentationFallbackAudio", opts || {}),\n getStyles: () => rpc.call("getStyles"),\n createPaintStyle: (name, paints) => rpc.call("createPaintStyle", { name, paints }),\n getVariables: () => rpc.call("getVariables"),\n setVariableValue: (variableId, modeId, value) => rpc.call("setVariableValue", { variableId, modeId, value }),\n exportNode: (id, options) => rpc.call("exportNode", { id, options: options || {} }),\n openExternal: (url) => rpc.call("openExternal", { url }),\n notify: (message, options) => rpc.call("notify", { message: String(message), error: !!(options && options.error) }),\n showUI: (options) => rpc.call("showUI", options || {}),\n hideUI: () => rpc.call("hideUI"),\n /** Ends the run. The optional message is shown as a notification. */\n closePlugin: (message) => rpc.call("closePlugin", { message }),\n storage: {\n get: (key) => rpc.call("storageGet", { key }),\n set: (key, value) => rpc.call("storageSet", { key, value })\n },\n ui: {\n get onmessage() {\n return uiOnMessage;\n },\n set onmessage(cb) {\n uiOnMessage = cb;\n flushUI();\n },\n postMessage: (msg) => rpc.send({ kind: "toUI", data: msg }),\n on: (cb) => {\n uiHandlers.push(cb);\n flushUI();\n }\n },\n widget: {\n register(def) {\n if (!def || typeof def.render !== "function") throw new Error("popcraft.widget.register needs a render(state) function");\n widgetDef = def;\n widgetQueue.splice(0).forEach(handleWidgetClick);\n },\n insert(options) {\n if (!widgetDef) return Promise.reject(new Error("Call popcraft.widget.register first"));\n const o = options || {};\n const state = o.state !== void 0 ? clone(o.state) : initialWidgetState();\n return rpc.call("widgetInsert", { state, tree: renderWidget(state).tree, x: o.x, y: o.y });\n },\n getState: (nodeId) => rpc.call("widgetGet", { id: nodeId }),\n setState(nodeId, state) {\n if (!widgetDef) return Promise.reject(new Error("Call popcraft.widget.register first"));\n return commitWidget(nodeId, clone(state));\n }\n },\n on: (event, cb) => rpc.on(event, cb),\n off: (event, cb) => rpc.off(event, cb)\n };\n rpc.on("init", (data) => {\n var _a, _b, _c;\n popcraft.command = data.command;\n popcraft.exportRequest = (_c = data.exportRequest) != null ? _c : null;\n popcraft.importMode = (_a = data.importMode) != null ? _a : null;\n popcraft.importFile = (_b = data.importFile) != null ? _b : null;\n });\n return popcraft;\n }\n function installMainApi() {\n const rpc = createRpcClient();\n const api = createMainApi(rpc);\n const w = window;\n w.__popcraftRpc = rpc;\n w.popcraft = api;\n w.vizpops = api;\n window.addEventListener("error", (e) => rpc.send({ kind: "error", message: String(e.message || e) }));\n window.addEventListener("unhandledrejection", (e) => rpc.send({ kind: "error", message: String(e.reason && e.reason.message || e.reason) }));\n return api;\n }\n\n // src/runtime/main.entry.ts\n installMainApi();\n})();';
|
|
357384
358171
|
UI_RUNTIME = '"use strict";\n(() => {\n // src/runtime/rpc.ts\n function createRpcClient() {\n let port = null;\n const queue = [];\n const pending = {};\n const listeners = {};\n let nextId = 1;\n function send(msg) {\n if (port) port.postMessage(msg);\n else queue.push(msg);\n }\n function call(method, params) {\n return new Promise((resolve, reject) => {\n const id = nextId++;\n pending[id] = { resolve, reject };\n send({ kind: "rpc", id, method, params });\n });\n }\n function emit(event, data) {\n for (const cb of (listeners[event] || []).slice()) {\n try {\n cb(data);\n } catch (e) {\n console.error(e);\n }\n }\n }\n window.addEventListener("message", (e) => {\n const data = e.data;\n if (e.source !== window.parent || !data || data.type !== "popcraft-plugin-port" || port) return;\n port = e.ports[0];\n port.onmessage = (ev) => {\n const m = ev.data || {};\n if (m.kind === "result" && m.id !== void 0 && pending[m.id]) {\n const p = pending[m.id];\n delete pending[m.id];\n if (m.error) p.reject(new Error(m.error));\n else p.resolve(m.result);\n } else if (m.kind === "event" && m.event) {\n emit(m.event, m.data);\n }\n };\n for (const msg of queue.splice(0)) port.postMessage(msg);\n });\n return {\n call,\n send,\n on(event, cb) {\n (listeners[event] = listeners[event] || []).push(cb);\n },\n off(event, cb) {\n listeners[event] = (listeners[event] || []).filter((x) => x !== cb);\n }\n };\n }\n\n // src/runtime/ui.ts\n function createUiApi(rpc = createRpcClient()) {\n const popcraft = {\n onmessage: null,\n postMessage: (msg) => rpc.send({ kind: "fromUI", data: msg }),\n close: () => rpc.send({ kind: "closeUI" })\n };\n rpc.on("message", (msg) => {\n if (typeof popcraft.onmessage === "function") popcraft.onmessage(msg);\n window.dispatchEvent(new MessageEvent("message", { data: { pluginMessage: msg } }));\n });\n return popcraft;\n }\n function installUiApi() {\n const rpc = createRpcClient();\n const api = createUiApi(rpc);\n const w = window;\n w.__popcraftRpc = rpc;\n w.popcraft = api;\n w.vizpops = api;\n return api;\n }\n\n // src/runtime/ui.entry.ts\n installUiApi();\n})();';
|
|
357385
358172
|
}
|
|
357386
358173
|
});
|
|
357387
358174
|
|
|
357388
|
-
// node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=
|
|
358175
|
+
// node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=997b73fa0364896bf8afb3420ac81e52de261b88cad7cac3e2e206341916c9a5/node_modules/@popcraft/plugins/dist/host.js
|
|
357389
358176
|
function csp(network) {
|
|
357390
358177
|
const connect2 = network ? "connect-src * data: blob:;" : "connect-src 'none';";
|
|
357391
358178
|
const img = network ? "img-src * data: blob:;" : "img-src data: blob:;";
|
|
@@ -357413,40 +358200,40 @@ function buildUIDocument(uiHtml, network) {
|
|
|
357413
358200
|
}
|
|
357414
358201
|
var escapeScript;
|
|
357415
358202
|
var init_host2 = __esm({
|
|
357416
|
-
"node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=
|
|
358203
|
+
"node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=997b73fa0364896bf8afb3420ac81e52de261b88cad7cac3e2e206341916c9a5/node_modules/@popcraft/plugins/dist/host.js"() {
|
|
357417
358204
|
init_runtime4();
|
|
357418
358205
|
escapeScript = (code) => code.replace(/<\/script/gi, "<\\/script");
|
|
357419
358206
|
}
|
|
357420
358207
|
});
|
|
357421
358208
|
|
|
357422
|
-
// node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=
|
|
358209
|
+
// node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=997b73fa0364896bf8afb3420ac81e52de261b88cad7cac3e2e206341916c9a5/node_modules/@popcraft/plugins/dist/runtime/rpc.js
|
|
357423
358210
|
var init_rpc = __esm({
|
|
357424
|
-
"node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=
|
|
358211
|
+
"node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=997b73fa0364896bf8afb3420ac81e52de261b88cad7cac3e2e206341916c9a5/node_modules/@popcraft/plugins/dist/runtime/rpc.js"() {
|
|
357425
358212
|
}
|
|
357426
358213
|
});
|
|
357427
358214
|
|
|
357428
|
-
// node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=
|
|
358215
|
+
// node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=997b73fa0364896bf8afb3420ac81e52de261b88cad7cac3e2e206341916c9a5/node_modules/@popcraft/plugins/dist/runtime/main.js
|
|
357429
358216
|
var init_main = __esm({
|
|
357430
|
-
"node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=
|
|
358217
|
+
"node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=997b73fa0364896bf8afb3420ac81e52de261b88cad7cac3e2e206341916c9a5/node_modules/@popcraft/plugins/dist/runtime/main.js"() {
|
|
357431
358218
|
init_rpc();
|
|
357432
358219
|
}
|
|
357433
358220
|
});
|
|
357434
358221
|
|
|
357435
|
-
// node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=
|
|
358222
|
+
// node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=997b73fa0364896bf8afb3420ac81e52de261b88cad7cac3e2e206341916c9a5/node_modules/@popcraft/plugins/dist/types.js
|
|
357436
358223
|
var init_types9 = __esm({
|
|
357437
|
-
"node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=
|
|
358224
|
+
"node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=997b73fa0364896bf8afb3420ac81e52de261b88cad7cac3e2e206341916c9a5/node_modules/@popcraft/plugins/dist/types.js"() {
|
|
357438
358225
|
}
|
|
357439
358226
|
});
|
|
357440
358227
|
|
|
357441
|
-
// node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=
|
|
358228
|
+
// node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=997b73fa0364896bf8afb3420ac81e52de261b88cad7cac3e2e206341916c9a5/node_modules/@popcraft/plugins/dist/widget.js
|
|
357442
358229
|
var init_widget = __esm({
|
|
357443
|
-
"node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=
|
|
358230
|
+
"node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=997b73fa0364896bf8afb3420ac81e52de261b88cad7cac3e2e206341916c9a5/node_modules/@popcraft/plugins/dist/widget.js"() {
|
|
357444
358231
|
}
|
|
357445
358232
|
});
|
|
357446
358233
|
|
|
357447
|
-
// node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=
|
|
358234
|
+
// node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=997b73fa0364896bf8afb3420ac81e52de261b88cad7cac3e2e206341916c9a5/node_modules/@popcraft/plugins/dist/index.js
|
|
357448
358235
|
var init_dist = __esm({
|
|
357449
|
-
"node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=
|
|
358236
|
+
"node_modules/.pnpm/@popcraft+plugins@1.0.0_patch_hash=997b73fa0364896bf8afb3420ac81e52de261b88cad7cac3e2e206341916c9a5/node_modules/@popcraft/plugins/dist/index.js"() {
|
|
357450
358237
|
init_host2();
|
|
357451
358238
|
init_main();
|
|
357452
358239
|
init_runtime4();
|
|
@@ -357819,8 +358606,8 @@ var init_package2 = __esm({
|
|
|
357819
358606
|
|
|
357820
358607
|
// lib/plugins/registry.ts
|
|
357821
358608
|
async function listPlugins() {
|
|
357822
|
-
const
|
|
357823
|
-
return
|
|
358609
|
+
const all4 = await values2(db2());
|
|
358610
|
+
return all4.sort((a, b) => a.manifest.name.localeCompare(b.manifest.name));
|
|
357824
358611
|
}
|
|
357825
358612
|
async function getPlugin(id3) {
|
|
357826
358613
|
return get2(id3, db2());
|
|
@@ -358628,9 +359415,9 @@ var init_import = __esm({
|
|
|
358628
359415
|
return node2;
|
|
358629
359416
|
}
|
|
358630
359417
|
vectorFrom(b, name2) {
|
|
358631
|
-
const
|
|
358632
|
-
const minX = Math.min(...
|
|
358633
|
-
const maxX = Math.max(...
|
|
359418
|
+
const all4 = this.bezierPoints(b);
|
|
359419
|
+
const minX = Math.min(...all4.map((q) => q[0])), minY = Math.min(...all4.map((q) => q[1]));
|
|
359420
|
+
const maxX = Math.max(...all4.map((q) => q[0])), maxY = Math.max(...all4.map((q) => q[1]));
|
|
358634
359421
|
return createVector({ name: name2, x: minX, y: minY, width: Math.max(1e-3, maxX - minX), height: Math.max(1e-3, maxY - minY), paths: [this.pathFrom(b, minX, minY)], fills: [], strokes: [] });
|
|
358635
359422
|
}
|
|
358636
359423
|
/** Every vertex and control point of `b`, absolute. */
|
|
@@ -381124,8 +381911,8 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
381124
381911
|
CurrentPointers.setTimeStamp(event.timeStamp);
|
|
381125
381912
|
stopEvent(event);
|
|
381126
381913
|
}
|
|
381127
|
-
static _cleanup(
|
|
381128
|
-
if (
|
|
381914
|
+
static _cleanup(all4) {
|
|
381915
|
+
if (all4) {
|
|
381129
381916
|
this._currentDrawId = -1;
|
|
381130
381917
|
this._currentParent = null;
|
|
381131
381918
|
_DrawingEditor.#currentDraw = null;
|
|
@@ -387894,6 +388681,23 @@ var init_plugin = __esm({
|
|
|
387894
388681
|
expose: { plugin: { method: "getImportFile", shape: (r) => r.data } },
|
|
387895
388682
|
run: (_p, ctx2) => ({ summary: "Import file", data: hostEnv(ctx2).importFile ?? null })
|
|
387896
388683
|
}),
|
|
388684
|
+
defineCommand({
|
|
388685
|
+
id: pluginCommandId("getStorefront"),
|
|
388686
|
+
title: "Get storefront design",
|
|
388687
|
+
domain: "export",
|
|
388688
|
+
params: empty,
|
|
388689
|
+
effect: "none",
|
|
388690
|
+
permission: "read",
|
|
388691
|
+
expose: { plugin: { method: "getStorefront", shape: (r) => r.data } },
|
|
388692
|
+
// A storefront design in a neutral form (lib/io/web/project/storefront.ts `storefrontDesign`): what an exporter
|
|
388693
|
+
// plugin turns into its own store's templates, as PopCraft turns it into a Next.js Commerce store or a Shopify theme.
|
|
388694
|
+
run: async (_p, ctx2) => {
|
|
388695
|
+
const [{ componentScreens: componentScreens2 }, { storefrontDesign: storefrontDesign2 }] = await Promise.all([Promise.resolve().then(() => (init_components(), components_exports)), Promise.resolve().then(() => (init_storefront(), storefront_exports))]);
|
|
388696
|
+
const doc2 = ctx2.doc();
|
|
388697
|
+
const design = storefrontDesign2(doc2, componentScreens2(doc2, ctx2.pageId()));
|
|
388698
|
+
return { summary: `Storefront: ${design.pages.length} pages`, data: design };
|
|
388699
|
+
}
|
|
388700
|
+
}),
|
|
387897
388701
|
defineCommand({
|
|
387898
388702
|
id: pluginCommandId("getExportRequest"),
|
|
387899
388703
|
title: "Get export request",
|
|
@@ -388080,7 +388884,7 @@ function attached(done, ctx2) {
|
|
|
388080
388884
|
ctx2.notice(`Database attached: ${where}`);
|
|
388081
388885
|
return { summary: `Attached ${where} (${db3.connection.provider}, ${db3.connection.account}): the site's forms are saved there once it is published`, data: { provider: db3.connection.provider, account: db3.connection.account, target: db3.target } };
|
|
388082
388886
|
}
|
|
388083
|
-
var integrationList, integrationOpen, asPath2, integrationListResources, place3, integrationAddDestination, integrationDeploy, integrationAttachDatabase, integrationSubmissions, integrationSetSignIn, integrationConfirmCommands;
|
|
388887
|
+
var integrationList, integrationOpen, asPath2, integrationListResources, place3, integrationAddDestination, integrationDeploy, integrationAttachDatabase, integrationSubmissions, integrationSetSignIn, integrationConfirmCommands, integrationPullProducts;
|
|
388084
388888
|
var init_integration = __esm({
|
|
388085
388889
|
"lib/commands/integration.ts"() {
|
|
388086
388890
|
"use strict";
|
|
@@ -388094,13 +388898,13 @@ var init_integration = __esm({
|
|
|
388094
388898
|
effect: "none",
|
|
388095
388899
|
permission: null,
|
|
388096
388900
|
params: external_exports.object({
|
|
388097
|
-
capability: external_exports.enum(["repo", "deploy", "database", "auth"]).optional().describe("Only the integrations that can do this: repo (push code to a repository), deploy (host the site), database (store what forms send and what collections hold), auth (sign-in for the site's visitors).")
|
|
388901
|
+
capability: external_exports.enum(["repo", "deploy", "database", "auth", "commerce"]).optional().describe("Only the integrations that can do this: repo (push code to a repository), deploy (host the site), database (store what forms send and what collections hold), auth (sign-in for the site's visitors), commerce (a store whose products a storefront design is drawn with).")
|
|
388098
388902
|
}),
|
|
388099
388903
|
expose: {
|
|
388100
388904
|
agent: {
|
|
388101
388905
|
name: "list_integrations",
|
|
388102
388906
|
readOnly: true,
|
|
388103
|
-
description: "The services this workspace can connect its own accounts to (GitHub, Vercel, Neon, Supabase), what each can do
|
|
388907
|
+
description: "The services this workspace can connect its own accounts to (GitHub, Vercel, Neon, Supabase, Shopify), what each can do (repo, deploy, database, auth, commerce), which accounts are connected, and whether the user can connect more. `notYet` lists what an integration is meant to do and cannot yet: never promise those. Call it before recommending one, and before any step that needs a connection. You cannot connect an account yourself: when one is missing, say which integration fits and why, then call open_integrations so the user can connect it."
|
|
388104
388908
|
}
|
|
388105
388909
|
},
|
|
388106
388910
|
run: async ({ capability: capability2 }) => {
|
|
@@ -388237,9 +389041,9 @@ var init_integration = __esm({
|
|
|
388237
389041
|
run: async (p2, ctx2) => {
|
|
388238
389042
|
const key5 = await openFile();
|
|
388239
389043
|
const { deployDestination: deployDestination2, listDestinations: listDestinations2 } = await Promise.resolve().then(() => (init_integrations(), integrations_exports));
|
|
388240
|
-
const
|
|
388241
|
-
const dest = p2.destinationId ?
|
|
388242
|
-
if (!dest) throw new CommandError(
|
|
389044
|
+
const all4 = await listDestinations2(key5);
|
|
389045
|
+
const dest = p2.destinationId ? all4.find((d) => d.id === p2.destinationId) : all4.length === 1 ? all4[0] : void 0;
|
|
389046
|
+
if (!dest) throw new CommandError(all4.length ? `Say which destination: ${all4.map((d) => `${d.id} (${d.target.map((t3) => t3.name).join(" / ")})`).join(", ")}.` : "This file has no destination yet. Add one first (add_site_destination).", "invalid_params");
|
|
388243
389047
|
const done = await deployDestination2(key5, dest.id, p2.version);
|
|
388244
389048
|
ctx2.notice(done.status === "building" ? `Deploying: ${done.url}` : `Sent: ${done.url}`);
|
|
388245
389049
|
return { summary: `Version ${done.version} ${done.status === "building" ? "is deploying" : "was sent"}: ${done.url}`, data: { url: done.url, ref: done.ref, status: done.status, version: done.version, destinationId: dest.id } };
|
|
@@ -388335,6 +389139,56 @@ var init_integration = __esm({
|
|
|
388335
389139
|
}
|
|
388336
389140
|
});
|
|
388337
389141
|
integrationConfirmCommands = [integrationAddDestination, integrationDeploy, integrationAttachDatabase, integrationSetSignIn];
|
|
389142
|
+
integrationPullProducts = defineCommand({
|
|
389143
|
+
id: "integration.pullProducts",
|
|
389144
|
+
title: "Draw the design with a store's products",
|
|
389145
|
+
domain: "integration",
|
|
389146
|
+
effect: "document",
|
|
389147
|
+
permission: "write",
|
|
389148
|
+
undoLabel: "Store products",
|
|
389149
|
+
params: external_exports.object({
|
|
389150
|
+
connectionId: external_exports.string().optional().describe("The connected store, from list_integrations (capability commerce). Omit when one store is connected."),
|
|
389151
|
+
collection: external_exports.string().optional().describe("The collection to fill, by id or name; it must stand for store products (schema commerce.product). Omit when the file has one."),
|
|
389152
|
+
limit: external_exports.number().int().min(1).max(100).default(24).describe("How many of the store's newest products.")
|
|
389153
|
+
}).strict(),
|
|
389154
|
+
expose: {
|
|
389155
|
+
ui: { label: "Draw with my store's products", keywords: ["shopify", "store", "products", "commerce", "shop", "catalogue", "import"] },
|
|
389156
|
+
agent: {
|
|
389157
|
+
name: "pull_store_products",
|
|
389158
|
+
description: "Replace the records of a storefront design's product collection (schema commerce.product) with a connected store's real products (Shopify): titles, prices, pictures, handles and variant ids, newest first. The design's lists and product pages then show them. It reads the store; it never changes it. Needs a Shopify connection (list_integrations, capability commerce); you cannot connect one yourself."
|
|
389159
|
+
}
|
|
389160
|
+
},
|
|
389161
|
+
run: async (args2, ctx2) => {
|
|
389162
|
+
const [{ cloudUser: cloudUser2 }, { integrationsWorkspaceId: integrationsWorkspaceId2, listWorkspaceIntegrations: listWorkspaceIntegrations2, storeProducts: storeProducts2 }, { commerceItem: commerceItem2, COMMERCE_FIELDS: COMMERCE_FIELDS2 }, { fieldKey: fieldKey2, removeRecords: removeRecords2, upsertRecords: upsertRecords2 }] = await Promise.all([
|
|
389163
|
+
Promise.resolve().then(() => (init_session(), session_exports)),
|
|
389164
|
+
Promise.resolve().then(() => (init_integrations(), integrations_exports)),
|
|
389165
|
+
Promise.resolve().then(() => (init_commerce(), commerce_exports)),
|
|
389166
|
+
Promise.resolve().then(() => (init_collections(), collections_exports))
|
|
389167
|
+
]);
|
|
389168
|
+
if (!cloudUser2()) throw new CommandError("You are not signed in: a store is connected to your account's workspace.", "denied");
|
|
389169
|
+
const doc2 = ctx2.doc();
|
|
389170
|
+
const pick5 = Object.values(doc2.collections ?? {}).filter((c2) => c2.schema === "commerce.product" && (!args2.collection || c2.id === args2.collection || c2.name.toLowerCase() === args2.collection.toLowerCase()));
|
|
389171
|
+
if (!pick5.length) throw new CommandError(args2.collection ? `No store products collection "${args2.collection}".` : "This file has no collection that stands for store products: set one to Store products in Collections first.", "invalid_params");
|
|
389172
|
+
if (pick5.length > 1) throw new CommandError(`Name the collection: ${pick5.map((c2) => c2.name).join(", ")}.`, "invalid_params");
|
|
389173
|
+
const collection = pick5[0];
|
|
389174
|
+
let connectionId = args2.connectionId;
|
|
389175
|
+
if (!connectionId) {
|
|
389176
|
+
const workspaceId = integrationsWorkspaceId2();
|
|
389177
|
+
if (!workspaceId) throw new CommandError("Your workspaces have not loaded yet. Try again in a moment.", "failed");
|
|
389178
|
+
const stores2 = (await listWorkspaceIntegrations2(workspaceId)).integrations.filter((i2) => i2.manifest.capabilities.includes("commerce")).flatMap((i2) => i2.connections);
|
|
389179
|
+
if (!stores2.length) throw new CommandError("No store is connected. Connect Shopify in Integrations first.", "failed");
|
|
389180
|
+
if (stores2.length > 1) throw new CommandError(`Name the store: ${stores2.map((c2) => `${c2.account} (${c2.id})`).join(", ")}.`, "invalid_params");
|
|
389181
|
+
connectionId = stores2[0].id;
|
|
389182
|
+
}
|
|
389183
|
+
const products = await storeProducts2(connectionId, args2.limit);
|
|
389184
|
+
if (!products.length) throw new CommandError("The store has no products to show.", "failed");
|
|
389185
|
+
const keys4 = new Map(COMMERCE_FIELDS2["commerce.product"].map((f2) => [fieldKey2(f2.name), f2.name]));
|
|
389186
|
+
const rows = products.map((p2) => ({ values: Object.fromEntries(Object.entries(commerceItem2("commerce.product", p2).values).filter(([k2]) => keys4.has(k2)).map(([k2, v]) => [keys4.get(k2), v])) }));
|
|
389187
|
+
const cleared = removeRecords2(doc2, collection.order);
|
|
389188
|
+
ctx2.commit(upsertRecords2(cleared, collection.id, rows).document);
|
|
389189
|
+
return { summary: `Drew ${collection.name} with ${products.length} of the store's products`, data: { collection: collection.id, products: products.length } };
|
|
389190
|
+
}
|
|
389191
|
+
});
|
|
388338
389192
|
}
|
|
388339
389193
|
});
|
|
388340
389194
|
|
|
@@ -389339,6 +390193,7 @@ function designRecorder() {
|
|
|
389339
390193
|
var installed;
|
|
389340
390194
|
var init_recorders = __esm({
|
|
389341
390195
|
"lib/agent/design-script/recorders.ts"() {
|
|
390196
|
+
"use strict";
|
|
389342
390197
|
installed = null;
|
|
389343
390198
|
}
|
|
389344
390199
|
});
|
|
@@ -390854,8 +391709,8 @@ var init_app = __esm({
|
|
|
390854
391709
|
s.setActiveBreakpoint(breakpoint2);
|
|
390855
391710
|
const { breakpointsOf: breakpointsOf2 } = await Promise.resolve().then(() => (init_breakpoints(), breakpoints_exports));
|
|
390856
391711
|
const shown2 = (await store5()).activeBreakpoint;
|
|
390857
|
-
const
|
|
390858
|
-
return { summary: `Showing ${(
|
|
391712
|
+
const all4 = breakpointsOf2(s.document);
|
|
391713
|
+
return { summary: `Showing ${(all4.find((b) => b.id === shown2) ?? all4[0]).name}`, data: { breakpoint: shown2 ?? all4[0].id } };
|
|
390859
391714
|
}
|
|
390860
391715
|
});
|
|
390861
391716
|
appCommands = [modeSet, modeEdit, nodeRasterize, panelOpen, panelToggle, dialogOpen, aiOpen, docAction, toolSet, toolPlace, nodeOps, canvasToggle, viewSetBreakpoint, popcornOpen, pageGo];
|
|
@@ -391688,9 +392543,9 @@ var init_check = __esm({
|
|
|
391688
392543
|
MAX_FRAME_PX = 8192;
|
|
391689
392544
|
label2 = (t3) => `"${(t3.characters || t3.name).replace(/\s+/g, " ").slice(0, 40)}"`;
|
|
391690
392545
|
presetOf = (doc2, w, h) => {
|
|
391691
|
-
const
|
|
391692
|
-
const web =
|
|
391693
|
-
return (doc2.settings?.kind === "WEB" || web &&
|
|
392546
|
+
const all4 = PAGE_PRESETS.filter((p2) => p2.unit === "px" && p2.width === w && p2.height === h);
|
|
392547
|
+
const web = all4.find((p2) => p2.category === "WEB");
|
|
392548
|
+
return (doc2.settings?.kind === "WEB" || web && all4.length > 1 && w >= 1024 ? web : void 0)?.id ?? all4[0]?.id;
|
|
391694
392549
|
};
|
|
391695
392550
|
}
|
|
391696
392551
|
});
|
|
@@ -392485,6 +393340,7 @@ var init_site3 = __esm({
|
|
|
392485
393340
|
init_controls();
|
|
392486
393341
|
init_types();
|
|
392487
393342
|
init_routes();
|
|
393343
|
+
init_commerce();
|
|
392488
393344
|
init_doc_helpers();
|
|
392489
393345
|
init_errors();
|
|
392490
393346
|
init_types5();
|
|
@@ -392540,9 +393396,9 @@ var init_site3 = __esm({
|
|
|
392540
393396
|
run: (args2, ctx2) => {
|
|
392541
393397
|
const { doc: doc2, ids: ids2 } = resolveTargets(ctx2, args2.ids, "set_responsive");
|
|
392542
393398
|
if (!args2.set && !args2.reset) throw new ToolError("set_responsive needs set or reset.");
|
|
392543
|
-
const
|
|
392544
|
-
if (!
|
|
392545
|
-
if (isBaseBreakpoint(doc2, args2.breakpoint)) throw new ToolError(`"${args2.breakpoint}" is the base: what a layer has there is the layer itself. Use update_nodes, or name a narrower breakpoint (${
|
|
393399
|
+
const all4 = breakpointsOf(doc2);
|
|
393400
|
+
if (!all4.some((b) => b.id === args2.breakpoint)) throw new ToolError(`No breakpoint "${args2.breakpoint}". This file has: ${all4.map((b) => b.id).join(", ")}.`);
|
|
393401
|
+
if (isBaseBreakpoint(doc2, args2.breakpoint)) throw new ToolError(`"${args2.breakpoint}" is the base: what a layer has there is the layer itself. Use update_nodes, or name a narrower breakpoint (${all4.slice(1).map((b) => b.id).join(", ")}).`);
|
|
392546
393402
|
const patches = /* @__PURE__ */ new Map();
|
|
392547
393403
|
for (const id3 of ids2) {
|
|
392548
393404
|
let node2 = doc2.nodes[id3];
|
|
@@ -392639,7 +393495,7 @@ var init_site3 = __esm({
|
|
|
392639
393495
|
options: external_exports.array(external_exports.object({ value: external_exports.string().max(200), label: external_exports.string().max(200) })).max(200).optional().describe("SELECT: its choices."),
|
|
392640
393496
|
buttonType: external_exports.enum(["submit", "reset", "button"]).optional().describe("BUTTON: what it does in a form (default submit)."),
|
|
392641
393497
|
variableId: external_exports.string().nullable().optional().describe("The variable typing writes, so layers bound to it follow; null unbinds."),
|
|
392642
|
-
formAction: external_exports.enum(["signUp", "signIn", "signOut", "updateAccount", "changePassword", "deleteAccount", "forgotPassword", "resetPassword", "deleteRecord", "updateRecord"]).nullable().optional().describe(`FORM: what sending does on a published site with sign-in. signUp: make an account from its fields named name, email and password. signIn: sign in with email and password. signOut: end the session. updateAccount: change the signed-in visitor's name (field name). changePassword: fields password (the current one) and new_password. deleteAccount: field password, then the visitor is signed out for good. forgotPassword: field email, emails a reset link that opens the site's /reset-password page; resetPassword (on that page): field new_password. deleteRecord: a form inside a repeated list's copy removes that copy's record from the visitor's own. updateRecord: a form inside a copy changes that copy's record \u2014 the fields it sends take their values, the rest stay; a BUTTON with a name and a value sends them with the form it sends ("Mark done" is a button named done with value Yes). null (default): save its values (to the visitor's own records when the form's collectionId is a perVisitor collection: each control's name is a field). onSubmit runs only when it worked; a refusal is put in the variable user/signInError.`),
|
|
393498
|
+
formAction: external_exports.enum(["signUp", "signIn", "signOut", "updateAccount", "changePassword", "deleteAccount", "forgotPassword", "resetPassword", "deleteRecord", "updateRecord", ...COMMERCE_ACTIONS]).nullable().optional().describe(`FORM: what sending does on a published site with sign-in. signUp: make an account from its fields named name, email and password. signIn: sign in with email and password. signOut: end the session. updateAccount: change the signed-in visitor's name (field name). changePassword: fields password (the current one) and new_password. deleteAccount: field password, then the visitor is signed out for good. forgotPassword: field email, emails a reset link that opens the site's /reset-password page; resetPassword (on that page): field new_password. deleteRecord: a form inside a repeated list's copy removes that copy's record from the visitor's own. updateRecord: a form inside a copy changes that copy's record \u2014 the fields it sends take their values, the rest stay; a BUTTON with a name and a value sends them with the form it sends ("Mark done" is a button named done with value Yes). null (default): save its values (to the visitor's own records when the form's collectionId is a perVisitor collection: each control's name is a field). onSubmit runs only when it worked; a refusal is put in the variable user/signInError. Storefront actions (for a design exported as components for a Next.js Commerce store): addToCart (a field or hidden input named merchandiseId, usually {{item.variant_id}}), updateCartLine (merchandiseId and quantity), removeCartLine (merchandiseId), checkout, search (a field named q); each becomes a prop of the exported component (onAddToCart, \u2026) its form sends to.`),
|
|
392643
393499
|
collectionId: external_exports.string().nullable().optional().describe("FORM: the collection its values are kept in as a record (each control named as a field)."),
|
|
392644
393500
|
onSubmit: external_exports.record(external_exports.string(), external_exports.unknown()).nullable().optional().describe('FORM: a prototype action run once it is sent, as edit_prototype takes them ({navigationType: "NAVIGATE", destinationId: <thank-you frame>}).')
|
|
392645
393501
|
}).strict(),
|
|
@@ -392811,7 +393667,8 @@ var init_site3 = __esm({
|
|
|
392811
393667
|
name: c2.name,
|
|
392812
393668
|
records: c2.order.filter((id3) => doc2.records?.[id3]).length,
|
|
392813
393669
|
fields: c2.fields.map((f2) => ({ id: f2.id, name: f2.name, key: fieldKey(f2.name), type: f2.type, ...f2.options ? { options: f2.options } : {} })),
|
|
392814
|
-
slugField: c2.fields.find((f2) => f2.id === c2.slugFieldId)?.name ?? null
|
|
393670
|
+
slugField: c2.fields.find((f2) => f2.id === c2.slugFieldId)?.name ?? null,
|
|
393671
|
+
...c2.schema ? { schema: c2.schema } : {}
|
|
392815
393672
|
});
|
|
392816
393673
|
dataEditCollection = defineCommand({
|
|
392817
393674
|
id: "data.editCollection",
|
|
@@ -392832,6 +393689,7 @@ var init_site3 = __esm({
|
|
|
392832
393689
|
slugField: external_exports.string().nullable().optional().describe("The field a record's page address is made from (by name); default: the first SLUG or TEXT field."),
|
|
392833
393690
|
shared: external_exports.boolean().optional().describe("With perVisitor (turned on with it): every signed-in visitor sees everyone's records \u2014 a guest book, a team board. Each record says who made it (item_by) and whether it is the visitor's own (item_mine); only its maker changes or deletes it."),
|
|
392834
393691
|
perVisitor: external_exports.boolean().optional().describe("Each signed-in visitor of the published site has their own records: a list repeated from it shows only theirs, and a form bound to it adds to theirs, kept in the site's database. The records in the file are samples the design is drawn with. Needs a database with sign-in attached."),
|
|
393692
|
+
schema: external_exports.enum(COMMERCE_SCHEMAS).nullable().optional().describe("What its records stand for in a storefront: commerce.product, commerce.collection, commerce.cart (one record: the cart count and totals, shown by a list of one), commerce.cartLine or commerce.menu. Its fields become the schema's (leave fields out) and its records are samples; exported as components, a list repeated from it is a typed prop (products, collections, cart, lines, menu) a Next.js Commerce store fills. null clears it."),
|
|
392835
393693
|
remove: external_exports.boolean().optional().describe("Delete the collection, its records, and the repeaters and collection pages that used it.")
|
|
392836
393694
|
}).strict(),
|
|
392837
393695
|
expose: {
|
|
@@ -392850,6 +393708,7 @@ var init_site3 = __esm({
|
|
|
392850
393708
|
return { summary: `Removed collection ${before.name}`, data: { removed: before.id } };
|
|
392851
393709
|
}
|
|
392852
393710
|
if (!before && !args2.name) throw new ToolError("A new collection needs a name.");
|
|
393711
|
+
if (args2.schema && !args2.fields) args2 = { ...args2, fields: COMMERCE_FIELDS[args2.schema].map((f2) => ({ name: f2.name, type: f2.type })) };
|
|
392853
393712
|
if (!before && !args2.fields) throw new ToolError("A new collection needs fields.");
|
|
392854
393713
|
if (!before && Object.keys(doc2.collections ?? {}).length >= COLLECTION_LIMITS.collections) throw new ToolError(`A file holds up to ${COLLECTION_LIMITS.collections} collections.`);
|
|
392855
393714
|
const keys4 = (args2.fields ?? []).map((f2) => fieldKey(f2.name));
|
|
@@ -392870,6 +393729,11 @@ var init_site3 = __esm({
|
|
|
392870
393729
|
void _was;
|
|
392871
393730
|
next2 = { ...next2, collections: { ...next2.collections, [draft.id]: args2.shared ? { ...rest, shared: true, perVisitor: true } : rest } };
|
|
392872
393731
|
}
|
|
393732
|
+
if (args2.schema !== void 0) {
|
|
393733
|
+
const { schema: _was, ...rest } = next2.collections[draft.id];
|
|
393734
|
+
void _was;
|
|
393735
|
+
next2 = { ...next2, collections: { ...next2.collections, [draft.id]: args2.schema ? { ...rest, schema: args2.schema } : rest } };
|
|
393736
|
+
}
|
|
392873
393737
|
if (args2.perVisitor !== void 0) {
|
|
392874
393738
|
const { perVisitor: _was, ...rest } = next2.collections[draft.id];
|
|
392875
393739
|
void _was;
|
|
@@ -392953,11 +393817,11 @@ var init_site3 = __esm({
|
|
|
392953
393817
|
return { summary: list2.length ? `${list2.length} collections: ${list2.map((c3) => c3.name).join(", ")}` : "No collections", data: { collections: list2 } };
|
|
392954
393818
|
}
|
|
392955
393819
|
const c2 = collectionOf(doc2, args2.collection);
|
|
392956
|
-
const
|
|
393820
|
+
const all4 = recordsIn(doc2, c2.id);
|
|
392957
393821
|
const slugs = recordSlugs(doc2, c2.id);
|
|
392958
393822
|
const from2 = args2.offset ?? 0;
|
|
392959
|
-
const records =
|
|
392960
|
-
return { summary: `${c2.name}: ${records.length} of ${
|
|
393823
|
+
const records = all4.slice(from2, from2 + (args2.limit ?? 50)).map((r) => ({ id: r.id, slug: slugs.get(r.id), values: Object.fromEntries(c2.fields.map((f2) => [fieldKey(f2.name), r.values[f2.id] ?? null])) }));
|
|
393824
|
+
return { summary: `${c2.name}: ${records.length} of ${all4.length} records`, data: { collection: described2(c2, doc2), total: all4.length, records } };
|
|
392961
393825
|
}
|
|
392962
393826
|
});
|
|
392963
393827
|
nodeSetRepeat = defineCommand({
|
|
@@ -394098,6 +394962,7 @@ var init_builtin4 = __esm({
|
|
|
394098
394962
|
exportPages,
|
|
394099
394963
|
exportPptx,
|
|
394100
394964
|
exportWeb,
|
|
394965
|
+
exportStorefront,
|
|
394101
394966
|
// state machines (lib/motion/state-machine.ts): interactive timelines (appended, as above)
|
|
394102
394967
|
motionEditStateMachine,
|
|
394103
394968
|
motionGetStateMachine,
|
|
@@ -394131,6 +394996,7 @@ var init_builtin4 = __esm({
|
|
|
394131
394996
|
integrationOpen,
|
|
394132
394997
|
integrationListResources,
|
|
394133
394998
|
integrationSubmissions,
|
|
394999
|
+
integrationPullProducts,
|
|
394134
395000
|
// a copy of the open file as a new file (lib/commands/file.ts) (appended, as above)
|
|
394135
395001
|
fileDuplicate,
|
|
394136
395002
|
// a whiteboard as one picture, or its stickies as Markdown / CSV (lib/popcorn/board-export.ts) (appended, as above)
|
|
@@ -399353,11 +400219,11 @@ function fileStorage(path) {
|
|
|
399353
400219
|
return {
|
|
399354
400220
|
get: async (key5) => read6()[key5],
|
|
399355
400221
|
set: async (key5, value3) => {
|
|
399356
|
-
const
|
|
399357
|
-
|
|
400222
|
+
const all4 = read6();
|
|
400223
|
+
all4[key5] = value3;
|
|
399358
400224
|
if (!path) return;
|
|
399359
400225
|
mkdirSync3(dirname(path), { recursive: true });
|
|
399360
|
-
writeFileSync3(path, JSON.stringify(
|
|
400226
|
+
writeFileSync3(path, JSON.stringify(all4));
|
|
399361
400227
|
}
|
|
399362
400228
|
};
|
|
399363
400229
|
}
|
|
@@ -399950,15 +400816,15 @@ function runCommandsList(positionals, flags, out) {
|
|
|
399950
400816
|
out.line(commandHelp(command));
|
|
399951
400817
|
return;
|
|
399952
400818
|
}
|
|
399953
|
-
const
|
|
399954
|
-
const rows = cliCommands().filter((c2) =>
|
|
400819
|
+
const all4 = flagBool(flags, "all");
|
|
400820
|
+
const rows = cliCommands().filter((c2) => all4 || ["local", "browser"].includes(availability2(c2)));
|
|
399955
400821
|
if (out.json) {
|
|
399956
400822
|
out.result(`${rows.length} commands`, rows.map((c2) => ({ id: c2.id, title: c2.title, availability: availability2(c2), effect: c2.effect, flat: specOf(c2).flat })));
|
|
399957
400823
|
return;
|
|
399958
400824
|
}
|
|
399959
400825
|
out.line(table([["COMMAND", "WHERE", "TITLE"], ...rows.map((c2) => [c2.id, WHERE[availability2(c2)], c2.title])]));
|
|
399960
400826
|
out.line(`
|
|
399961
|
-
${rows.length} commands${
|
|
400827
|
+
${rows.length} commands${all4 ? "" : " that run from the CLI (--all lists every command, with where the rest run)"}. \`popcraft commands <id>\` shows a command's flags.`);
|
|
399962
400828
|
}
|
|
399963
400829
|
function suggest(key5) {
|
|
399964
400830
|
const k2 = key5.toLowerCase().replace(/[^a-z]/g, "");
|
|
@@ -401056,6 +401922,64 @@ export default defineTemplate({
|
|
|
401056
401922
|
}
|
|
401057
401923
|
});
|
|
401058
401924
|
|
|
401925
|
+
// packages/cli/src/storefront.ts
|
|
401926
|
+
var storefront_exports2 = {};
|
|
401927
|
+
__export(storefront_exports2, {
|
|
401928
|
+
runStorefront: () => runStorefront
|
|
401929
|
+
});
|
|
401930
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "node:fs";
|
|
401931
|
+
import { dirname as dirname4, join as join11 } from "node:path";
|
|
401932
|
+
async function mediaFor(refs, file2, appUrl) {
|
|
401933
|
+
const out = {};
|
|
401934
|
+
await Promise.all(refs.map(async (ref3) => {
|
|
401935
|
+
const hash3 = ref3.slice("media://".length);
|
|
401936
|
+
const local = join11(dirname4(file2), "media", hash3);
|
|
401937
|
+
const bytes2 = existsSync12(local) ? new Uint8Array(readFileSync12(local)) : await fetch(`${appUrl}/templates/media/${hash3}`).then(async (r) => r.ok ? new Uint8Array(await r.arrayBuffer()) : null, () => null);
|
|
401938
|
+
if (bytes2) out[ref3] = { bytes: bytes2, type: sniff(bytes2) };
|
|
401939
|
+
}));
|
|
401940
|
+
return out;
|
|
401941
|
+
}
|
|
401942
|
+
async function runStorefront(rest, flags, out, appUrl) {
|
|
401943
|
+
const file2 = rest[0];
|
|
401944
|
+
if (!file2) throw usage("popcraft storefront <file.popcraft> [--target next-commerce|shopify-theme] [--out <dir>] [--page <id|name>] [--styling inline|tailwind] [--dir components/popcraft]");
|
|
401945
|
+
const target2 = flagString(flags, "target") ?? "next-commerce";
|
|
401946
|
+
if (!STOREFRONT_TARGET_IDS.includes(target2)) throw usage(`--target is one of ${STOREFRONT_TARGET_IDS.join(", ")}`);
|
|
401947
|
+
const doc2 = readPopcraft(file2);
|
|
401948
|
+
const ref3 = flagString(flags, "page");
|
|
401949
|
+
const pageId2 = ref3 ? resolvePage(doc2, ref3) : doc2.pages[0];
|
|
401950
|
+
if (!pageId2) throw usage(`No page ${ref3}`);
|
|
401951
|
+
const styling = flagString(flags, "styling");
|
|
401952
|
+
if (styling && styling !== "inline" && styling !== "tailwind") throw usage("--styling is inline or tailwind");
|
|
401953
|
+
const screens = componentScreens(doc2, pageId2);
|
|
401954
|
+
if (!screens.length) throw usage("That page has no screens: a top-level frame is a component.");
|
|
401955
|
+
const refs = componentMedia(doc2, screens);
|
|
401956
|
+
const media2 = await mediaFor(refs, file2, appUrl);
|
|
401957
|
+
const missing = refs.filter((r) => !media2[r]);
|
|
401958
|
+
if (missing.length) out.info(`${missing.length} picture(s) not found beside the file or on ${appUrl}; they keep their media:// address: ${missing.join(", ")}`);
|
|
401959
|
+
const dir = flagString(flags, "dir");
|
|
401960
|
+
const files = target2 === "next-commerce" && dir ? componentFiles(doc2, screens, { styling, dir, media: media2 }) : STOREFRONT_TARGETS[target2].files(doc2, screens, { styling, media: media2 });
|
|
401961
|
+
const root2 = flagString(flags, "out") ?? ".";
|
|
401962
|
+
for (const f2 of files) {
|
|
401963
|
+
const at3 = join11(root2, f2.path);
|
|
401964
|
+
mkdirSync8(dirname4(at3), { recursive: true });
|
|
401965
|
+
writeFileSync9(at3, f2.content);
|
|
401966
|
+
}
|
|
401967
|
+
out.result(`Wrote ${STOREFRONT_TARGETS[target2].label}: ${screens.length} page${screens.length === 1 ? "" : "s"} (${screens.map((s) => s.name).join(", ")}) and ${files.filter((f2) => /^(public|assets)\/.*\.(jpg|png|webp|gif|avif|svg)$/.test(f2.path)).length} picture(s) under ${root2}`, out.json ? { target: target2, pages: screens.map((s) => s.name), files: files.map((f2) => f2.path) } : void 0);
|
|
401968
|
+
return 0;
|
|
401969
|
+
}
|
|
401970
|
+
var sniff;
|
|
401971
|
+
var init_storefront3 = __esm({
|
|
401972
|
+
"packages/cli/src/storefront.ts"() {
|
|
401973
|
+
"use strict";
|
|
401974
|
+
init_components();
|
|
401975
|
+
init_storefront();
|
|
401976
|
+
init_args();
|
|
401977
|
+
init_headless2();
|
|
401978
|
+
init_io();
|
|
401979
|
+
sniff = (b) => b[0] === 255 && b[1] === 216 ? "image/jpeg" : b[0] === 137 && b[1] === 80 ? "image/png" : b[8] === 87 && b[9] === 69 ? "image/webp" : b[0] === 71 && b[1] === 73 ? "image/gif" : "application/octet-stream";
|
|
401980
|
+
}
|
|
401981
|
+
});
|
|
401982
|
+
|
|
401059
401983
|
// lib/desktop/local-assets.ts
|
|
401060
401984
|
function parsePluginFolder(manifestText, files) {
|
|
401061
401985
|
let raw;
|
|
@@ -401091,36 +402015,36 @@ __export(plugins_exports, {
|
|
|
401091
402015
|
runPluginHeadless: () => runPluginHeadless
|
|
401092
402016
|
});
|
|
401093
402017
|
import { spawn } from "node:child_process";
|
|
401094
|
-
import { existsSync as
|
|
401095
|
-
import { dirname as
|
|
402018
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync9, readFileSync as readFileSync13, statSync as statSync6, writeFileSync as writeFileSync10 } from "node:fs";
|
|
402019
|
+
import { dirname as dirname5, extname as extname3, join as join12, resolve as resolve5, sep } from "node:path";
|
|
401096
402020
|
function loadPlugin(ref3, root2 = desktopDataDir()) {
|
|
401097
402021
|
let path = ref3;
|
|
401098
|
-
if (!
|
|
402022
|
+
if (!existsSync13(path)) {
|
|
401099
402023
|
const installed3 = listResources2("plugins", root2).find((r) => r.name === ref3);
|
|
401100
402024
|
if (!installed3) throw usage(`No plugin "${ref3}": give its folder, .zip or .json, or the name of one in \`popcraft plugins list\`.`);
|
|
401101
|
-
path =
|
|
402025
|
+
path = join12(root2, installed3.path);
|
|
401102
402026
|
}
|
|
401103
402027
|
if (statSync6(path).isDirectory()) {
|
|
401104
402028
|
const dir = resolve5(path);
|
|
401105
|
-
const manifest2 =
|
|
401106
|
-
if (!
|
|
402029
|
+
const manifest2 = join12(dir, "manifest.json");
|
|
402030
|
+
if (!existsSync13(manifest2)) throw usage(`${path} has no manifest.json.`);
|
|
401107
402031
|
const files = new Proxy({}, {
|
|
401108
402032
|
get: (_, rel) => {
|
|
401109
402033
|
if (typeof rel !== "string") return void 0;
|
|
401110
402034
|
const file2 = resolve5(dir, rel);
|
|
401111
|
-
return file2.startsWith(dir + sep) &&
|
|
402035
|
+
return file2.startsWith(dir + sep) && existsSync13(file2) ? readFileSync13(file2, "utf8") : void 0;
|
|
401112
402036
|
}
|
|
401113
402037
|
});
|
|
401114
|
-
return parsePluginFolder(
|
|
402038
|
+
return parsePluginFolder(readFileSync13(manifest2, "utf8"), files);
|
|
401115
402039
|
}
|
|
401116
|
-
if (extname3(path).toLowerCase() === ".zip") return parsePluginZip(new Uint8Array(
|
|
401117
|
-
return parsePluginBundle(
|
|
402040
|
+
if (extname3(path).toLowerCase() === ".zip") return parsePluginZip(new Uint8Array(readFileSync13(path)));
|
|
402041
|
+
return parsePluginBundle(readFileSync13(path, "utf8"));
|
|
401118
402042
|
}
|
|
401119
402043
|
async function approvedPermissions(manifest2, dir) {
|
|
401120
402044
|
const asked = manifest2.permissions;
|
|
401121
402045
|
if (!asked.length) return [];
|
|
401122
|
-
const file2 = dir ?
|
|
401123
|
-
const approved = file2 &&
|
|
402046
|
+
const file2 = dir ? join12(dir, "plugin-permissions.json") : null;
|
|
402047
|
+
const approved = file2 && existsSync13(file2) ? JSON.parse(readFileSync13(file2, "utf8")) : {};
|
|
401124
402048
|
if (asked.every((p2) => approved[manifest2.id]?.includes(p2))) return asked.slice();
|
|
401125
402049
|
const answer2 = await askConfirmation({
|
|
401126
402050
|
id: newConfirmId(),
|
|
@@ -401131,8 +402055,8 @@ async function approvedPermissions(manifest2, dir) {
|
|
|
401131
402055
|
});
|
|
401132
402056
|
if (!answer2.approved) throw new CliError(`${manifest2.name} was not run: ${answer2.reason}.`, 3);
|
|
401133
402057
|
if (file2) {
|
|
401134
|
-
|
|
401135
|
-
|
|
402058
|
+
mkdirSync9(dirname5(file2), { recursive: true });
|
|
402059
|
+
writeFileSync10(file2, JSON.stringify({ ...approved, [manifest2.id]: asked }));
|
|
401136
402060
|
}
|
|
401137
402061
|
return asked.slice();
|
|
401138
402062
|
}
|
|
@@ -401145,8 +402069,8 @@ async function runPluginHeadless(plugin, opts) {
|
|
|
401145
402069
|
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
401146
402070
|
const storageDir = opts.storageDir ?? null;
|
|
401147
402071
|
const granted = await approvedPermissions(manifest2, storageDir);
|
|
401148
|
-
const storageFile = storageDir ?
|
|
401149
|
-
const storage = storageFile &&
|
|
402072
|
+
const storageFile = storageDir ? join12(storageDir, "plugin-storage", `${manifest2.id}.json`) : null;
|
|
402073
|
+
const storage = storageFile && existsSync13(storageFile) ? JSON.parse(readFileSync13(storageFile, "utf8")) : {};
|
|
401150
402074
|
const errors2 = [];
|
|
401151
402075
|
const app = (what) => new Error(`${manifest2.name} ${what}, which only works in the app: install it there with \`popcraft plugins install\`.`);
|
|
401152
402076
|
let finish3;
|
|
@@ -401172,8 +402096,8 @@ async function runPluginHeadless(plugin, opts) {
|
|
|
401172
402096
|
storageSet: async (key5, value3) => {
|
|
401173
402097
|
storage[key5] = value3;
|
|
401174
402098
|
if (!storageFile) return;
|
|
401175
|
-
|
|
401176
|
-
|
|
402099
|
+
mkdirSync9(dirname5(storageFile), { recursive: true });
|
|
402100
|
+
writeFileSync10(storageFile, JSON.stringify(storage));
|
|
401177
402101
|
},
|
|
401178
402102
|
exportNode: async () => {
|
|
401179
402103
|
throw app("renders with the canvas");
|
|
@@ -401226,7 +402150,7 @@ async function runPluginHeadless(plugin, opts) {
|
|
|
401226
402150
|
async function runPluginCommand(args2, flags, out) {
|
|
401227
402151
|
const [ref3, file2] = args2;
|
|
401228
402152
|
if (!ref3 || !file2) throw usage("Usage: popcraft plugins run <plugin> <file.popcraft> [--command <id>] [--out <file>] [--dry-run] [--timeout <seconds>]");
|
|
401229
|
-
if (!
|
|
402153
|
+
if (!existsSync13(file2)) throw usage(`No such file: ${file2}`);
|
|
401230
402154
|
const plugin = loadPlugin(ref3, flagString(flags, "dataDir") ?? desktopDataDir());
|
|
401231
402155
|
openInStore(readPopcraft(file2));
|
|
401232
402156
|
const before = currentDocument();
|
|
@@ -401356,7 +402280,7 @@ init_resources();
|
|
|
401356
402280
|
init_desktop();
|
|
401357
402281
|
init_hypery();
|
|
401358
402282
|
import { createInterface } from "node:readline";
|
|
401359
|
-
var VERSION2 = "0.
|
|
402283
|
+
var VERSION2 = "0.15.0";
|
|
401360
402284
|
var HELP = `popcraft ${VERSION2} \u2014 the PopCraft command line
|
|
401361
402285
|
|
|
401362
402286
|
Files (headless, on .popcraft files):
|
|
@@ -401398,6 +402322,10 @@ Templates (made as PopCraft's own are, with @popcraft/kit installed beside them)
|
|
|
401398
402322
|
popcraft publish [dir] [--dry-run] [--changed-since <ref>] marketplace items under dir (default: .), templates
|
|
401399
402323
|
with their media/ and pictures/
|
|
401400
402324
|
|
|
402325
|
+
Storefronts (one design, bound to a store's data, as a store's project):
|
|
402326
|
+
popcraft storefront <file> [--target next-commerce|shopify-theme] [--out <dir>] [--page <id|name>]
|
|
402327
|
+
[--styling inline|tailwind] [--dir components/popcraft] [--app-url <url>]
|
|
402328
|
+
|
|
401401
402329
|
The desktop app's local folders:
|
|
401402
402330
|
popcraft plugins|themes|fonts|skills|agents [list | install <path|url> | remove <name> | path]
|
|
401403
402331
|
popcraft plugins run <plugin> <file> [--command <id>] a plugin's main script on the file, sandboxed (no panel)
|
|
@@ -401520,6 +402448,10 @@ async function main(argv) {
|
|
|
401520
402448
|
const { runTemplate: runTemplate2 } = await Promise.resolve().then(() => (init_template(), template_exports));
|
|
401521
402449
|
return runTemplate2(rest, flags, { out, appUrl: (flagString(flags, "appUrl") ?? process.env.POPCRAFT_APP_URL ?? url4).replace(/\/+$/, ""), target: target2 });
|
|
401522
402450
|
}
|
|
402451
|
+
case "storefront": {
|
|
402452
|
+
const { runStorefront: runStorefront2 } = await Promise.resolve().then(() => (init_storefront3(), storefront_exports2));
|
|
402453
|
+
return runStorefront2(rest, flags, out, (flagString(flags, "appUrl") ?? process.env.POPCRAFT_APP_URL ?? url4).replace(/\/+$/, ""));
|
|
402454
|
+
}
|
|
401523
402455
|
case "pictures": {
|
|
401524
402456
|
const { runPictures: runPictures2 } = await Promise.resolve().then(() => (init_pictures(), pictures_exports));
|
|
401525
402457
|
await runPictures2(rest[0] ?? ".", (flagString(flags, "appUrl") ?? process.env.POPCRAFT_APP_URL ?? url4).replace(/\/+$/, ""), out);
|