@fayz-ai/storefront 0.7.0 → 0.8.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/README.md +3 -1
- package/dist/components/StorefrontHeader.d.ts.map +1 -1
- package/dist/createStorefrontApp.d.ts.map +1 -1
- package/dist/index.cjs +215 -98
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +215 -99
- package/dist/index.js.map +1 -1
- package/dist/presets.d.ts +5 -0
- package/dist/presets.d.ts.map +1 -1
- package/dist/stores/cart.store.d.ts +5 -0
- package/dist/stores/cart.store.d.ts.map +1 -1
- package/dist/testids.d.ts +1 -0
- package/dist/testids.d.ts.map +1 -1
- package/dist/theme.d.ts +18 -2
- package/dist/theme.d.ts.map +1 -1
- package/dist/workflows/checkout.d.ts.map +1 -1
- package/package.json +13 -7
- package/src/components/StorefrontHeader.tsx +35 -8
- package/src/createStorefrontApp.tsx +18 -1
- package/src/index.ts +1 -0
- package/src/presets.ts +66 -0
- package/src/stores/cart.store.ts +16 -1
- package/src/testids.ts +1 -0
- package/src/theme.ts +33 -3
- package/src/workflows/checkout.ts +4 -1
package/README.md
CHANGED
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/@fayz-ai/storefront)
|
|
6
6
|
[](https://github.com/FayaLabs/fayz-sdk/blob/main/LICENSE)
|
|
7
7
|
|
|
8
|
+
**Status:** beta — published to npm and used across Fayz dogfood apps. Pre-1.0: minor APIs may change before 1.0.
|
|
9
|
+
|
|
8
10
|
`@fayz-ai/storefront` is the customer-facing surface of the Fayz SDK: a storefront scaffold that renders a page as a tree of **blocks** (hero, products, manifesto, cart, …) defined in the app manifest. Two completely different brands come out of the same template with zero custom components — the storefront is *data*, not a fork.
|
|
9
11
|
|
|
10
|
-
It reads commerce from `@fayz-ai/shop`, so the same engine powering an admin also powers the public store. Customize from labels to a fully bespoke section via the [customization ladder](../../docs/
|
|
12
|
+
It reads commerce from `@fayz-ai/shop`, so the same engine powering an admin also powers the public store. Customize from labels to a fully bespoke section via the [customization ladder](../../docs/CUSTOMIZATION.md) — never by editing this package.
|
|
11
13
|
|
|
12
14
|
## What's inside
|
|
13
15
|
- **Scaffold** — `defineStorefront(config)` + `StorefrontScaffold` rendered by `renderApp`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StorefrontHeader.d.ts","sourceRoot":"","sources":["../../src/components/StorefrontHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"StorefrontHeader.d.ts","sourceRoot":"","sources":["../../src/components/StorefrontHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAA;AA0SvC,wBAAgB,gBAAgB,sBA2E/B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createStorefrontApp.d.ts","sourceRoot":"","sources":["../src/createStorefrontApp.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAKzB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAG1D,OAAO,KAAK,EAAE,gBAAgB,EAA4B,MAAM,UAAU,CAAA;AAC1E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AACjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"createStorefrontApp.d.ts","sourceRoot":"","sources":["../src/createStorefrontApp.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAKzB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAG1D,OAAO,KAAK,EAAE,gBAAgB,EAA4B,MAAM,UAAU,CAAA;AAC1E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AACjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AA2GnD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAmCpE;AAED;gFACgF;AAChF,wBAAgB,eAAe,sBAkC9B;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,gBAAgB,GAAG,KAAK,CAAC,aAAa,CAajF;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,gBAAgB,CAAA;IACxB,QAAQ,CAAC,EAAE,YAAY,CAAA;IACvB,UAAU,CAAC,EAAE,oBAAoB,CAAA;IACjC,MAAM,CAAC,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAA;IACnC,KAAK,CAAC,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAA;IAClC,QAAQ,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAA;CACxC;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,KAAK,CAAC,aAAa,CAgBtF"}
|
package/dist/index.cjs
CHANGED
|
@@ -229,92 +229,6 @@ function matchPath(pattern, path) {
|
|
|
229
229
|
function Link({ to, children, ...rest }) {
|
|
230
230
|
return React6__default.default.createElement("a", { href: `#${to}`, ...rest }, children);
|
|
231
231
|
}
|
|
232
|
-
var RADIUS_MAP = {
|
|
233
|
-
none: { button: "0px", card: "0px", input: "0px" },
|
|
234
|
-
soft: { button: "6px", card: "10px", input: "6px" },
|
|
235
|
-
round: { button: "10px", card: "16px", input: "10px" },
|
|
236
|
-
pill: { button: "999px", card: "20px", input: "999px" }
|
|
237
|
-
};
|
|
238
|
-
var COLOR_VAR_MAP = {
|
|
239
|
-
background: "--background",
|
|
240
|
-
foreground: "--foreground",
|
|
241
|
-
primary: "--primary",
|
|
242
|
-
primaryForeground: "--primary-foreground",
|
|
243
|
-
card: "--card",
|
|
244
|
-
cardForeground: "--card-foreground",
|
|
245
|
-
muted: "--muted",
|
|
246
|
-
mutedForeground: "--muted-foreground",
|
|
247
|
-
border: "--border",
|
|
248
|
-
headerBackground: "--sf-header-bg",
|
|
249
|
-
headerForeground: "--sf-header-fg",
|
|
250
|
-
announcementBackground: "--sf-announcement-bg",
|
|
251
|
-
announcementForeground: "--sf-announcement-fg"
|
|
252
|
-
};
|
|
253
|
-
function themeToCss(theme) {
|
|
254
|
-
const lines = [];
|
|
255
|
-
for (const [key, cssVar] of Object.entries(COLOR_VAR_MAP)) {
|
|
256
|
-
const value = theme.colors?.[key];
|
|
257
|
-
if (value) lines.push(`${cssVar}: ${value};`);
|
|
258
|
-
}
|
|
259
|
-
if (!theme.colors?.headerBackground && theme.colors?.background) {
|
|
260
|
-
lines.push(`--sf-header-bg: ${theme.colors.background};`);
|
|
261
|
-
}
|
|
262
|
-
if (!theme.colors?.headerForeground && theme.colors?.foreground) {
|
|
263
|
-
lines.push(`--sf-header-fg: ${theme.colors.foreground};`);
|
|
264
|
-
}
|
|
265
|
-
if (theme.font) {
|
|
266
|
-
const fallback = theme.font.fallback ?? "sans-serif";
|
|
267
|
-
lines.push(`--font-family: '${theme.font.body}', ${fallback};`);
|
|
268
|
-
lines.push(`--sf-font-heading: '${theme.font.heading}', ${fallback};`);
|
|
269
|
-
}
|
|
270
|
-
const radius = RADIUS_MAP[theme.radius ?? "soft"];
|
|
271
|
-
lines.push(`--button-radius: ${radius.button};`);
|
|
272
|
-
lines.push(`--card-radius: ${radius.card};`);
|
|
273
|
-
lines.push(`--input-radius: ${radius.input};`);
|
|
274
|
-
lines.push(`--sf-radius-button: ${radius.button};`);
|
|
275
|
-
lines.push(`--sf-radius-card: ${radius.card};`);
|
|
276
|
-
lines.push(`--sf-radius-input: ${radius.input};`);
|
|
277
|
-
let css = `:root {
|
|
278
|
-
${lines.join("\n ")}
|
|
279
|
-
}
|
|
280
|
-
`;
|
|
281
|
-
css += `body { font-family: var(--font-family); }
|
|
282
|
-
`;
|
|
283
|
-
css += `h1, h2, h3, h4, .sf-heading { font-family: var(--sf-font-heading, var(--font-family)); }
|
|
284
|
-
`;
|
|
285
|
-
if (theme.uppercaseButtons) {
|
|
286
|
-
css += `.sf-cta { text-transform: uppercase; letter-spacing: 0.08em; }
|
|
287
|
-
`;
|
|
288
|
-
}
|
|
289
|
-
if (theme.header?.uppercaseNav) {
|
|
290
|
-
css += `.sf-nav-link { text-transform: uppercase; letter-spacing: 0.06em; font-size: 0.8rem; }
|
|
291
|
-
`;
|
|
292
|
-
}
|
|
293
|
-
return css;
|
|
294
|
-
}
|
|
295
|
-
function googleFontsHref(theme) {
|
|
296
|
-
if (!theme.font) return null;
|
|
297
|
-
const families = theme.font.googleFonts ?? [theme.font.heading, theme.font.body];
|
|
298
|
-
const unique = [...new Set(families)];
|
|
299
|
-
const params = unique.map((f) => `family=${encodeURIComponent(f).replace(/%20/g, "+")}:wght@300;400;500;600;700`).join("&");
|
|
300
|
-
return `https://fonts.googleapis.com/css2?${params}&display=swap`;
|
|
301
|
-
}
|
|
302
|
-
function StorefrontThemeStyle({ theme }) {
|
|
303
|
-
const fontsHref = googleFontsHref(theme);
|
|
304
|
-
React6.useEffect(() => {
|
|
305
|
-
if (!fontsHref) return;
|
|
306
|
-
const id = "sf-theme-fonts";
|
|
307
|
-
let link = document.getElementById(id);
|
|
308
|
-
if (!link) {
|
|
309
|
-
link = document.createElement("link");
|
|
310
|
-
link.id = id;
|
|
311
|
-
link.rel = "stylesheet";
|
|
312
|
-
document.head.appendChild(link);
|
|
313
|
-
}
|
|
314
|
-
link.href = fontsHref;
|
|
315
|
-
}, [fontsHref]);
|
|
316
|
-
return React6__default.default.createElement("style", { "data-sf-theme": theme.name }, themeToCss(theme));
|
|
317
|
-
}
|
|
318
232
|
|
|
319
233
|
// src/format.ts
|
|
320
234
|
function formatMoney(value, currency = "BRL", locale = "pt-BR") {
|
|
@@ -367,7 +281,7 @@ function productOptionSelectionKey(selection) {
|
|
|
367
281
|
// src/stores/cart.store.ts
|
|
368
282
|
var useCartStore = zustand.create()(
|
|
369
283
|
middleware.persist(
|
|
370
|
-
(set) => ({
|
|
284
|
+
(set, get) => ({
|
|
371
285
|
lines: [],
|
|
372
286
|
discountCode: null,
|
|
373
287
|
discountPercent: 0,
|
|
@@ -419,7 +333,16 @@ var useCartStore = zustand.create()(
|
|
|
419
333
|
clearDiscount: () => set({ discountCode: null, discountPercent: 0 }),
|
|
420
334
|
clear: () => set({ lines: [], discountCode: null, discountPercent: 0 }),
|
|
421
335
|
openDrawer: () => set({ isOpen: true }),
|
|
422
|
-
closeDrawer: () => set({ isOpen: false, justAddedLineId: null })
|
|
336
|
+
closeDrawer: () => set({ isOpen: false, justAddedLineId: null }),
|
|
337
|
+
reconcile: async (resolve) => {
|
|
338
|
+
const lines = get().lines;
|
|
339
|
+
if (lines.length === 0) return;
|
|
340
|
+
const keep = await Promise.all(
|
|
341
|
+
lines.map((line) => resolve(line).catch(() => true))
|
|
342
|
+
);
|
|
343
|
+
const kept = lines.filter((_, i) => keep[i]);
|
|
344
|
+
if (kept.length !== lines.length) set({ lines: kept });
|
|
345
|
+
}
|
|
423
346
|
}),
|
|
424
347
|
{
|
|
425
348
|
name: "fayz.storefront.cart.v1",
|
|
@@ -441,6 +364,102 @@ var selectShipping = (s, cfg) => {
|
|
|
441
364
|
return cfg.shipping.flatRate;
|
|
442
365
|
};
|
|
443
366
|
var selectTotal = (s, cfg) => roundCents(selectSubtotal(s) - selectDiscountTotal(s) + selectShipping(s, cfg));
|
|
367
|
+
var RADIUS_MAP = {
|
|
368
|
+
none: { button: "0px", card: "0px", input: "0px" },
|
|
369
|
+
soft: { button: "6px", card: "10px", input: "6px" },
|
|
370
|
+
round: { button: "10px", card: "16px", input: "10px" },
|
|
371
|
+
pill: { button: "999px", card: "20px", input: "999px" }
|
|
372
|
+
};
|
|
373
|
+
var COLOR_VAR_MAP = {
|
|
374
|
+
background: "--background",
|
|
375
|
+
foreground: "--foreground",
|
|
376
|
+
primary: "--primary",
|
|
377
|
+
primaryForeground: "--primary-foreground",
|
|
378
|
+
card: "--card",
|
|
379
|
+
cardForeground: "--card-foreground",
|
|
380
|
+
muted: "--muted",
|
|
381
|
+
mutedForeground: "--muted-foreground",
|
|
382
|
+
border: "--border",
|
|
383
|
+
headerBackground: "--sf-header-bg",
|
|
384
|
+
headerForeground: "--sf-header-fg",
|
|
385
|
+
announcementBackground: "--sf-announcement-bg",
|
|
386
|
+
announcementForeground: "--sf-announcement-fg",
|
|
387
|
+
accent: "--sf-accent",
|
|
388
|
+
accentForeground: "--sf-accent-foreground"
|
|
389
|
+
};
|
|
390
|
+
function themeToCss(theme) {
|
|
391
|
+
const lines = [];
|
|
392
|
+
for (const [key, cssVar] of Object.entries(COLOR_VAR_MAP)) {
|
|
393
|
+
const value = theme.colors?.[key];
|
|
394
|
+
if (value) lines.push(`${cssVar}: ${value};`);
|
|
395
|
+
}
|
|
396
|
+
if (!theme.colors?.headerBackground && theme.colors?.background) {
|
|
397
|
+
lines.push(`--sf-header-bg: ${theme.colors.background};`);
|
|
398
|
+
}
|
|
399
|
+
if (!theme.colors?.headerForeground && theme.colors?.foreground) {
|
|
400
|
+
lines.push(`--sf-header-fg: ${theme.colors.foreground};`);
|
|
401
|
+
}
|
|
402
|
+
if (theme.font) {
|
|
403
|
+
const fallback = theme.font.fallback ?? "sans-serif";
|
|
404
|
+
lines.push(`--font-family: '${theme.font.body}', ${fallback};`);
|
|
405
|
+
lines.push(`--sf-font-heading: '${theme.font.heading}', ${fallback};`);
|
|
406
|
+
if (theme.font.display) lines.push(`--sf-font-display: '${theme.font.display}', ${fallback};`);
|
|
407
|
+
if (theme.font.serif) lines.push(`--sf-font-serif: '${theme.font.serif}', serif;`);
|
|
408
|
+
}
|
|
409
|
+
for (const [key, value] of Object.entries(theme.tokens ?? {})) {
|
|
410
|
+
const name = key.startsWith("--") ? key : `--${key}`;
|
|
411
|
+
lines.push(`${name}: ${value};`);
|
|
412
|
+
}
|
|
413
|
+
const radius = RADIUS_MAP[theme.radius ?? "soft"];
|
|
414
|
+
lines.push(`--button-radius: ${radius.button};`);
|
|
415
|
+
lines.push(`--card-radius: ${radius.card};`);
|
|
416
|
+
lines.push(`--input-radius: ${radius.input};`);
|
|
417
|
+
lines.push(`--sf-radius-button: ${radius.button};`);
|
|
418
|
+
lines.push(`--sf-radius-card: ${radius.card};`);
|
|
419
|
+
lines.push(`--sf-radius-input: ${radius.input};`);
|
|
420
|
+
let css = `:root {
|
|
421
|
+
${lines.join("\n ")}
|
|
422
|
+
}
|
|
423
|
+
`;
|
|
424
|
+
css += `body { font-family: var(--font-family); }
|
|
425
|
+
`;
|
|
426
|
+
css += `h1, h2, h3, h4, .sf-heading { font-family: var(--sf-font-heading, var(--font-family)); }
|
|
427
|
+
`;
|
|
428
|
+
if (theme.uppercaseButtons) {
|
|
429
|
+
css += `.sf-cta { text-transform: uppercase; letter-spacing: 0.08em; }
|
|
430
|
+
`;
|
|
431
|
+
}
|
|
432
|
+
if (theme.header?.uppercaseNav) {
|
|
433
|
+
css += `.sf-nav-link { text-transform: uppercase; letter-spacing: 0.06em; font-size: 0.8rem; }
|
|
434
|
+
`;
|
|
435
|
+
}
|
|
436
|
+
return css;
|
|
437
|
+
}
|
|
438
|
+
function googleFontsHref(theme) {
|
|
439
|
+
if (!theme.font) return null;
|
|
440
|
+
const families = theme.font.googleFonts ?? [theme.font.heading, theme.font.body, theme.font.display, theme.font.serif].filter(
|
|
441
|
+
(f) => Boolean(f)
|
|
442
|
+
);
|
|
443
|
+
const unique = [...new Set(families)];
|
|
444
|
+
const params = unique.map((f) => `family=${encodeURIComponent(f).replace(/%20/g, "+")}:wght@300;400;500;600;700`).join("&");
|
|
445
|
+
return `https://fonts.googleapis.com/css2?${params}&display=swap`;
|
|
446
|
+
}
|
|
447
|
+
function StorefrontThemeStyle({ theme }) {
|
|
448
|
+
const fontsHref = googleFontsHref(theme);
|
|
449
|
+
React6.useEffect(() => {
|
|
450
|
+
if (!fontsHref) return;
|
|
451
|
+
const id = "sf-theme-fonts";
|
|
452
|
+
let link = document.getElementById(id);
|
|
453
|
+
if (!link) {
|
|
454
|
+
link = document.createElement("link");
|
|
455
|
+
link.id = id;
|
|
456
|
+
link.rel = "stylesheet";
|
|
457
|
+
document.head.appendChild(link);
|
|
458
|
+
}
|
|
459
|
+
link.href = fontsHref;
|
|
460
|
+
}, [fontsHref]);
|
|
461
|
+
return React6__default.default.createElement("style", { "data-sf-theme": theme.name }, themeToCss(theme));
|
|
462
|
+
}
|
|
444
463
|
var initial = {
|
|
445
464
|
search: "",
|
|
446
465
|
categoryId: null,
|
|
@@ -549,6 +568,7 @@ function usePopOnChange(value) {
|
|
|
549
568
|
var TID = {
|
|
550
569
|
// header
|
|
551
570
|
headerSearch: "header-search",
|
|
571
|
+
headerSearchToggle: "header-search-toggle",
|
|
552
572
|
cartButton: "cart-button",
|
|
553
573
|
cartCount: "cart-count",
|
|
554
574
|
accountLink: "account-link",
|
|
@@ -737,12 +757,26 @@ function UtilityBar() {
|
|
|
737
757
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto flex items-center gap-4", children: social?.map((s) => /* @__PURE__ */ jsxRuntime.jsx("a", { href: s.href, target: "_blank", rel: "noreferrer", className: "hover:underline", children: s.label }, s.href)) })
|
|
738
758
|
] }) });
|
|
739
759
|
}
|
|
740
|
-
function SearchInput({ className }) {
|
|
760
|
+
function SearchInput({ className, iconOnly = false }) {
|
|
741
761
|
const config = useStorefrontConfig();
|
|
742
762
|
const search = useCatalogStore((s) => s.search);
|
|
743
763
|
const setSearch = useCatalogStore((s) => s.setSearch);
|
|
744
764
|
const path = useHashPath();
|
|
745
|
-
|
|
765
|
+
const [open, setOpen] = React6.useState(false);
|
|
766
|
+
if (iconOnly && !open) {
|
|
767
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
768
|
+
"button",
|
|
769
|
+
{
|
|
770
|
+
type: "button",
|
|
771
|
+
"aria-label": "Buscar produtos",
|
|
772
|
+
"data-testid": TID.headerSearchToggle,
|
|
773
|
+
onClick: () => setOpen(true),
|
|
774
|
+
className: "rounded-full p-2.5 transition-opacity hover:opacity-70",
|
|
775
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.Search, { className: "h-5 w-5" })
|
|
776
|
+
}
|
|
777
|
+
);
|
|
778
|
+
}
|
|
779
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `relative ${iconOnly ? "w-full max-w-xs" : className ?? ""}`, children: [
|
|
746
780
|
/* @__PURE__ */ jsxRuntime.jsx(LucideIcons.Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 opacity-60" }),
|
|
747
781
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
748
782
|
"input",
|
|
@@ -751,10 +785,17 @@ function SearchInput({ className }) {
|
|
|
751
785
|
type: "search",
|
|
752
786
|
placeholder: "Buscar produtos...",
|
|
753
787
|
value: search,
|
|
788
|
+
autoFocus: iconOnly,
|
|
754
789
|
onChange: (e) => {
|
|
755
790
|
setSearch(e.target.value);
|
|
756
791
|
if (path !== config.catalogPath) navigateTo(config.catalogPath);
|
|
757
792
|
},
|
|
793
|
+
onKeyDown: (e) => {
|
|
794
|
+
if (e.key === "Escape" && iconOnly) setOpen(false);
|
|
795
|
+
},
|
|
796
|
+
onBlur: () => {
|
|
797
|
+
if (iconOnly && !search) setOpen(false);
|
|
798
|
+
},
|
|
758
799
|
className: "w-full border bg-white/10 py-2 pl-9 pr-4 text-sm outline-none transition-colors placeholder:opacity-60 focus:border-primary focus:bg-white focus:text-gray-900",
|
|
759
800
|
style: {
|
|
760
801
|
borderRadius: "var(--sf-radius-input)",
|
|
@@ -907,6 +948,7 @@ function StorefrontHeader() {
|
|
|
907
948
|
const variant = config.theme?.header?.variant ?? "classic";
|
|
908
949
|
const scrolled = useScrolled();
|
|
909
950
|
const showSearch = config.theme?.header?.showSearch !== false;
|
|
951
|
+
const iconSearch = config.theme?.header?.searchStyle === "icon";
|
|
910
952
|
const logo = /* @__PURE__ */ jsxRuntime.jsx(Link, { to: "/", className: "sf-heading shrink-0 text-xl font-bold tracking-tight", children: config.logo ?? config.name });
|
|
911
953
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
912
954
|
"header",
|
|
@@ -920,7 +962,7 @@ function StorefrontHeader() {
|
|
|
920
962
|
// Rio/Flex pattern: centered logo row, nav row below
|
|
921
963
|
/* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
922
964
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto grid h-16 max-w-7xl grid-cols-[1fr_auto_1fr] items-center px-4 sm:px-6", children: [
|
|
923
|
-
showSearch ? /* @__PURE__ */ jsxRuntime.jsx(SearchInput, { className: "hidden w-full max-w-xs sm:block" }) : /* @__PURE__ */ jsxRuntime.jsx("div", {}),
|
|
965
|
+
showSearch ? /* @__PURE__ */ jsxRuntime.jsx(SearchInput, { iconOnly: iconSearch, className: "hidden w-full max-w-xs sm:block" }) : /* @__PURE__ */ jsxRuntime.jsx("div", {}),
|
|
924
966
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center", children: logo }),
|
|
925
967
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "justify-self-end", children: /* @__PURE__ */ jsxRuntime.jsx(HeaderActions, {}) })
|
|
926
968
|
] }),
|
|
@@ -930,7 +972,7 @@ function StorefrontHeader() {
|
|
|
930
972
|
// Brasília pattern: prominent search left, logo center, actions right; nav row below
|
|
931
973
|
/* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
932
974
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto grid h-16 max-w-7xl grid-cols-[1fr_auto_1fr] items-center gap-6 px-4 sm:px-6", children: [
|
|
933
|
-
showSearch ? /* @__PURE__ */ jsxRuntime.jsx(SearchInput, { className: "hidden w-full max-w-sm sm:block" }) : /* @__PURE__ */ jsxRuntime.jsx("div", {}),
|
|
975
|
+
showSearch ? /* @__PURE__ */ jsxRuntime.jsx(SearchInput, { iconOnly: iconSearch, className: "hidden w-full max-w-sm sm:block" }) : /* @__PURE__ */ jsxRuntime.jsx("div", {}),
|
|
934
976
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center", children: logo }),
|
|
935
977
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "justify-self-end", children: /* @__PURE__ */ jsxRuntime.jsx(HeaderActions, {}) })
|
|
936
978
|
] }),
|
|
@@ -942,17 +984,19 @@ function StorefrontHeader() {
|
|
|
942
984
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-5", children: /* @__PURE__ */ jsxRuntime.jsx(NavLinks, { className: "hidden sm:flex" }) }),
|
|
943
985
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center", children: logo }),
|
|
944
986
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-3", children: [
|
|
945
|
-
showSearch && /* @__PURE__ */ jsxRuntime.jsx(SearchInput, { className: "hidden w-44 lg:block" }),
|
|
987
|
+
showSearch && /* @__PURE__ */ jsxRuntime.jsx(SearchInput, { iconOnly: iconSearch, className: "hidden w-44 lg:block" }),
|
|
946
988
|
/* @__PURE__ */ jsxRuntime.jsx(HeaderActions, {})
|
|
947
989
|
] })
|
|
948
990
|
] })
|
|
949
991
|
) : (
|
|
950
|
-
// classic: logo left,
|
|
992
|
+
// classic: logo left, nav, then a right-aligned search + actions cluster
|
|
951
993
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto flex h-16 max-w-7xl items-center gap-6 px-4 sm:px-6", children: [
|
|
952
994
|
logo,
|
|
953
995
|
/* @__PURE__ */ jsxRuntime.jsx(NavLinks, { className: "hidden md:flex" }),
|
|
954
|
-
|
|
955
|
-
|
|
996
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ml-auto flex items-center gap-2 sm:gap-3", children: [
|
|
997
|
+
showSearch && /* @__PURE__ */ jsxRuntime.jsx(SearchInput, { iconOnly: iconSearch, className: iconSearch ? "" : "hidden w-full max-w-sm sm:block" }),
|
|
998
|
+
/* @__PURE__ */ jsxRuntime.jsx(HeaderActions, {})
|
|
999
|
+
] })
|
|
956
1000
|
] })
|
|
957
1001
|
)
|
|
958
1002
|
]
|
|
@@ -2960,7 +3004,8 @@ async function placeStorefrontOrder({
|
|
|
2960
3004
|
}))
|
|
2961
3005
|
});
|
|
2962
3006
|
if (markPaid) {
|
|
2963
|
-
await provider.
|
|
3007
|
+
if (provider.confirmPayment) await provider.confirmPayment(order.id);
|
|
3008
|
+
else await provider.updateOrder(order.id, { financialStatus: "paid" });
|
|
2964
3009
|
}
|
|
2965
3010
|
return { order, customerId: customerId ?? order.customerId ?? "" };
|
|
2966
3011
|
}
|
|
@@ -4440,6 +4485,15 @@ function initStorefrontRuntime(config) {
|
|
|
4440
4485
|
} else {
|
|
4441
4486
|
runtime.setShopProvider(mock.createMockShopProvider(buildMockSeed(config)));
|
|
4442
4487
|
}
|
|
4488
|
+
const reconcileCart = () => {
|
|
4489
|
+
const provider = runtime.getShopProvider();
|
|
4490
|
+
void useCartStore.getState().reconcile(async (line) => {
|
|
4491
|
+
const product = await provider.getProduct(line.productId);
|
|
4492
|
+
return product != null;
|
|
4493
|
+
});
|
|
4494
|
+
};
|
|
4495
|
+
if (useCartStore.persist.hasHydrated()) reconcileCart();
|
|
4496
|
+
else useCartStore.persist.onFinishHydration(reconcileCart);
|
|
4443
4497
|
if (config.supabaseUrl || config.supabaseAnonKey) {
|
|
4444
4498
|
console.warn(
|
|
4445
4499
|
"@fayz-ai/shop: supabaseUrl/supabaseAnonKey are legacy fields. Pass an explicit provider/adapter or use the Fayz SDK broker path."
|
|
@@ -4799,11 +4853,73 @@ var atelierTemplate = {
|
|
|
4799
4853
|
]
|
|
4800
4854
|
})
|
|
4801
4855
|
};
|
|
4856
|
+
var foodTemplate = {
|
|
4857
|
+
id: "food",
|
|
4858
|
+
inspiration: "Delivery / restaurant storefront",
|
|
4859
|
+
announcement: "ENTREGA GR\xC1TIS ACIMA DE R$ 150 \xB7 PE\xC7A J\xC1",
|
|
4860
|
+
theme: {
|
|
4861
|
+
name: "food",
|
|
4862
|
+
colors: {
|
|
4863
|
+
background: "30 33% 97%",
|
|
4864
|
+
foreground: "20 14% 15%",
|
|
4865
|
+
primary: "14 84% 50%",
|
|
4866
|
+
primaryForeground: "0 0% 100%",
|
|
4867
|
+
card: "30 33% 99%",
|
|
4868
|
+
cardForeground: "20 14% 15%",
|
|
4869
|
+
muted: "28 20% 92%",
|
|
4870
|
+
mutedForeground: "22 10% 42%",
|
|
4871
|
+
border: "28 18% 85%",
|
|
4872
|
+
headerBackground: "20 14% 11%",
|
|
4873
|
+
headerForeground: "30 24% 96%",
|
|
4874
|
+
announcementBackground: "14 84% 50%",
|
|
4875
|
+
announcementForeground: "0 0% 100%"
|
|
4876
|
+
},
|
|
4877
|
+
font: { heading: "Poppins", body: "Inter" },
|
|
4878
|
+
radius: "round",
|
|
4879
|
+
header: { variant: "classic" },
|
|
4880
|
+
productCard: { style: "card", imageAspect: "square" }
|
|
4881
|
+
},
|
|
4882
|
+
home: (storeName, images) => ({
|
|
4883
|
+
sections: [
|
|
4884
|
+
{
|
|
4885
|
+
type: "hero",
|
|
4886
|
+
variant: "banner",
|
|
4887
|
+
height: "tall",
|
|
4888
|
+
slides: [
|
|
4889
|
+
{ title: "Sabor de verdade, na sua porta", subtitle: `${storeName} \u2014 feito na hora, do jeito que voc\xEA ama.`, cta: "Ver card\xE1pio", href: "/catalog", hue: 20, image: images?.hero?.[0] }
|
|
4890
|
+
]
|
|
4891
|
+
},
|
|
4892
|
+
{
|
|
4893
|
+
type: "benefits",
|
|
4894
|
+
items: [
|
|
4895
|
+
{ icon: "Flame", title: "Feito na hora", text: "Preparado com capricho" },
|
|
4896
|
+
{ icon: "Truck", title: "Entrega r\xE1pida", text: "Frete gr\xE1tis acima de R$ 150" },
|
|
4897
|
+
{ icon: "CreditCard", title: "Pagamento f\xE1cil", text: "Pix, cart\xE3o e mais" }
|
|
4898
|
+
]
|
|
4899
|
+
},
|
|
4900
|
+
{ type: "categories", style: "tiles", title: "Nosso card\xE1pio" },
|
|
4901
|
+
{ type: "products", title: "Mais pedidos", eyebrow: "favoritos da casa", filter: "all", limit: 8 },
|
|
4902
|
+
{ type: "banner", title: "Combo do dia", eyebrow: "oferta", subtitle: "Sele\xE7\xE3o especial com desconto", cta: "Aproveitar", hue: 14, image: images?.banners?.[0] },
|
|
4903
|
+
{ type: "products", title: "Novidades no card\xE1pio", filter: "new", limit: 4 },
|
|
4904
|
+
{
|
|
4905
|
+
type: "testimonials",
|
|
4906
|
+
title: "O que dizem por a\xED",
|
|
4907
|
+
items: [
|
|
4908
|
+
{ quote: "Chegou quentinho e absurdo de bom. Virei cliente!", author: "Rafael M." },
|
|
4909
|
+
{ quote: "Sabor de restaurante em casa, sem complica\xE7\xE3o.", author: "Beatriz L." },
|
|
4910
|
+
{ quote: "Entrega r\xE1pida e por\xE7\xE3o generosa. Recomendo demais.", author: "Diego S." }
|
|
4911
|
+
]
|
|
4912
|
+
},
|
|
4913
|
+
{ type: "newsletter", title: "Receba nossas ofertas", subtitle: "Promo\xE7\xF5es e novidades do card\xE1pio, direto no seu e-mail." }
|
|
4914
|
+
]
|
|
4915
|
+
})
|
|
4916
|
+
};
|
|
4802
4917
|
var storefrontTemplates = {
|
|
4803
4918
|
mare: mareTemplate,
|
|
4804
4919
|
sertao: sertaoTemplate,
|
|
4805
4920
|
volt: voltTemplate,
|
|
4806
|
-
atelier: atelierTemplate
|
|
4921
|
+
atelier: atelierTemplate,
|
|
4922
|
+
food: foodTemplate
|
|
4807
4923
|
};
|
|
4808
4924
|
|
|
4809
4925
|
Object.defineProperty(exports, "getSupabaseClientOptional", {
|
|
@@ -4860,6 +4976,7 @@ exports.defineStorefrontConfig = defineStorefrontConfig;
|
|
|
4860
4976
|
exports.defineStorefrontRoutes = defineStorefrontRoutes;
|
|
4861
4977
|
exports.defineStorefrontSections = defineStorefrontSections;
|
|
4862
4978
|
exports.establishCustomerSession = establishCustomerSession;
|
|
4979
|
+
exports.foodTemplate = foodTemplate;
|
|
4863
4980
|
exports.formatMoney = formatMoney;
|
|
4864
4981
|
exports.formatProductOptionSelection = formatProductOptionSelection;
|
|
4865
4982
|
exports.getCustomerAuthAdapter = getCustomerAuthAdapter;
|