pagiera 0.2.0-alpha.39 → 0.2.0-alpha.40
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/full-editor.js +981 -420
- package/dist/full-editor.js.map +4 -4
- package/dist/full.css +27 -25
- package/dist/internal/app/p/editor/template-preview.d.ts +55 -0
- package/dist/internal/app/p/editor/template-preview.d.ts.map +1 -0
- package/dist/internal/app/p/editor/template-preview.js +142 -0
- package/dist/internal/app/p/editor/template-preview.js.map +1 -0
- package/dist/internal/app/p/editor/templates-panel.d.ts.map +1 -1
- package/dist/internal/app/p/editor/templates-panel.js +12 -10
- package/dist/internal/app/p/editor/templates-panel.js.map +1 -1
- package/dist/server.js +94 -2
- package/dist/server.js.map +4 -4
- package/package.json +1 -1
package/dist/full-editor.js
CHANGED
|
@@ -37,11 +37,11 @@ import {
|
|
|
37
37
|
import { AnimatePresence as AnimatePresence7, motion as motion7, useReducedMotion } from "motion/react";
|
|
38
38
|
import {
|
|
39
39
|
useCallback as useCallback3,
|
|
40
|
-
useEffect as
|
|
40
|
+
useEffect as useEffect11,
|
|
41
41
|
useLayoutEffect as useLayoutEffect2,
|
|
42
|
-
useMemo as
|
|
43
|
-
useRef as
|
|
44
|
-
useState as
|
|
42
|
+
useMemo as useMemo4,
|
|
43
|
+
useRef as useRef5,
|
|
44
|
+
useState as useState14,
|
|
45
45
|
useTransition as useTransition2
|
|
46
46
|
} from "react";
|
|
47
47
|
|
|
@@ -3861,6 +3861,18 @@ function overrideChain(cascade, targetId) {
|
|
|
3861
3861
|
between.sort((a, b) => goingNarrower ? b.width - a.width : a.width - b.width);
|
|
3862
3862
|
return between.map((item) => item.id);
|
|
3863
3863
|
}
|
|
3864
|
+
function mediaPlan(cascade) {
|
|
3865
|
+
const base = baseOf(cascade);
|
|
3866
|
+
const narrower = cascade.breakpoints.filter((item) => item.id !== base.id && item.width < base.width).sort((a, b) => b.width - a.width).map((item) => {
|
|
3867
|
+
const ceiling = cascade.breakpoints.filter((other) => other.width > item.width).reduce(
|
|
3868
|
+
(lowest, other) => Math.min(lowest, other.width),
|
|
3869
|
+
Number.POSITIVE_INFINITY
|
|
3870
|
+
);
|
|
3871
|
+
return { id: item.id, query: `(max-width: ${ceiling - 1}px)` };
|
|
3872
|
+
});
|
|
3873
|
+
const wider = cascade.breakpoints.filter((item) => item.id !== base.id && item.width > base.width).sort((a, b) => a.width - b.width).map((item) => ({ id: item.id, query: `(min-width: ${item.width}px)` }));
|
|
3874
|
+
return [...narrower, ...wider];
|
|
3875
|
+
}
|
|
3864
3876
|
var chainCache = /* @__PURE__ */ new WeakMap();
|
|
3865
3877
|
function chainFor(cascade, targetId) {
|
|
3866
3878
|
let byTarget = chainCache.get(cascade);
|
|
@@ -4418,12 +4430,112 @@ function isNote(element, byId, breakpoint, frameWidth, rootLayout = "absolute",
|
|
|
4418
4430
|
const right = x + (style.widthMode === "fixed" ? style.w : 0);
|
|
4419
4431
|
return right <= 0 || x >= frameWidth;
|
|
4420
4432
|
}
|
|
4433
|
+
function noteIds(elements, byId, breakpoint, frameWidth, rootLayout = "absolute", cascade = DEFAULT_CASCADE) {
|
|
4434
|
+
const notes = /* @__PURE__ */ new Set();
|
|
4435
|
+
for (const element of elements) {
|
|
4436
|
+
if (isNote(element, byId, breakpoint, frameWidth, rootLayout, cascade)) {
|
|
4437
|
+
for (const id of subtreeIds(elements, element.id)) notes.add(id);
|
|
4438
|
+
}
|
|
4439
|
+
}
|
|
4440
|
+
return notes;
|
|
4441
|
+
}
|
|
4421
4442
|
|
|
4422
4443
|
// src/internal/lib/render/css.ts
|
|
4444
|
+
var UNITLESS = /* @__PURE__ */ new Set([
|
|
4445
|
+
"opacity",
|
|
4446
|
+
"zIndex",
|
|
4447
|
+
"flexGrow",
|
|
4448
|
+
"flexShrink",
|
|
4449
|
+
"flexBasis",
|
|
4450
|
+
"lineHeight",
|
|
4451
|
+
"order",
|
|
4452
|
+
"fontWeight",
|
|
4453
|
+
"columns"
|
|
4454
|
+
]);
|
|
4455
|
+
function kebab(property) {
|
|
4456
|
+
return property.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
|
|
4457
|
+
}
|
|
4458
|
+
function declarationsToCss(css) {
|
|
4459
|
+
return Object.entries(css).filter(([, value]) => value !== void 0 && value !== null && value !== "").map(([property, value]) => {
|
|
4460
|
+
const rendered = typeof value === "number" && !UNITLESS.has(property) ? `${value}px` : String(value);
|
|
4461
|
+
return `${kebab(property)}:${rendered}`;
|
|
4462
|
+
}).join(";");
|
|
4463
|
+
}
|
|
4464
|
+
function classFor(id) {
|
|
4465
|
+
return `pg-${id.replace(/[^a-zA-Z0-9_-]/g, "-")}`;
|
|
4466
|
+
}
|
|
4423
4467
|
var DEFAULT_PAGE_FONT = "ui-sans-serif, system-ui, sans-serif";
|
|
4468
|
+
function pageTransitionCss(rootStyle) {
|
|
4469
|
+
const kind = rootStyle.pageTransition ?? "smooth";
|
|
4470
|
+
if (kind === "none") return "html{scrollbar-gutter:stable}";
|
|
4471
|
+
const duration = Math.max(120, Math.min(1200, rootStyle.pageTransitionDuration ?? 380));
|
|
4472
|
+
const leaveDuration = Math.max(90, Math.round(duration * 0.48));
|
|
4473
|
+
const frames = kind === "fade" ? {
|
|
4474
|
+
leave: "to{opacity:0}",
|
|
4475
|
+
enter: "from{opacity:0}to{opacity:1}"
|
|
4476
|
+
} : kind === "slide" ? {
|
|
4477
|
+
leave: "to{opacity:0;transform:translateX(-20px)}",
|
|
4478
|
+
enter: "from{opacity:0;transform:translateX(26px)}to{opacity:1;transform:none}"
|
|
4479
|
+
} : {
|
|
4480
|
+
leave: "to{opacity:0;transform:translateY(-6px);filter:blur(3px)}",
|
|
4481
|
+
enter: "from{opacity:0;transform:translateY(10px);filter:blur(5px)}to{opacity:1;transform:none;filter:blur(0)}"
|
|
4482
|
+
};
|
|
4483
|
+
return `
|
|
4484
|
+
@view-transition{navigation:auto}
|
|
4485
|
+
html{scrollbar-gutter:stable}
|
|
4486
|
+
::view-transition-old(root),::view-transition-new(root){mix-blend-mode:normal;animation-fill-mode:both}
|
|
4487
|
+
::view-transition-old(root){animation:pg-page-leave ${leaveDuration}ms cubic-bezier(.4,0,1,1) both}
|
|
4488
|
+
::view-transition-new(root){animation:pg-page-enter ${duration}ms cubic-bezier(.16,1,.3,1) both}
|
|
4489
|
+
@keyframes pg-page-leave{${frames.leave}}
|
|
4490
|
+
@keyframes pg-page-enter{${frames.enter}}
|
|
4491
|
+
@media (prefers-reduced-motion:reduce){::view-transition-old(root),::view-transition-new(root){animation:none}}
|
|
4492
|
+
`;
|
|
4493
|
+
}
|
|
4424
4494
|
function resolveFont(fontFamily) {
|
|
4425
4495
|
return fontFamily === "inherit" || fontFamily === "" ? DEFAULT_PAGE_FONT : fontFamily;
|
|
4426
4496
|
}
|
|
4497
|
+
function rulesFor(element, byId, breakpoint, rootStyle, cascade) {
|
|
4498
|
+
const parent = element.parentId ? byId.get(element.parentId) : void 0;
|
|
4499
|
+
const parentStyle = parent ? resolveStyle(parent, breakpoint, cascade) : void 0;
|
|
4500
|
+
const style = resolveStyle(element, breakpoint, cascade);
|
|
4501
|
+
const css = styleToCss(
|
|
4502
|
+
style,
|
|
4503
|
+
{
|
|
4504
|
+
parentLayout: parentStyle?.layout ?? "stack",
|
|
4505
|
+
parentDirection: parentStyle?.direction ?? "column",
|
|
4506
|
+
parentAlign: parentStyle?.align ?? rootStyle.align
|
|
4507
|
+
},
|
|
4508
|
+
element
|
|
4509
|
+
);
|
|
4510
|
+
if (style.hidden) css.display = "none";
|
|
4511
|
+
if (!isBand(element.type, style, rootStyle) || style.hidden) {
|
|
4512
|
+
return [["", declarationsToCss(css)]];
|
|
4513
|
+
}
|
|
4514
|
+
const { shell, inner } = splitBand(css, rootStyle.maxWidth);
|
|
4515
|
+
return [
|
|
4516
|
+
["", declarationsToCss(shell)],
|
|
4517
|
+
[">.pg-inner", declarationsToCss(inner)]
|
|
4518
|
+
];
|
|
4519
|
+
}
|
|
4520
|
+
function interactionDeclarations(element, byId, breakpoint, rootStyle, cascade, patch) {
|
|
4521
|
+
const parent = element.parentId ? byId.get(element.parentId) : void 0;
|
|
4522
|
+
const parentStyle = parent ? resolveStyle(parent, breakpoint, cascade) : void 0;
|
|
4523
|
+
const context = {
|
|
4524
|
+
parentLayout: parentStyle?.layout ?? "stack",
|
|
4525
|
+
parentDirection: parentStyle?.direction ?? "column",
|
|
4526
|
+
parentAlign: parentStyle?.align ?? rootStyle.align
|
|
4527
|
+
};
|
|
4528
|
+
const resting = resolveStyle(element, breakpoint, cascade);
|
|
4529
|
+
const restingCss = styleToCss(resting, context, element);
|
|
4530
|
+
const activeCss = styleToCss({ ...resting, ...patch }, context, element);
|
|
4531
|
+
const delta = {};
|
|
4532
|
+
for (const property of Object.keys(activeCss)) {
|
|
4533
|
+
if (activeCss[property] !== restingCss[property]) {
|
|
4534
|
+
delta[property] = activeCss[property];
|
|
4535
|
+
}
|
|
4536
|
+
}
|
|
4537
|
+
return declarationsToCss(delta);
|
|
4538
|
+
}
|
|
4427
4539
|
var ENTRANCE_KEYFRAMES = `
|
|
4428
4540
|
@keyframes pg-fade{from{opacity:0}to{opacity:1}}
|
|
4429
4541
|
@keyframes pg-up{from{opacity:0;translate:0 28px}to{opacity:1;translate:none}}
|
|
@@ -4471,6 +4583,88 @@ var ENTRANCE_SCRIPT = `
|
|
|
4471
4583
|
setTimeout(all,3000);
|
|
4472
4584
|
})();
|
|
4473
4585
|
`.trim();
|
|
4586
|
+
function hasEntrances(elements, cascade = DEFAULT_CASCADE) {
|
|
4587
|
+
const baseId = baseOf(cascade).id;
|
|
4588
|
+
return elements.some(
|
|
4589
|
+
(el) => resolveStyle(el, baseId, cascade).entrance !== "none"
|
|
4590
|
+
);
|
|
4591
|
+
}
|
|
4592
|
+
function stylesheetFor(elements, rootStyle) {
|
|
4593
|
+
const byId = new Map(elements.map((el) => [el.id, el]));
|
|
4594
|
+
const cascade = cascadeOf(rootStyle.breakpoints, rootStyle.baseBreakpointId);
|
|
4595
|
+
const baseId = baseOf(cascade).id;
|
|
4596
|
+
const parts = [];
|
|
4597
|
+
parts.push(pageTransitionCss(rootStyle));
|
|
4598
|
+
for (const font of rootStyle.customFonts ?? []) {
|
|
4599
|
+
const family = font.name.replace(/["'{};]/g, "");
|
|
4600
|
+
const rawUrl = font.url.replace(/["'()\\]/g, "");
|
|
4601
|
+
const url = rawUrl === "/fonts/manrope-variable.woff2" ? "/api/pagiera/assets/manrope-variable.woff2" : rawUrl;
|
|
4602
|
+
parts.push(`@font-face{font-family:"${family}";src:url("${url}") format("woff2");font-weight:${font.weight};font-style:${font.style};font-display:swap}`);
|
|
4603
|
+
}
|
|
4604
|
+
parts.push(`html,body{margin:0;padding:0;background:${rootStyle.bg}}`);
|
|
4605
|
+
parts.push(`html{scroll-behavior:smooth}.pg-root{${declarationsToCss(rootStyleToCss(rootStyle))}}`);
|
|
4606
|
+
parts.push(
|
|
4607
|
+
// The font is pinned on `.pg-root` rather than on <body>: the app's
|
|
4608
|
+
// layout puts a font class on <body>, which would out-specify an
|
|
4609
|
+
// element selector and leak the editor's typeface into the site.
|
|
4610
|
+
// The shell spans the viewport; the content width is applied by each
|
|
4611
|
+
// band's inner box, so section backgrounds reach both edges.
|
|
4612
|
+
`.pg-root{font-family:${resolveFont(rootStyle.fontFamily)}}.pg-node{box-sizing:border-box}.pg-node:is(input,textarea,button){font:inherit}.pg-node:is(input,textarea){outline:none}.pg-node:is(textarea){resize:none}.pg-form-status:empty{display:none}.pg-form-status{font-size:12px;line-height:1.4}.pg-node[data-pg-state=success] .pg-form-status{color:#22c55e}.pg-node[data-pg-state=error] .pg-form-status{color:#ef4444}.pg-node img{display:block;width:100%;height:100%}.pg-link{text-decoration:none;color:inherit}`
|
|
4613
|
+
);
|
|
4614
|
+
for (const element of elements) {
|
|
4615
|
+
const emitted = rulesFor(element, byId, baseId, rootStyle, cascade).map(([suffix, decl]) => `.${classFor(element.id)}${suffix}{${decl}}`).join("");
|
|
4616
|
+
parts.push(emitted);
|
|
4617
|
+
}
|
|
4618
|
+
for (const plan of mediaPlan(cascade)) {
|
|
4619
|
+
const breakpoint = plan.id;
|
|
4620
|
+
const affected = elements.filter((el) => {
|
|
4621
|
+
if (el.overrides?.[breakpoint]) return true;
|
|
4622
|
+
const parent = el.parentId ? byId.get(el.parentId) : void 0;
|
|
4623
|
+
return Boolean(parent?.overrides?.[breakpoint]);
|
|
4624
|
+
});
|
|
4625
|
+
if (affected.length === 0) continue;
|
|
4626
|
+
const rules = affected.flatMap(
|
|
4627
|
+
(el) => rulesFor(el, byId, breakpoint, rootStyle, cascade).map(
|
|
4628
|
+
([suffix, decl]) => `.${classFor(el.id)}${suffix}{${decl}}`
|
|
4629
|
+
)
|
|
4630
|
+
).join("");
|
|
4631
|
+
parts.push(`@media ${plan.query}{${rules}}`);
|
|
4632
|
+
}
|
|
4633
|
+
if (hasEntrances(elements, cascade)) {
|
|
4634
|
+
parts.push(ENTRANCE_KEYFRAMES);
|
|
4635
|
+
for (const element of elements) {
|
|
4636
|
+
const style = resolveStyle(element, baseId, cascade);
|
|
4637
|
+
if (style.entrance === "none") continue;
|
|
4638
|
+
parts.push(
|
|
4639
|
+
`.pg-ready .${classFor(element.id)}.pg-in{animation:pg-${style.entrance} ${style.entranceDuration}ms ${style.entranceCurve === "spring" ? `cubic-bezier(.16,${1 + Math.max(0, 45 - style.springDamping) / 100},${Math.max(0.12, Math.min(0.52, 120 / style.springStiffness))},1)` : `cubic-bezier(${style.entranceBezier})`} ${style.entranceDelay}ms both}`
|
|
4640
|
+
);
|
|
4641
|
+
}
|
|
4642
|
+
}
|
|
4643
|
+
for (const element of elements) {
|
|
4644
|
+
if (element.hover || element.press) parts.push(`.${classFor(element.id)}{transition:transform .42s cubic-bezier(.16,1,.3,1),scale .42s cubic-bezier(.16,1,.3,1),rotate .42s cubic-bezier(.16,1,.3,1),translate .42s cubic-bezier(.16,1,.3,1),background-color .32s ease,color .32s ease,border-color .32s ease,box-shadow .42s cubic-bezier(.16,1,.3,1),opacity .32s ease,filter .42s ease;will-change:transform}`);
|
|
4645
|
+
if (element.hover && Object.keys(element.hover).length) parts.push(`.${classFor(element.id)}:hover{${interactionDeclarations(element, byId, baseId, rootStyle, cascade, element.hover)}}`);
|
|
4646
|
+
if (element.press && Object.keys(element.press).length) parts.push(`.${classFor(element.id)}:active{${interactionDeclarations(element, byId, baseId, rootStyle, cascade, element.press)}}`);
|
|
4647
|
+
if (element.loop) {
|
|
4648
|
+
const name = element.loop.type;
|
|
4649
|
+
parts.push(`.${classFor(element.id)}{animation:pg-loop-${name} ${element.loop.duration}ms ease-in-out infinite}`);
|
|
4650
|
+
}
|
|
4651
|
+
}
|
|
4652
|
+
for (const plan of mediaPlan(cascade)) {
|
|
4653
|
+
const rules = elements.flatMap((element) => {
|
|
4654
|
+
if (!element.hover && !element.press) return [];
|
|
4655
|
+
const parent = element.parentId ? byId.get(element.parentId) : void 0;
|
|
4656
|
+
if (!element.overrides?.[plan.id] && !parent?.overrides?.[plan.id]) return [];
|
|
4657
|
+
const selector = `.${classFor(element.id)}`;
|
|
4658
|
+
return [
|
|
4659
|
+
element.hover && Object.keys(element.hover).length ? `${selector}:hover{${interactionDeclarations(element, byId, plan.id, rootStyle, cascade, element.hover)}}` : "",
|
|
4660
|
+
element.press && Object.keys(element.press).length ? `${selector}:active{${interactionDeclarations(element, byId, plan.id, rootStyle, cascade, element.press)}}` : ""
|
|
4661
|
+
].filter(Boolean);
|
|
4662
|
+
}).join("");
|
|
4663
|
+
if (rules) parts.push(`@media ${plan.query}{${rules}}`);
|
|
4664
|
+
}
|
|
4665
|
+
if (elements.some((element) => element.loop)) parts.push(`@keyframes pg-loop-pulse{0%,100%{scale:1}50%{scale:1.06}}@keyframes pg-loop-float{0%,100%{translate:0 0}50%{translate:0 -12px}}@keyframes pg-loop-spin{to{rotate:360deg}}@media(prefers-reduced-motion:reduce){.pg-node{animation:none!important}}`);
|
|
4666
|
+
return parts.join("\n");
|
|
4667
|
+
}
|
|
4474
4668
|
|
|
4475
4669
|
// src/internal/lib/editor/snap.ts
|
|
4476
4670
|
var SNAP_THRESHOLD = 6;
|
|
@@ -9251,8 +9445,8 @@ function VariablesPanel({ rootStyle, selectedElement, setRootStyle, setElements
|
|
|
9251
9445
|
// src/internal/app/p/editor/templates-panel.tsx
|
|
9252
9446
|
import { IconAlertTriangle as IconAlertTriangle2, IconArrowUpRight, IconCheck as IconCheck5, IconRefresh, IconSearch as IconSearch4, IconSparkles as IconSparkles4, IconTemplate, IconX as IconX5 } from "@tabler/icons-react";
|
|
9253
9447
|
import { AnimatePresence as AnimatePresence6, motion as motion6 } from "motion/react";
|
|
9254
|
-
import { useEffect as
|
|
9255
|
-
import { createPortal as
|
|
9448
|
+
import { useEffect as useEffect10, useMemo as useMemo3, useState as useState13 } from "react";
|
|
9449
|
+
import { createPortal as createPortal4 } from "react-dom";
|
|
9256
9450
|
import { usePagieraFonts as usePagieraFonts2 } from "pagiera/provider";
|
|
9257
9451
|
|
|
9258
9452
|
// src/internal/lib/editor/template-registry.ts
|
|
@@ -9381,8 +9575,370 @@ async function loadTemplateRegistry(url = DEFAULT_TEMPLATE_REGISTRY_URL, force =
|
|
|
9381
9575
|
}
|
|
9382
9576
|
}
|
|
9383
9577
|
|
|
9578
|
+
// src/internal/app/p/editor/template-preview.tsx
|
|
9579
|
+
import { useEffect as useEffect9, useMemo as useMemo2, useRef as useRef4, useState as useState12 } from "react";
|
|
9580
|
+
import { createPortal as createPortal3 } from "react-dom";
|
|
9581
|
+
|
|
9582
|
+
// src/internal/lib/render/page-render.tsx
|
|
9583
|
+
import React2 from "react";
|
|
9584
|
+
import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
9585
|
+
function RenderedPage({
|
|
9586
|
+
elements: all,
|
|
9587
|
+
rootStyle,
|
|
9588
|
+
data = {}
|
|
9589
|
+
}) {
|
|
9590
|
+
const frameWidth = rootStyle.fullWidth ? Number.POSITIVE_INFINITY : rootStyle.maxWidth;
|
|
9591
|
+
const cascade = cascadeOf(rootStyle.breakpoints, rootStyle.baseBreakpointId);
|
|
9592
|
+
const baseId = baseOf(cascade).id;
|
|
9593
|
+
const notes = noteIds(all, indexById(all), baseId, frameWidth, rootStyle.layout, cascade);
|
|
9594
|
+
const elements = all.filter((element) => !notes.has(element.id) && element.componentRole !== "master");
|
|
9595
|
+
return /* @__PURE__ */ jsxs10(Fragment4, { children: [
|
|
9596
|
+
/* @__PURE__ */ jsx11(
|
|
9597
|
+
"style",
|
|
9598
|
+
{
|
|
9599
|
+
dangerouslySetInnerHTML: { __html: stylesheetFor(elements, rootStyle) }
|
|
9600
|
+
}
|
|
9601
|
+
),
|
|
9602
|
+
/* @__PURE__ */ jsx11("main", { className: "pg-root", children: childrenOf(elements, void 0).map((el) => /* @__PURE__ */ jsx11(
|
|
9603
|
+
RenderedNode,
|
|
9604
|
+
{
|
|
9605
|
+
element: el,
|
|
9606
|
+
elements,
|
|
9607
|
+
rootStyle,
|
|
9608
|
+
data
|
|
9609
|
+
},
|
|
9610
|
+
el.id
|
|
9611
|
+
)) }),
|
|
9612
|
+
hasEntrances(elements) && /* @__PURE__ */ jsx11(
|
|
9613
|
+
"script",
|
|
9614
|
+
{
|
|
9615
|
+
dangerouslySetInnerHTML: { __html: ENTRANCE_SCRIPT }
|
|
9616
|
+
}
|
|
9617
|
+
),
|
|
9618
|
+
elements.some((element) => element.draggable) && /* @__PURE__ */ jsx11("script", { dangerouslySetInnerHTML: { __html: DRAG_SCRIPT } }),
|
|
9619
|
+
elements.some((element) => element.interaction && ["toggle-layer", "show-layer", "hide-layer"].includes(element.interaction.action)) && /* @__PURE__ */ jsx11("script", { dangerouslySetInnerHTML: { __html: ACTION_SCRIPT } }),
|
|
9620
|
+
elements.some((element) => element.type === "Form" && element.formSubmitMode !== "native") && /* @__PURE__ */ jsx11("script", { dangerouslySetInnerHTML: { __html: FORM_SCRIPT } })
|
|
9621
|
+
] });
|
|
9622
|
+
}
|
|
9623
|
+
function RenderedNode({
|
|
9624
|
+
element: raw,
|
|
9625
|
+
elements,
|
|
9626
|
+
rootStyle,
|
|
9627
|
+
data,
|
|
9628
|
+
row
|
|
9629
|
+
}) {
|
|
9630
|
+
const cascade = cascadeOf(rootStyle.breakpoints, rootStyle.baseBreakpointId);
|
|
9631
|
+
const baseId = baseOf(cascade).id;
|
|
9632
|
+
const directRow = row ?? (raw.sourceId ? data[raw.sourceId]?.[0] : void 0);
|
|
9633
|
+
const element = bindElement(raw, directRow);
|
|
9634
|
+
const children = childrenOf(elements, element.id);
|
|
9635
|
+
const style = resolveStyle(element, baseId, cascade);
|
|
9636
|
+
const band = isBand(element.type, style, rootStyle);
|
|
9637
|
+
const className = `pg-node ${classFor(element.id)}` + (band ? " pg-band" : "") + (style.entrance === "none" ? "" : " pg-anim");
|
|
9638
|
+
const renderChildren = () => element.type === "Repeat" ? rowsFor(element, data, true).flatMap(
|
|
9639
|
+
(dataRow, index) => children.map((child) => /* @__PURE__ */ jsx11(
|
|
9640
|
+
RenderedNode,
|
|
9641
|
+
{
|
|
9642
|
+
element: child,
|
|
9643
|
+
elements,
|
|
9644
|
+
rootStyle,
|
|
9645
|
+
data,
|
|
9646
|
+
row: dataRow
|
|
9647
|
+
},
|
|
9648
|
+
`${index}:${child.id}`
|
|
9649
|
+
))
|
|
9650
|
+
) : children.map((child) => /* @__PURE__ */ jsx11(
|
|
9651
|
+
RenderedNode,
|
|
9652
|
+
{
|
|
9653
|
+
element: child,
|
|
9654
|
+
elements,
|
|
9655
|
+
rootStyle,
|
|
9656
|
+
data,
|
|
9657
|
+
row: element.type === "Request" ? data[element.sourceId ?? ""]?.[0] : row
|
|
9658
|
+
},
|
|
9659
|
+
child.id
|
|
9660
|
+
));
|
|
9661
|
+
const content = /* @__PURE__ */ jsxs10(Fragment4, { children: [
|
|
9662
|
+
/* @__PURE__ */ jsx11(ElementContent, { element }),
|
|
9663
|
+
renderChildren(),
|
|
9664
|
+
element.type === "Form" && /* @__PURE__ */ jsx11("span", { className: "pg-form-status", "data-pg-form-status": true, "aria-live": "polite" })
|
|
9665
|
+
] });
|
|
9666
|
+
const body = band ? /* @__PURE__ */ jsx11("div", { className: "pg-inner", children: content }) : content;
|
|
9667
|
+
const interactionHref = element.interaction?.action === "scroll-to" ? `#${classFor(element.interaction.value)}` : element.interaction?.action === "navigate" ? element.interaction.value : void 0;
|
|
9668
|
+
const href = interactionHref || element.href;
|
|
9669
|
+
const target = element.interaction?.target || element.target;
|
|
9670
|
+
if (element.type === "Input") {
|
|
9671
|
+
return /* @__PURE__ */ jsx11(
|
|
9672
|
+
"input",
|
|
9673
|
+
{
|
|
9674
|
+
id: classFor(element.id),
|
|
9675
|
+
className,
|
|
9676
|
+
type: element.inputType ?? "text",
|
|
9677
|
+
name: element.fieldName,
|
|
9678
|
+
placeholder: element.placeholder,
|
|
9679
|
+
required: element.required
|
|
9680
|
+
}
|
|
9681
|
+
);
|
|
9682
|
+
}
|
|
9683
|
+
if (element.type === "Textarea") {
|
|
9684
|
+
return /* @__PURE__ */ jsx11(
|
|
9685
|
+
"textarea",
|
|
9686
|
+
{
|
|
9687
|
+
id: classFor(element.id),
|
|
9688
|
+
className,
|
|
9689
|
+
name: element.fieldName,
|
|
9690
|
+
placeholder: element.placeholder,
|
|
9691
|
+
required: element.required,
|
|
9692
|
+
defaultValue: element.content
|
|
9693
|
+
}
|
|
9694
|
+
);
|
|
9695
|
+
}
|
|
9696
|
+
if (href) {
|
|
9697
|
+
return /* @__PURE__ */ jsx11(
|
|
9698
|
+
"a",
|
|
9699
|
+
{
|
|
9700
|
+
id: classFor(element.id),
|
|
9701
|
+
"data-pg-drag": element.draggable ? "true" : void 0,
|
|
9702
|
+
"data-pg-action": element.interaction?.action,
|
|
9703
|
+
"data-pg-target": element.interaction && !["navigate", "scroll-to"].includes(element.interaction.action) ? classFor(element.interaction.value) : void 0,
|
|
9704
|
+
className: `${className} pg-link`,
|
|
9705
|
+
href,
|
|
9706
|
+
target,
|
|
9707
|
+
rel: target === "_blank" ? "noopener noreferrer" : void 0,
|
|
9708
|
+
children: body
|
|
9709
|
+
}
|
|
9710
|
+
);
|
|
9711
|
+
}
|
|
9712
|
+
const tag = semanticTag(element);
|
|
9713
|
+
return React2.createElement(tag, {
|
|
9714
|
+
id: classFor(element.id),
|
|
9715
|
+
type: tag === "button" ? element.buttonType ?? "button" : void 0,
|
|
9716
|
+
"data-pg-drag": element.draggable ? "true" : void 0,
|
|
9717
|
+
"data-pg-action": element.interaction?.action,
|
|
9718
|
+
"data-pg-target": element.interaction && !["navigate", "scroll-to"].includes(element.interaction.action) ? classFor(element.interaction.value) : void 0,
|
|
9719
|
+
"data-pg-display": element.type === "Grid" || element.type === "Repeat" ? "grid" : isContainerType(element.type) || element.type === "Section" ? "flex" : "block",
|
|
9720
|
+
className,
|
|
9721
|
+
action: tag === "form" ? element.formAction : void 0,
|
|
9722
|
+
method: tag === "form" ? element.formMethod === "GET" ? "get" : "post" : void 0,
|
|
9723
|
+
"data-pg-form-mode": tag === "form" ? element.formSubmitMode ?? "request" : void 0,
|
|
9724
|
+
"data-pg-form-method": tag === "form" ? element.formMethod ?? "POST" : void 0,
|
|
9725
|
+
"data-pg-form-content": tag === "form" ? element.formContentType ?? "json" : void 0,
|
|
9726
|
+
"data-pg-form-body": tag === "form" ? element.formBody : void 0,
|
|
9727
|
+
"data-pg-form-headers": tag === "form" ? element.formHeaders : void 0,
|
|
9728
|
+
"data-pg-form-success": tag === "form" ? element.formSuccessMessage ?? "Sent successfully." : void 0,
|
|
9729
|
+
"data-pg-form-error": tag === "form" ? element.formErrorMessage ?? "Something went wrong." : void 0,
|
|
9730
|
+
"data-pg-form-reset": tag === "form" && element.formResetOnSuccess ? "true" : void 0
|
|
9731
|
+
}, body);
|
|
9732
|
+
}
|
|
9733
|
+
function semanticTag(element) {
|
|
9734
|
+
const name = (element.name ?? "").toLowerCase();
|
|
9735
|
+
if (element.type === "Button") return "button";
|
|
9736
|
+
if (element.type === "Form") return "form";
|
|
9737
|
+
if (element.type === "Heading") {
|
|
9738
|
+
const level = name.match(/(?:^|\s)h([1-6])(?:\s|$)/)?.[1] ?? "2";
|
|
9739
|
+
return `h${level}`;
|
|
9740
|
+
}
|
|
9741
|
+
if (element.type === "Text") return "p";
|
|
9742
|
+
if (name.includes("navbar") || name === "nav" || name.includes("navigation")) return "nav";
|
|
9743
|
+
if (name.includes("footer")) return "footer";
|
|
9744
|
+
if (name.includes("header")) return "header";
|
|
9745
|
+
if (element.type === "Section") return "section";
|
|
9746
|
+
return "div";
|
|
9747
|
+
}
|
|
9748
|
+
var DRAG_SCRIPT = `(function(){document.querySelectorAll('[data-pg-drag]').forEach(function(n){n.style.touchAction='none';n.style.cursor='grab';n.addEventListener('pointerdown',function(e){if(e.button!==0)return;e.preventDefault();var sx=e.clientX,sy=e.clientY,ox=Number(n.dataset.dx||0),oy=Number(n.dataset.dy||0);n.setPointerCapture(e.pointerId);n.style.cursor='grabbing';var move=function(p){var x=ox+p.clientX-sx,y=oy+p.clientY-sy;n.dataset.dx=String(x);n.dataset.dy=String(y);n.style.translate=x+'px '+y+'px'};var up=function(){n.style.cursor='grab';n.removeEventListener('pointermove',move);n.removeEventListener('pointerup',up)};n.addEventListener('pointermove',move);n.addEventListener('pointerup',up)})})})();`;
|
|
9749
|
+
var ACTION_SCRIPT = `(function(){document.querySelectorAll('[data-pg-target]').forEach(function(trigger){trigger.style.cursor='pointer';trigger.addEventListener('click',function(event){var target=document.getElementById(trigger.dataset.pgTarget);if(!target)return;event.preventDefault();var action=trigger.dataset.pgAction;var open=target.dataset.pgOpen==='true';var next=action==='show-layer'?true:action==='hide-layer'?false:!open;target.dataset.pgOpen=next?'true':'false';target.style.setProperty('display',next?(target.dataset.pgDisplay||'flex'):'none','important');trigger.setAttribute('aria-expanded',String(next));target.setAttribute('aria-hidden',String(!next))})})})();`;
|
|
9750
|
+
var FORM_SCRIPT = `(function(){function headers(raw){var out={};String(raw||'').split(/\\r?\\n/).forEach(function(line){var at=line.indexOf(':');if(at>0)out[line.slice(0,at).trim()]=line.slice(at+1).trim()});return out}function fields(data){var out={};data.forEach(function(value,key){var next=value instanceof File?value.name:String(value);if(out[key]===undefined)out[key]=next;else if(Array.isArray(out[key]))out[key].push(next);else out[key]=[out[key],next]});return out}function tokens(value,map){return String(value||'').replace(/{{\\s*form\\.([A-Za-z0-9_.-]+)\\s*}}/g,function(_,key){var found=map[key];return found==null?'':Array.isArray(found)?found.join(','):String(found)})}document.querySelectorAll('form[data-pg-form-mode="request"]').forEach(function(form){if(form.dataset.pgFormBound)return;form.dataset.pgFormBound='true';form.addEventListener('submit',async function(event){event.preventDefault();var status=form.querySelector('[data-pg-form-status]');var submit=form.querySelector('[type="submit"]');var data=new FormData(form),map=fields(data),method=form.dataset.pgFormMethod||'POST',kind=form.dataset.pgFormContent||'json',url=form.getAttribute('action')||location.href,custom=tokens(form.dataset.pgFormBody,map),requestHeaders=headers(tokens(form.dataset.pgFormHeaders,map)),options={method:method,headers:requestHeaders};if(method==='GET'){var query=new URLSearchParams(custom||Object.entries(map).flatMap(function(pair){return Array.isArray(pair[1])?pair[1].map(function(value){return [pair[0],value]}):[[pair[0],pair[1]]] }));var target=new URL(url,location.href);query.forEach(function(value,key){target.searchParams.append(key,value)});url=target.href}else if(kind==='form-data'){if(custom){try{var parsed=JSON.parse(custom);Object.keys(parsed).forEach(function(key){data.set(key,String(parsed[key]))})}catch(_){data.set('_body',custom)}}options.body=data}else if(kind==='urlencoded'){options.body=custom||new URLSearchParams(Object.entries(map).flatMap(function(pair){return Array.isArray(pair[1])?pair[1].map(function(value){return [pair[0],value]}):[[pair[0],pair[1]]] })).toString();if(!requestHeaders['Content-Type'])requestHeaders['Content-Type']='application/x-www-form-urlencoded;charset=UTF-8'}else{options.body=custom||JSON.stringify(map);if(!requestHeaders['Content-Type'])requestHeaders['Content-Type']='application/json'}form.setAttribute('aria-busy','true');form.dataset.pgState='loading';if(submit)submit.disabled=true;if(status)status.textContent='';try{var response=await fetch(url,options);if(!response.ok)throw new Error('HTTP '+response.status);form.dataset.pgState='success';if(status)status.textContent=form.dataset.pgFormSuccess||'Sent successfully.';if(form.dataset.pgFormReset==='true')form.reset();form.dispatchEvent(new CustomEvent('pagiera:form-success',{bubbles:true,detail:{response:response}}))}catch(error){form.dataset.pgState='error';if(status)status.textContent=form.dataset.pgFormError||'Something went wrong.';form.dispatchEvent(new CustomEvent('pagiera:form-error',{bubbles:true,detail:{error:error}}))}finally{form.removeAttribute('aria-busy');if(submit)submit.disabled=false}})})})();`;
|
|
9751
|
+
function isContainerType(type) {
|
|
9752
|
+
return ["Frame", "Stack", "Container", "Form", "Request", "Repeat"].includes(type);
|
|
9753
|
+
}
|
|
9754
|
+
function ElementContent({ element }) {
|
|
9755
|
+
if (element.code) return /* @__PURE__ */ jsx11("iframe", { title: element.name ?? "Code component", srcDoc: element.code, sandbox: "", style: { width: "100%", height: "100%", border: 0, borderRadius: "inherit" } });
|
|
9756
|
+
if (element.type === "Image") {
|
|
9757
|
+
if (!element.src) return null;
|
|
9758
|
+
return (
|
|
9759
|
+
// biome-ignore lint/performance/noImgElement: the src is author-supplied at runtime and cannot be statically optimised
|
|
9760
|
+
/* @__PURE__ */ jsx11(
|
|
9761
|
+
"img",
|
|
9762
|
+
{
|
|
9763
|
+
src: element.src,
|
|
9764
|
+
alt: element.alt ?? "",
|
|
9765
|
+
style: { objectFit: element.objectFit ?? "cover", borderRadius: "inherit" }
|
|
9766
|
+
}
|
|
9767
|
+
)
|
|
9768
|
+
);
|
|
9769
|
+
}
|
|
9770
|
+
if (element.type === "Video") {
|
|
9771
|
+
if (!element.src) return null;
|
|
9772
|
+
return /* @__PURE__ */ jsx11(
|
|
9773
|
+
"iframe",
|
|
9774
|
+
{
|
|
9775
|
+
src: element.src,
|
|
9776
|
+
title: element.name ?? "Video",
|
|
9777
|
+
allow: "accelerometer; autoplay; clipboard-write; encrypted-media; picture-in-picture",
|
|
9778
|
+
allowFullScreen: true,
|
|
9779
|
+
style: { width: "100%", height: "100%", border: 0, borderRadius: "inherit" }
|
|
9780
|
+
}
|
|
9781
|
+
);
|
|
9782
|
+
}
|
|
9783
|
+
if (element.type === "Icon") return /* @__PURE__ */ jsx11(IconGlyph, { element });
|
|
9784
|
+
if (!element.content) return null;
|
|
9785
|
+
return /* @__PURE__ */ jsx11("span", { style: { display: "block", width: "100%", whiteSpace: "pre-wrap" }, children: element.content });
|
|
9786
|
+
}
|
|
9787
|
+
|
|
9788
|
+
// src/internal/app/p/editor/template-preview.tsx
|
|
9789
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
9790
|
+
var FALLBACK_DEVICES = [
|
|
9791
|
+
{ id: "desktop", name: "Desktop", width: 1440 },
|
|
9792
|
+
{ id: "tablet", name: "Tablet", width: 834 },
|
|
9793
|
+
{ id: "mobile", name: "Mobile", width: 390 }
|
|
9794
|
+
];
|
|
9795
|
+
function previewUrlFor(templateId) {
|
|
9796
|
+
return `${DEFAULT_TEMPLATE_REGISTRY_URL.replace(/registry\.json$/, "")}${encodeURIComponent(templateId)}/preview`;
|
|
9797
|
+
}
|
|
9798
|
+
function useTemplatePreview(templateId) {
|
|
9799
|
+
const [pages, setPages] = useState12();
|
|
9800
|
+
const [error, setError] = useState12("");
|
|
9801
|
+
const [loading, setLoading] = useState12(false);
|
|
9802
|
+
const cache = useRef4(/* @__PURE__ */ new Map());
|
|
9803
|
+
useEffect9(() => {
|
|
9804
|
+
if (!templateId) return;
|
|
9805
|
+
const cached = cache.current.get(templateId);
|
|
9806
|
+
if (cached) {
|
|
9807
|
+
setPages(cached);
|
|
9808
|
+
setError("");
|
|
9809
|
+
return;
|
|
9810
|
+
}
|
|
9811
|
+
let active = true;
|
|
9812
|
+
setLoading(true);
|
|
9813
|
+
setError("");
|
|
9814
|
+
setPages(void 0);
|
|
9815
|
+
fetch(previewUrlFor(templateId), { headers: { Accept: "application/json" } }).then(async (response) => {
|
|
9816
|
+
const payload = await response.json().catch(() => ({}));
|
|
9817
|
+
if (!response.ok) throw new Error(payload?.error ?? `Preview returned ${response.status}.`);
|
|
9818
|
+
if (!Array.isArray(payload?.pages) || payload.pages.length === 0) {
|
|
9819
|
+
throw new Error("This template has no previewable pages.");
|
|
9820
|
+
}
|
|
9821
|
+
return payload.pages;
|
|
9822
|
+
}).then((result) => {
|
|
9823
|
+
cache.current.set(templateId, result);
|
|
9824
|
+
if (!active) return;
|
|
9825
|
+
setPages(result);
|
|
9826
|
+
}).catch((reason) => {
|
|
9827
|
+
if (!active) return;
|
|
9828
|
+
setError(reason instanceof Error ? reason.message : "Could not load the preview.");
|
|
9829
|
+
}).finally(() => {
|
|
9830
|
+
if (active) setLoading(false);
|
|
9831
|
+
});
|
|
9832
|
+
return () => {
|
|
9833
|
+
active = false;
|
|
9834
|
+
};
|
|
9835
|
+
}, [templateId]);
|
|
9836
|
+
return { pages, loading, error };
|
|
9837
|
+
}
|
|
9838
|
+
function devicesFor(page) {
|
|
9839
|
+
const defined = page?.rootStyle.breakpoints;
|
|
9840
|
+
if (!defined?.length) return FALLBACK_DEVICES;
|
|
9841
|
+
return [...defined].sort((a, b) => b.width - a.width).map((item) => ({ id: item.id, name: item.name, width: item.width }));
|
|
9842
|
+
}
|
|
9843
|
+
function TemplatePreviewStage({
|
|
9844
|
+
page,
|
|
9845
|
+
width,
|
|
9846
|
+
className = ""
|
|
9847
|
+
}) {
|
|
9848
|
+
const containerRef = useRef4(null);
|
|
9849
|
+
const [body, setBody] = useState12(null);
|
|
9850
|
+
const [box, setBox] = useState12({ width: 0, height: 0 });
|
|
9851
|
+
useEffect9(() => {
|
|
9852
|
+
const node2 = containerRef.current;
|
|
9853
|
+
if (!node2) return;
|
|
9854
|
+
const observer = new ResizeObserver(([entry]) => {
|
|
9855
|
+
setBox({
|
|
9856
|
+
width: entry.contentRect.width,
|
|
9857
|
+
height: entry.contentRect.height
|
|
9858
|
+
});
|
|
9859
|
+
});
|
|
9860
|
+
observer.observe(node2);
|
|
9861
|
+
return () => observer.disconnect();
|
|
9862
|
+
}, []);
|
|
9863
|
+
const scale = box.width > 0 ? Math.min(1, box.width / width) : 0;
|
|
9864
|
+
return /* @__PURE__ */ jsxs11("div", { ref: containerRef, className: `relative overflow-hidden ${className}`, children: [
|
|
9865
|
+
scale > 0 && /* @__PURE__ */ jsx12(
|
|
9866
|
+
"iframe",
|
|
9867
|
+
{
|
|
9868
|
+
title: `${page.name} preview`,
|
|
9869
|
+
sandbox: "allow-same-origin",
|
|
9870
|
+
srcDoc: "<!doctype html><html><head><meta charset='utf-8'></head><body></body></html>",
|
|
9871
|
+
onLoad: (event) => setBody(event.currentTarget.contentDocument?.body ?? null),
|
|
9872
|
+
style: {
|
|
9873
|
+
width,
|
|
9874
|
+
height: box.height / scale,
|
|
9875
|
+
border: 0,
|
|
9876
|
+
transform: `scale(${scale})`,
|
|
9877
|
+
transformOrigin: "top left"
|
|
9878
|
+
}
|
|
9879
|
+
},
|
|
9880
|
+
`${page.slug}:${width}`
|
|
9881
|
+
),
|
|
9882
|
+
body && createPortal3(
|
|
9883
|
+
/* @__PURE__ */ jsx12(RenderedPage, { elements: page.elements, rootStyle: page.rootStyle }),
|
|
9884
|
+
body
|
|
9885
|
+
)
|
|
9886
|
+
] });
|
|
9887
|
+
}
|
|
9888
|
+
function TemplatePreview({
|
|
9889
|
+
pages,
|
|
9890
|
+
loading,
|
|
9891
|
+
error,
|
|
9892
|
+
className = "",
|
|
9893
|
+
controlsClassName = ""
|
|
9894
|
+
}) {
|
|
9895
|
+
const [slug, setSlug] = useState12();
|
|
9896
|
+
const [deviceId, setDeviceId] = useState12();
|
|
9897
|
+
const page = useMemo2(
|
|
9898
|
+
() => pages?.find((item) => item.slug === slug) ?? pages?.[0],
|
|
9899
|
+
[pages, slug]
|
|
9900
|
+
);
|
|
9901
|
+
const devices = useMemo2(() => devicesFor(page), [page]);
|
|
9902
|
+
const device = devices.find((item) => item.id === deviceId) ?? devices[0];
|
|
9903
|
+
useEffect9(() => {
|
|
9904
|
+
if (deviceId && !devices.some((item) => item.id === deviceId)) setDeviceId(void 0);
|
|
9905
|
+
}, [deviceId, devices]);
|
|
9906
|
+
return /* @__PURE__ */ jsxs11("div", { className: `flex min-h-0 flex-col ${className}`, children: [
|
|
9907
|
+
/* @__PURE__ */ jsxs11("div", { className: `flex shrink-0 items-center gap-2 ${controlsClassName}`, children: [
|
|
9908
|
+
/* @__PURE__ */ jsx12("div", { className: "flex min-w-0 flex-1 gap-1 overflow-x-auto scrollbar-none", children: (pages ?? []).map((item) => /* @__PURE__ */ jsx12(
|
|
9909
|
+
"button",
|
|
9910
|
+
{
|
|
9911
|
+
type: "button",
|
|
9912
|
+
onClick: () => setSlug(item.slug),
|
|
9913
|
+
className: `h-7 shrink-0 rounded-full px-3 text-[10px] font-medium transition-colors ${item.slug === page?.slug ? "bg-ed-field-hover text-ed-text" : "text-ed-faint hover:text-ed-muted"}`,
|
|
9914
|
+
children: item.name
|
|
9915
|
+
},
|
|
9916
|
+
item.slug
|
|
9917
|
+
)) }),
|
|
9918
|
+
/* @__PURE__ */ jsx12("div", { className: "flex shrink-0 gap-1 rounded-full bg-ed-subtle p-1", children: devices.map((item) => /* @__PURE__ */ jsx12(
|
|
9919
|
+
"button",
|
|
9920
|
+
{
|
|
9921
|
+
type: "button",
|
|
9922
|
+
onClick: () => setDeviceId(item.id),
|
|
9923
|
+
title: `${item.name} \xB7 ${item.width}px`,
|
|
9924
|
+
className: `h-6 rounded-full px-2.5 text-[9px] font-medium transition-colors ${item.id === device?.id ? "bg-ed-surface text-ed-text" : "text-ed-faint hover:text-ed-muted"}`,
|
|
9925
|
+
children: item.name
|
|
9926
|
+
},
|
|
9927
|
+
item.id
|
|
9928
|
+
)) })
|
|
9929
|
+
] }),
|
|
9930
|
+
/* @__PURE__ */ jsxs11("div", { className: "relative mt-2 min-h-0 flex-1 overflow-hidden rounded-2xl bg-ed-subtle", children: [
|
|
9931
|
+
page && device && /* @__PURE__ */ jsx12(TemplatePreviewStage, { page, width: device.width, className: "h-full w-full" }),
|
|
9932
|
+
(loading || error || !page) && /* @__PURE__ */ jsx12("div", { className: "absolute inset-0 flex items-center justify-center bg-ed-subtle px-6 text-center", children: loading ? /* @__PURE__ */ jsxs11("span", { className: "flex items-center gap-2 text-[10px] text-ed-faint", children: [
|
|
9933
|
+
/* @__PURE__ */ jsx12("span", { className: "size-1.5 animate-pulse rounded-full bg-ed-accent" }),
|
|
9934
|
+
"Loading preview\u2026"
|
|
9935
|
+
] }) : /* @__PURE__ */ jsx12("p", { className: "max-w-[280px] text-[10px] leading-relaxed text-ed-muted", children: error || "This template cannot be previewed." }) })
|
|
9936
|
+
] })
|
|
9937
|
+
] });
|
|
9938
|
+
}
|
|
9939
|
+
|
|
9384
9940
|
// src/internal/app/p/editor/templates-panel.tsx
|
|
9385
|
-
import { jsx as
|
|
9941
|
+
import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
9386
9942
|
var INSTALL_STEPS = [
|
|
9387
9943
|
{ id: "fetching", label: "Fetching template", detail: "Loading the latest bundle on the server" },
|
|
9388
9944
|
{ id: "replacing", label: "Replacing pages", detail: "Removing the previous site inside one transaction" },
|
|
@@ -9404,19 +9960,20 @@ function TemplatesPanel({
|
|
|
9404
9960
|
onInstall,
|
|
9405
9961
|
onInstalled
|
|
9406
9962
|
}) {
|
|
9407
|
-
const [templates, setTemplates] =
|
|
9408
|
-
const [status, setStatus] =
|
|
9409
|
-
const [error, setError] =
|
|
9410
|
-
const [query, setQuery] =
|
|
9411
|
-
const [category, setCategory] =
|
|
9412
|
-
const [installing, setInstalling] =
|
|
9413
|
-
const [installStage, setInstallStage] =
|
|
9414
|
-
const [pendingTemplate, setPendingTemplate] =
|
|
9415
|
-
const [installError, setInstallError] =
|
|
9416
|
-
const [selectedFont, setSelectedFont] =
|
|
9417
|
-
const [portalContainer, setPortalContainer] =
|
|
9963
|
+
const [templates, setTemplates] = useState13(FALLBACK_TEMPLATE_REGISTRY.templates);
|
|
9964
|
+
const [status, setStatus] = useState13("loading");
|
|
9965
|
+
const [error, setError] = useState13("");
|
|
9966
|
+
const [query, setQuery] = useState13("");
|
|
9967
|
+
const [category, setCategory] = useState13("All");
|
|
9968
|
+
const [installing, setInstalling] = useState13();
|
|
9969
|
+
const [installStage, setInstallStage] = useState13();
|
|
9970
|
+
const [pendingTemplate, setPendingTemplate] = useState13();
|
|
9971
|
+
const [installError, setInstallError] = useState13("");
|
|
9972
|
+
const [selectedFont, setSelectedFont] = useState13("");
|
|
9973
|
+
const [portalContainer, setPortalContainer] = useState13(null);
|
|
9418
9974
|
const providerFonts = usePagieraFonts2();
|
|
9419
|
-
const
|
|
9975
|
+
const preview = useTemplatePreview(pendingTemplate?.id);
|
|
9976
|
+
const fontOptions = useMemo3(() => {
|
|
9420
9977
|
const options = [
|
|
9421
9978
|
...pendingTemplate?.font?.url ? [{ label: `${pendingTemplate.font.title} \xB7 Template`, value: pendingTemplate.font.family }] : [],
|
|
9422
9979
|
...providerFonts.map((font) => ({ label: font.title, value: font.family })),
|
|
@@ -9432,13 +9989,13 @@ function TemplatesPanel({
|
|
|
9432
9989
|
setStatus(result.source);
|
|
9433
9990
|
if (result.error) setError(result.error instanceof Error ? result.error.message : "Could not refresh templates.");
|
|
9434
9991
|
};
|
|
9435
|
-
|
|
9992
|
+
useEffect10(() => {
|
|
9436
9993
|
void refresh();
|
|
9437
9994
|
}, [registryUrl]);
|
|
9438
|
-
|
|
9995
|
+
useEffect10(() => {
|
|
9439
9996
|
setPortalContainer(document.querySelector(".pg-editor"));
|
|
9440
9997
|
}, []);
|
|
9441
|
-
|
|
9998
|
+
useEffect10(() => {
|
|
9442
9999
|
if (!pendingTemplate) return;
|
|
9443
10000
|
const onKeyDown = (event) => {
|
|
9444
10001
|
if (event.key === "Escape" && !installing) setPendingTemplate(void 0);
|
|
@@ -9446,15 +10003,15 @@ function TemplatesPanel({
|
|
|
9446
10003
|
window.addEventListener("keydown", onKeyDown);
|
|
9447
10004
|
return () => window.removeEventListener("keydown", onKeyDown);
|
|
9448
10005
|
}, [installing, pendingTemplate]);
|
|
9449
|
-
|
|
10006
|
+
useEffect10(() => {
|
|
9450
10007
|
if (!pendingTemplate) return;
|
|
9451
10008
|
const preferred = pendingTemplate.font ? providerFonts.find((font) => font.title.toLowerCase() === pendingTemplate.font?.title.toLowerCase() || font.family === pendingTemplate.font?.family) : void 0;
|
|
9452
10009
|
setSelectedFont(
|
|
9453
10010
|
pendingTemplate.font?.url ? pendingTemplate.font.family : preferred?.family ?? providerFonts[0]?.family ?? FONT_STACKS.find((font) => font.label === "Sans")?.value ?? "ui-sans-serif, system-ui, sans-serif"
|
|
9454
10011
|
);
|
|
9455
10012
|
}, [pendingTemplate, providerFonts]);
|
|
9456
|
-
const categories =
|
|
9457
|
-
const visible =
|
|
10013
|
+
const categories = useMemo3(() => ["All", ...new Set(templates.map((template) => template.category))], [templates]);
|
|
10014
|
+
const visible = useMemo3(() => {
|
|
9458
10015
|
const needle = query.trim().toLowerCase();
|
|
9459
10016
|
return templates.filter(
|
|
9460
10017
|
(template) => (category === "All" || template.category === category) && (!needle || [template.name, template.description, template.category, ...template.tags].some((value) => value.toLowerCase().includes(needle)))
|
|
@@ -9490,85 +10047,85 @@ function TemplatesPanel({
|
|
|
9490
10047
|
setInstallStage(void 0);
|
|
9491
10048
|
}
|
|
9492
10049
|
};
|
|
9493
|
-
return /* @__PURE__ */
|
|
9494
|
-
/* @__PURE__ */
|
|
9495
|
-
/* @__PURE__ */
|
|
9496
|
-
/* @__PURE__ */
|
|
9497
|
-
/* @__PURE__ */
|
|
9498
|
-
/* @__PURE__ */
|
|
9499
|
-
/* @__PURE__ */
|
|
9500
|
-
/* @__PURE__ */
|
|
10050
|
+
return /* @__PURE__ */ jsxs12("div", { className: "min-h-full bg-ed-surface", children: [
|
|
10051
|
+
/* @__PURE__ */ jsx13("div", { className: "sticky top-0 z-10 border-b border-ed-border bg-ed-surface/90 backdrop-blur-xl", children: /* @__PURE__ */ jsxs12("div", { className: "mx-auto max-w-[1480px] px-6 py-5 lg:px-10", children: [
|
|
10052
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-start justify-between gap-5", children: [
|
|
10053
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex min-w-0 items-center gap-3.5", children: [
|
|
10054
|
+
/* @__PURE__ */ jsx13("span", { className: "flex size-10 shrink-0 items-center justify-center rounded-2xl bg-ed-accent-soft text-ed-accent", children: /* @__PURE__ */ jsx13(IconTemplate, { size: 18 }) }),
|
|
10055
|
+
/* @__PURE__ */ jsxs12("div", { className: "min-w-0", children: [
|
|
10056
|
+
/* @__PURE__ */ jsx13("h2", { className: "text-[18px] font-semibold tracking-[-.025em] text-ed-text", children: "Template marketplace" }),
|
|
10057
|
+
/* @__PURE__ */ jsx13("p", { className: "mt-1 text-[11px] text-ed-faint", children: "Discover and install complete, responsive Pagiera sites." })
|
|
9501
10058
|
] })
|
|
9502
10059
|
] }),
|
|
9503
|
-
/* @__PURE__ */
|
|
10060
|
+
/* @__PURE__ */ jsx13("button", { type: "button", onClick: () => void refresh(true), disabled: status === "loading", className: "flex size-9 shrink-0 items-center justify-center rounded-full bg-ed-field text-ed-muted transition-colors hover:bg-ed-field-hover hover:text-ed-text disabled:opacity-40", title: "Refresh template catalog", children: /* @__PURE__ */ jsx13(IconRefresh, { size: 14, className: status === "loading" ? "animate-spin" : "" }) })
|
|
9504
10061
|
] }),
|
|
9505
|
-
/* @__PURE__ */
|
|
9506
|
-
/* @__PURE__ */
|
|
9507
|
-
/* @__PURE__ */
|
|
9508
|
-
/* @__PURE__ */
|
|
10062
|
+
/* @__PURE__ */ jsxs12("div", { className: "mt-5 flex max-w-[720px] gap-2.5", children: [
|
|
10063
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex h-10 min-w-0 flex-1 items-center gap-2.5 rounded-full bg-ed-field px-4 transition-colors focus-within:ring-1 focus-within:ring-ed-accent", children: [
|
|
10064
|
+
/* @__PURE__ */ jsx13(IconSearch4, { size: 13, className: "shrink-0 text-ed-faint" }),
|
|
10065
|
+
/* @__PURE__ */ jsx13("input", { value: query, onChange: (event) => setQuery(event.target.value), placeholder: "Search templates, styles and categories\u2026", className: "min-w-0 flex-1 bg-transparent text-[11px] text-ed-text outline-none placeholder:text-ed-faint" })
|
|
9509
10066
|
] }),
|
|
9510
|
-
/* @__PURE__ */
|
|
9511
|
-
/* @__PURE__ */
|
|
9512
|
-
/* @__PURE__ */
|
|
10067
|
+
/* @__PURE__ */ jsxs12(Select, { value: category, onValueChange: setCategory, children: [
|
|
10068
|
+
/* @__PURE__ */ jsx13(SelectTrigger, { "aria-label": "Template category", className: "h-10 min-w-0 w-[150px] rounded-full px-4 text-[10px]", children: /* @__PURE__ */ jsx13(SelectValue, {}) }),
|
|
10069
|
+
/* @__PURE__ */ jsx13(SelectContent, { children: categories.map((item) => /* @__PURE__ */ jsx13(SelectItem, { value: item, children: item }, item)) })
|
|
9513
10070
|
] })
|
|
9514
10071
|
] }),
|
|
9515
|
-
/* @__PURE__ */
|
|
9516
|
-
/* @__PURE__ */
|
|
10072
|
+
/* @__PURE__ */ jsxs12("div", { className: "mt-3 flex max-w-[720px] items-center justify-between px-1 text-[9px] text-ed-faint", children: [
|
|
10073
|
+
/* @__PURE__ */ jsxs12("span", { children: [
|
|
9517
10074
|
visible.length,
|
|
9518
10075
|
" templates available"
|
|
9519
10076
|
] }),
|
|
9520
|
-
/* @__PURE__ */
|
|
9521
|
-
/* @__PURE__ */
|
|
10077
|
+
/* @__PURE__ */ jsxs12("span", { className: "flex items-center gap-1.5", children: [
|
|
10078
|
+
/* @__PURE__ */ jsx13("i", { className: `size-1.5 rounded-full ${status === "local" || status === "network" ? "bg-emerald-400" : status === "loading" ? "animate-pulse bg-ed-accent" : "bg-amber-400"}` }),
|
|
9522
10079
|
status === "local" ? "Local templates" : status === "network" ? registryUrl.includes("/api/pagiera/templates/") ? "Package catalog" : registryUrl.includes("raw.githubusercontent.com") ? "GitHub catalog" : "Custom catalog" : status === "cache" ? "Cached catalog" : status === "loading" ? "Refreshing" : "Offline catalog"
|
|
9523
10080
|
] })
|
|
9524
10081
|
] })
|
|
9525
10082
|
] }) }),
|
|
9526
|
-
/* @__PURE__ */
|
|
9527
|
-
error && /* @__PURE__ */
|
|
9528
|
-
/* @__PURE__ */
|
|
9529
|
-
/* @__PURE__ */
|
|
9530
|
-
/* @__PURE__ */
|
|
9531
|
-
/* @__PURE__ */
|
|
9532
|
-
/* @__PURE__ */
|
|
9533
|
-
template.thumbnail && /* @__PURE__ */
|
|
10083
|
+
/* @__PURE__ */ jsxs12("div", { className: "mx-auto max-w-[1480px] px-6 py-7 lg:px-10", children: [
|
|
10084
|
+
error && /* @__PURE__ */ jsx13("div", { className: "mb-5 rounded-2xl bg-amber-400/8 px-4 py-3 text-[10px] leading-relaxed text-amber-200", children: error }),
|
|
10085
|
+
/* @__PURE__ */ jsx13("div", { className: "grid grid-cols-1 gap-5 md:grid-cols-2 2xl:grid-cols-3", children: visible.map((template, index) => /* @__PURE__ */ jsxs12(motion6.article, { initial: { opacity: 0, y: 10 }, animate: { opacity: 1, y: 0 }, transition: { delay: Math.min(index * 0.035, 0.16), duration: 0.28 }, className: "group overflow-hidden rounded-3xl bg-ed-subtle p-2 transition-colors hover:bg-ed-field", children: [
|
|
10086
|
+
/* @__PURE__ */ jsxs12("div", { className: "relative aspect-[16/10] overflow-hidden rounded-[20px]", style: { background: template.preview.background, color: template.preview.foreground }, children: [
|
|
10087
|
+
/* @__PURE__ */ jsx13("div", { className: "absolute inset-0 opacity-75", style: { background: `radial-gradient(circle at 90% 0%, ${template.preview.accent}66, transparent 55%)` } }),
|
|
10088
|
+
/* @__PURE__ */ jsx13("span", { className: "relative block px-6 pt-6 font-mono text-[8px] font-bold tracking-[.14em]", style: { color: template.preview.accent }, children: template.preview.eyebrow }),
|
|
10089
|
+
/* @__PURE__ */ jsx13("p", { className: "relative mt-12 max-w-[88%] px-6 text-[28px] font-semibold leading-[.92] tracking-[-.05em]", children: template.preview.headline }),
|
|
10090
|
+
template.thumbnail && /* @__PURE__ */ jsx13("img", { src: templateThumbnailUrl(template, registryUrl), alt: `${template.name} template preview`, className: "absolute inset-0 h-full w-full object-cover transition-transform duration-500 group-hover:scale-[1.025]", onError: (event) => {
|
|
9534
10091
|
event.currentTarget.hidden = true;
|
|
9535
10092
|
} }),
|
|
9536
|
-
template.featured && /* @__PURE__ */
|
|
10093
|
+
template.featured && /* @__PURE__ */ jsx13("span", { className: "absolute right-3 top-3 rounded-full bg-black/60 px-2.5 py-1 text-[8px] font-semibold text-white backdrop-blur", children: "Featured" })
|
|
9537
10094
|
] }),
|
|
9538
|
-
/* @__PURE__ */
|
|
9539
|
-
/* @__PURE__ */
|
|
9540
|
-
/* @__PURE__ */
|
|
9541
|
-
/* @__PURE__ */
|
|
9542
|
-
/* @__PURE__ */
|
|
10095
|
+
/* @__PURE__ */ jsxs12("div", { className: "p-3 pb-2", children: [
|
|
10096
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-start gap-3", children: [
|
|
10097
|
+
/* @__PURE__ */ jsxs12("div", { className: "min-w-0 flex-1", children: [
|
|
10098
|
+
/* @__PURE__ */ jsx13("h3", { className: "truncate text-[13px] font-semibold tracking-[-.015em] text-ed-text", children: template.name }),
|
|
10099
|
+
/* @__PURE__ */ jsx13("p", { className: "mt-1 line-clamp-2 min-h-8 text-[10px] leading-[1.55] text-ed-muted", children: template.description })
|
|
9543
10100
|
] }),
|
|
9544
|
-
/* @__PURE__ */
|
|
10101
|
+
/* @__PURE__ */ jsx13("button", { type: "button", disabled: busy || Boolean(installing), onClick: () => {
|
|
9545
10102
|
setError("");
|
|
9546
10103
|
setInstallError("");
|
|
9547
10104
|
setPendingTemplate(template);
|
|
9548
|
-
}, className: "flex size-9 shrink-0 select-none items-center justify-center rounded-full bg-ed-surface text-ed-text transition-colors hover:bg-ed-accent hover:text-white disabled:cursor-wait disabled:opacity-45", "aria-label": `Review and install ${template.name}`, children: /* @__PURE__ */
|
|
10105
|
+
}, className: "flex size-9 shrink-0 select-none items-center justify-center rounded-full bg-ed-surface text-ed-text transition-colors hover:bg-ed-accent hover:text-white disabled:cursor-wait disabled:opacity-45", "aria-label": `Review and install ${template.name}`, children: /* @__PURE__ */ jsx13(IconArrowUpRight, { size: 14 }) })
|
|
9549
10106
|
] }),
|
|
9550
|
-
/* @__PURE__ */
|
|
9551
|
-
/* @__PURE__ */
|
|
9552
|
-
/* @__PURE__ */
|
|
9553
|
-
/* @__PURE__ */
|
|
10107
|
+
/* @__PURE__ */ jsxs12("div", { className: "mt-3 flex items-center gap-2 text-[9px] text-ed-faint", children: [
|
|
10108
|
+
/* @__PURE__ */ jsx13("span", { children: template.category }),
|
|
10109
|
+
/* @__PURE__ */ jsx13("i", { className: "size-0.5 rounded-full bg-ed-faint" }),
|
|
10110
|
+
/* @__PURE__ */ jsxs12("span", { children: [
|
|
9554
10111
|
template.pages.length,
|
|
9555
10112
|
" pages"
|
|
9556
10113
|
] }),
|
|
9557
|
-
/* @__PURE__ */
|
|
9558
|
-
/* @__PURE__ */
|
|
10114
|
+
/* @__PURE__ */ jsx13("i", { className: "size-0.5 rounded-full bg-ed-faint" }),
|
|
10115
|
+
/* @__PURE__ */ jsxs12("span", { children: [
|
|
9559
10116
|
"v",
|
|
9560
10117
|
template.version
|
|
9561
10118
|
] })
|
|
9562
10119
|
] })
|
|
9563
10120
|
] })
|
|
9564
10121
|
] }, template.id)) }),
|
|
9565
|
-
visible.length === 0 && /* @__PURE__ */
|
|
9566
|
-
/* @__PURE__ */
|
|
9567
|
-
/* @__PURE__ */
|
|
10122
|
+
visible.length === 0 && /* @__PURE__ */ jsxs12("div", { className: "rounded-3xl bg-ed-subtle px-5 py-20 text-center", children: [
|
|
10123
|
+
/* @__PURE__ */ jsx13(IconTemplate, { size: 22, className: "mx-auto text-ed-faint" }),
|
|
10124
|
+
/* @__PURE__ */ jsx13("p", { className: "mt-3 text-[11px] font-medium text-ed-muted", children: "No templates match this search." })
|
|
9568
10125
|
] })
|
|
9569
10126
|
] }),
|
|
9570
|
-
portalContainer &&
|
|
9571
|
-
/* @__PURE__ */
|
|
10127
|
+
portalContainer && createPortal4(
|
|
10128
|
+
/* @__PURE__ */ jsx13(AnimatePresence6, { children: pendingTemplate && /* @__PURE__ */ jsx13(
|
|
9572
10129
|
motion6.div,
|
|
9573
10130
|
{
|
|
9574
10131
|
className: "fixed inset-0 z-[1000] flex items-center justify-center bg-black/60 p-4 backdrop-blur-sm",
|
|
@@ -9578,7 +10135,7 @@ function TemplatesPanel({
|
|
|
9578
10135
|
onMouseDown: (event) => {
|
|
9579
10136
|
if (event.target === event.currentTarget && !installing) setPendingTemplate(void 0);
|
|
9580
10137
|
},
|
|
9581
|
-
children: /* @__PURE__ */
|
|
10138
|
+
children: /* @__PURE__ */ jsxs12(
|
|
9582
10139
|
motion6.div,
|
|
9583
10140
|
{
|
|
9584
10141
|
role: "dialog",
|
|
@@ -9588,17 +10145,17 @@ function TemplatesPanel({
|
|
|
9588
10145
|
animate: { opacity: 1, y: 0, scale: 1 },
|
|
9589
10146
|
exit: { opacity: 0, y: 6, scale: 0.98 },
|
|
9590
10147
|
transition: { duration: 0.18, ease: [0.16, 1, 0.3, 1] },
|
|
9591
|
-
className: "w-full max-w-[
|
|
10148
|
+
className: "flex max-h-[min(880px,94vh)] w-full max-w-[1180px] flex-col rounded-3xl bg-ed-surface p-2 text-ed-text shadow-2xl",
|
|
9592
10149
|
children: [
|
|
9593
|
-
/* @__PURE__ */
|
|
9594
|
-
/* @__PURE__ */
|
|
9595
|
-
/* @__PURE__ */
|
|
9596
|
-
/* @__PURE__ */
|
|
10150
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex shrink-0 items-center gap-3 px-4 py-3.5", children: [
|
|
10151
|
+
/* @__PURE__ */ jsx13("span", { className: "flex size-10 shrink-0 items-center justify-center rounded-xl bg-ed-field text-ed-accent", children: /* @__PURE__ */ jsx13(IconTemplate, { size: 17 }) }),
|
|
10152
|
+
/* @__PURE__ */ jsxs12("div", { className: "min-w-0 flex-1", children: [
|
|
10153
|
+
/* @__PURE__ */ jsxs12("h3", { id: "template-install-title", className: "truncate text-[14px] font-semibold", children: [
|
|
9597
10154
|
installing ? "Installing" : "Install",
|
|
9598
10155
|
" ",
|
|
9599
10156
|
pendingTemplate.name
|
|
9600
10157
|
] }),
|
|
9601
|
-
/* @__PURE__ */
|
|
10158
|
+
/* @__PURE__ */ jsxs12("p", { className: "mt-1 text-[10px] text-ed-faint", children: [
|
|
9602
10159
|
pendingTemplate.pages.length,
|
|
9603
10160
|
" editable pages \xB7 v",
|
|
9604
10161
|
pendingTemplate.version,
|
|
@@ -9606,63 +10163,67 @@ function TemplatesPanel({
|
|
|
9606
10163
|
pendingTemplate.id
|
|
9607
10164
|
] })
|
|
9608
10165
|
] }),
|
|
9609
|
-
/* @__PURE__ */
|
|
10166
|
+
/* @__PURE__ */ jsx13("button", { type: "button", "aria-label": "Close template confirmation", disabled: Boolean(installing), onClick: () => setPendingTemplate(void 0), className: "flex size-8 select-none items-center justify-center rounded-xl text-ed-muted transition-colors hover:bg-ed-field-hover hover:text-ed-text disabled:opacity-40", children: /* @__PURE__ */ jsx13(IconX5, { size: 15 }) })
|
|
9610
10167
|
] }),
|
|
9611
|
-
/* @__PURE__ */
|
|
9612
|
-
/* @__PURE__ */
|
|
9613
|
-
|
|
9614
|
-
|
|
9615
|
-
|
|
9616
|
-
|
|
9617
|
-
|
|
9618
|
-
|
|
9619
|
-
|
|
9620
|
-
|
|
9621
|
-
|
|
9622
|
-
|
|
9623
|
-
|
|
9624
|
-
|
|
9625
|
-
|
|
9626
|
-
|
|
9627
|
-
|
|
9628
|
-
/* @__PURE__ */
|
|
10168
|
+
/* @__PURE__ */ jsxs12("div", { className: "grid min-h-0 flex-1 gap-2 px-1 pb-1 lg:grid-cols-[minmax(0,1fr)_380px]", children: [
|
|
10169
|
+
/* @__PURE__ */ jsx13(
|
|
10170
|
+
TemplatePreview,
|
|
10171
|
+
{
|
|
10172
|
+
pages: preview.pages,
|
|
10173
|
+
loading: preview.loading,
|
|
10174
|
+
error: preview.error,
|
|
10175
|
+
className: "min-h-[320px] lg:min-h-0",
|
|
10176
|
+
controlsClassName: "px-1"
|
|
10177
|
+
}
|
|
10178
|
+
),
|
|
10179
|
+
/* @__PURE__ */ jsx13("div", { className: "min-h-0 overflow-y-auto p-3 scrollbar-none lg:pl-2", children: /* @__PURE__ */ jsx13(AnimatePresence6, { mode: "wait", initial: false, children: installing && installStage ? /* @__PURE__ */ jsxs12(motion6.div, { initial: { opacity: 0, y: 6 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: -4 }, "aria-live": "polite", children: [
|
|
10180
|
+
/* @__PURE__ */ jsx13("div", { className: "overflow-hidden rounded-2xl bg-ed-subtle p-2", children: INSTALL_STEPS.map((step, index) => {
|
|
10181
|
+
const activeIndex = INSTALL_STEPS.findIndex((item) => item.id === installStage);
|
|
10182
|
+
const complete = index < activeIndex;
|
|
10183
|
+
const active = index === activeIndex;
|
|
10184
|
+
return /* @__PURE__ */ jsxs12("div", { className: `flex items-center gap-3 rounded-xl px-3 py-3 transition-colors ${active ? "bg-ed-field-hover" : ""}`, children: [
|
|
10185
|
+
/* @__PURE__ */ jsx13("span", { className: `flex size-7 shrink-0 items-center justify-center rounded-full ${complete ? "bg-ed-accent text-white" : active ? "bg-ed-accent-soft text-ed-accent" : "bg-ed-field text-ed-faint"}`, children: complete ? /* @__PURE__ */ jsx13(IconCheck5, { size: 13 }) : active ? /* @__PURE__ */ jsx13("span", { className: "size-2 animate-pulse rounded-full bg-current" }) : /* @__PURE__ */ jsx13("span", { className: "text-[9px] font-semibold", children: index + 1 }) }),
|
|
10186
|
+
/* @__PURE__ */ jsxs12("span", { className: "min-w-0 flex-1", children: [
|
|
10187
|
+
/* @__PURE__ */ jsx13("span", { className: `block text-[10px] font-semibold ${active || complete ? "text-ed-text" : "text-ed-faint"}`, children: step.label }),
|
|
10188
|
+
/* @__PURE__ */ jsx13("span", { className: "mt-0.5 block truncate text-[9px] text-ed-faint", children: step.detail })
|
|
10189
|
+
] }),
|
|
10190
|
+
active && /* @__PURE__ */ jsx13("span", { className: "text-[9px] font-medium text-ed-accent", children: "Working\u2026" })
|
|
10191
|
+
] }, step.id);
|
|
10192
|
+
}) }),
|
|
10193
|
+
/* @__PURE__ */ jsx13("div", { className: "mt-3 h-1 overflow-hidden rounded-full bg-ed-field", children: /* @__PURE__ */ jsx13(motion6.div, { className: "h-full rounded-full bg-ed-accent", animate: { width: `${(INSTALL_STEPS.findIndex((item) => item.id === installStage) + 1) / INSTALL_STEPS.length * 100}%` }, transition: { type: "spring", stiffness: 220, damping: 28 } }) }),
|
|
10194
|
+
/* @__PURE__ */ jsx13("p", { className: "mt-3 text-center text-[9px] text-ed-faint", children: "Keep this window open while the project is replaced." })
|
|
10195
|
+
] }, "progress") : /* @__PURE__ */ jsxs12(motion6.div, { initial: { opacity: 0, y: 4 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: -4 }, children: [
|
|
10196
|
+
/* @__PURE__ */ jsxs12("div", { className: "mb-3 flex items-center gap-3 rounded-2xl bg-ed-subtle px-3.5 py-3", children: [
|
|
10197
|
+
/* @__PURE__ */ jsxs12("div", { className: "min-w-0 flex-1", children: [
|
|
10198
|
+
/* @__PURE__ */ jsx13("p", { className: "text-[10px] font-semibold text-ed-text", children: "Site font" }),
|
|
10199
|
+
/* @__PURE__ */ jsx13("p", { className: "mt-0.5 text-[9px] leading-relaxed text-ed-faint", children: pendingTemplate.font?.url ? `${pendingTemplate.font.title} is bundled with the template and downloads automatically.` : pendingTemplate.font && !providerFonts.some((font) => font.title.toLowerCase() === pendingTemplate.font?.title.toLowerCase() || font.family === pendingTemplate.font?.family) ? `${pendingTemplate.font.title} is not configured. Choose an available fallback.` : "Applied to every page installed by this template." })
|
|
9629
10200
|
] }),
|
|
9630
|
-
|
|
9631
|
-
|
|
9632
|
-
|
|
9633
|
-
|
|
9634
|
-
/* @__PURE__ */ jsx11("p", { className: "mt-3 text-center text-[9px] text-ed-faint", children: "Keep this window open while the project is replaced." })
|
|
9635
|
-
] }, "progress") : /* @__PURE__ */ jsxs10(motion6.div, { initial: { opacity: 0, y: 4 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: -4 }, children: [
|
|
9636
|
-
/* @__PURE__ */ jsxs10("div", { className: "mb-3 flex items-center gap-3 rounded-2xl bg-ed-subtle px-3.5 py-3", children: [
|
|
9637
|
-
/* @__PURE__ */ jsxs10("div", { className: "min-w-0 flex-1", children: [
|
|
9638
|
-
/* @__PURE__ */ jsx11("p", { className: "text-[10px] font-semibold text-ed-text", children: "Site font" }),
|
|
9639
|
-
/* @__PURE__ */ jsx11("p", { className: "mt-0.5 text-[9px] leading-relaxed text-ed-faint", children: pendingTemplate.font?.url ? `${pendingTemplate.font.title} is bundled with the template and downloads automatically.` : pendingTemplate.font && !providerFonts.some((font) => font.title.toLowerCase() === pendingTemplate.font?.title.toLowerCase() || font.family === pendingTemplate.font?.family) ? `${pendingTemplate.font.title} is not configured. Choose an available fallback.` : "Applied to every page installed by this template." })
|
|
10201
|
+
/* @__PURE__ */ jsxs12(Select, { value: selectedFont, onValueChange: setSelectedFont, children: [
|
|
10202
|
+
/* @__PURE__ */ jsx13(SelectTrigger, { "aria-label": "Template site font", className: "h-8 w-[170px] shrink-0 rounded-full px-3 text-[10px]", children: /* @__PURE__ */ jsx13(SelectValue, { placeholder: "Choose font" }) }),
|
|
10203
|
+
/* @__PURE__ */ jsx13(SelectContent, { children: fontOptions.map((font) => /* @__PURE__ */ jsx13(SelectItem, { value: font.value, children: font.label }, font.value)) })
|
|
10204
|
+
] })
|
|
9640
10205
|
] }),
|
|
9641
|
-
/* @__PURE__ */
|
|
9642
|
-
/* @__PURE__ */
|
|
9643
|
-
/* @__PURE__ */
|
|
9644
|
-
|
|
9645
|
-
|
|
9646
|
-
|
|
9647
|
-
|
|
9648
|
-
/* @__PURE__ */
|
|
9649
|
-
/* @__PURE__ */
|
|
9650
|
-
|
|
9651
|
-
] })
|
|
9652
|
-
|
|
9653
|
-
|
|
9654
|
-
|
|
9655
|
-
|
|
9656
|
-
|
|
9657
|
-
|
|
9658
|
-
|
|
9659
|
-
/* @__PURE__ */ jsx11("button", { type: "button", onClick: () => setPendingTemplate(void 0), className: "h-9 select-none rounded-xl px-4 text-[10px] font-medium text-ed-muted transition-colors hover:bg-ed-field-hover hover:text-ed-text", children: "Cancel" }),
|
|
9660
|
-
/* @__PURE__ */ jsxs10("button", { type: "button", onClick: () => void install(pendingTemplate), className: "flex h-9 min-w-[132px] select-none items-center justify-center gap-2 rounded-xl bg-ed-accent px-4 text-[10px] font-semibold text-white transition hover:brightness-110", children: [
|
|
9661
|
-
/* @__PURE__ */ jsx11(IconSparkles4, { size: 13 }),
|
|
9662
|
-
" Install template"
|
|
10206
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-start gap-3 rounded-xl bg-amber-400/[.07] px-3.5 py-3", children: [
|
|
10207
|
+
/* @__PURE__ */ jsx13(IconAlertTriangle2, { size: 14, className: "mt-0.5 shrink-0 text-amber-300" }),
|
|
10208
|
+
/* @__PURE__ */ jsxs12("p", { className: "text-[10px] leading-relaxed text-ed-muted", children: [
|
|
10209
|
+
/* @__PURE__ */ jsx13("strong", { className: "font-semibold text-ed-text", children: "This replaces the current site." }),
|
|
10210
|
+
" Existing pages and revision history will be removed after installation succeeds."
|
|
10211
|
+
] })
|
|
10212
|
+
] }),
|
|
10213
|
+
/* @__PURE__ */ jsx13("div", { className: "mt-3 grid grid-cols-2 gap-1 rounded-xl bg-ed-subtle p-2", children: pendingTemplate.pages.slice(0, 6).map((page) => /* @__PURE__ */ jsxs12("span", { className: "flex h-8 min-w-0 items-center gap-2 rounded-lg px-2.5 text-[10px] text-ed-text", children: [
|
|
10214
|
+
/* @__PURE__ */ jsx13(IconCheck5, { size: 12, className: "shrink-0 text-ed-accent" }),
|
|
10215
|
+
/* @__PURE__ */ jsx13("span", { className: "truncate", children: page })
|
|
10216
|
+
] }, page)) }),
|
|
10217
|
+
installError && /* @__PURE__ */ jsx13("div", { className: "mt-2 rounded-xl bg-red-400/8 px-3 py-2.5 text-[9px] leading-relaxed text-red-200", children: installError }),
|
|
10218
|
+
/* @__PURE__ */ jsxs12("div", { className: "mt-4 flex justify-end gap-2 pt-1", children: [
|
|
10219
|
+
/* @__PURE__ */ jsx13("button", { type: "button", onClick: () => setPendingTemplate(void 0), className: "h-9 select-none rounded-xl px-4 text-[10px] font-medium text-ed-muted transition-colors hover:bg-ed-field-hover hover:text-ed-text", children: "Cancel" }),
|
|
10220
|
+
/* @__PURE__ */ jsxs12("button", { type: "button", onClick: () => void install(pendingTemplate), className: "flex h-9 min-w-[132px] select-none items-center justify-center gap-2 rounded-xl bg-ed-accent px-4 text-[10px] font-semibold text-white transition hover:brightness-110", children: [
|
|
10221
|
+
/* @__PURE__ */ jsx13(IconSparkles4, { size: 13 }),
|
|
10222
|
+
" Install template"
|
|
10223
|
+
] })
|
|
9663
10224
|
] })
|
|
9664
|
-
] })
|
|
9665
|
-
] }
|
|
10225
|
+
] }, "confirm") }) })
|
|
10226
|
+
] })
|
|
9666
10227
|
]
|
|
9667
10228
|
}
|
|
9668
10229
|
)
|
|
@@ -9674,7 +10235,7 @@ function TemplatesPanel({
|
|
|
9674
10235
|
}
|
|
9675
10236
|
|
|
9676
10237
|
// src/internal/app/p/editor/editor.tsx
|
|
9677
|
-
import { Fragment as
|
|
10238
|
+
import { Fragment as Fragment5, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
9678
10239
|
var MIN_SIZE = 10;
|
|
9679
10240
|
var COMPONENT_MIME = "application/pagiera-component";
|
|
9680
10241
|
var EDITOR_TABS_STORAGE_KEY = "pagiera:editor-tabs";
|
|
@@ -9698,22 +10259,22 @@ function ComponentAssetCards({
|
|
|
9698
10259
|
activeMasterId,
|
|
9699
10260
|
onOpen
|
|
9700
10261
|
}) {
|
|
9701
|
-
if (assets.length === 0) return /* @__PURE__ */
|
|
9702
|
-
return /* @__PURE__ */
|
|
9703
|
-
/* @__PURE__ */
|
|
9704
|
-
/* @__PURE__ */
|
|
9705
|
-
/* @__PURE__ */
|
|
9706
|
-
/* @__PURE__ */
|
|
9707
|
-
/* @__PURE__ */
|
|
10262
|
+
if (assets.length === 0) return /* @__PURE__ */ jsx14("p", { className: "rounded-2xl border border-dashed border-ed-border p-5 text-center text-[10px] text-ed-faint", children: "Create a shared asset or add one from code." });
|
|
10263
|
+
return /* @__PURE__ */ jsx14("div", { className: "space-y-3", children: assets.map((asset) => /* @__PURE__ */ jsxs13("section", { className: "overflow-hidden rounded-2xl border border-ed-border bg-ed-subtle", children: [
|
|
10264
|
+
/* @__PURE__ */ jsxs13("button", { type: "button", onClick: () => onOpen(asset.variants[0]), className: "flex w-full items-center gap-3 px-3 py-3 text-left hover:bg-ed-field", children: [
|
|
10265
|
+
/* @__PURE__ */ jsx14("span", { className: "flex size-9 items-center justify-center rounded-xl bg-ed-field text-ed-accent", children: /* @__PURE__ */ jsx14(IconComponents2, { size: 16 }) }),
|
|
10266
|
+
/* @__PURE__ */ jsxs13("span", { className: "min-w-0 flex-1", children: [
|
|
10267
|
+
/* @__PURE__ */ jsx14("span", { className: "block truncate text-[11px] font-semibold text-ed-text", children: asset.name }),
|
|
10268
|
+
/* @__PURE__ */ jsxs13("span", { className: "block text-[9px] text-ed-faint", children: [
|
|
9708
10269
|
asset.variants.length,
|
|
9709
10270
|
" variant",
|
|
9710
10271
|
asset.variants.length === 1 ? "" : "s",
|
|
9711
10272
|
" \xB7 shared across pages"
|
|
9712
10273
|
] })
|
|
9713
10274
|
] }),
|
|
9714
|
-
/* @__PURE__ */
|
|
10275
|
+
/* @__PURE__ */ jsx14(IconChevronRight6, { size: 14, className: "text-ed-faint" })
|
|
9715
10276
|
] }),
|
|
9716
|
-
/* @__PURE__ */
|
|
10277
|
+
/* @__PURE__ */ jsx14("div", { className: "grid grid-cols-2 gap-1.5 border-t border-ed-border p-2", children: asset.variants.map((variant) => /* @__PURE__ */ jsxs13(
|
|
9717
10278
|
"button",
|
|
9718
10279
|
{
|
|
9719
10280
|
type: "button",
|
|
@@ -9725,12 +10286,12 @@ function ComponentAssetCards({
|
|
|
9725
10286
|
onClick: () => onOpen(variant),
|
|
9726
10287
|
className: `group min-w-0 cursor-grab rounded-xl border p-1.5 text-left active:cursor-grabbing ${activeMasterId === variant.id ? "border-ed-accent bg-[var(--ed-accent-soft)]" : "border-transparent bg-ed-field hover:border-ed-border"}`,
|
|
9727
10288
|
children: [
|
|
9728
|
-
/* @__PURE__ */
|
|
10289
|
+
/* @__PURE__ */ jsx14("span", { className: "mb-1.5 flex h-12 items-center justify-center overflow-hidden rounded-lg border border-ed-border", style: { background: variant.base.gradient || variant.base.bg || "var(--ed-surface)" }, children: /* @__PURE__ */ jsxs13("span", { className: "rounded-full bg-black/35 px-2 py-1 font-mono text-[8px] text-white/80", children: [
|
|
9729
10290
|
Math.round(variant.base.w),
|
|
9730
10291
|
"\xD7",
|
|
9731
10292
|
Math.round(variant.base.h)
|
|
9732
10293
|
] }) }),
|
|
9733
|
-
/* @__PURE__ */
|
|
10294
|
+
/* @__PURE__ */ jsx14("span", { className: "block truncate px-1 text-[9px] font-semibold text-ed-text", children: variant.variant ?? "Default" })
|
|
9734
10295
|
]
|
|
9735
10296
|
},
|
|
9736
10297
|
variant.id
|
|
@@ -9803,8 +10364,8 @@ function Editor({
|
|
|
9803
10364
|
[adapters?.save]
|
|
9804
10365
|
)
|
|
9805
10366
|
});
|
|
9806
|
-
const [chromeTheme, setChromeTheme] =
|
|
9807
|
-
|
|
10367
|
+
const [chromeTheme, setChromeTheme] = useState14("dark");
|
|
10368
|
+
useEffect11(() => {
|
|
9808
10369
|
const stored = localStorage.getItem("pagiera:editor-theme");
|
|
9809
10370
|
if (stored === "dark" || stored === "light") setChromeTheme(stored);
|
|
9810
10371
|
}, []);
|
|
@@ -9818,11 +10379,11 @@ function Editor({
|
|
|
9818
10379
|
return next;
|
|
9819
10380
|
});
|
|
9820
10381
|
}, []);
|
|
9821
|
-
const [breakpoint, setBreakpoint] =
|
|
9822
|
-
const [breakpointPanel, setBreakpointPanel] =
|
|
10382
|
+
const [breakpoint, setBreakpoint] = useState14("desktop");
|
|
10383
|
+
const [breakpointPanel, setBreakpointPanel] = useState14(false);
|
|
9823
10384
|
const componentMode = rootStyle.documentMode === "component";
|
|
9824
10385
|
const componentMasters = elements.filter((element) => element.componentRole === "master");
|
|
9825
|
-
const componentAssets =
|
|
10386
|
+
const componentAssets = useMemo4(() => {
|
|
9826
10387
|
const grouped = /* @__PURE__ */ new Map();
|
|
9827
10388
|
for (const master of componentMasters) {
|
|
9828
10389
|
const id = master.componentId ?? master.id;
|
|
@@ -9832,17 +10393,17 @@ function Editor({
|
|
|
9832
10393
|
}
|
|
9833
10394
|
return [...grouped.values()];
|
|
9834
10395
|
}, [elements]);
|
|
9835
|
-
const [activeComponentMasterId, setActiveComponentMasterId] =
|
|
10396
|
+
const [activeComponentMasterId, setActiveComponentMasterId] = useState14(null);
|
|
9836
10397
|
const activeComponentMaster = componentMasters.find((element) => element.id === activeComponentMasterId) ?? componentMasters[0];
|
|
9837
10398
|
const activeComponentVariants = activeComponentMaster ? componentMasters.filter((element) => element.componentId === activeComponentMaster.componentId) : [];
|
|
9838
10399
|
const breakpointDefs = rootStyle.breakpoints?.length ? rootStyle.breakpoints : DEFAULT_BREAKPOINTS;
|
|
9839
|
-
const cascade =
|
|
10400
|
+
const cascade = useMemo4(
|
|
9840
10401
|
() => cascadeOf(rootStyle.breakpoints, rootStyle.baseBreakpointId),
|
|
9841
10402
|
[rootStyle.breakpoints, rootStyle.baseBreakpointId]
|
|
9842
10403
|
);
|
|
9843
10404
|
const selectedBreakpoint = breakpointDefs.find((item) => item.id === breakpoint) ?? breakpointDefs[0];
|
|
9844
10405
|
const frameWidthForBreakpoint = selectedBreakpoint.width;
|
|
9845
|
-
const frames =
|
|
10406
|
+
const frames = useMemo4(
|
|
9846
10407
|
() => componentMode ? activeComponentVariants.map((variant) => ({ bp: "desktop", width: Math.max(1, variant.base.w), masterId: variant.id })) : breakpointDefs.map((item) => ({ bp: item.id, width: item.width })),
|
|
9847
10408
|
[activeComponentVariants, breakpointDefs, componentMode]
|
|
9848
10409
|
);
|
|
@@ -9861,12 +10422,12 @@ function Editor({
|
|
|
9861
10422
|
recenter
|
|
9862
10423
|
} = useCanvasView(fitWidth);
|
|
9863
10424
|
const serverLeftTab = tabForDocumentMode(leftTabFromValue(initialPanel ?? null) ?? "Layers", componentMode);
|
|
9864
|
-
const [leftTab, setLeftTab] =
|
|
9865
|
-
const [rightTab, setRightTab] =
|
|
9866
|
-
const [tabsRestored, setTabsRestored] =
|
|
9867
|
-
const [isLeftCollapsed, setIsLeftCollapsed] =
|
|
9868
|
-
const [isRightCollapsed, setIsRightCollapsed] =
|
|
9869
|
-
const [search, setSearch] =
|
|
10425
|
+
const [leftTab, setLeftTab] = useState14(serverLeftTab);
|
|
10426
|
+
const [rightTab, setRightTab] = useState14("Design");
|
|
10427
|
+
const [tabsRestored, setTabsRestored] = useState14(false);
|
|
10428
|
+
const [isLeftCollapsed, setIsLeftCollapsed] = useState14(serverLeftTab === "Templates");
|
|
10429
|
+
const [isRightCollapsed, setIsRightCollapsed] = useState14(true);
|
|
10430
|
+
const [search, setSearch] = useState14("");
|
|
9870
10431
|
useLayoutEffect2(() => {
|
|
9871
10432
|
try {
|
|
9872
10433
|
const routed = leftTabFromValue(initialPanel ?? null) ?? leftTabFromPath(window.location.pathname);
|
|
@@ -9885,10 +10446,10 @@ function Editor({
|
|
|
9885
10446
|
setTabsRestored(true);
|
|
9886
10447
|
}
|
|
9887
10448
|
}, [initialPanel]);
|
|
9888
|
-
|
|
10449
|
+
useEffect11(() => {
|
|
9889
10450
|
setLeftTab((current) => tabForDocumentMode(current, componentMode));
|
|
9890
10451
|
}, [componentMode]);
|
|
9891
|
-
|
|
10452
|
+
useEffect11(() => {
|
|
9892
10453
|
if (!tabsRestored) return;
|
|
9893
10454
|
try {
|
|
9894
10455
|
localStorage.setItem(EDITOR_TABS_STORAGE_KEY, JSON.stringify({ left: leftTab, right: rightTab }));
|
|
@@ -9904,7 +10465,7 @@ function Editor({
|
|
|
9904
10465
|
} catch {
|
|
9905
10466
|
}
|
|
9906
10467
|
}, [adapters?.editorHref, leftTab, page.id, rightTab, tabsRestored]);
|
|
9907
|
-
|
|
10468
|
+
useEffect11(() => {
|
|
9908
10469
|
const restoreTabFromHistory = () => {
|
|
9909
10470
|
const routed = leftTabFromPath(window.location.pathname);
|
|
9910
10471
|
const queried = leftTabFromValue(new URLSearchParams(window.location.search).get("tab"));
|
|
@@ -9918,23 +10479,23 @@ function Editor({
|
|
|
9918
10479
|
window.addEventListener("popstate", restoreTabFromHistory);
|
|
9919
10480
|
return () => window.removeEventListener("popstate", restoreTabFromHistory);
|
|
9920
10481
|
}, [componentMode]);
|
|
9921
|
-
const [selectedIds, setSelectedIds] =
|
|
10482
|
+
const [selectedIds, setSelectedIds] = useState14([]);
|
|
9922
10483
|
const hasElementSelection = selectedIds.length > 0;
|
|
9923
|
-
const [editingId, setEditingId] =
|
|
9924
|
-
const [hoveredEffectIds, setHoveredEffectIds] =
|
|
9925
|
-
const [pressedEffectId, setPressedEffectId] =
|
|
9926
|
-
const [effectsPreview, setEffectsPreview] =
|
|
9927
|
-
const [previewVisibility, setPreviewVisibility] =
|
|
9928
|
-
const [marquee, setMarquee] =
|
|
9929
|
-
const [codeComposerOpen, setCodeComposerOpen] =
|
|
9930
|
-
const [codeComponentName, setCodeComponentName] =
|
|
9931
|
-
const [codeComponentSource, setCodeComponentSource] =
|
|
9932
|
-
const [draggedBreakpointId, setDraggedBreakpointId] =
|
|
9933
|
-
const [editingBreakpointId, setEditingBreakpointId] =
|
|
9934
|
-
const marqueePageRef =
|
|
9935
|
-
const marqueeBaseRef =
|
|
9936
|
-
const [contextMenu, setContextMenu] =
|
|
9937
|
-
|
|
10484
|
+
const [editingId, setEditingId] = useState14(null);
|
|
10485
|
+
const [hoveredEffectIds, setHoveredEffectIds] = useState14(() => /* @__PURE__ */ new Set());
|
|
10486
|
+
const [pressedEffectId, setPressedEffectId] = useState14(null);
|
|
10487
|
+
const [effectsPreview, setEffectsPreview] = useState14(false);
|
|
10488
|
+
const [previewVisibility, setPreviewVisibility] = useState14({});
|
|
10489
|
+
const [marquee, setMarquee] = useState14(null);
|
|
10490
|
+
const [codeComposerOpen, setCodeComposerOpen] = useState14(false);
|
|
10491
|
+
const [codeComponentName, setCodeComponentName] = useState14("Code Component");
|
|
10492
|
+
const [codeComponentSource, setCodeComponentSource] = useState14("<style>body{margin:0;font-family:system-ui;display:grid;place-items:center;height:100vh}button{border:0;border-radius:12px;padding:14px 22px;background:#4f8cff;color:white;font-weight:600}</style><button>Button</button>");
|
|
10493
|
+
const [draggedBreakpointId, setDraggedBreakpointId] = useState14(null);
|
|
10494
|
+
const [editingBreakpointId, setEditingBreakpointId] = useState14(null);
|
|
10495
|
+
const marqueePageRef = useRef5(null);
|
|
10496
|
+
const marqueeBaseRef = useRef5([]);
|
|
10497
|
+
const [contextMenu, setContextMenu] = useState14(null);
|
|
10498
|
+
useEffect11(() => {
|
|
9938
10499
|
setIsRightCollapsed(!hasElementSelection);
|
|
9939
10500
|
}, [hasElementSelection]);
|
|
9940
10501
|
const updateBreakpoints = (next) => setRootStyle({
|
|
@@ -10207,18 +10768,18 @@ function Editor({
|
|
|
10207
10768
|
});
|
|
10208
10769
|
});
|
|
10209
10770
|
};
|
|
10210
|
-
const [dragInfo, setDragInfo] =
|
|
10211
|
-
const [resizeInfo, setResizeInfo] =
|
|
10212
|
-
const [guides, setGuides] =
|
|
10213
|
-
const [ghost, setGhost] =
|
|
10214
|
-
const [dropTargetId, setDropTargetId] =
|
|
10771
|
+
const [dragInfo, setDragInfo] = useState14(null);
|
|
10772
|
+
const [resizeInfo, setResizeInfo] = useState14(null);
|
|
10773
|
+
const [guides, setGuides] = useState14({ origin: { x: 0, y: 0 }, lines: [] });
|
|
10774
|
+
const [ghost, setGhost] = useState14(null);
|
|
10775
|
+
const [dropTargetId, setDropTargetId] = useState14(
|
|
10215
10776
|
void 0
|
|
10216
10777
|
);
|
|
10217
|
-
const [clipboard, setClipboard] =
|
|
10218
|
-
const [samples, setSamples] =
|
|
10219
|
-
const [pageError, setPageError] =
|
|
10220
|
-
const [pageSwitchTarget, setPageSwitchTarget] =
|
|
10221
|
-
|
|
10778
|
+
const [clipboard, setClipboard] = useState14(null);
|
|
10779
|
+
const [samples, setSamples] = useState14({});
|
|
10780
|
+
const [pageError, setPageError] = useState14(null);
|
|
10781
|
+
const [pageSwitchTarget, setPageSwitchTarget] = useState14(null);
|
|
10782
|
+
useEffect11(() => {
|
|
10222
10783
|
setSelectedIds([]);
|
|
10223
10784
|
setEditingId(null);
|
|
10224
10785
|
setHoveredEffectIds(/* @__PURE__ */ new Set());
|
|
@@ -10228,21 +10789,21 @@ function Editor({
|
|
|
10228
10789
|
setContextMenu(null);
|
|
10229
10790
|
setPageSwitchTarget(null);
|
|
10230
10791
|
}, [page.id]);
|
|
10231
|
-
const canvasRef =
|
|
10232
|
-
const [canvasHeight, setCanvasHeight] =
|
|
10233
|
-
const [contentHeight, setContentHeight] =
|
|
10792
|
+
const canvasRef = useRef5(null);
|
|
10793
|
+
const [canvasHeight, setCanvasHeight] = useState14(rootStyle.canvasHeight);
|
|
10794
|
+
const [contentHeight, setContentHeight] = useState14(rootStyle.canvasHeight);
|
|
10234
10795
|
const displayCanvasHeight = Math.max(canvasHeight, contentHeight);
|
|
10235
|
-
const byId =
|
|
10236
|
-
const componentAssetIds =
|
|
10796
|
+
const byId = useMemo4(() => indexById(elements), [elements]);
|
|
10797
|
+
const componentAssetIds = useMemo4(() => {
|
|
10237
10798
|
const ids = /* @__PURE__ */ new Set();
|
|
10238
10799
|
for (const master of elements.filter((element) => element.componentRole === "master")) for (const id of subtreeIds(elements, master.id)) ids.add(id);
|
|
10239
10800
|
return ids;
|
|
10240
10801
|
}, [elements]);
|
|
10241
|
-
const activeComponentIds =
|
|
10802
|
+
const activeComponentIds = useMemo4(
|
|
10242
10803
|
() => activeComponentMaster ? subtreeIds(elements, activeComponentMaster.id) : /* @__PURE__ */ new Set(),
|
|
10243
10804
|
[activeComponentMaster, elements]
|
|
10244
10805
|
);
|
|
10245
|
-
const visibleEditorElements =
|
|
10806
|
+
const visibleEditorElements = useMemo4(() => elements.filter((element) => componentMode ? activeComponentIds.has(element.id) : !componentAssetIds.has(element.id)), [activeComponentIds, componentAssetIds, componentMode, elements]);
|
|
10246
10807
|
const componentInstanceFor = useCallback3((element) => {
|
|
10247
10808
|
if (componentMode) return void 0;
|
|
10248
10809
|
let cursor = element;
|
|
@@ -10258,13 +10819,13 @@ function Editor({
|
|
|
10258
10819
|
const selectedElement = selectedId ? byId.get(selectedId) : void 0;
|
|
10259
10820
|
const deviceWidth = frameWidthForBreakpoint;
|
|
10260
10821
|
const frameWidth = rootStyle.fullWidth ? deviceWidth : Math.min(deviceWidth, rootStyle.maxWidth);
|
|
10261
|
-
|
|
10262
|
-
|
|
10822
|
+
useEffect11(() => setCanvasHeight(rootStyle.canvasHeight), [rootStyle.canvasHeight]);
|
|
10823
|
+
useEffect11(() => {
|
|
10263
10824
|
if (!componentMode || !activeComponentMaster) return;
|
|
10264
10825
|
setCanvasHeight(Math.max(1, activeComponentMaster.base.h));
|
|
10265
10826
|
setContentHeight(Math.max(1, activeComponentMaster.base.h));
|
|
10266
10827
|
}, [activeComponentMaster?.base.h, activeComponentMaster?.id, componentMode]);
|
|
10267
|
-
|
|
10828
|
+
useEffect11(() => {
|
|
10268
10829
|
const node2 = canvasRef.current;
|
|
10269
10830
|
if (!node2) return;
|
|
10270
10831
|
const observer = new ResizeObserver(([entry]) => {
|
|
@@ -10594,7 +11155,7 @@ function Editor({
|
|
|
10594
11155
|
});
|
|
10595
11156
|
}, []);
|
|
10596
11157
|
const gesturing = dragInfo !== null || resizeInfo !== null;
|
|
10597
|
-
|
|
11158
|
+
useEffect11(() => {
|
|
10598
11159
|
if (!gesturing) return;
|
|
10599
11160
|
const handleMouseMove = (event) => {
|
|
10600
11161
|
const gestureBreakpoint = dragInfo?.breakpoint ?? resizeInfo?.breakpoint ?? breakpoint;
|
|
@@ -10773,7 +11334,7 @@ function Editor({
|
|
|
10773
11334
|
setEditingId(null);
|
|
10774
11335
|
setMarquee({ startX: event.clientX, startY: event.clientY, x: event.clientX, y: event.clientY });
|
|
10775
11336
|
};
|
|
10776
|
-
|
|
11337
|
+
useEffect11(() => {
|
|
10777
11338
|
if (!marquee) return;
|
|
10778
11339
|
const move = (event) => {
|
|
10779
11340
|
const left = Math.min(marquee.startX, event.clientX);
|
|
@@ -10846,7 +11407,7 @@ function Editor({
|
|
|
10846
11407
|
setElements((els) => [...els, element]);
|
|
10847
11408
|
setSelectedIds([element.id]);
|
|
10848
11409
|
};
|
|
10849
|
-
|
|
11410
|
+
useEffect11(() => {
|
|
10850
11411
|
const handler = (event) => {
|
|
10851
11412
|
const target = event.target;
|
|
10852
11413
|
const typing = !!target && (target.isContentEditable || ["INPUT", "TEXTAREA", "SELECT"].includes(target.tagName));
|
|
@@ -10955,7 +11516,7 @@ function Editor({
|
|
|
10955
11516
|
undo,
|
|
10956
11517
|
zoomTo
|
|
10957
11518
|
]);
|
|
10958
|
-
|
|
11519
|
+
useEffect11(() => {
|
|
10959
11520
|
if (!contextMenu) return;
|
|
10960
11521
|
const close = () => setContextMenu(null);
|
|
10961
11522
|
window.addEventListener("click", close);
|
|
@@ -11012,7 +11573,7 @@ function Editor({
|
|
|
11012
11573
|
else adapters?.refresh?.();
|
|
11013
11574
|
});
|
|
11014
11575
|
}, [adapters, page.id, saveNow]);
|
|
11015
|
-
const enclosingDataBlock =
|
|
11576
|
+
const enclosingDataBlock = useMemo4(() => {
|
|
11016
11577
|
if (!selectedElement) return void 0;
|
|
11017
11578
|
let cursor = selectedElement.parentId ? byId.get(selectedElement.parentId) : void 0;
|
|
11018
11579
|
const guard = /* @__PURE__ */ new Set([selectedElement.id]);
|
|
@@ -11025,7 +11586,7 @@ function Editor({
|
|
|
11025
11586
|
}, [byId, selectedElement]);
|
|
11026
11587
|
const bindingSourceId = enclosingDataBlock?.sourceId ?? selectedElement?.sourceId;
|
|
11027
11588
|
const bindingKeys = bindingSourceId ? samples[bindingSourceId]?.keys ?? [] : [];
|
|
11028
|
-
const canvasData =
|
|
11589
|
+
const canvasData = useMemo4(
|
|
11029
11590
|
() => Object.fromEntries(
|
|
11030
11591
|
Object.entries(samples).map(([id, sample]) => [id, sample.rows])
|
|
11031
11592
|
),
|
|
@@ -11080,7 +11641,7 @@ function Editor({
|
|
|
11080
11641
|
return (
|
|
11081
11642
|
// A canvas node is manipulated by pointer; the Layers panel is its keyboard equivalent.
|
|
11082
11643
|
// biome-ignore lint/a11y/noStaticElementInteractions: pointer-driven canvas node
|
|
11083
|
-
/* @__PURE__ */
|
|
11644
|
+
/* @__PURE__ */ jsxs13(
|
|
11084
11645
|
"div",
|
|
11085
11646
|
{
|
|
11086
11647
|
"data-canvas-element": el.id,
|
|
@@ -11126,7 +11687,7 @@ function Editor({
|
|
|
11126
11687
|
onDragLeave: container ? () => setDropTargetId((c) => c === el.id ? void 0 : c) : void 0,
|
|
11127
11688
|
onDrop: container ? (event) => handleDrop(event, el.id) : void 0,
|
|
11128
11689
|
children: [
|
|
11129
|
-
isEditing ? /* @__PURE__ */
|
|
11690
|
+
isEditing ? /* @__PURE__ */ jsx14(
|
|
11130
11691
|
"textarea",
|
|
11131
11692
|
{
|
|
11132
11693
|
ref: (node2) => node2?.focus(),
|
|
@@ -11145,9 +11706,9 @@ function Editor({
|
|
|
11145
11706
|
lineHeight: "inherit"
|
|
11146
11707
|
}
|
|
11147
11708
|
}
|
|
11148
|
-
) : /* @__PURE__ */
|
|
11149
|
-
split ? /* @__PURE__ */
|
|
11150
|
-
isSelected && !note && /* @__PURE__ */
|
|
11709
|
+
) : /* @__PURE__ */ jsx14(ElementBody, { element: el }),
|
|
11710
|
+
split ? /* @__PURE__ */ jsx14("div", { style: split.inner, children: renderChildren() }) : renderChildren(),
|
|
11711
|
+
isSelected && !note && /* @__PURE__ */ jsxs13(
|
|
11151
11712
|
"span",
|
|
11152
11713
|
{
|
|
11153
11714
|
className: "pointer-events-none absolute -bottom-1 left-1/2 z-[70] translate-y-full whitespace-nowrap rounded px-1.5 py-0.5 font-mono text-[10px] font-medium text-white shadow-sm",
|
|
@@ -11165,7 +11726,7 @@ function Editor({
|
|
|
11165
11726
|
]
|
|
11166
11727
|
}
|
|
11167
11728
|
),
|
|
11168
|
-
note && /* @__PURE__ */
|
|
11729
|
+
note && /* @__PURE__ */ jsx14(
|
|
11169
11730
|
"span",
|
|
11170
11731
|
{
|
|
11171
11732
|
className: "pointer-events-none absolute -top-5 left-0 whitespace-nowrap rounded px-1.5 py-0.5 text-[10px] font-medium",
|
|
@@ -11176,7 +11737,7 @@ function Editor({
|
|
|
11176
11737
|
children: "Note \xB7 not published"
|
|
11177
11738
|
}
|
|
11178
11739
|
),
|
|
11179
|
-
isSelected && !el.locked && selectedIds.length === 1 && /* @__PURE__ */
|
|
11740
|
+
isSelected && !el.locked && selectedIds.length === 1 && /* @__PURE__ */ jsx14(
|
|
11180
11741
|
ResizeHandles,
|
|
11181
11742
|
{
|
|
11182
11743
|
element: el,
|
|
@@ -11192,7 +11753,7 @@ function Editor({
|
|
|
11192
11753
|
};
|
|
11193
11754
|
const rootCss = rootStyleToCss(rootStyle);
|
|
11194
11755
|
const customFontCss = (rootStyle.customFonts ?? []).map((font) => `@font-face{font-family:"${font.name.replace(/["'{};]/g, "")}";src:url("${font.url.replace(/["'()\\]/g, "")}");font-weight:${font.weight};font-style:${font.style};font-display:swap}`).join("\n");
|
|
11195
|
-
const arrangeable =
|
|
11756
|
+
const arrangeable = useMemo4(() => {
|
|
11196
11757
|
if (selectedIds.length < 2) return false;
|
|
11197
11758
|
const parents = new Set(
|
|
11198
11759
|
selectedIds.map((id) => byId.get(id)?.parentId ?? "__root__")
|
|
@@ -11243,7 +11804,7 @@ function Editor({
|
|
|
11243
11804
|
const renderRailTab = (tab) => {
|
|
11244
11805
|
const Icon = iconForRailTab(tab);
|
|
11245
11806
|
const active = leftTab === tab && (tab === "Templates" || !isLeftCollapsed);
|
|
11246
|
-
return /* @__PURE__ */
|
|
11807
|
+
return /* @__PURE__ */ jsxs13(
|
|
11247
11808
|
"button",
|
|
11248
11809
|
{
|
|
11249
11810
|
type: "button",
|
|
@@ -11253,50 +11814,50 @@ function Editor({
|
|
|
11253
11814
|
"aria-label": tab,
|
|
11254
11815
|
"aria-pressed": active,
|
|
11255
11816
|
children: [
|
|
11256
|
-
/* @__PURE__ */
|
|
11257
|
-
/* @__PURE__ */
|
|
11817
|
+
/* @__PURE__ */ jsx14(Icon, { size: 15, stroke: 1.65 }),
|
|
11818
|
+
/* @__PURE__ */ jsx14("span", { className: "pointer-events-none absolute left-[calc(100%+10px)] z-[100] whitespace-nowrap rounded-full bg-[var(--ed-tooltip)] px-2.5 py-1.5 text-[10px] font-medium text-[var(--ed-tooltip-text)] opacity-0 transition-all duration-150 group-hover:translate-x-0.5 group-hover:opacity-100", children: tab })
|
|
11258
11819
|
]
|
|
11259
11820
|
},
|
|
11260
11821
|
tab
|
|
11261
11822
|
);
|
|
11262
11823
|
};
|
|
11263
11824
|
const ActiveLeftIcon = iconForRailTab(leftTab);
|
|
11264
|
-
return /* @__PURE__ */
|
|
11825
|
+
return /* @__PURE__ */ jsxs13(
|
|
11265
11826
|
"div",
|
|
11266
11827
|
{
|
|
11267
11828
|
className: "pg-editor flex h-screen w-full flex-col overflow-hidden bg-ed-surface font-sans text-xs text-ed-text selection:bg-blue-500/30",
|
|
11268
11829
|
"data-ed-theme": chromeTheme === "light" ? "light" : void 0,
|
|
11269
11830
|
children: [
|
|
11270
|
-
/* @__PURE__ */
|
|
11271
|
-
/* @__PURE__ */
|
|
11272
|
-
/* @__PURE__ */
|
|
11273
|
-
/* @__PURE__ */
|
|
11274
|
-
/* @__PURE__ */
|
|
11275
|
-
/* @__PURE__ */
|
|
11276
|
-
] }) : /* @__PURE__ */
|
|
11277
|
-
/* @__PURE__ */
|
|
11278
|
-
componentMode && /* @__PURE__ */
|
|
11279
|
-
/* @__PURE__ */
|
|
11831
|
+
/* @__PURE__ */ jsxs13("header", { className: "relative z-30 grid h-12 shrink-0 grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-2 border-b border-ed-border bg-ed-surface/95 px-2.5 backdrop-blur-xl", children: [
|
|
11832
|
+
/* @__PURE__ */ jsx14("button", { type: "button", onClick: () => setIsLeftCollapsed((current) => !current), title: "Toggle sidebar", className: "w-fit select-none rounded-full px-2 py-1 text-[12px] font-semibold tracking-[-.02em] text-ed-text transition-colors hover:bg-ed-field", children: "Pagiera" }),
|
|
11833
|
+
/* @__PURE__ */ jsx14("div", { className: "flex h-8 items-center gap-1 rounded-full bg-ed-subtle p-0.5", children: leftTab === "Templates" ? /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 px-3 text-[10px] font-semibold text-ed-text", children: [
|
|
11834
|
+
/* @__PURE__ */ jsx14(IconTemplate2, { size: 13, className: "text-ed-accent" }),
|
|
11835
|
+
/* @__PURE__ */ jsx14("span", { children: "Template marketplace" }),
|
|
11836
|
+
/* @__PURE__ */ jsx14("span", { className: "rounded-full bg-ed-field px-2 py-0.5 text-[8px] font-medium text-ed-faint", children: "Discover" })
|
|
11837
|
+
] }) : /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
11838
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-1 text-[10px] font-medium text-ed-muted", children: [
|
|
11839
|
+
componentMode && /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
11840
|
+
/* @__PURE__ */ jsxs13(Select, { value: activeComponentMaster?.id, onValueChange: (id) => {
|
|
11280
11841
|
setActiveComponentMasterId(id);
|
|
11281
11842
|
setSelectedIds([id]);
|
|
11282
11843
|
}, children: [
|
|
11283
|
-
/* @__PURE__ */
|
|
11284
|
-
/* @__PURE__ */
|
|
11844
|
+
/* @__PURE__ */ jsx14(SelectTrigger, { "aria-label": "Variant", children: /* @__PURE__ */ jsx14(SelectValue, { placeholder: "Select variant" }) }),
|
|
11845
|
+
/* @__PURE__ */ jsx14(SelectContent, { children: activeComponentVariants.map((master) => /* @__PURE__ */ jsx14(SelectItem, { value: master.id, children: master.variant ?? "Default" }, master.id)) })
|
|
11285
11846
|
] }),
|
|
11286
|
-
/* @__PURE__ */
|
|
11847
|
+
/* @__PURE__ */ jsx14("button", { type: "button", onClick: createComponentVariant, disabled: !activeComponentMaster, title: "Add variant", className: "flex size-6 items-center justify-center rounded-full text-ed-muted hover:bg-ed-field-hover hover:text-ed-text disabled:opacity-30", children: /* @__PURE__ */ jsx14(IconPlus8, { size: 12 }) })
|
|
11287
11848
|
] }),
|
|
11288
|
-
/* @__PURE__ */
|
|
11289
|
-
/* @__PURE__ */
|
|
11849
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-0.5", children: [
|
|
11850
|
+
/* @__PURE__ */ jsx14(
|
|
11290
11851
|
"button",
|
|
11291
11852
|
{
|
|
11292
11853
|
type: "button",
|
|
11293
11854
|
title: "Zoom out (Ctrl -)",
|
|
11294
11855
|
onClick: () => stepZoom(-1),
|
|
11295
11856
|
className: "flex size-6 items-center justify-center rounded-full transition-colors hover:bg-ed-field-hover hover:text-ed-text",
|
|
11296
|
-
children: /* @__PURE__ */
|
|
11857
|
+
children: /* @__PURE__ */ jsx14(IconMinus2, { size: 12 })
|
|
11297
11858
|
}
|
|
11298
11859
|
),
|
|
11299
|
-
/* @__PURE__ */
|
|
11860
|
+
/* @__PURE__ */ jsxs13(
|
|
11300
11861
|
"button",
|
|
11301
11862
|
{
|
|
11302
11863
|
type: "button",
|
|
@@ -11309,20 +11870,20 @@ function Editor({
|
|
|
11309
11870
|
]
|
|
11310
11871
|
}
|
|
11311
11872
|
),
|
|
11312
|
-
/* @__PURE__ */
|
|
11873
|
+
/* @__PURE__ */ jsx14(
|
|
11313
11874
|
"button",
|
|
11314
11875
|
{
|
|
11315
11876
|
type: "button",
|
|
11316
11877
|
title: "Zoom in (Ctrl +)",
|
|
11317
11878
|
onClick: () => stepZoom(1),
|
|
11318
11879
|
className: "flex size-6 items-center justify-center rounded-full transition-colors hover:bg-ed-field-hover hover:text-ed-text",
|
|
11319
|
-
children: /* @__PURE__ */
|
|
11880
|
+
children: /* @__PURE__ */ jsx14(IconPlus8, { size: 12 })
|
|
11320
11881
|
}
|
|
11321
11882
|
)
|
|
11322
11883
|
] })
|
|
11323
11884
|
] }),
|
|
11324
|
-
/* @__PURE__ */
|
|
11325
|
-
/* @__PURE__ */
|
|
11885
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-0.5 border-l border-ed-border pl-1 text-ed-muted", children: [
|
|
11886
|
+
/* @__PURE__ */ jsx14(
|
|
11326
11887
|
"button",
|
|
11327
11888
|
{
|
|
11328
11889
|
type: "button",
|
|
@@ -11330,10 +11891,10 @@ function Editor({
|
|
|
11330
11891
|
onClick: undo,
|
|
11331
11892
|
disabled: !canUndo,
|
|
11332
11893
|
className: "flex size-6 items-center justify-center rounded-full transition-colors hover:bg-ed-field-hover hover:text-ed-text disabled:cursor-not-allowed disabled:opacity-35 disabled:hover:bg-transparent disabled:hover:text-ed-muted",
|
|
11333
|
-
children: /* @__PURE__ */
|
|
11894
|
+
children: /* @__PURE__ */ jsx14(IconArrowBackUp, { size: 14 })
|
|
11334
11895
|
}
|
|
11335
11896
|
),
|
|
11336
|
-
/* @__PURE__ */
|
|
11897
|
+
/* @__PURE__ */ jsx14(
|
|
11337
11898
|
"button",
|
|
11338
11899
|
{
|
|
11339
11900
|
type: "button",
|
|
@@ -11341,18 +11902,18 @@ function Editor({
|
|
|
11341
11902
|
onClick: redo,
|
|
11342
11903
|
disabled: !canRedo,
|
|
11343
11904
|
className: "flex size-6 items-center justify-center rounded-full transition-colors hover:bg-ed-field-hover hover:text-ed-text disabled:cursor-not-allowed disabled:opacity-35 disabled:hover:bg-transparent disabled:hover:text-ed-muted",
|
|
11344
|
-
children: /* @__PURE__ */
|
|
11905
|
+
children: /* @__PURE__ */ jsx14(IconArrowForwardUp, { size: 14 })
|
|
11345
11906
|
}
|
|
11346
11907
|
)
|
|
11347
11908
|
] })
|
|
11348
11909
|
] }) }),
|
|
11349
|
-
/* @__PURE__ */
|
|
11350
|
-
/* @__PURE__ */
|
|
11351
|
-
/* @__PURE__ */
|
|
11352
|
-
/* @__PURE__ */
|
|
11353
|
-
] }) : /* @__PURE__ */
|
|
11354
|
-
/* @__PURE__ */
|
|
11355
|
-
componentMode ? /* @__PURE__ */
|
|
11910
|
+
/* @__PURE__ */ jsx14("div", { className: "flex min-w-0 items-center justify-end gap-1", children: leftTab === "Templates" ? /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
11911
|
+
/* @__PURE__ */ jsx14("span", { className: "hidden text-[9px] text-ed-faint lg:block", children: "Curated responsive starting points" }),
|
|
11912
|
+
/* @__PURE__ */ jsx14("button", { type: "button", onClick: () => openLeftPanel("Layers"), className: "h-7 select-none rounded-full bg-ed-field px-3 text-[9px] font-semibold text-ed-text transition-colors hover:bg-ed-field-hover", children: "Back to canvas" }),
|
|
11913
|
+
/* @__PURE__ */ jsx14("button", { type: "button", title: chromeTheme === "dark" ? "Switch to light editor" : "Switch to dark editor", "aria-label": "Toggle editor theme", onClick: toggleChromeTheme, className: "flex size-7 items-center justify-center rounded-full text-ed-muted transition-colors hover:bg-ed-field hover:text-ed-text", children: chromeTheme === "dark" ? /* @__PURE__ */ jsx14(IconSun, { size: 14 }) : /* @__PURE__ */ jsx14(IconMoon, { size: 14 }) })
|
|
11914
|
+
] }) : /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
11915
|
+
/* @__PURE__ */ jsx14("span", { className: "mr-1 hidden lg:block", children: /* @__PURE__ */ jsx14(SaveIndicator, { status: saveStatus, error: saveError }) }),
|
|
11916
|
+
componentMode ? /* @__PURE__ */ jsx14(
|
|
11356
11917
|
"button",
|
|
11357
11918
|
{
|
|
11358
11919
|
type: "button",
|
|
@@ -11365,8 +11926,8 @@ function Editor({
|
|
|
11365
11926
|
className: "h-7 select-none rounded-full bg-ed-field px-3 text-[10px] font-semibold text-ed-text transition-colors hover:bg-ed-field-hover",
|
|
11366
11927
|
children: "Back to pages"
|
|
11367
11928
|
}
|
|
11368
|
-
) : /* @__PURE__ */
|
|
11369
|
-
page.publishedAt && /* @__PURE__ */
|
|
11929
|
+
) : /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
11930
|
+
page.publishedAt && /* @__PURE__ */ jsx14(
|
|
11370
11931
|
"a",
|
|
11371
11932
|
{
|
|
11372
11933
|
href: (adapters?.publishedHref ?? defaultPublishedHref)(page.slug),
|
|
@@ -11374,10 +11935,10 @@ function Editor({
|
|
|
11374
11935
|
rel: "noopener noreferrer",
|
|
11375
11936
|
className: "hidden size-7 items-center justify-center rounded-full text-emerald-500 transition-colors hover:bg-emerald-500/10 hover:text-emerald-400 xl:flex",
|
|
11376
11937
|
title: (adapters?.publishedHref ?? defaultPublishedHref)(page.slug),
|
|
11377
|
-
children: /* @__PURE__ */
|
|
11938
|
+
children: /* @__PURE__ */ jsx14(IconWorld2, { size: 14 })
|
|
11378
11939
|
}
|
|
11379
11940
|
),
|
|
11380
|
-
/* @__PURE__ */
|
|
11941
|
+
/* @__PURE__ */ jsx14(
|
|
11381
11942
|
"button",
|
|
11382
11943
|
{
|
|
11383
11944
|
type: "button",
|
|
@@ -11388,7 +11949,7 @@ function Editor({
|
|
|
11388
11949
|
children: isPending ? "Working\u2026" : page.publishedAt ? "Republish" : "Publish"
|
|
11389
11950
|
}
|
|
11390
11951
|
),
|
|
11391
|
-
page.publishedAt && /* @__PURE__ */
|
|
11952
|
+
page.publishedAt && /* @__PURE__ */ jsx14(
|
|
11392
11953
|
"button",
|
|
11393
11954
|
{
|
|
11394
11955
|
type: "button",
|
|
@@ -11398,7 +11959,7 @@ function Editor({
|
|
|
11398
11959
|
}
|
|
11399
11960
|
)
|
|
11400
11961
|
] }),
|
|
11401
|
-
/* @__PURE__ */
|
|
11962
|
+
/* @__PURE__ */ jsx14(
|
|
11402
11963
|
"button",
|
|
11403
11964
|
{
|
|
11404
11965
|
type: "button",
|
|
@@ -11406,10 +11967,10 @@ function Editor({
|
|
|
11406
11967
|
"aria-label": "Toggle editor theme",
|
|
11407
11968
|
onClick: toggleChromeTheme,
|
|
11408
11969
|
className: "flex size-7 items-center justify-center rounded-full text-ed-muted transition-colors hover:bg-ed-field hover:text-ed-text",
|
|
11409
|
-
children: chromeTheme === "dark" ? /* @__PURE__ */
|
|
11970
|
+
children: chromeTheme === "dark" ? /* @__PURE__ */ jsx14(IconSun, { size: 14 }) : /* @__PURE__ */ jsx14(IconMoon, { size: 14 })
|
|
11410
11971
|
}
|
|
11411
11972
|
),
|
|
11412
|
-
/* @__PURE__ */
|
|
11973
|
+
/* @__PURE__ */ jsx14(
|
|
11413
11974
|
"button",
|
|
11414
11975
|
{
|
|
11415
11976
|
type: "button",
|
|
@@ -11418,37 +11979,37 @@ function Editor({
|
|
|
11418
11979
|
title: hasElementSelection ? "Toggle properties panel" : "Select an element to open properties",
|
|
11419
11980
|
"aria-label": "Toggle properties panel",
|
|
11420
11981
|
className: "flex size-7 items-center justify-center rounded-full text-ed-faint transition-colors hover:bg-ed-field hover:text-ed-text disabled:cursor-not-allowed disabled:opacity-25 disabled:hover:bg-transparent",
|
|
11421
|
-
children: isRightCollapsed ? /* @__PURE__ */
|
|
11982
|
+
children: isRightCollapsed ? /* @__PURE__ */ jsx14(IconLayoutSidebarLeftCollapse, { size: 15 }) : /* @__PURE__ */ jsx14(IconLayoutSidebarRightCollapse, { size: 15 })
|
|
11422
11983
|
}
|
|
11423
11984
|
)
|
|
11424
11985
|
] }) })
|
|
11425
11986
|
] }),
|
|
11426
|
-
/* @__PURE__ */
|
|
11427
|
-
/* @__PURE__ */
|
|
11428
|
-
/* @__PURE__ */
|
|
11987
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex flex-1 overflow-hidden bg-ed-canvas", children: [
|
|
11988
|
+
/* @__PURE__ */ jsxs13("aside", { className: "z-20 flex w-12 shrink-0 flex-col items-center border-r border-ed-border bg-ed-surface p-1.5", children: [
|
|
11989
|
+
/* @__PURE__ */ jsx14("div", { className: "flex w-full items-center justify-center", children: /* @__PURE__ */ jsxs13("button", { type: "button", title: "Insert elements (A)", "aria-label": "Insert elements", "aria-pressed": leftTab === "Elements" && !isLeftCollapsed, className: `group relative flex size-8 items-center justify-center rounded-full transition-colors ${leftTab === "Elements" && !isLeftCollapsed ? "bg-ed-accent text-white" : "text-ed-muted hover:bg-ed-field-hover hover:text-ed-text"}`, onClick: () => {
|
|
11429
11990
|
setLeftTab("Elements");
|
|
11430
11991
|
setIsLeftCollapsed(false);
|
|
11431
11992
|
}, children: [
|
|
11432
|
-
/* @__PURE__ */
|
|
11433
|
-
/* @__PURE__ */
|
|
11993
|
+
/* @__PURE__ */ jsx14(IconPlus8, { size: 14, stroke: 1.8 }),
|
|
11994
|
+
/* @__PURE__ */ jsx14("span", { className: "pointer-events-none absolute left-[calc(100%+10px)] z-[100] whitespace-nowrap rounded-full bg-[var(--ed-tooltip)] px-2.5 py-1.5 text-[10px] font-medium text-[var(--ed-tooltip-text)] opacity-0 transition-all duration-150 group-hover:translate-x-0.5 group-hover:opacity-100", children: "Insert \xB7 A" })
|
|
11434
11995
|
] }) }),
|
|
11435
|
-
/* @__PURE__ */
|
|
11436
|
-
/* @__PURE__ */
|
|
11437
|
-
/* @__PURE__ */
|
|
11438
|
-
/* @__PURE__ */
|
|
11439
|
-
!componentMode && /* @__PURE__ */
|
|
11996
|
+
/* @__PURE__ */ jsx14("div", { className: "my-1.5 h-px w-5 bg-ed-border" }),
|
|
11997
|
+
/* @__PURE__ */ jsx14("nav", { "aria-label": "Project panels", className: "flex w-full flex-col items-center gap-1 rounded-full bg-ed-subtle p-0.5", children: projectRailTabs.map(renderRailTab) }),
|
|
11998
|
+
/* @__PURE__ */ jsx14("div", { className: "my-1.5 h-px w-5 bg-ed-border" }),
|
|
11999
|
+
/* @__PURE__ */ jsx14("nav", { "aria-label": "Editor tools", className: "flex w-full flex-col items-center gap-1 rounded-full bg-ed-subtle p-0.5", children: utilityRailTabs.map(renderRailTab) }),
|
|
12000
|
+
!componentMode && /* @__PURE__ */ jsx14("nav", { "aria-label": "Site settings", className: "mt-auto flex w-full justify-center rounded-full bg-ed-subtle p-0.5", children: renderRailTab("Settings") })
|
|
11440
12001
|
] }),
|
|
11441
|
-
/* @__PURE__ */
|
|
11442
|
-
/* @__PURE__ */
|
|
11443
|
-
/* @__PURE__ */
|
|
11444
|
-
/* @__PURE__ */
|
|
11445
|
-
/* @__PURE__ */
|
|
12002
|
+
/* @__PURE__ */ jsx14(AnimatePresence7, { initial: false, children: !isLeftCollapsed && leftTab !== "Templates" && /* @__PURE__ */ jsxs13(motion7.aside, { initial: { width: 0, opacity: 0, x: -12 }, animate: { width: leftTab === "AI" ? 380 : 292, opacity: 1, x: 0 }, exit: { width: 0, opacity: 0, x: -12 }, transition: { type: "spring", stiffness: 420, damping: 38 }, className: "relative z-10 flex shrink-0 flex-col overflow-hidden border-r border-ed-border bg-ed-surface/95 backdrop-blur-xl", children: [
|
|
12003
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex h-12 shrink-0 items-center justify-between border-b border-ed-border px-3.5", children: [
|
|
12004
|
+
/* @__PURE__ */ jsxs13("span", { className: "flex min-w-0 items-center gap-2.5", children: [
|
|
12005
|
+
/* @__PURE__ */ jsx14("span", { className: "flex size-6 shrink-0 items-center justify-center rounded-full bg-ed-accent-soft text-ed-accent", children: /* @__PURE__ */ jsx14(ActiveLeftIcon, { size: 13, stroke: 1.7 }) }),
|
|
12006
|
+
/* @__PURE__ */ jsx14("span", { className: "truncate text-[11px] font-semibold text-ed-text", children: leftTab })
|
|
11446
12007
|
] }),
|
|
11447
|
-
/* @__PURE__ */
|
|
12008
|
+
/* @__PURE__ */ jsx14("button", { type: "button", onClick: () => setIsLeftCollapsed(true), className: "rounded-full p-1 text-ed-faint transition-colors hover:bg-ed-field hover:text-ed-muted", children: /* @__PURE__ */ jsx14(IconX6, { size: 16 }) })
|
|
11448
12009
|
] }),
|
|
11449
|
-
leftTab !== "Pages" && leftTab !== "Components" && leftTab !== "Assets" && leftTab !== "Library" && leftTab !== "Variables" && leftTab !== "Data" && leftTab !== "AI" && /* @__PURE__ */
|
|
11450
|
-
/* @__PURE__ */
|
|
11451
|
-
/* @__PURE__ */
|
|
12010
|
+
leftTab !== "Pages" && leftTab !== "Components" && leftTab !== "Assets" && leftTab !== "Library" && leftTab !== "Variables" && leftTab !== "Data" && leftTab !== "AI" && /* @__PURE__ */ jsx14("div", { className: "border-b border-ed-border p-3 bg-ed-subtle", children: /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 rounded-md border border-ed-border bg-ed-surface px-2.5 py-1.5 transition-all focus-within:border-ed-accent/50 focus-within:ring-1 focus-within:ring-blue-500/20", children: [
|
|
12011
|
+
/* @__PURE__ */ jsx14(IconSearch5, { size: 14, className: "text-ed-faint" }),
|
|
12012
|
+
/* @__PURE__ */ jsx14(
|
|
11452
12013
|
"input",
|
|
11453
12014
|
{
|
|
11454
12015
|
type: "text",
|
|
@@ -11458,9 +12019,9 @@ function Editor({
|
|
|
11458
12019
|
className: "w-full bg-transparent text-xs text-ed-text outline-none placeholder:text-ed-faint"
|
|
11459
12020
|
}
|
|
11460
12021
|
),
|
|
11461
|
-
/* @__PURE__ */
|
|
12022
|
+
/* @__PURE__ */ jsx14(IconCommand, { size: 12, className: "text-ed-faint" })
|
|
11462
12023
|
] }) }),
|
|
11463
|
-
/* @__PURE__ */
|
|
12024
|
+
/* @__PURE__ */ jsx14("div", { className: "custom-scrollbar flex-1 overflow-y-auto", children: leftTab === "Layers" ? /* @__PURE__ */ jsx14(
|
|
11464
12025
|
LayersPanel,
|
|
11465
12026
|
{
|
|
11466
12027
|
elements: visibleEditorElements,
|
|
@@ -11486,7 +12047,7 @@ function Editor({
|
|
|
11486
12047
|
onReparent: doReparent,
|
|
11487
12048
|
onOpenComponent: openComponentEditor
|
|
11488
12049
|
}
|
|
11489
|
-
) : leftTab === "Elements" ? /* @__PURE__ */
|
|
12050
|
+
) : leftTab === "Elements" ? /* @__PURE__ */ jsx14(ElementsPanel, { search, onInsert: insertElement }) : leftTab === "Icons" ? /* @__PURE__ */ jsx14(IconsPanel, { search, onInsert: (iconName) => insertElement("Icon", { iconName }) }) : leftTab === "Data" ? /* @__PURE__ */ jsx14(
|
|
11490
12051
|
DataPanel,
|
|
11491
12052
|
{
|
|
11492
12053
|
sources: dataSources,
|
|
@@ -11495,40 +12056,40 @@ function Editor({
|
|
|
11495
12056
|
onSample: (id, sample) => setSamples((prev) => ({ ...prev, [id]: sample })),
|
|
11496
12057
|
preview: adapters?.previewSource ?? (async () => ({ status: "error", message: "No data preview adapter configured." }))
|
|
11497
12058
|
}
|
|
11498
|
-
) : leftTab === "Library" ? /* @__PURE__ */
|
|
12059
|
+
) : leftTab === "Library" ? /* @__PURE__ */ jsx14(
|
|
11499
12060
|
LibraryPanel,
|
|
11500
12061
|
{
|
|
11501
12062
|
pages: library,
|
|
11502
12063
|
currentPageId: page.id,
|
|
11503
12064
|
onInsert: insertFromLibrary
|
|
11504
12065
|
}
|
|
11505
|
-
) : leftTab === "Assets" ? /* @__PURE__ */
|
|
11506
|
-
/* @__PURE__ */
|
|
11507
|
-
/* @__PURE__ */
|
|
11508
|
-
/* @__PURE__ */
|
|
12066
|
+
) : leftTab === "Assets" ? /* @__PURE__ */ jsxs13("div", { className: "p-3", children: [
|
|
12067
|
+
/* @__PURE__ */ jsxs13("div", { className: "mb-3 rounded-2xl border border-ed-border bg-ed-subtle p-3", children: [
|
|
12068
|
+
/* @__PURE__ */ jsx14("p", { className: "text-[11px] font-semibold text-ed-text", children: "Assets" }),
|
|
12069
|
+
/* @__PURE__ */ jsx14("p", { className: "mt-1 text-[9px] leading-relaxed text-ed-faint", children: "Navbar, sidebar, footer and reusable components live here once. Drag the exact variant you need onto any page." })
|
|
11509
12070
|
] }),
|
|
11510
|
-
/* @__PURE__ */
|
|
11511
|
-
/* @__PURE__ */
|
|
12071
|
+
/* @__PURE__ */ jsxs13("div", { className: "mb-2.5 flex items-center justify-between", children: [
|
|
12072
|
+
/* @__PURE__ */ jsxs13("span", { className: "text-[10px] font-semibold text-ed-muted", children: [
|
|
11512
12073
|
componentAssets.length,
|
|
11513
12074
|
" shared asset",
|
|
11514
12075
|
componentAssets.length === 1 ? "" : "s"
|
|
11515
12076
|
] }),
|
|
11516
|
-
/* @__PURE__ */
|
|
11517
|
-
/* @__PURE__ */
|
|
11518
|
-
/* @__PURE__ */
|
|
12077
|
+
/* @__PURE__ */ jsxs13("span", { className: "flex gap-1", children: [
|
|
12078
|
+
/* @__PURE__ */ jsxs13("button", { type: "button", onClick: createBlankComponent, className: "flex items-center gap-1 rounded-full bg-ed-field px-2.5 py-1.5 text-[9px] text-ed-muted hover:text-ed-text", children: [
|
|
12079
|
+
/* @__PURE__ */ jsx14(IconPlus8, { size: 10 }),
|
|
11519
12080
|
" New"
|
|
11520
12081
|
] }),
|
|
11521
|
-
/* @__PURE__ */
|
|
12082
|
+
/* @__PURE__ */ jsx14("button", { type: "button", onClick: () => setCodeComposerOpen(true), className: "rounded-full bg-ed-field px-2.5 py-1.5 text-[9px] text-ed-muted hover:text-ed-text", children: "Code" })
|
|
11522
12083
|
] })
|
|
11523
12084
|
] }),
|
|
11524
|
-
/* @__PURE__ */
|
|
12085
|
+
/* @__PURE__ */ jsx14(ComponentAssetCards, { assets: componentAssets, activeMasterId: activeComponentMaster?.id, onOpen: (master) => {
|
|
11525
12086
|
setRootStyle({ ...rootStyle, documentMode: "component" });
|
|
11526
12087
|
setActiveComponentMasterId(master.id);
|
|
11527
12088
|
setSelectedIds([master.id]);
|
|
11528
12089
|
setBreakpoint("desktop");
|
|
11529
12090
|
setLeftTab("Components");
|
|
11530
12091
|
} })
|
|
11531
|
-
] }) : leftTab === "Variables" ? /* @__PURE__ */
|
|
12092
|
+
] }) : leftTab === "Variables" ? /* @__PURE__ */ jsx14(
|
|
11532
12093
|
VariablesPanel,
|
|
11533
12094
|
{
|
|
11534
12095
|
rootStyle,
|
|
@@ -11536,7 +12097,7 @@ function Editor({
|
|
|
11536
12097
|
setRootStyle,
|
|
11537
12098
|
setElements
|
|
11538
12099
|
}
|
|
11539
|
-
) : leftTab === "AI" ? /* @__PURE__ */
|
|
12100
|
+
) : leftTab === "AI" ? /* @__PURE__ */ jsx14(
|
|
11540
12101
|
AiPanel,
|
|
11541
12102
|
{
|
|
11542
12103
|
pageId: page.id,
|
|
@@ -11546,37 +12107,37 @@ function Editor({
|
|
|
11546
12107
|
onApply: applyAiPlan,
|
|
11547
12108
|
generate: adapters?.generate
|
|
11548
12109
|
}
|
|
11549
|
-
) : leftTab === "Components" ? /* @__PURE__ */
|
|
11550
|
-
/* @__PURE__ */
|
|
11551
|
-
/* @__PURE__ */
|
|
11552
|
-
/* @__PURE__ */
|
|
11553
|
-
/* @__PURE__ */
|
|
12110
|
+
) : leftTab === "Components" ? /* @__PURE__ */ jsxs13("div", { className: "p-3", children: [
|
|
12111
|
+
/* @__PURE__ */ jsxs13("div", { className: "mb-3 flex items-center justify-between", children: [
|
|
12112
|
+
/* @__PURE__ */ jsxs13("div", { children: [
|
|
12113
|
+
/* @__PURE__ */ jsx14("p", { className: "text-[11px] font-semibold text-ed-text", children: "Asset canvas" }),
|
|
12114
|
+
/* @__PURE__ */ jsx14("p", { className: "mt-1 text-[9px] text-ed-faint", children: "One asset, multiple variants\u2014similar to its own breakpoint set." })
|
|
11554
12115
|
] }),
|
|
11555
|
-
/* @__PURE__ */
|
|
12116
|
+
/* @__PURE__ */ jsx14("button", { type: "button", onClick: () => {
|
|
11556
12117
|
setRootStyle({ ...rootStyle, documentMode: "page" });
|
|
11557
12118
|
setLeftTab("Assets");
|
|
11558
12119
|
}, className: "rounded-full bg-ed-field px-2.5 py-1.5 text-[9px] text-ed-muted hover:text-ed-text", children: "Back to page" })
|
|
11559
12120
|
] }),
|
|
11560
|
-
activeComponentMaster && /* @__PURE__ */
|
|
11561
|
-
/* @__PURE__ */
|
|
11562
|
-
/* @__PURE__ */
|
|
11563
|
-
/* @__PURE__ */
|
|
12121
|
+
activeComponentMaster && /* @__PURE__ */ jsxs13("div", { className: "mb-3 space-y-2 rounded-2xl border border-ed-border bg-ed-subtle p-2.5", children: [
|
|
12122
|
+
/* @__PURE__ */ jsxs13("label", { className: "flex items-center gap-2 text-[9px] text-ed-faint", children: [
|
|
12123
|
+
/* @__PURE__ */ jsx14("span", { className: "w-16", children: "Asset" }),
|
|
12124
|
+
/* @__PURE__ */ jsx14("input", { value: activeComponentMaster.name ?? "", placeholder: "Asset name", onChange: (event) => patchProps(activeComponentMaster.id, { name: event.target.value }), className: "h-8 min-w-0 flex-1 rounded-xl bg-ed-field px-2.5 text-[10px] text-ed-text outline-none focus:ring-1 focus:ring-ed-accent" })
|
|
11564
12125
|
] }),
|
|
11565
|
-
/* @__PURE__ */
|
|
11566
|
-
/* @__PURE__ */
|
|
11567
|
-
/* @__PURE__ */
|
|
12126
|
+
/* @__PURE__ */ jsxs13("label", { className: "flex items-center gap-2 text-[9px] text-ed-faint", children: [
|
|
12127
|
+
/* @__PURE__ */ jsx14("span", { className: "w-16", children: "Variant" }),
|
|
12128
|
+
/* @__PURE__ */ jsx14("input", { value: activeComponentMaster.variant ?? "Default", onChange: (event) => patchProps(activeComponentMaster.id, { variant: event.target.value }), className: "h-8 min-w-0 flex-1 rounded-xl bg-ed-field px-2.5 text-[10px] text-ed-text outline-none focus:ring-1 focus:ring-ed-accent" })
|
|
11568
12129
|
] })
|
|
11569
12130
|
] }),
|
|
11570
|
-
/* @__PURE__ */
|
|
12131
|
+
/* @__PURE__ */ jsx14(ComponentAssetCards, { assets: componentAssets, activeMasterId: activeComponentMaster?.id, onOpen: (master) => {
|
|
11571
12132
|
setActiveComponentMasterId(master.id);
|
|
11572
12133
|
setSelectedIds([master.id]);
|
|
11573
12134
|
} }),
|
|
11574
|
-
/* @__PURE__ */
|
|
11575
|
-
/* @__PURE__ */
|
|
12135
|
+
/* @__PURE__ */ jsxs13("button", { type: "button", onClick: createComponentVariant, disabled: !activeComponentMaster, className: "mt-3 flex w-full items-center justify-center gap-1.5 rounded-full bg-ed-accent px-3 py-2 text-[10px] font-semibold text-white disabled:opacity-30", children: [
|
|
12136
|
+
/* @__PURE__ */ jsx14(IconPlus8, { size: 12 }),
|
|
11576
12137
|
" Add variant to ",
|
|
11577
12138
|
activeComponentMaster?.name ?? "asset"
|
|
11578
12139
|
] })
|
|
11579
|
-
] }) : leftTab === "Settings" ? /* @__PURE__ */
|
|
12140
|
+
] }) : leftTab === "Settings" ? /* @__PURE__ */ jsx14("div", { className: "px-4 py-3", children: /* @__PURE__ */ jsx14(PageInspector, { rootStyle, onChange: updatePageSettings }) }) : /* @__PURE__ */ jsx14(
|
|
11580
12141
|
PagesPanel,
|
|
11581
12142
|
{
|
|
11582
12143
|
pages,
|
|
@@ -11595,14 +12156,14 @@ function Editor({
|
|
|
11595
12156
|
publishedHref: adapters?.publishedHref ?? defaultPublishedHref
|
|
11596
12157
|
}
|
|
11597
12158
|
) }),
|
|
11598
|
-
leftTab === "Layers" && /* @__PURE__ */
|
|
11599
|
-
/* @__PURE__ */
|
|
12159
|
+
leftTab === "Layers" && /* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between border-t border-ed-border p-2 px-3 text-ed-muted", children: [
|
|
12160
|
+
/* @__PURE__ */ jsxs13("span", { className: "text-[10px] tabular-nums", children: [
|
|
11600
12161
|
elements.length,
|
|
11601
12162
|
" element",
|
|
11602
12163
|
elements.length === 1 ? "" : "s"
|
|
11603
12164
|
] }),
|
|
11604
|
-
/* @__PURE__ */
|
|
11605
|
-
/* @__PURE__ */
|
|
12165
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-1", children: [
|
|
12166
|
+
/* @__PURE__ */ jsx14(
|
|
11606
12167
|
"button",
|
|
11607
12168
|
{
|
|
11608
12169
|
type: "button",
|
|
@@ -11610,10 +12171,10 @@ function Editor({
|
|
|
11610
12171
|
disabled: selectedIds.length === 0,
|
|
11611
12172
|
onClick: () => duplicateElements(selectedIds),
|
|
11612
12173
|
className: "rounded-full p-1.5 transition-colors hover:bg-ed-field hover:text-ed-text disabled:pointer-events-none disabled:opacity-30",
|
|
11613
|
-
children: /* @__PURE__ */
|
|
12174
|
+
children: /* @__PURE__ */ jsx14(IconCopy3, { size: 16 })
|
|
11614
12175
|
}
|
|
11615
12176
|
),
|
|
11616
|
-
/* @__PURE__ */
|
|
12177
|
+
/* @__PURE__ */ jsx14(
|
|
11617
12178
|
"button",
|
|
11618
12179
|
{
|
|
11619
12180
|
type: "button",
|
|
@@ -11621,13 +12182,13 @@ function Editor({
|
|
|
11621
12182
|
disabled: selectedIds.length === 0,
|
|
11622
12183
|
onClick: () => deleteElements(selectedIds),
|
|
11623
12184
|
className: "rounded-full p-1.5 transition-colors hover:bg-ed-field hover:text-ed-text disabled:pointer-events-none disabled:opacity-30",
|
|
11624
|
-
children: /* @__PURE__ */
|
|
12185
|
+
children: /* @__PURE__ */ jsx14(IconTrash8, { size: 16 })
|
|
11625
12186
|
}
|
|
11626
12187
|
)
|
|
11627
12188
|
] })
|
|
11628
12189
|
] })
|
|
11629
12190
|
] }) }),
|
|
11630
|
-
/* @__PURE__ */
|
|
12191
|
+
/* @__PURE__ */ jsxs13(
|
|
11631
12192
|
"main",
|
|
11632
12193
|
{
|
|
11633
12194
|
className: "relative flex flex-1 flex-col overflow-hidden bg-ed-canvas",
|
|
@@ -11642,7 +12203,7 @@ function Editor({
|
|
|
11642
12203
|
if (event.target === event.currentTarget) setSelectedIds([]);
|
|
11643
12204
|
},
|
|
11644
12205
|
children: [
|
|
11645
|
-
leftTab === "Templates" && /* @__PURE__ */
|
|
12206
|
+
leftTab === "Templates" && /* @__PURE__ */ jsx14("div", { className: "absolute inset-0 z-50 overflow-y-auto bg-ed-surface", children: /* @__PURE__ */ jsx14(
|
|
11646
12207
|
TemplatesPanel,
|
|
11647
12208
|
{
|
|
11648
12209
|
busy: isPending,
|
|
@@ -11654,7 +12215,7 @@ function Editor({
|
|
|
11654
12215
|
}
|
|
11655
12216
|
}
|
|
11656
12217
|
) }),
|
|
11657
|
-
/* @__PURE__ */
|
|
12218
|
+
/* @__PURE__ */ jsx14(
|
|
11658
12219
|
"div",
|
|
11659
12220
|
{
|
|
11660
12221
|
ref: viewportRef,
|
|
@@ -11676,7 +12237,7 @@ function Editor({
|
|
|
11676
12237
|
canvasY: rect ? Math.round((event.clientY - rect.top) / scale) : 0
|
|
11677
12238
|
});
|
|
11678
12239
|
},
|
|
11679
|
-
children: /* @__PURE__ */
|
|
12240
|
+
children: /* @__PURE__ */ jsx14(AnimatePresence7, { initial: false, mode: "wait", children: /* @__PURE__ */ jsx14(
|
|
11680
12241
|
motion7.div,
|
|
11681
12242
|
{
|
|
11682
12243
|
initial: reduceMotion ? false : { opacity: 0, y: 12, filter: "blur(5px)" },
|
|
@@ -11699,8 +12260,8 @@ function Editor({
|
|
|
11699
12260
|
const showFrameWidth = frameHeaderWidth >= 160;
|
|
11700
12261
|
const showFrameRange = frameHeaderWidth >= 330;
|
|
11701
12262
|
const showFrameActions = frameHeaderWidth >= 210;
|
|
11702
|
-
return /* @__PURE__ */
|
|
11703
|
-
/* @__PURE__ */
|
|
12263
|
+
return /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-2", children: [
|
|
12264
|
+
/* @__PURE__ */ jsxs13(
|
|
11704
12265
|
"div",
|
|
11705
12266
|
{
|
|
11706
12267
|
draggable: !componentMode,
|
|
@@ -11723,7 +12284,7 @@ function Editor({
|
|
|
11723
12284
|
className: `flex h-8 min-w-0 cursor-grab items-center gap-2 overflow-hidden rounded-lg border px-2 active:cursor-grabbing ${draggedBreakpointId === frame.bp ? "border-ed-accent bg-ed-accent/10 opacity-60" : "border-ed-border bg-ed-subtle"}`,
|
|
11724
12285
|
style: { width: frameHeaderWidth },
|
|
11725
12286
|
children: [
|
|
11726
|
-
editingBreakpointId === frame.bp && !componentMode ? /* @__PURE__ */
|
|
12287
|
+
editingBreakpointId === frame.bp && !componentMode ? /* @__PURE__ */ jsx14(
|
|
11727
12288
|
"input",
|
|
11728
12289
|
{
|
|
11729
12290
|
ref: (node2) => node2?.select(),
|
|
@@ -11740,7 +12301,7 @@ function Editor({
|
|
|
11740
12301
|
},
|
|
11741
12302
|
className: "min-w-0 flex-1 rounded bg-ed-field px-1 text-[11px] font-medium text-ed-text outline-none ring-1 ring-ed-accent"
|
|
11742
12303
|
}
|
|
11743
|
-
) : /* @__PURE__ */
|
|
12304
|
+
) : /* @__PURE__ */ jsx14(
|
|
11744
12305
|
"button",
|
|
11745
12306
|
{
|
|
11746
12307
|
type: "button",
|
|
@@ -11758,7 +12319,7 @@ function Editor({
|
|
|
11758
12319
|
children: componentMode ? `${frameMaster?.name ?? "Asset"} / ${frameMaster?.variant ?? "Default"}` : definition?.name ?? frame.bp
|
|
11759
12320
|
}
|
|
11760
12321
|
),
|
|
11761
|
-
componentMode && showFrameWidth ? /* @__PURE__ */
|
|
12322
|
+
componentMode && showFrameWidth ? /* @__PURE__ */ jsx14("span", { className: "font-mono text-[10px] text-ed-faint", children: `${frame.width} \xD7 ${frameCanvasHeight}` }) : !componentMode && showFrameWidth ? /* @__PURE__ */ jsx14(
|
|
11762
12323
|
"input",
|
|
11763
12324
|
{
|
|
11764
12325
|
type: "number",
|
|
@@ -11769,9 +12330,9 @@ function Editor({
|
|
|
11769
12330
|
className: "w-12 bg-transparent font-mono text-[10px] text-ed-faint outline-none hover:text-ed-muted focus:text-ed-text [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none"
|
|
11770
12331
|
}
|
|
11771
12332
|
) : null,
|
|
11772
|
-
!componentMode && showFrameRange && /* @__PURE__ */
|
|
11773
|
-
showFrameActions && /* @__PURE__ */
|
|
11774
|
-
!componentMode && /* @__PURE__ */
|
|
12333
|
+
!componentMode && showFrameRange && /* @__PURE__ */ jsx14("span", { className: "shrink-0 font-mono text-[10px] text-ed-faint/60", children: breakpointRange(frame.bp) }),
|
|
12334
|
+
showFrameActions && /* @__PURE__ */ jsxs13("div", { className: "ml-auto flex shrink-0 items-center gap-1", children: [
|
|
12335
|
+
!componentMode && /* @__PURE__ */ jsx14(
|
|
11775
12336
|
"button",
|
|
11776
12337
|
{
|
|
11777
12338
|
type: "button",
|
|
@@ -11782,10 +12343,10 @@ function Editor({
|
|
|
11782
12343
|
disabled: isBaseFrame,
|
|
11783
12344
|
title: isBaseFrame ? "Main breakpoint \u2014 its edits are shared" : "Make main breakpoint",
|
|
11784
12345
|
className: `flex size-5 items-center justify-center rounded-md ${isBaseFrame ? "bg-ed-accent/15 text-ed-accent" : "bg-ed-field text-ed-muted hover:bg-ed-field-hover hover:text-ed-text"}`,
|
|
11785
|
-
children: isBaseFrame ? /* @__PURE__ */
|
|
12346
|
+
children: isBaseFrame ? /* @__PURE__ */ jsx14(IconPinFilled, { size: 11 }) : /* @__PURE__ */ jsx14(IconPin, { size: 11 })
|
|
11786
12347
|
}
|
|
11787
12348
|
),
|
|
11788
|
-
!componentMode && breakpointDefs.length > 1 && /* @__PURE__ */
|
|
12349
|
+
!componentMode && breakpointDefs.length > 1 && /* @__PURE__ */ jsx14(
|
|
11789
12350
|
"button",
|
|
11790
12351
|
{
|
|
11791
12352
|
type: "button",
|
|
@@ -11795,19 +12356,19 @@ function Editor({
|
|
|
11795
12356
|
},
|
|
11796
12357
|
title: "Remove breakpoint",
|
|
11797
12358
|
className: "flex size-5 items-center justify-center rounded-md bg-ed-field text-ed-muted hover:bg-red-500/15 hover:text-red-400",
|
|
11798
|
-
children: /* @__PURE__ */
|
|
12359
|
+
children: /* @__PURE__ */ jsx14(IconTrash8, { size: 11 })
|
|
11799
12360
|
}
|
|
11800
12361
|
),
|
|
11801
|
-
/* @__PURE__ */
|
|
12362
|
+
/* @__PURE__ */ jsx14("button", { type: "button", onClick: (event) => {
|
|
11802
12363
|
event.stopPropagation();
|
|
11803
12364
|
if (componentMode) createComponentVariant();
|
|
11804
12365
|
else addBreakpoint();
|
|
11805
|
-
}, disabled: componentMode && !activeComponentMaster, className: "flex size-5 items-center justify-center rounded-md bg-ed-field text-ed-muted hover:bg-ed-field-hover hover:text-ed-text disabled:opacity-30", title: componentMode ? "Add variant" : "Add breakpoint", children: /* @__PURE__ */
|
|
12366
|
+
}, disabled: componentMode && !activeComponentMaster, className: "flex size-5 items-center justify-center rounded-md bg-ed-field text-ed-muted hover:bg-ed-field-hover hover:text-ed-text disabled:opacity-30", title: componentMode ? "Add variant" : "Add breakpoint", children: /* @__PURE__ */ jsx14(IconPlus8, { size: 12 }) })
|
|
11806
12367
|
] })
|
|
11807
12368
|
]
|
|
11808
12369
|
}
|
|
11809
12370
|
),
|
|
11810
|
-
/* @__PURE__ */
|
|
12371
|
+
/* @__PURE__ */ jsxs13(
|
|
11811
12372
|
"div",
|
|
11812
12373
|
{
|
|
11813
12374
|
className: "group/frame relative",
|
|
@@ -11817,7 +12378,7 @@ function Editor({
|
|
|
11817
12378
|
flexShrink: 0
|
|
11818
12379
|
},
|
|
11819
12380
|
children: [
|
|
11820
|
-
/* @__PURE__ */
|
|
12381
|
+
/* @__PURE__ */ jsx14(
|
|
11821
12382
|
"div",
|
|
11822
12383
|
{
|
|
11823
12384
|
ref: primary ? frameRef : void 0,
|
|
@@ -11837,7 +12398,7 @@ function Editor({
|
|
|
11837
12398
|
if (event.target === event.currentTarget)
|
|
11838
12399
|
beginMarquee(event, frame.bp);
|
|
11839
12400
|
},
|
|
11840
|
-
children: /* @__PURE__ */
|
|
12401
|
+
children: /* @__PURE__ */ jsxs13(
|
|
11841
12402
|
"div",
|
|
11842
12403
|
{
|
|
11843
12404
|
ref: primary ? canvasRef : void 0,
|
|
@@ -11867,7 +12428,7 @@ function Editor({
|
|
|
11867
12428
|
beginMarquee(event, frame.bp);
|
|
11868
12429
|
},
|
|
11869
12430
|
children: [
|
|
11870
|
-
frameElements.length === 0 && /* @__PURE__ */
|
|
12431
|
+
frameElements.length === 0 && /* @__PURE__ */ jsx14("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-center text-sm font-medium text-ed-muted", children: "Drag an element here to start" }),
|
|
11871
12432
|
childrenOf(frameElements, void 0).map(
|
|
11872
12433
|
(el) => renderNode(
|
|
11873
12434
|
el,
|
|
@@ -11876,7 +12437,7 @@ function Editor({
|
|
|
11876
12437
|
`${frame.bp}:`
|
|
11877
12438
|
)
|
|
11878
12439
|
),
|
|
11879
|
-
primary && guides.lines.map((guide) => /* @__PURE__ */
|
|
12440
|
+
primary && guides.lines.map((guide) => /* @__PURE__ */ jsx14(
|
|
11880
12441
|
"div",
|
|
11881
12442
|
{
|
|
11882
12443
|
className: "pointer-events-none absolute z-[9999] bg-fuchsia-500",
|
|
@@ -11899,14 +12460,14 @@ function Editor({
|
|
|
11899
12460
|
)
|
|
11900
12461
|
}
|
|
11901
12462
|
),
|
|
11902
|
-
componentMode && /* @__PURE__ */
|
|
12463
|
+
componentMode && /* @__PURE__ */ jsx14("button", { type: "button", "aria-label": "Resize component width", onMouseDown: (event) => {
|
|
11903
12464
|
if (frameMaster && frameMaster.id !== activeComponentMaster?.id) {
|
|
11904
12465
|
setActiveComponentMasterId(frameMaster.id);
|
|
11905
12466
|
setSelectedIds([frameMaster.id]);
|
|
11906
12467
|
}
|
|
11907
12468
|
beginComponentWidthResize(event, frameMaster);
|
|
11908
|
-
}, className: "absolute -right-1.5 inset-y-0 z-30 w-3 cursor-ew-resize opacity-0 transition-opacity group-hover/frame:opacity-100", children: /* @__PURE__ */
|
|
11909
|
-
primary && /* @__PURE__ */
|
|
12469
|
+
}, className: "absolute -right-1.5 inset-y-0 z-30 w-3 cursor-ew-resize opacity-0 transition-opacity group-hover/frame:opacity-100", children: /* @__PURE__ */ jsx14("span", { className: "absolute inset-y-1/2 left-1/2 h-12 w-1 -translate-x-1/2 -translate-y-1/2 rounded-full bg-ed-accent shadow-[0_0_0_3px_var(--ed-accent-soft)]" }) }),
|
|
12470
|
+
primary && /* @__PURE__ */ jsx14("button", { type: "button", "aria-label": `Resize ${componentMode ? "component" : "page"} canvas height`, onMouseDown: beginCanvasResize, className: "absolute -bottom-1.5 inset-x-0 z-30 h-3 cursor-ns-resize opacity-0 transition-opacity group-hover/frame:opacity-100", children: /* @__PURE__ */ jsx14("span", { className: "absolute left-1/2 top-1/2 h-1 w-14 -translate-x-1/2 -translate-y-1/2 rounded-full bg-ed-accent shadow-[0_0_0_3px_var(--ed-accent-soft)]" }) })
|
|
11910
12471
|
]
|
|
11911
12472
|
}
|
|
11912
12473
|
)
|
|
@@ -11917,7 +12478,7 @@ function Editor({
|
|
|
11917
12478
|
) })
|
|
11918
12479
|
}
|
|
11919
12480
|
),
|
|
11920
|
-
/* @__PURE__ */
|
|
12481
|
+
/* @__PURE__ */ jsx14("div", { className: "absolute bottom-0 left-0 z-20 flex h-8 w-full items-center gap-2 border-t border-ed-border bg-ed-surface px-4 text-[11px] text-ed-muted shadow-sm", children: /* @__PURE__ */ jsx14(
|
|
11921
12482
|
Breadcrumbs,
|
|
11922
12483
|
{
|
|
11923
12484
|
byId,
|
|
@@ -11925,24 +12486,24 @@ function Editor({
|
|
|
11925
12486
|
onSelect: (id) => setSelectedIds([id])
|
|
11926
12487
|
}
|
|
11927
12488
|
) }),
|
|
11928
|
-
/* @__PURE__ */
|
|
11929
|
-
/* @__PURE__ */
|
|
12489
|
+
/* @__PURE__ */ jsxs13("div", { className: "absolute bottom-12 right-6 z-20 flex items-center gap-0.5 rounded-lg border border-ed-border bg-ed-surface/90 p-1 backdrop-blur", children: [
|
|
12490
|
+
/* @__PURE__ */ jsx14("button", { type: "button", title: effectsPreview ? "Stop interaction preview" : "Preview hover, press and layer actions", onClick: () => {
|
|
11930
12491
|
setEffectsPreview((value) => !value);
|
|
11931
12492
|
setHoveredEffectIds(/* @__PURE__ */ new Set());
|
|
11932
12493
|
setPressedEffectId(null);
|
|
11933
12494
|
setPreviewVisibility({});
|
|
11934
|
-
}, className: `rounded-md p-1.5 transition-colors ${effectsPreview ? "bg-ed-accent text-white" : "text-ed-faint hover:bg-ed-field hover:text-ed-text"}`, children: /* @__PURE__ */
|
|
11935
|
-
/* @__PURE__ */
|
|
12495
|
+
}, className: `rounded-md p-1.5 transition-colors ${effectsPreview ? "bg-ed-accent text-white" : "text-ed-faint hover:bg-ed-field hover:text-ed-text"}`, children: /* @__PURE__ */ jsx14(IconPlayerPlay5, { size: 14, stroke: 1.5 }) }),
|
|
12496
|
+
/* @__PURE__ */ jsx14(
|
|
11936
12497
|
"button",
|
|
11937
12498
|
{
|
|
11938
12499
|
type: "button",
|
|
11939
12500
|
title: "Recentre the canvas",
|
|
11940
12501
|
onClick: recenter,
|
|
11941
12502
|
className: "rounded-md p-1.5 text-ed-faint transition-colors hover:bg-ed-field hover:text-ed-text",
|
|
11942
|
-
children: /* @__PURE__ */
|
|
12503
|
+
children: /* @__PURE__ */ jsx14(IconFocusCentered, { size: 16, stroke: 1.5 })
|
|
11943
12504
|
}
|
|
11944
12505
|
),
|
|
11945
|
-
/* @__PURE__ */
|
|
12506
|
+
/* @__PURE__ */ jsx14(
|
|
11946
12507
|
"button",
|
|
11947
12508
|
{
|
|
11948
12509
|
type: "button",
|
|
@@ -11952,22 +12513,22 @@ function Editor({
|
|
|
11952
12513
|
children: "1:1"
|
|
11953
12514
|
}
|
|
11954
12515
|
),
|
|
11955
|
-
/* @__PURE__ */
|
|
12516
|
+
/* @__PURE__ */ jsx14(
|
|
11956
12517
|
"button",
|
|
11957
12518
|
{
|
|
11958
12519
|
type: "button",
|
|
11959
12520
|
title: "Fit to width",
|
|
11960
12521
|
onClick: () => zoomToFit(),
|
|
11961
12522
|
className: "rounded-md p-1.5 text-ed-faint transition-colors hover:bg-ed-field hover:text-ed-text",
|
|
11962
|
-
children: /* @__PURE__ */
|
|
12523
|
+
children: /* @__PURE__ */ jsx14(IconArrowsMaximize, { size: 16, stroke: 1.5 })
|
|
11963
12524
|
}
|
|
11964
12525
|
)
|
|
11965
12526
|
] })
|
|
11966
12527
|
]
|
|
11967
12528
|
}
|
|
11968
12529
|
),
|
|
11969
|
-
/* @__PURE__ */
|
|
11970
|
-
/* @__PURE__ */
|
|
12530
|
+
/* @__PURE__ */ jsx14(AnimatePresence7, { initial: false, children: leftTab !== "Templates" && !isRightCollapsed && hasElementSelection && /* @__PURE__ */ jsxs13(motion7.aside, { initial: { width: 0, opacity: 0, x: 14 }, animate: { width: 312, opacity: 1, x: 0 }, exit: { width: 0, opacity: 0, x: 14 }, transition: { type: "spring", stiffness: 420, damping: 38 }, className: "z-10 flex w-[312px] shrink-0 flex-col overflow-hidden border-l border-ed-border bg-ed-surface/95 backdrop-blur-xl", children: [
|
|
12531
|
+
/* @__PURE__ */ jsx14("div", { className: "flex h-11 shrink-0 items-end gap-0.5 border-b border-ed-border px-2", children: ["Design", "Content", "Hover", "Interact"].map((tab) => /* @__PURE__ */ jsxs13(
|
|
11971
12532
|
"button",
|
|
11972
12533
|
{
|
|
11973
12534
|
type: "button",
|
|
@@ -11976,7 +12537,7 @@ function Editor({
|
|
|
11976
12537
|
className: `relative flex-1 px-2 pb-3 pt-2 text-[11px] font-medium transition-colors disabled:opacity-30 ${rightTab === tab ? "text-ed-text" : "text-ed-muted hover:text-ed-text"}`,
|
|
11977
12538
|
children: [
|
|
11978
12539
|
tab === "Hover" ? "Effects" : tab === "Interact" ? "Actions" : tab,
|
|
11979
|
-
rightTab === tab && selectedElement && /* @__PURE__ */
|
|
12540
|
+
rightTab === tab && selectedElement && /* @__PURE__ */ jsx14(
|
|
11980
12541
|
motion7.span,
|
|
11981
12542
|
{
|
|
11982
12543
|
layoutId: "inspector-tab",
|
|
@@ -11988,36 +12549,36 @@ function Editor({
|
|
|
11988
12549
|
},
|
|
11989
12550
|
tab
|
|
11990
12551
|
)) }),
|
|
11991
|
-
selectedElement && breakpoint !== "desktop" && /* @__PURE__ */
|
|
12552
|
+
selectedElement && breakpoint !== "desktop" && /* @__PURE__ */ jsxs13("p", { className: "border-b border-ed-border bg-amber-500/10 px-5 py-2.5 text-[11px] leading-relaxed text-amber-500", children: [
|
|
11992
12553
|
"Editing the ",
|
|
11993
|
-
/* @__PURE__ */
|
|
12554
|
+
/* @__PURE__ */ jsx14("b", { children: breakpoint }),
|
|
11994
12555
|
" breakpoint. Changes here override desktop and only apply at this size."
|
|
11995
12556
|
] }),
|
|
11996
|
-
/* @__PURE__ */
|
|
11997
|
-
/* @__PURE__ */
|
|
11998
|
-
/* @__PURE__ */
|
|
11999
|
-
/* @__PURE__ */
|
|
12557
|
+
/* @__PURE__ */ jsx14("div", { className: "custom-scrollbar flex flex-1 flex-col overflow-y-auto px-4 py-3", children: selectedElement ? /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
12558
|
+
/* @__PURE__ */ jsxs13("div", { className: "mb-1 flex items-baseline justify-between", children: [
|
|
12559
|
+
/* @__PURE__ */ jsx14("span", { className: "text-[15px] font-semibold tracking-tight text-ed-text", children: selectedElement.type }),
|
|
12560
|
+
/* @__PURE__ */ jsx14("span", { className: "font-mono text-[10px] text-ed-faint", children: selectedElement.id.slice(0, 6) })
|
|
12000
12561
|
] }),
|
|
12001
|
-
/* @__PURE__ */
|
|
12002
|
-
!componentMode && rootStyle.layout === "absolute" && selectedElement.parentId && /* @__PURE__ */
|
|
12003
|
-
selectedElement.componentRole === "master" && /* @__PURE__ */
|
|
12004
|
-
/* @__PURE__ */
|
|
12562
|
+
/* @__PURE__ */ jsxs13("div", { className: "mb-3 flex items-center gap-1.5", children: [
|
|
12563
|
+
!componentMode && rootStyle.layout === "absolute" && selectedElement.parentId && /* @__PURE__ */ jsx14("button", { type: "button", onClick: () => doReparent(selectedElement.id, void 0), className: "flex-1 rounded-lg border border-ed-border bg-ed-subtle px-2.5 py-2 text-[10px] font-medium text-ed-muted hover:border-ed-accent/50 hover:bg-ed-field hover:text-ed-text", children: "Detach to canvas" }),
|
|
12564
|
+
selectedElement.componentRole === "master" && /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
12565
|
+
/* @__PURE__ */ jsxs13("span", { className: "rounded-md bg-ed-accent/15 px-2 py-1 text-[9px] font-semibold uppercase text-ed-accent", children: [
|
|
12005
12566
|
"Master \xB7 ",
|
|
12006
12567
|
selectedElement.variant
|
|
12007
12568
|
] }),
|
|
12008
|
-
/* @__PURE__ */
|
|
12009
|
-
/* @__PURE__ */
|
|
12569
|
+
/* @__PURE__ */ jsx14("button", { type: "button", onClick: createComponentInstance, className: "rounded-lg bg-ed-field px-2 py-1.5 text-[9px] text-ed-text hover:bg-ed-field-hover", children: "Instance" }),
|
|
12570
|
+
/* @__PURE__ */ jsx14("button", { type: "button", onClick: createComponentVariant, className: "rounded-lg bg-ed-field px-2 py-1.5 text-[9px] text-ed-text hover:bg-ed-field-hover", children: "+ Variant" })
|
|
12010
12571
|
] }),
|
|
12011
|
-
selectedElement.componentRole === "instance" && /* @__PURE__ */
|
|
12572
|
+
selectedElement.componentRole === "instance" && /* @__PURE__ */ jsxs13(
|
|
12012
12573
|
Select,
|
|
12013
12574
|
{
|
|
12014
12575
|
value: selectedElement.variant ?? "Default",
|
|
12015
12576
|
onValueChange: switchInstanceVariant,
|
|
12016
12577
|
children: [
|
|
12017
|
-
/* @__PURE__ */
|
|
12018
|
-
/* @__PURE__ */
|
|
12578
|
+
/* @__PURE__ */ jsx14(SelectTrigger, { className: "h-8 min-w-0 flex-1", "aria-label": "Component variant", children: /* @__PURE__ */ jsx14(SelectValue, {}) }),
|
|
12579
|
+
/* @__PURE__ */ jsx14(SelectContent, { children: elements.filter(
|
|
12019
12580
|
(element) => element.componentRole === "master" && element.componentId === selectedElement.componentId
|
|
12020
|
-
).map((element) => /* @__PURE__ */
|
|
12581
|
+
).map((element) => /* @__PURE__ */ jsx14(
|
|
12021
12582
|
SelectItem,
|
|
12022
12583
|
{
|
|
12023
12584
|
value: element.variant ?? "Default",
|
|
@@ -12029,13 +12590,13 @@ function Editor({
|
|
|
12029
12590
|
}
|
|
12030
12591
|
)
|
|
12031
12592
|
] }),
|
|
12032
|
-
/* @__PURE__ */
|
|
12593
|
+
/* @__PURE__ */ jsx14(
|
|
12033
12594
|
motion7.div,
|
|
12034
12595
|
{
|
|
12035
12596
|
initial: { opacity: 0, y: 7 },
|
|
12036
12597
|
animate: { opacity: 1, y: 0 },
|
|
12037
12598
|
transition: { duration: 0.18, ease: [0.16, 1, 0.3, 1] },
|
|
12038
|
-
children: /* @__PURE__ */
|
|
12599
|
+
children: /* @__PURE__ */ jsx14(
|
|
12039
12600
|
Inspector,
|
|
12040
12601
|
{
|
|
12041
12602
|
tab: rightTab,
|
|
@@ -12057,7 +12618,7 @@ function Editor({
|
|
|
12057
12618
|
},
|
|
12058
12619
|
rightTab
|
|
12059
12620
|
)
|
|
12060
|
-
] }) : selectedIds.length > 1 ? /* @__PURE__ */
|
|
12621
|
+
] }) : selectedIds.length > 1 ? /* @__PURE__ */ jsx14(
|
|
12061
12622
|
MultiSelectPanel,
|
|
12062
12623
|
{
|
|
12063
12624
|
count: selectedIds.length,
|
|
@@ -12072,45 +12633,45 @@ function Editor({
|
|
|
12072
12633
|
) : null })
|
|
12073
12634
|
] }) })
|
|
12074
12635
|
] }),
|
|
12075
|
-
codeComposerOpen && /* @__PURE__ */
|
|
12076
|
-
/* @__PURE__ */
|
|
12077
|
-
/* @__PURE__ */
|
|
12078
|
-
/* @__PURE__ */
|
|
12079
|
-
/* @__PURE__ */
|
|
12636
|
+
codeComposerOpen && /* @__PURE__ */ jsx14("div", { className: "fixed inset-0 z-[100] flex items-center justify-center bg-black/65 p-6 backdrop-blur-sm", onMouseDown: () => setCodeComposerOpen(false), children: /* @__PURE__ */ jsxs13("div", { className: "flex h-[min(720px,85vh)] w-[min(820px,92vw)] flex-col overflow-hidden rounded-2xl border border-ed-border bg-ed-surface shadow-2xl", onMouseDown: (event) => event.stopPropagation(), children: [
|
|
12637
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex h-12 items-center justify-between border-b border-ed-border px-4", children: [
|
|
12638
|
+
/* @__PURE__ */ jsxs13("div", { children: [
|
|
12639
|
+
/* @__PURE__ */ jsx14("p", { className: "text-xs font-semibold text-ed-text", children: "New code component" }),
|
|
12640
|
+
/* @__PURE__ */ jsx14("p", { className: "text-[9px] text-ed-faint", children: "Sandboxed HTML and CSS \u2014 scripts stay disabled." })
|
|
12080
12641
|
] }),
|
|
12081
|
-
/* @__PURE__ */
|
|
12642
|
+
/* @__PURE__ */ jsx14("button", { type: "button", onClick: () => setCodeComposerOpen(false), className: "rounded-md p-1.5 text-ed-muted hover:bg-ed-field hover:text-ed-text", children: /* @__PURE__ */ jsx14(IconX6, { size: 15 }) })
|
|
12082
12643
|
] }),
|
|
12083
|
-
/* @__PURE__ */
|
|
12084
|
-
/* @__PURE__ */
|
|
12085
|
-
/* @__PURE__ */
|
|
12644
|
+
/* @__PURE__ */ jsxs13("div", { className: "grid min-h-0 flex-1 grid-cols-2", children: [
|
|
12645
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex min-h-0 flex-col gap-3 border-r border-ed-border p-4", children: [
|
|
12646
|
+
/* @__PURE__ */ jsxs13("label", { className: "text-[10px] font-medium text-ed-muted", children: [
|
|
12086
12647
|
"Name",
|
|
12087
|
-
/* @__PURE__ */
|
|
12648
|
+
/* @__PURE__ */ jsx14("input", { value: codeComponentName, onChange: (event) => setCodeComponentName(event.target.value), className: "mt-1.5 h-9 w-full rounded-lg border border-ed-border bg-ed-field px-3 text-[11px] text-ed-text outline-none focus:border-ed-accent" })
|
|
12088
12649
|
] }),
|
|
12089
|
-
/* @__PURE__ */
|
|
12650
|
+
/* @__PURE__ */ jsxs13("label", { className: "flex min-h-0 flex-1 flex-col text-[10px] font-medium text-ed-muted", children: [
|
|
12090
12651
|
"HTML / CSS",
|
|
12091
|
-
/* @__PURE__ */
|
|
12652
|
+
/* @__PURE__ */ jsx14("textarea", { value: codeComponentSource, onChange: (event) => setCodeComponentSource(event.target.value), spellCheck: false, className: "mt-1.5 min-h-0 flex-1 resize-none rounded-xl border border-ed-border bg-[#101114] p-3 font-mono text-[11px] leading-relaxed text-zinc-300 outline-none focus:border-ed-accent" })
|
|
12092
12653
|
] })
|
|
12093
12654
|
] }),
|
|
12094
|
-
/* @__PURE__ */
|
|
12095
|
-
/* @__PURE__ */
|
|
12096
|
-
/* @__PURE__ */
|
|
12655
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex min-h-0 flex-col bg-ed-canvas p-4", children: [
|
|
12656
|
+
/* @__PURE__ */ jsx14("span", { className: "mb-2 text-[10px] font-medium text-ed-muted", children: "Preview" }),
|
|
12657
|
+
/* @__PURE__ */ jsx14("iframe", { title: "Code component preview", srcDoc: codeComponentSource, sandbox: "", className: "min-h-0 flex-1 rounded-xl border border-ed-border bg-white" })
|
|
12097
12658
|
] })
|
|
12098
12659
|
] }),
|
|
12099
|
-
/* @__PURE__ */
|
|
12100
|
-
/* @__PURE__ */
|
|
12101
|
-
/* @__PURE__ */
|
|
12660
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex h-14 items-center justify-end gap-2 border-t border-ed-border px-4", children: [
|
|
12661
|
+
/* @__PURE__ */ jsx14("button", { type: "button", onClick: () => setCodeComposerOpen(false), className: "rounded-lg px-3 py-2 text-[10px] text-ed-muted hover:bg-ed-field", children: "Cancel" }),
|
|
12662
|
+
/* @__PURE__ */ jsx14("button", { type: "button", onClick: createCodeComponent, disabled: !codeComponentSource.trim(), className: "rounded-lg bg-ed-accent px-3 py-2 text-[10px] font-semibold text-white disabled:opacity-30", children: "Create component" })
|
|
12102
12663
|
] })
|
|
12103
12664
|
] }) }),
|
|
12104
|
-
breakpointPanel && !componentMode && /* @__PURE__ */
|
|
12105
|
-
/* @__PURE__ */
|
|
12106
|
-
/* @__PURE__ */
|
|
12107
|
-
/* @__PURE__ */
|
|
12108
|
-
/* @__PURE__ */
|
|
12665
|
+
breakpointPanel && !componentMode && /* @__PURE__ */ jsxs13("div", { className: "fixed left-1/2 top-16 z-[80] w-[420px] -translate-x-1/2 rounded-2xl border border-ed-border bg-ed-surface p-4 shadow-2xl", children: [
|
|
12666
|
+
/* @__PURE__ */ jsxs13("div", { className: "mb-4 flex items-start justify-between", children: [
|
|
12667
|
+
/* @__PURE__ */ jsxs13("div", { children: [
|
|
12668
|
+
/* @__PURE__ */ jsx14("h3", { className: "text-sm font-semibold text-ed-text", children: "Breakpoints" }),
|
|
12669
|
+
/* @__PURE__ */ jsx14("p", { className: "mt-1 text-[11px] text-ed-muted", children: "Rename, resize and reorder the viewports. Main values are shared by every other size." })
|
|
12109
12670
|
] }),
|
|
12110
|
-
/* @__PURE__ */
|
|
12671
|
+
/* @__PURE__ */ jsx14("button", { type: "button", onClick: () => setBreakpointPanel(false), className: "rounded p-1 text-ed-muted hover:bg-ed-field", children: /* @__PURE__ */ jsx14(IconX6, { size: 15 }) })
|
|
12111
12672
|
] }),
|
|
12112
|
-
/* @__PURE__ */
|
|
12113
|
-
/* @__PURE__ */
|
|
12673
|
+
/* @__PURE__ */ jsx14("div", { className: "flex max-h-[360px] flex-col gap-2 overflow-y-auto scrollbar-none", children: breakpointDefs.map((item, index) => /* @__PURE__ */ jsxs13("div", { className: "grid grid-cols-[1fr_86px_auto] items-center gap-2 rounded-xl border border-ed-border bg-ed-subtle p-2", children: [
|
|
12674
|
+
/* @__PURE__ */ jsx14(
|
|
12114
12675
|
"input",
|
|
12115
12676
|
{
|
|
12116
12677
|
"aria-label": "Breakpoint name",
|
|
@@ -12120,8 +12681,8 @@ function Editor({
|
|
|
12120
12681
|
className: "min-w-0 rounded-lg border border-ed-border bg-ed-field px-2.5 py-2 text-xs text-ed-text outline-none focus:border-ed-accent"
|
|
12121
12682
|
}
|
|
12122
12683
|
),
|
|
12123
|
-
/* @__PURE__ */
|
|
12124
|
-
/* @__PURE__ */
|
|
12684
|
+
/* @__PURE__ */ jsxs13("label", { className: "flex items-center rounded-lg border border-ed-border bg-ed-field px-2 py-2 text-xs text-ed-muted", children: [
|
|
12685
|
+
/* @__PURE__ */ jsx14(
|
|
12125
12686
|
"input",
|
|
12126
12687
|
{
|
|
12127
12688
|
"aria-label": "Breakpoint width",
|
|
@@ -12135,23 +12696,23 @@ function Editor({
|
|
|
12135
12696
|
),
|
|
12136
12697
|
"px"
|
|
12137
12698
|
] }),
|
|
12138
|
-
/* @__PURE__ */
|
|
12139
|
-
item.id === cascade.baseId ? /* @__PURE__ */
|
|
12140
|
-
/* @__PURE__ */
|
|
12699
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-0.5", children: [
|
|
12700
|
+
item.id === cascade.baseId ? /* @__PURE__ */ jsx14("span", { className: "rounded-md bg-ed-accent/15 px-2 py-1.5 text-[10px] font-semibold text-ed-accent", children: "MAIN" }) : /* @__PURE__ */ jsx14("button", { type: "button", title: "Make main", onClick: () => setBaseBreakpoint(item.id), className: "rounded-md px-2 py-1.5 text-[10px] font-semibold text-ed-muted hover:bg-ed-field hover:text-ed-text", children: "MAIN" }),
|
|
12701
|
+
/* @__PURE__ */ jsx14("button", { type: "button", disabled: index === 0, title: "Move left", onClick: () => {
|
|
12141
12702
|
const next = [...breakpointDefs];
|
|
12142
12703
|
[next[index - 1], next[index]] = [next[index], next[index - 1]];
|
|
12143
12704
|
updateBreakpoints(next);
|
|
12144
|
-
}, className: "rounded p-1 text-ed-faint hover:bg-ed-field disabled:opacity-20", children: /* @__PURE__ */
|
|
12145
|
-
/* @__PURE__ */
|
|
12705
|
+
}, className: "rounded p-1 text-ed-faint hover:bg-ed-field disabled:opacity-20", children: /* @__PURE__ */ jsx14(IconChevronLeft2, { size: 13 }) }),
|
|
12706
|
+
/* @__PURE__ */ jsx14("button", { type: "button", disabled: index === breakpointDefs.length - 1, title: "Move right", onClick: () => {
|
|
12146
12707
|
const next = [...breakpointDefs];
|
|
12147
12708
|
[next[index], next[index + 1]] = [next[index + 1], next[index]];
|
|
12148
12709
|
updateBreakpoints(next);
|
|
12149
|
-
}, className: "rounded p-1 text-ed-faint hover:bg-ed-field disabled:opacity-20", children: /* @__PURE__ */
|
|
12150
|
-
item.id !== cascade.baseId && breakpointDefs.length > 1 && /* @__PURE__ */
|
|
12710
|
+
}, className: "rounded p-1 text-ed-faint hover:bg-ed-field disabled:opacity-20", children: /* @__PURE__ */ jsx14(IconChevronRight6, { size: 13 }) }),
|
|
12711
|
+
item.id !== cascade.baseId && breakpointDefs.length > 1 && /* @__PURE__ */ jsx14("button", { type: "button", title: "Delete", onClick: () => removeBreakpoint(item.id), className: "rounded p-1 text-ed-faint hover:bg-red-500/10 hover:text-red-400", children: /* @__PURE__ */ jsx14(IconTrash8, { size: 13 }) })
|
|
12151
12712
|
] })
|
|
12152
12713
|
] }, item.id)) })
|
|
12153
12714
|
] }),
|
|
12154
|
-
contextMenu && menuElementId && /* @__PURE__ */
|
|
12715
|
+
contextMenu && menuElementId && /* @__PURE__ */ jsx14(
|
|
12155
12716
|
ContextMenu,
|
|
12156
12717
|
{
|
|
12157
12718
|
x: contextMenu.x,
|
|
@@ -12190,45 +12751,45 @@ function Editor({
|
|
|
12190
12751
|
onDelete: () => deleteElements([menuElementId])
|
|
12191
12752
|
}
|
|
12192
12753
|
),
|
|
12193
|
-
contextMenu && !contextMenu.elementId && /* @__PURE__ */
|
|
12194
|
-
["Text", "Heading", "Button", "Container"].map((type) => /* @__PURE__ */
|
|
12754
|
+
contextMenu && !contextMenu.elementId && /* @__PURE__ */ jsxs13("div", { className: "fixed z-[90] w-48 overflow-hidden rounded-xl border border-ed-border bg-ed-surface p-1.5 shadow-2xl", style: { left: contextMenu.x, top: contextMenu.y }, children: [
|
|
12755
|
+
["Text", "Heading", "Button", "Container"].map((type) => /* @__PURE__ */ jsxs13("button", { type: "button", onClick: () => {
|
|
12195
12756
|
const created = createElement(type, { x: contextMenu.canvasX ?? 0, y: contextMenu.canvasY ?? 0, z: nextZ(elements) });
|
|
12196
12757
|
if (type === "Text") created.content = "Canvas note";
|
|
12197
12758
|
setElements((current) => [...current, created]);
|
|
12198
12759
|
setSelectedIds([created.id]);
|
|
12199
12760
|
setContextMenu(null);
|
|
12200
12761
|
}, className: "flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-xs text-ed-muted hover:bg-ed-field hover:text-ed-text", children: [
|
|
12201
|
-
/* @__PURE__ */
|
|
12762
|
+
/* @__PURE__ */ jsx14(IconPlus8, { size: 13 }),
|
|
12202
12763
|
" Add ",
|
|
12203
12764
|
type
|
|
12204
12765
|
] }, type)),
|
|
12205
|
-
/* @__PURE__ */
|
|
12206
|
-
componentMode ? /* @__PURE__ */
|
|
12766
|
+
/* @__PURE__ */ jsx14("div", { className: "my-1 h-px bg-ed-border" }),
|
|
12767
|
+
componentMode ? /* @__PURE__ */ jsxs13("button", { type: "button", onClick: () => {
|
|
12207
12768
|
createComponentVariant();
|
|
12208
12769
|
setContextMenu(null);
|
|
12209
12770
|
}, disabled: !activeComponentMaster, className: "flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-xs font-medium text-ed-muted hover:bg-ed-field hover:text-ed-text disabled:opacity-30", children: [
|
|
12210
|
-
/* @__PURE__ */
|
|
12771
|
+
/* @__PURE__ */ jsx14(IconComponents2, { size: 13 }),
|
|
12211
12772
|
" Add variant"
|
|
12212
|
-
] }) : /* @__PURE__ */
|
|
12213
|
-
/* @__PURE__ */
|
|
12773
|
+
] }) : /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
12774
|
+
/* @__PURE__ */ jsxs13("button", { type: "button", onClick: () => {
|
|
12214
12775
|
addBreakpoint();
|
|
12215
12776
|
setBreakpointPanel(true);
|
|
12216
12777
|
setContextMenu(null);
|
|
12217
12778
|
}, className: "flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-xs font-medium text-ed-muted hover:bg-ed-field hover:text-ed-text", children: [
|
|
12218
|
-
/* @__PURE__ */
|
|
12779
|
+
/* @__PURE__ */ jsx14(IconLayoutColumns, { size: 13 }),
|
|
12219
12780
|
" Add breakpoint"
|
|
12220
12781
|
] }),
|
|
12221
|
-
/* @__PURE__ */
|
|
12782
|
+
/* @__PURE__ */ jsxs13("button", { type: "button", onClick: () => {
|
|
12222
12783
|
setBreakpointPanel(true);
|
|
12223
12784
|
setContextMenu(null);
|
|
12224
12785
|
}, className: "flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-xs text-ed-muted hover:bg-ed-field hover:text-ed-text", children: [
|
|
12225
|
-
/* @__PURE__ */
|
|
12786
|
+
/* @__PURE__ */ jsx14(IconBox3, { size: 13 }),
|
|
12226
12787
|
" Breakpoint settings"
|
|
12227
12788
|
] })
|
|
12228
12789
|
] })
|
|
12229
12790
|
] }),
|
|
12230
|
-
marquee && /* @__PURE__ */
|
|
12231
|
-
/* @__PURE__ */
|
|
12791
|
+
marquee && /* @__PURE__ */ jsx14("div", { className: "pointer-events-none fixed z-[110] border border-blue-400 bg-blue-500/20 shadow-[0_0_0_1px_rgba(59,130,246,.15)]", style: { left: Math.min(marquee.startX, marquee.x), top: Math.min(marquee.startY, marquee.y), width: Math.abs(marquee.x - marquee.startX), height: Math.abs(marquee.y - marquee.startY) } }),
|
|
12792
|
+
/* @__PURE__ */ jsx14(
|
|
12232
12793
|
"style",
|
|
12233
12794
|
{
|
|
12234
12795
|
dangerouslySetInnerHTML: {
|