update shopify storefront

This commit is contained in:
Rami Bitar
2026-06-03 22:38:26 -04:00
parent 47b773444e
commit 52424c9ba3
20 changed files with 293 additions and 430 deletions

View File

@@ -1,227 +0,0 @@
import {
convertToModelMessages,
stepCountIs,
streamText,
tool,
type UIMessage,
} from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { z } from "zod";
import {
reactEditorTools,
getEditorContext,
} from "@reacteditor/plugin-ai/server";
import { shopifyFetch } from "@/services/shopify/client";
import {
GET_PRODUCTS_QUERY,
GET_PRODUCT_QUERY,
} from "@/graphql/products";
import {
GET_COLLECTIONS_QUERY,
GET_COLLECTION_PRODUCTS_QUERY,
} from "@/graphql/collections";
type Body = {
messages: UIMessage[];
editorContext?: Parameters<typeof getEditorContext>[0];
route?: string;
};
export async function POST(req: Request) {
const { messages, editorContext } = (await req.json()) as Body;
const generateImage = tool({
description: "Generate an image from a prompt and return its URL.",
inputSchema: z.object({
prompt: z.string(),
width: z.number().int().positive().optional(),
height: z.number().int().positive().optional(),
}),
execute: async ({ width = 768, height = 768 }) => ({
url: `https://picsum.photos/${width}/${height}?random=${Math.floor(
Math.random() * 1_000_000,
)}`,
}),
});
const credentials = {
domain:
process.env.VITE_SHOPIFY_DOMAIN ??
process.env.SHOPIFY_DOMAIN ??
"mock.shop",
token:
process.env.VITE_SHOPIFY_STOREFRONT_ACCESS_TOKEN ??
process.env.SHOPIFY_STOREFRONT_ACCESS_TOKEN ??
"",
};
const searchProducts = tool({
description:
"Search the Shopify store for products. Returns up to `limit` products matching `query`.",
inputSchema: z.object({
query: z.string().optional(),
limit: z.number().int().min(1).max(20).optional(),
}),
execute: async ({ query, limit = 8 }) => {
try {
const res = await shopifyFetch<any>({
query: GET_PRODUCTS_QUERY,
variables: {
first: limit,
query: query ?? null,
sortKey: query ? "RELEVANCE" : "BEST_SELLING",
reverse: false,
},
credentials,
});
const products = (res.data?.products?.edges ?? []).map((e: any) => {
const n = e.node;
return {
id: n.id,
handle: n.handle,
title: n.title,
description: n.description,
featuredImage: n.images?.edges?.[0]?.node ?? null,
priceRange: n.priceRange,
};
});
return { ok: true, products };
} catch (err) {
return {
ok: false,
error: err instanceof Error ? err.message : "fetch failed",
};
}
},
});
const getProductByHandle = tool({
description: "Fetch a single product by its handle.",
inputSchema: z.object({ handle: z.string() }),
execute: async ({ handle }) => {
try {
const res = await shopifyFetch<any>({
query: GET_PRODUCT_QUERY,
variables: { handle },
credentials,
});
const p = res.data?.product ?? null;
if (!p) return { ok: false, error: "not_found" };
return {
ok: true,
product: {
id: p.id,
handle: p.handle,
title: p.title,
description: p.description,
featuredImage: p.images?.edges?.[0]?.node ?? null,
priceRange: p.priceRange,
},
};
} catch (err) {
return {
ok: false,
error: err instanceof Error ? err.message : "fetch failed",
};
}
},
});
const searchCollections = tool({
description: "List up to `limit` collections from the Shopify store.",
inputSchema: z.object({
limit: z.number().int().min(1).max(20).optional(),
}),
execute: async ({ limit = 8 }) => {
try {
const res = await shopifyFetch<any>({
query: GET_COLLECTIONS_QUERY,
variables: { first: limit },
credentials,
});
const collections = (res.data?.collections?.edges ?? []).map(
(e: any) => {
const n = e.node;
return {
id: n.id,
handle: n.handle,
title: n.title,
description: n.description,
image: n.image ?? null,
};
},
);
return { ok: true, collections };
} catch (err) {
return {
ok: false,
error: err instanceof Error ? err.message : "fetch failed",
};
}
},
});
const getCollectionByHandle = tool({
description:
"Fetch a single collection by its handle, including a small page of its products.",
inputSchema: z.object({
handle: z.string(),
limit: z.number().int().min(1).max(20).optional(),
}),
execute: async ({ handle, limit = 8 }) => {
try {
const res = await shopifyFetch<any>({
query: GET_COLLECTION_PRODUCTS_QUERY,
variables: {
handle,
first: limit,
sortKey: "BEST_SELLING",
reverse: false,
},
credentials,
});
const c = res.data?.collection ?? null;
if (!c) return { ok: false, error: "not_found" };
return {
ok: true,
collection: {
id: c.id,
handle: c.handle,
title: c.title,
description: c.description,
image: c.image ?? null,
products: (c.products?.edges ?? []).map((e: any) => ({
id: e.node.id,
handle: e.node.handle,
title: e.node.title,
featuredImage: e.node.images?.edges?.[0]?.node ?? null,
priceRange: e.node.priceRange,
})),
},
};
} catch (err) {
return {
ok: false,
error: err instanceof Error ? err.message : "fetch failed",
};
}
},
});
const result = streamText({
model: anthropic("claude-sonnet-4-5"),
system: getEditorContext(editorContext),
messages: await convertToModelMessages(messages),
tools: {
...reactEditorTools,
generateImage,
searchProducts,
getProductByHandle,
searchCollections,
getCollectionByHandle,
},
stopWhen: stepCountIs(50),
});
return result.toUIMessageStreamResponse();
}

View File

@@ -1,44 +0,0 @@
"use client";
import { useMemo } from "react";
import { Editor } from "@reacteditor/core";
import createTailwindCdnPlugin from "@reacteditor/plugin-tailwind-cdn";
import type { UserConfig } from "@/config/types";
export type EditorShellProps = {
config: UserConfig;
data: any;
routeKey?: string;
};
export function EditorShell({ config, data, routeKey }: EditorShellProps) {
const plugins = useMemo(() => [createTailwindCdnPlugin()], []);
const handlePublish = async (nextData: any, route?: any) => {
const resolved = route ?? (routeKey ? { key: routeKey } : undefined);
console.log({
type: "PUBLISH",
data: { data: nextData, route: JSON.stringify(resolved) },
});
if (typeof window !== "undefined" && window.parent !== window) {
window.parent.postMessage(
{ type: "PUBLISH", data: { data: nextData, route: resolved } },
"*",
);
}
await new Promise((resolve) => setTimeout(resolve, 1000));
};
return (
<div className="h-screen w-screen">
<Editor
config={config as any}
data={data}
plugins={plugins}
iframe={{ enabled: true }}
ui={{ leftSideBarVisible: false }}
onPublish={handlePublish}
/>
</div>
);
}

View File

@@ -0,0 +1,55 @@
"use client";
import { useMemo } from "react";
import { useParams } from "next/navigation";
import { Editor } from "@reacteditor/core";
import createTailwindCdnPlugin from "@reacteditor/plugin-tailwind-cdn";
import createShopifyPlugin from "@reacteditor/plugin-shopify";
import { collectionsConfig } from "@/editor.config";
import schema from "@/app.schema.json";
const currentRoute = "/collections/:handle";
export default function CollectionEditorPage() {
const params = useParams();
const handle = typeof params?.handle === "string" ? params.handle : "";
const data = (schema as any)["/collections/:handle"];
const plugins = useMemo(
() => [
createTailwindCdnPlugin(),
createShopifyPlugin({
storeDomain:
process.env.NEXT_PUBLIC_SHOPIFY_DOMAIN ?? "mock.shop",
publicAccessToken:
process.env.NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN,
}),
],
[],
);
const handlePublish = async (nextData: any, route?: any) => {
const resolved = route ?? { key: currentRoute };
if (typeof window !== "undefined" && window.parent !== window) {
window.parent.postMessage(
{ type: "PUBLISH", data: { data: nextData, route: resolved } },
"*",
);
}
await new Promise((resolve) => setTimeout(resolve, 1000));
};
return (
<div className="h-screen w-screen">
<Editor
config={collectionsConfig as any}
data={data}
currentRoute={currentRoute}
route={{ key: currentRoute, path: `/collections/${handle}`, params: { handle } }}
plugins={plugins}
iframe={{ enabled: true }}
ui={{ leftSideBarVisible: false }}
onPublish={handlePublish}
/>
</div>
);
}

View File

@@ -1,10 +1,10 @@
"use client";
import { Render } from "@reacteditor/core";
import { collectionsConfig } from "@/config/configs";
import { collectionsConfig } from "@/editor.config";
import schema from "@/app.schema.json";
export default function CollectionPage() {
const data = (schema as any)["/collections/:handle"];
return <Render config={collectionsConfig as any} data={data} />;
const pageData = (schema as any)["/collections/:handle"];
return <Render config={collectionsConfig as any} data={pageData} />;
}

View File

@@ -1,16 +0,0 @@
"use client";
import { EditorShell } from "@/app/_components/editor-shell";
import { collectionsConfig } from "@/config/configs";
import schema from "@/app.schema.json";
export default function CollectionEditorPage() {
const data = (schema as any)["/collections/:handle"];
return (
<EditorShell
config={collectionsConfig}
data={data}
routeKey="/collections/:handle"
/>
);
}

View File

@@ -1,10 +0,0 @@
"use client";
import { EditorShell } from "@/app/_components/editor-shell";
import { homeConfig } from "@/config/configs";
import schema from "@/app.schema.json";
export default function HomeEditorPage() {
const data = (schema as any)["/"];
return <EditorShell config={homeConfig} data={data} routeKey="/" />;
}

View File

@@ -1,16 +0,0 @@
"use client";
import { EditorShell } from "@/app/_components/editor-shell";
import { productConfig } from "@/config/configs";
import schema from "@/app.schema.json";
export default function ProductEditorPage() {
const data = (schema as any)["/products/:handle"];
return (
<EditorShell
config={productConfig}
data={data}
routeKey="/products/:handle"
/>
);
}

View File

@@ -1,10 +0,0 @@
"use client";
import { EditorShell } from "@/app/_components/editor-shell";
import { searchConfig } from "@/config/configs";
import schema from "@/app.schema.json";
export default function SearchEditorPage() {
const data = (schema as any)["/search"];
return <EditorShell config={searchConfig} data={data} routeKey="/search" />;
}

View File

@@ -1,10 +1,10 @@
"use client";
import { Render } from "@reacteditor/core";
import { homeConfig } from "@/config/configs";
import { homeConfig } from "@/editor.config";
import schema from "@/app.schema.json";
export default function HomePage() {
const data = (schema as any)["/"];
return <Render config={homeConfig as any} data={data} />;
const pageData = (schema as any)["/"];
return <Render config={homeConfig as any} data={pageData} />;
}

View File

@@ -0,0 +1,55 @@
"use client";
import { useMemo } from "react";
import { useParams } from "next/navigation";
import { Editor } from "@reacteditor/core";
import createTailwindCdnPlugin from "@reacteditor/plugin-tailwind-cdn";
import createShopifyPlugin from "@reacteditor/plugin-shopify";
import { productConfig } from "@/editor.config";
import schema from "@/app.schema.json";
const currentRoute = "/products/:handle";
export default function ProductEditorPage() {
const params = useParams();
const handle = typeof params?.handle === "string" ? params.handle : "";
const data = (schema as any)["/products/:handle"];
const plugins = useMemo(
() => [
createTailwindCdnPlugin(),
createShopifyPlugin({
storeDomain:
process.env.NEXT_PUBLIC_SHOPIFY_DOMAIN ?? "mock.shop",
publicAccessToken:
process.env.NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN,
}),
],
[],
);
const handlePublish = async (nextData: any, route?: any) => {
const resolved = route ?? { key: currentRoute };
if (typeof window !== "undefined" && window.parent !== window) {
window.parent.postMessage(
{ type: "PUBLISH", data: { data: nextData, route: resolved } },
"*",
);
}
await new Promise((resolve) => setTimeout(resolve, 1000));
};
return (
<div className="h-screen w-screen">
<Editor
config={productConfig as any}
data={data}
currentRoute={currentRoute}
route={{ key: currentRoute, path: `/products/${handle}`, params: { handle } }}
plugins={plugins}
iframe={{ enabled: true }}
ui={{ leftSideBarVisible: false }}
onPublish={handlePublish}
/>
</div>
);
}

View File

@@ -1,10 +1,10 @@
"use client";
import { Render } from "@reacteditor/core";
import { productConfig } from "@/config/configs";
import { productConfig } from "@/editor.config";
import schema from "@/app.schema.json";
export default function ProductPage() {
const data = (schema as any)["/products/:handle"];
return <Render config={productConfig as any} data={data} />;
const pageData = (schema as any)["/products/:handle"];
return <Render config={productConfig as any} data={pageData} />;
}

View File

@@ -0,0 +1,52 @@
"use client";
import { useMemo } from "react";
import { Editor } from "@reacteditor/core";
import createTailwindCdnPlugin from "@reacteditor/plugin-tailwind-cdn";
import createShopifyPlugin from "@reacteditor/plugin-shopify";
import { searchConfig } from "@/editor.config";
import schema from "@/app.schema.json";
const currentRoute = "/search";
export default function SearchEditorPage() {
const data = (schema as any)["/search"];
const plugins = useMemo(
() => [
createTailwindCdnPlugin(),
createShopifyPlugin({
storeDomain:
process.env.NEXT_PUBLIC_SHOPIFY_DOMAIN ?? "mock.shop",
publicAccessToken:
process.env.NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN,
}),
],
[],
);
const handlePublish = async (nextData: any, route?: any) => {
const resolved = route ?? { key: currentRoute };
if (typeof window !== "undefined" && window.parent !== window) {
window.parent.postMessage(
{ type: "PUBLISH", data: { data: nextData, route: resolved } },
"*",
);
}
await new Promise((resolve) => setTimeout(resolve, 1000));
};
return (
<div className="h-screen w-screen">
<Editor
config={searchConfig as any}
data={data}
currentRoute={currentRoute}
route={{ key: currentRoute, path: currentRoute, params: {} }}
plugins={plugins}
iframe={{ enabled: true }}
ui={{ leftSideBarVisible: false }}
onPublish={handlePublish}
/>
</div>
);
}

View File

@@ -1,10 +1,10 @@
"use client";
import { Render } from "@reacteditor/core";
import { searchConfig } from "@/config/configs";
import { searchConfig } from "@/editor.config";
import schema from "@/app.schema.json";
export default function SearchPage() {
const data = (schema as any)["/search"];
return <Render config={searchConfig as any} data={data} />;
const pageData = (schema as any)["/search"];
return <Render config={searchConfig as any} data={pageData} />;
}

28
next.config.mjs Normal file
View File

@@ -0,0 +1,28 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
typescript: {
ignoreBuildErrors: true,
},
images: {
remotePatterns: [
{
protocol: "https",
hostname: "cdn.shopify.com",
pathname: "/**",
},
{
protocol: "https",
hostname: "**.myshopify.com",
pathname: "/**",
},
{
protocol: "https",
hostname: "supabase.frontend.co",
pathname: "/storage/v1/object/public/**",
},
],
},
};
export default nextConfig;

View File

@@ -1,10 +0,0 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
reactStrictMode: true,
typescript: {
ignoreBuildErrors: true,
},
};
export default nextConfig;

View File

@@ -3,7 +3,7 @@
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "next dev",
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
"lint": "next lint"
@@ -25,11 +25,12 @@
"@radix-ui/react-switch": "^1.2.5",
"@radix-ui/react-tabs": "^1.1.12",
"@radix-ui/react-tooltip": "^1.2.7",
"@reacteditor/core": "0.0.30",
"@reacteditor/core": "0.0.32",
"@reacteditor/field-google-fonts": "^0.0.3",
"@reacteditor/field-shopify": "^0.0.2",
"@reacteditor/plugin-ai": "^0.0.7",
"@reacteditor/plugin-media": "^0.0.4",
"@reacteditor/plugin-shopify": "^0.0.1",
"@reacteditor/plugin-tailwind-cdn": "^0.0.3",
"@shopify/storefront-api-client": "^1.0.0",
"@tailwindcss/postcss": "^4.1.11",
@@ -37,10 +38,10 @@
"clsx": "^2.1.1",
"embla-carousel-react": "^8.6.0",
"framer-motion": "^12.16.0",
"lucide-react": "^1.14.0",
"next": "16.2.6",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"lucide-react": "^1.17.0",
"next": "^16.2.6",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"react-router": "^7",
"tailwind-merge": "^3.5.0",
"tailwindcss": "^4.3.0",
@@ -49,9 +50,9 @@
"zod": "3.25.76"
},
"devDependencies": {
"@types/node": "^22.0.0",
"@types/node": "^25.2.0",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
"typescript": "^5.5.4"
"typescript": "^5.7.0"
}
}

View File

@@ -50,7 +50,7 @@
"lib",
"services",
"vendor",
"next.config.ts",
"next.config.mjs",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",

File diff suppressed because one or more lines are too long

155
yarn.lock
View File

@@ -662,50 +662,50 @@
dependencies:
"@tybys/wasm-util" "^0.10.1"
"@next/env@16.2.6":
version "16.2.6"
resolved "https://registry.yarnpkg.com/@next/env/-/env-16.2.6.tgz#93a173801cb088463070cc6a113c68e26c1838ea"
integrity sha512-gd8HoHN4ufj73WmR3JmVolrpJR47ILK6LouP5xElPglaVxir6e1a7VzvTvDWkOoPXT9rkkTzyCxBu4yeZfZwcw==
"@next/env@16.2.7":
version "16.2.7"
resolved "https://registry.yarnpkg.com/@next/env/-/env-16.2.7.tgz#994c91972bb4a40aed52d3767bc0a60660a6e846"
integrity sha512-tMJizPlj6ZYpBMMdK8S0LJufrP4QTdR6pcv9KQ/bVETPAmg0j1mlHE9G2c38UyGHxoBapgwuj7XjbGJ2RcDFOg==
"@next/swc-darwin-arm64@16.2.6":
version "16.2.6"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.2.6.tgz#0e19055594fbd2d198ce95cf5842bdbe57235d4e"
integrity sha512-ZJGkkcNfYgrrMkqOdZ7zoLa1TOy0qpcMfk/z4Mh/FKUz40gVO+HNQWqmLxf67Z5WB64DRp0dhEbyHfel+6sJUg==
"@next/swc-darwin-arm64@16.2.7":
version "16.2.7"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.2.7.tgz#457a13330258d3b833b314654f9aa9a9adfb9da9"
integrity sha512-vm1EDI/pVaBNNiychmxk3fft+OhQPVD9cIM/tReLZIQ3TfQ4kqI9DwKk00dzuS1ulC7icbrzCFrmRRlk9PfNdw==
"@next/swc-darwin-x64@16.2.6":
version "16.2.6"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-16.2.6.tgz#487086280b56017bb547f5975ef1a3d6235a070f"
integrity sha512-v/YLBHIY132Ced3puBJ7YJKw1lqsCrgcNo2aRJlCEyQrrCeRJlvGlnmxhPxNQI3KE3N1DN5r9TPNPvka3nq5RQ==
"@next/swc-darwin-x64@16.2.7":
version "16.2.7"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-16.2.7.tgz#37e8354b22b339b712e8ebe372be7e8616fa8375"
integrity sha512-O3IRSv1ZBL1zs0WrIgefTEcTKFVn+ryxBNe54erJ6KsD+2f/Mmt7g2jOYh8PSBdUwPtKQJuCsTMlZ7tIu2AcsQ==
"@next/swc-linux-arm64-gnu@16.2.6":
version "16.2.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.2.6.tgz#b28ffbc31ee527a3ad48f29c2fd7b7f75bbdf180"
integrity sha512-RPOvqlYBbcQjkz9VQQDZ2T2bARIjXZV1KFlt+V2Mr6SW/e4I9fcKsaA0hdyf2FHoTlsV2xnBd5Y912rP/1Ce6w==
"@next/swc-linux-arm64-gnu@16.2.7":
version "16.2.7"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.2.7.tgz#2d02d6b6e9d29552863c5eda23e9c747ab7486cd"
integrity sha512-Re6PZtjBDd0aMU+VcZcC/PrIvj4WhrjDYtMhhCVQamWN4L90EVP0pcEOBQD25prSlw7OzNw5QpHLWMilRLsRNw==
"@next/swc-linux-arm64-musl@16.2.6":
version "16.2.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.2.6.tgz#d2eac5600e7083527669fa8cb8758efbbf9c8210"
integrity sha512-URUTu1+dMkxJsPFgm+OeEvq9wf5sujw0EvgYy80TDGHTSLTnIHeqb0Eu8A3sC95IRgjejQL+kC4mw+4yPxiAXA==
"@next/swc-linux-arm64-musl@16.2.7":
version "16.2.7"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.2.7.tgz#f9d171041e8e7a0974979d184bbed65340623b55"
integrity sha512-qyogG9QtBzWxgJfeGBvOEHI3851gTfCF3wLZ5RDLTBJGAmE9p1qDwKCOdrBrvBzRvYDT+gUDp72pzlSEfAXgNA==
"@next/swc-linux-x64-gnu@16.2.6":
version "16.2.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.2.6.tgz#e70dc3469bf9bfef16da2ba240c07ef6cfe8ad55"
integrity sha512-DOj182mPV8G3UkrayLoREM5YEYI+Dk5wv7Ox9xl1fFibAELEsFD0lDPfHIeILlutMMfdyhlzYPELG3peuKaurw==
"@next/swc-linux-x64-gnu@16.2.7":
version "16.2.7"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.2.7.tgz#23da8f39ef473c4f6026fb9b7aac1cac25254711"
integrity sha512-Vhe4ZDuBpmMogrGi5D4R2Kq4JAQlj6+wvgaFYy31zfES0zPmt6TLA+cuYpM/OLrPZjo2MYQTHVqNUSCR6+fDZQ==
"@next/swc-linux-x64-musl@16.2.6":
version "16.2.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.2.6.tgz#49ecd2f622d0f3741654c59411f604dbbe1a38de"
integrity sha512-HKQ5SP/V/ub73UvF7n/zeJlxk2kLmtL7Wzrg4WfmkjmNos5onJ2tKu7yZOPdL18A6Svfn3max29ym+ry7NkK4g==
"@next/swc-linux-x64-musl@16.2.7":
version "16.2.7"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.2.7.tgz#188ff88c6807ce7f250436b09f792d7879ae8c97"
integrity sha512-srvian89JahFLw1YLBEuhvPJ0DO5lpUeJQMXy4xYo7g628ZlNgXdNkqoxSAv9OYrBfByh6vxISMwW/mRbzCY+g==
"@next/swc-win32-arm64-msvc@16.2.6":
version "16.2.6"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.2.6.tgz#8a6dfec005364e1cf4fa1724c3d7fa0093660406"
integrity sha512-LZXpTlPyS5v7HhSmnvsLGP3iIYgYOBnc8r8ArlT55sGHV89bR2HlDdBjWQ+PY6SJMmk8TuVGFuxalnP3k/0Dwg==
"@next/swc-win32-arm64-msvc@16.2.7":
version "16.2.7"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.2.7.tgz#10b57a146d9a3cb68790ce62c3f79fb3c6592c2b"
integrity sha512-GX3wvLpULFuRFJzwHaKfm7QZJ18F4ZSuxlPJ96BoBglCzBmdSjyeBKF+ZhWhvL/ckxNfLnNa7bsObO2ipYpszw==
"@next/swc-win32-x64-msvc@16.2.6":
version "16.2.6"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.2.6.tgz#4fb656ccfcf60cbf8ffedb40fc1b625987c82742"
integrity sha512-F0+4i0h9J6C4eE3EAPWsoCk7UW/dbzOjyzxY0qnDUOYFu6FFmdZ6l97/XdV3/Nz3VYyO7UWjyEJUXkGqcoXfMA==
"@next/swc-win32-x64-msvc@16.2.7":
version "16.2.7"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.2.7.tgz#8dd310e032fa8c297521de3f03047d6e4ffe8b08"
integrity sha512-J4WlM72NMk076Qsg0jTdK3SNXatlSdnjW7L7oNGLst1tAGjHrJh/FYi+pw9wyIjEtGRKDNzD0zuiY16oWYWVaw==
"@opentelemetry/api@1.9.0":
version "1.9.0"
@@ -1162,10 +1162,10 @@
resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.1.tgz#78244efe12930c56fd255d7923865857c41ac8cb"
integrity sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==
"@reacteditor/core@0.0.30":
version "0.0.30"
resolved "https://registry.yarnpkg.com/@reacteditor/core/-/core-0.0.30.tgz#c00434581a6f3fef3aae4700ece90a29d1a41ee0"
integrity sha512-L2wWpF3uSqgpZsA9k715cqfPeJJ2uO5dv1NWBBofegOuCeidWS4os+b49uSw1/peVN+9450Le14ADKsJWj6nTw==
"@reacteditor/core@0.0.32":
version "0.0.32"
resolved "https://registry.yarnpkg.com/@reacteditor/core/-/core-0.0.32.tgz#371968f2ea70be0087a498a7963a187a305f4b60"
integrity sha512-WnaSzx33oiCpIuug7RNieY3WHBosHT11PRqJo7kH1qY1QJPmexcOCYVwPgFBKbpNYGKV1MpO0MpWgfz+RhzNfw==
dependencies:
"@chakra-ui/react" "^3.35.0"
"@dnd-kit/abstract" "0.4.0"
@@ -1233,6 +1233,11 @@
resolved "https://registry.yarnpkg.com/@reacteditor/plugin-media/-/plugin-media-0.0.4.tgz#b46ad9bd4a1f791b9c3279b53633fd9cbe26bca3"
integrity sha512-UzyP0sqdrkREpFYDw6K6ObpH3AiTPswy35P24EWI222g0ylHHgp475ArYMUJILjtOTrxV+jwf2E1O4i40rHkFg==
"@reacteditor/plugin-shopify@^0.0.1":
version "0.0.1"
resolved "https://registry.yarnpkg.com/@reacteditor/plugin-shopify/-/plugin-shopify-0.0.1.tgz#5c419b7ab93e46b43d6ec53836d401ff4298b45a"
integrity sha512-MpikjXcNw7RNBlMnC61OcX3qZeEvaf4meolqS9eC2mNSaQWjK2WA/2g2afqnwilx5HNG14Eu+8GLXLEH8hhOzQ==
"@reacteditor/plugin-tailwind-cdn@^0.0.3":
version "0.0.3"
resolved "https://registry.yarnpkg.com/@reacteditor/plugin-tailwind-cdn/-/plugin-tailwind-cdn-0.0.3.tgz#355af37a738b3477778294f6fa1f339d90ae6f07"
@@ -1576,12 +1581,12 @@
dependencies:
undici-types "~7.19.0"
"@types/node@^22.0.0":
version "22.19.17"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.19.17.tgz#09c71fb34ba2510f8ac865361b1fcb9552b8a581"
integrity sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==
"@types/node@^25.2.0":
version "25.9.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-25.9.1.tgz#3bda556db500ae4319c08e7fc9ab94f19013ba0b"
integrity sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==
dependencies:
undici-types "~6.21.0"
undici-types ">=7.24.0 <7.24.7"
"@types/parse-json@^4.0.0":
version "4.0.2"
@@ -2931,10 +2936,10 @@ longest-streak@^3.0.0:
resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-3.1.0.tgz#62fa67cd958742a1574af9f39866364102d90cd4"
integrity sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==
lucide-react@^1.14.0:
version "1.14.0"
resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-1.14.0.tgz#3c3867749f5ff4eeb5a6f423557ec6a50521366f"
integrity sha512-+1mdWcfSJVUsaTIjN9zoezmUhfXo5l0vP7ekBMPo3jcS/aIkxHnXqAPsByszMZx/Y8oQBRJxJx5xg+RH3urzxA==
lucide-react@^1.17.0:
version "1.17.0"
resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-1.17.0.tgz#5b8ddd7d6975e3e45dc9d03025afc7674d78f8a8"
integrity sha512-9FA9evdox/JQL5PT57fdA1x/yg8T7knJ98+zjTL3UfKza6pflQUUh3XtaQIHKvnsJw1lmsEyHVlt5jchYxOQ5w==
magic-string@^0.30.21:
version "0.30.21"
@@ -3423,26 +3428,26 @@ nanoid@^3.3.11, nanoid@^3.3.6:
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.12.tgz#ab3d912e217a6d0a514f00a72a16543a28982c05"
integrity sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==
next@16.2.6:
version "16.2.6"
resolved "https://registry.yarnpkg.com/next/-/next-16.2.6.tgz#4564833d2865efc598b7c63541b5771792d3d811"
integrity sha512-qOVgKJg1+At15NpeUP+eJgCHvTCgXsogweq87Ri/Ix7PkqQHg4sdaXmSFqKlgaIXE4kW0g25LE68W87UANlHtw==
next@^16.2.6:
version "16.2.7"
resolved "https://registry.yarnpkg.com/next/-/next-16.2.7.tgz#c4f9e7f4aff6744afd827f7f9d883ca38a1fb4b0"
integrity sha512-eMJxgjRzBaj3olkP4cBamHDXL79A8FC6u1GcsO1D1Tsx8bw/LLXUJCaoajVxtnhD3A1IJqIT8IcRJjgBIPJq4w==
dependencies:
"@next/env" "16.2.6"
"@next/env" "16.2.7"
"@swc/helpers" "0.5.15"
baseline-browser-mapping "^2.9.19"
caniuse-lite "^1.0.30001579"
postcss "8.4.31"
styled-jsx "5.1.6"
optionalDependencies:
"@next/swc-darwin-arm64" "16.2.6"
"@next/swc-darwin-x64" "16.2.6"
"@next/swc-linux-arm64-gnu" "16.2.6"
"@next/swc-linux-arm64-musl" "16.2.6"
"@next/swc-linux-x64-gnu" "16.2.6"
"@next/swc-linux-x64-musl" "16.2.6"
"@next/swc-win32-arm64-msvc" "16.2.6"
"@next/swc-win32-x64-msvc" "16.2.6"
"@next/swc-darwin-arm64" "16.2.7"
"@next/swc-darwin-x64" "16.2.7"
"@next/swc-linux-arm64-gnu" "16.2.7"
"@next/swc-linux-arm64-musl" "16.2.7"
"@next/swc-linux-x64-gnu" "16.2.7"
"@next/swc-linux-x64-musl" "16.2.7"
"@next/swc-win32-arm64-msvc" "16.2.7"
"@next/swc-win32-x64-msvc" "16.2.7"
sharp "^0.34.5"
object-hash@^3.0.0:
@@ -3645,10 +3650,10 @@ proxy-memoize@3.0.1:
dependencies:
proxy-compare "^3.0.0"
react-dom@^19.1.1:
version "19.2.5"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.2.5.tgz#b8768b10837d0b8e9ca5b9e2d58dff3d880ea25e"
integrity sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==
react-dom@^19.2.0:
version "19.2.7"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.2.7.tgz#0450dc9ae9ddbff76ef196401cd8b8c7fb466ccc"
integrity sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==
dependencies:
scheduler "^0.27.0"
@@ -3714,10 +3719,10 @@ react-style-singleton@^2.2.2, react-style-singleton@^2.2.3:
get-nonce "^1.0.0"
tslib "^2.0.0"
react@^19.1.1:
version "19.2.5"
resolved "https://registry.yarnpkg.com/react/-/react-19.2.5.tgz#c888ab8b8ef33e2597fae8bdb2d77edbdb42858b"
integrity sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==
react@^19.2.0:
version "19.2.7"
resolved "https://registry.yarnpkg.com/react/-/react-19.2.7.tgz#1f47a1bfc06f8ec885752c6f4af14369a9f8260b"
integrity sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==
remark-gfm@^4.0.0:
version "4.0.1"
@@ -3942,15 +3947,15 @@ tw-animate-css@^1.4.0:
resolved "https://registry.yarnpkg.com/tw-animate-css/-/tw-animate-css-1.4.0.tgz#b4a06f68244cba39428aa47e65e6e4c0babc21ee"
integrity sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==
typescript@^5.5.4:
typescript@^5.7.0:
version "5.9.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f"
integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==
undici-types@~6.21.0:
version "6.21.0"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb"
integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==
"undici-types@>=7.24.0 <7.24.7":
version "7.24.6"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.24.6.tgz#61275b485d7fd4e9d269c7cf04ec2873c9cc0f91"
integrity sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==
undici-types@~7.19.0:
version "7.19.2"