camox 0.63.0 → 0.66.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/createApp.d.ts +28 -28
- package/dist/core/createLayout.d.ts +1 -1
- package/dist/core/derivedRoutes.js +3 -30
- package/dist/core/editing/createEditableBlock.d.ts +604 -604
- package/dist/features/canvas/CamoxCanvas.js +195 -173
- package/dist/features/canvas/canvasCamera.js +11 -2
- package/dist/features/canvas/canvasFrameCapture.js +5 -12
- package/dist/features/canvas/canvasFrameDocument.js +90 -29
- package/dist/features/canvas/canvasItems.js +22 -6
- package/dist/features/canvas/sidebar/ContentSidebar.js +19 -21
- package/dist/features/canvas/sidebar/LayoutPageOverview.js +22 -49
- package/dist/features/canvas/sidebar/LayoutPageSeo.js +73 -76
- package/dist/features/canvas/sidebar/PageInspector.js +61 -50
- package/dist/features/canvas/sidebar/PageInspectorSkeleton.js +4 -4
- package/dist/features/canvas/useCanvasCamera.js +36 -15
- package/dist/features/page/CuratedPageContent.js +2 -1
- package/dist/features/page/UnplacedBlockContent.js +52 -0
- package/dist/features/preview/components/PageInfo.js +103 -100
- package/dist/features/preview/components/PreviewPanel.js +40 -12
- package/dist/features/preview/components/SidebarStack.js +78 -9
- package/dist/features/preview/strayCaretGuard.js +34 -0
- package/dist/features/provider/CoreCamoxProvider.js +5 -3
- package/dist/features/routes/pageRuntime.d.ts +2 -0
- package/dist/features/routes/pageRuntime.js +8 -5
- package/dist/features/runtime/RuntimeChrome.js +66 -40
- package/dist/features/runtime/pageApp.js +111 -74
- package/dist/features/runtime/pageClient.js +22 -2
- package/dist/features/runtime/runtime.d.ts +10 -0
- package/dist/features/runtime/runtime.js +314 -4
- package/dist/features/runtime/runtimeRoutes.d.ts +5 -0
- package/dist/features/runtime/runtimeRoutes.js +5 -0
- package/dist/features/studio/components/AgentSidebar.js +3 -3
- package/dist/features/studio/components/ChatWidget.js +106 -75
- package/dist/features/studio/components/ConnectAgent.js +313 -0
- package/dist/features/studio/components/DraftsControl.js +172 -159
- package/dist/features/studio/components/Patrol.js +605 -350
- package/dist/features/studio/components/ReviewDraftSheet.js +566 -430
- package/dist/features/studio/components/Squareling.js +74 -41
- package/dist/features/studio/components/ThreadComposer.js +192 -107
- package/dist/features/studio/components/ThreadMessages.js +95 -18
- package/dist/features/studio/components/UnnamedDraftBar.js +349 -0
- package/dist/features/studio/components/clientLogoPaths.js +10 -0
- package/dist/features/studio/findingSentence.js +37 -0
- package/dist/features/studio/patrollerBio.js +40 -0
- package/dist/features/studio/reportSentence.js +15 -0
- package/dist/features/studio/studioStore.js +36 -1
- package/dist/features/studio/workingSentence.js +10 -7
- package/dist/lib/api-client.d.ts +1 -0
- package/dist/lib/auth.js +34 -32
- package/dist/lib/queries.js +9 -1
- package/dist/lib/revisions.js +25 -3
- package/dist/lib/server-auth-cookie.js +17 -4
- package/dist/lib/studio-reads.d.ts +1 -1
- package/dist/lib/studio-reads.js +5 -1
- package/dist/lib/use-thread.js +1 -1
- package/dist/package.js +1 -1
- package/dist/studio.css +1 -1
- package/package.json +15 -4
- package/dist/features/canvas/sidebar/DerivedPageInspector.js +0 -49
- package/dist/features/canvas/sidebar/SingletonPageInspector.js +0 -39
|
@@ -11,6 +11,7 @@ import { DebouncedFieldEditor } from "./DebouncedFieldEditor.js";
|
|
|
11
11
|
import { Metadata, MetadataRow, formatRelativeTime } from "./Metadata.js";
|
|
12
12
|
import { useLocalizedPath } from "../../../lib/view-locale.js";
|
|
13
13
|
import { PageInfoSkeleton } from "./PageInfoSkeleton.js";
|
|
14
|
+
import { useLatestRevision } from "../../../lib/revisions.js";
|
|
14
15
|
import { useRendererAnswer } from "../../renderer/RendererFrames.js";
|
|
15
16
|
import { PageLocationFieldset } from "./PageLocationFieldset.js";
|
|
16
17
|
import { PageNicknameField } from "./PageNicknameField.js";
|
|
@@ -1428,62 +1429,64 @@ const SearchEnginePreview = (t0) => {
|
|
|
1428
1429
|
return t10;
|
|
1429
1430
|
};
|
|
1430
1431
|
const SocialPreviewSection = (t0) => {
|
|
1431
|
-
const $ = c(
|
|
1432
|
+
const $ = c(61);
|
|
1432
1433
|
const { page, metaTitle, metaDescription } = t0;
|
|
1433
1434
|
const studioCache = useStudioCache();
|
|
1434
1435
|
const localized = useLocalizedPath();
|
|
1435
|
-
const { scope } = useOptionalDraftScope();
|
|
1436
|
+
const { scope, draftId } = useOptionalDraftScope();
|
|
1437
|
+
const revision = useLatestRevision(draftId);
|
|
1436
1438
|
let t1;
|
|
1437
1439
|
let t2;
|
|
1438
|
-
if ($[0] !== localized || $[1] !== page.fullPath || $[2] !== page.metaDescription || $[3] !== page.metaTitle) {
|
|
1439
|
-
const version = new URLSearchParams({ v: `${page.metaTitle ?? ""}|${page.metaDescription ?? ""}` });
|
|
1440
|
-
if ($[
|
|
1440
|
+
if ($[0] !== localized || $[1] !== page.fullPath || $[2] !== page.metaDescription || $[3] !== page.metaTitle || $[4] !== revision) {
|
|
1441
|
+
const version = new URLSearchParams({ v: `${page.metaTitle ?? ""}|${page.metaDescription ?? ""}|${revision ?? ""}` });
|
|
1442
|
+
if ($[7] !== localized || $[8] !== page.fullPath) {
|
|
1441
1443
|
t1 = pageImageUrl({
|
|
1442
1444
|
origin: "",
|
|
1443
1445
|
path: localized(page.fullPath)
|
|
1444
1446
|
});
|
|
1445
|
-
$[
|
|
1446
|
-
$[
|
|
1447
|
-
$[
|
|
1448
|
-
} else t1 = $[
|
|
1447
|
+
$[7] = localized;
|
|
1448
|
+
$[8] = page.fullPath;
|
|
1449
|
+
$[9] = t1;
|
|
1450
|
+
} else t1 = $[9];
|
|
1449
1451
|
t2 = version.toString();
|
|
1450
1452
|
$[0] = localized;
|
|
1451
1453
|
$[1] = page.fullPath;
|
|
1452
1454
|
$[2] = page.metaDescription;
|
|
1453
1455
|
$[3] = page.metaTitle;
|
|
1454
|
-
$[4] =
|
|
1455
|
-
$[5] =
|
|
1456
|
+
$[4] = revision;
|
|
1457
|
+
$[5] = t1;
|
|
1458
|
+
$[6] = t2;
|
|
1456
1459
|
} else {
|
|
1457
|
-
t1 = $[
|
|
1458
|
-
t2 = $[
|
|
1460
|
+
t1 = $[5];
|
|
1461
|
+
t2 = $[6];
|
|
1459
1462
|
}
|
|
1460
1463
|
const generatedOgImage = `${t1}&${t2}`;
|
|
1461
1464
|
let t3;
|
|
1462
|
-
if ($[
|
|
1465
|
+
if ($[10] !== generatedOgImage || $[11] !== page.customOgImageUrl || $[12] !== scope) {
|
|
1463
1466
|
t3 = page.customOgImageUrl || (scope?.hrefFor(generatedOgImage) ?? generatedOgImage);
|
|
1464
|
-
$[
|
|
1465
|
-
$[
|
|
1466
|
-
$[
|
|
1467
|
-
$[
|
|
1468
|
-
} else t3 = $[
|
|
1467
|
+
$[10] = generatedOgImage;
|
|
1468
|
+
$[11] = page.customOgImageUrl;
|
|
1469
|
+
$[12] = scope;
|
|
1470
|
+
$[13] = t3;
|
|
1471
|
+
} else t3 = $[13];
|
|
1469
1472
|
const ogImage = t3;
|
|
1470
1473
|
const origin = typeof window !== "undefined" ? window.location.origin : "";
|
|
1471
1474
|
let t4;
|
|
1472
|
-
if ($[
|
|
1475
|
+
if ($[14] !== localized || $[15] !== page.fullPath) {
|
|
1473
1476
|
t4 = localized(page.fullPath);
|
|
1474
|
-
$[
|
|
1475
|
-
$[
|
|
1476
|
-
$[
|
|
1477
|
-
} else t4 = $[
|
|
1477
|
+
$[14] = localized;
|
|
1478
|
+
$[15] = page.fullPath;
|
|
1479
|
+
$[16] = t4;
|
|
1480
|
+
} else t4 = $[16];
|
|
1478
1481
|
const url = `${origin}${t4}`;
|
|
1479
1482
|
const fileInputRef = React.useRef(null);
|
|
1480
1483
|
let t5;
|
|
1481
|
-
if ($[
|
|
1484
|
+
if ($[17] === Symbol.for("react.memo_cache_sentinel")) {
|
|
1482
1485
|
t5 = pageMutations.uploadCustomOgImage();
|
|
1483
|
-
$[
|
|
1484
|
-
} else t5 = $[
|
|
1486
|
+
$[17] = t5;
|
|
1487
|
+
} else t5 = $[17];
|
|
1485
1488
|
let t6;
|
|
1486
|
-
if ($[
|
|
1489
|
+
if ($[18] !== page.id || $[19] !== studioCache) {
|
|
1487
1490
|
t6 = {
|
|
1488
1491
|
...t5,
|
|
1489
1492
|
onSuccess: () => {
|
|
@@ -1491,18 +1494,18 @@ const SocialPreviewSection = (t0) => {
|
|
|
1491
1494
|
},
|
|
1492
1495
|
onError: _temp13
|
|
1493
1496
|
};
|
|
1494
|
-
$[
|
|
1495
|
-
$[
|
|
1496
|
-
$[
|
|
1497
|
-
} else t6 = $[
|
|
1497
|
+
$[18] = page.id;
|
|
1498
|
+
$[19] = studioCache;
|
|
1499
|
+
$[20] = t6;
|
|
1500
|
+
} else t6 = $[20];
|
|
1498
1501
|
const uploadCustomOgImage = useMutation(t6);
|
|
1499
1502
|
let t7;
|
|
1500
|
-
if ($[
|
|
1503
|
+
if ($[21] === Symbol.for("react.memo_cache_sentinel")) {
|
|
1501
1504
|
t7 = pageMutations.deleteCustomOgImage();
|
|
1502
|
-
$[
|
|
1503
|
-
} else t7 = $[
|
|
1505
|
+
$[21] = t7;
|
|
1506
|
+
} else t7 = $[21];
|
|
1504
1507
|
let t8;
|
|
1505
|
-
if ($[
|
|
1508
|
+
if ($[22] !== page.id || $[23] !== studioCache) {
|
|
1506
1509
|
t8 = {
|
|
1507
1510
|
...t7,
|
|
1508
1511
|
onSuccess: () => {
|
|
@@ -1510,15 +1513,15 @@ const SocialPreviewSection = (t0) => {
|
|
|
1510
1513
|
},
|
|
1511
1514
|
onError: _temp14
|
|
1512
1515
|
};
|
|
1513
|
-
$[
|
|
1514
|
-
$[
|
|
1515
|
-
$[
|
|
1516
|
-
} else t8 = $[
|
|
1516
|
+
$[22] = page.id;
|
|
1517
|
+
$[23] = studioCache;
|
|
1518
|
+
$[24] = t8;
|
|
1519
|
+
} else t8 = $[24];
|
|
1517
1520
|
const deleteCustomOgImage = useMutation(t8);
|
|
1518
1521
|
const hasCustomImage = !!page.customOgImageUrl;
|
|
1519
1522
|
const isBusy = uploadCustomOgImage.isPending || deleteCustomOgImage.isPending;
|
|
1520
1523
|
let t9;
|
|
1521
|
-
if ($[
|
|
1524
|
+
if ($[25] !== page.id || $[26] !== uploadCustomOgImage) {
|
|
1522
1525
|
t9 = (files) => {
|
|
1523
1526
|
const file = files[0];
|
|
1524
1527
|
if (file) uploadCustomOgImage.mutate({
|
|
@@ -1526,30 +1529,30 @@ const SocialPreviewSection = (t0) => {
|
|
|
1526
1529
|
file
|
|
1527
1530
|
});
|
|
1528
1531
|
};
|
|
1529
|
-
$[
|
|
1530
|
-
$[
|
|
1531
|
-
$[
|
|
1532
|
-
} else t9 = $[
|
|
1532
|
+
$[25] = page.id;
|
|
1533
|
+
$[26] = uploadCustomOgImage;
|
|
1534
|
+
$[27] = t9;
|
|
1535
|
+
} else t9 = $[27];
|
|
1533
1536
|
const handleFiles = t9;
|
|
1534
1537
|
let t10;
|
|
1535
|
-
if ($[
|
|
1538
|
+
if ($[28] === Symbol.for("react.memo_cache_sentinel")) {
|
|
1536
1539
|
t10 = /* @__PURE__ */ jsx(Label, { children: "Social preview" });
|
|
1537
|
-
$[
|
|
1538
|
-
} else t10 = $[
|
|
1540
|
+
$[28] = t10;
|
|
1541
|
+
} else t10 = $[28];
|
|
1539
1542
|
let t11;
|
|
1540
|
-
if ($[
|
|
1543
|
+
if ($[29] === Symbol.for("react.memo_cache_sentinel")) {
|
|
1541
1544
|
t11 = () => fileInputRef.current?.click();
|
|
1542
|
-
$[
|
|
1543
|
-
} else t11 = $[
|
|
1545
|
+
$[29] = t11;
|
|
1546
|
+
} else t11 = $[29];
|
|
1544
1547
|
let t12;
|
|
1545
|
-
if ($[
|
|
1548
|
+
if ($[30] !== uploadCustomOgImage.isPending) {
|
|
1546
1549
|
t12 = uploadCustomOgImage.isPending ? /* @__PURE__ */ jsx(Spinner, {}) : /* @__PURE__ */ jsx(Upload, { className: "size-3.5" });
|
|
1547
|
-
$[
|
|
1548
|
-
$[
|
|
1549
|
-
} else t12 = $[
|
|
1550
|
+
$[30] = uploadCustomOgImage.isPending;
|
|
1551
|
+
$[31] = t12;
|
|
1552
|
+
} else t12 = $[31];
|
|
1550
1553
|
const t13 = hasCustomImage ? "Replace custom image" : "Upload custom image";
|
|
1551
1554
|
let t14;
|
|
1552
|
-
if ($[
|
|
1555
|
+
if ($[32] !== isBusy || $[33] !== t12 || $[34] !== t13) {
|
|
1553
1556
|
t14 = /* @__PURE__ */ jsxs(Button, {
|
|
1554
1557
|
type: "button",
|
|
1555
1558
|
variant: "secondary",
|
|
@@ -1558,13 +1561,13 @@ const SocialPreviewSection = (t0) => {
|
|
|
1558
1561
|
onClick: t11,
|
|
1559
1562
|
children: [t12, t13]
|
|
1560
1563
|
});
|
|
1561
|
-
$[
|
|
1562
|
-
$[
|
|
1563
|
-
$[
|
|
1564
|
-
$[
|
|
1565
|
-
} else t14 = $[
|
|
1564
|
+
$[32] = isBusy;
|
|
1565
|
+
$[33] = t12;
|
|
1566
|
+
$[34] = t13;
|
|
1567
|
+
$[35] = t14;
|
|
1568
|
+
} else t14 = $[35];
|
|
1566
1569
|
let t15;
|
|
1567
|
-
if ($[
|
|
1570
|
+
if ($[36] !== deleteCustomOgImage || $[37] !== hasCustomImage || $[38] !== isBusy || $[39] !== page.id) {
|
|
1568
1571
|
t15 = hasCustomImage && /* @__PURE__ */ jsxs(Button, {
|
|
1569
1572
|
type: "button",
|
|
1570
1573
|
variant: "ghost",
|
|
@@ -1577,14 +1580,14 @@ const SocialPreviewSection = (t0) => {
|
|
|
1577
1580
|
"Clear"
|
|
1578
1581
|
]
|
|
1579
1582
|
});
|
|
1580
|
-
$[
|
|
1581
|
-
$[
|
|
1582
|
-
$[
|
|
1583
|
-
$[
|
|
1584
|
-
$[
|
|
1585
|
-
} else t15 = $[
|
|
1583
|
+
$[36] = deleteCustomOgImage;
|
|
1584
|
+
$[37] = hasCustomImage;
|
|
1585
|
+
$[38] = isBusy;
|
|
1586
|
+
$[39] = page.id;
|
|
1587
|
+
$[40] = t15;
|
|
1588
|
+
} else t15 = $[40];
|
|
1586
1589
|
let t16;
|
|
1587
|
-
if ($[
|
|
1590
|
+
if ($[41] !== handleFiles) {
|
|
1588
1591
|
t16 = /* @__PURE__ */ jsx("input", {
|
|
1589
1592
|
type: "file",
|
|
1590
1593
|
ref: fileInputRef,
|
|
@@ -1595,11 +1598,11 @@ const SocialPreviewSection = (t0) => {
|
|
|
1595
1598
|
e.target.value = "";
|
|
1596
1599
|
}
|
|
1597
1600
|
});
|
|
1598
|
-
$[
|
|
1599
|
-
$[
|
|
1600
|
-
} else t16 = $[
|
|
1601
|
+
$[41] = handleFiles;
|
|
1602
|
+
$[42] = t16;
|
|
1603
|
+
} else t16 = $[42];
|
|
1601
1604
|
let t17;
|
|
1602
|
-
if ($[
|
|
1605
|
+
if ($[43] !== t14 || $[44] !== t15 || $[45] !== t16) {
|
|
1603
1606
|
t17 = /* @__PURE__ */ jsxs("div", {
|
|
1604
1607
|
className: "flex items-center gap-2",
|
|
1605
1608
|
children: [
|
|
@@ -1608,47 +1611,47 @@ const SocialPreviewSection = (t0) => {
|
|
|
1608
1611
|
t16
|
|
1609
1612
|
]
|
|
1610
1613
|
});
|
|
1611
|
-
$[
|
|
1612
|
-
$[
|
|
1613
|
-
$[
|
|
1614
|
-
$[
|
|
1615
|
-
} else t17 = $[
|
|
1614
|
+
$[43] = t14;
|
|
1615
|
+
$[44] = t15;
|
|
1616
|
+
$[45] = t16;
|
|
1617
|
+
$[46] = t17;
|
|
1618
|
+
} else t17 = $[46];
|
|
1616
1619
|
const t18 = hasCustomImage ? "Drop image to replace" : "Drop image to upload";
|
|
1617
1620
|
let t19;
|
|
1618
|
-
if ($[
|
|
1621
|
+
if ($[47] !== ogImage) {
|
|
1619
1622
|
t19 = /* @__PURE__ */ jsx(SocialPreviewImage, { src: ogImage });
|
|
1620
|
-
$[
|
|
1621
|
-
$[
|
|
1622
|
-
} else t19 = $[
|
|
1623
|
+
$[47] = ogImage;
|
|
1624
|
+
$[48] = t19;
|
|
1625
|
+
} else t19 = $[48];
|
|
1623
1626
|
let t20;
|
|
1624
|
-
if ($[
|
|
1627
|
+
if ($[49] !== handleFiles || $[50] !== t18 || $[51] !== t19) {
|
|
1625
1628
|
t20 = /* @__PURE__ */ jsx(UploadDropZone, {
|
|
1626
1629
|
onDrop: handleFiles,
|
|
1627
1630
|
label: t18,
|
|
1628
1631
|
className: "block",
|
|
1629
1632
|
children: t19
|
|
1630
1633
|
});
|
|
1631
|
-
$[
|
|
1632
|
-
$[
|
|
1633
|
-
$[
|
|
1634
|
-
$[
|
|
1635
|
-
} else t20 = $[
|
|
1634
|
+
$[49] = handleFiles;
|
|
1635
|
+
$[50] = t18;
|
|
1636
|
+
$[51] = t19;
|
|
1637
|
+
$[52] = t20;
|
|
1638
|
+
} else t20 = $[52];
|
|
1636
1639
|
let t21;
|
|
1637
|
-
if ($[
|
|
1640
|
+
if ($[53] !== metaDescription || $[54] !== metaTitle || $[55] !== t20 || $[56] !== url) {
|
|
1638
1641
|
t21 = /* @__PURE__ */ jsx(SocialPreviewCard, {
|
|
1639
1642
|
image: t20,
|
|
1640
1643
|
metaTitle,
|
|
1641
1644
|
metaDescription,
|
|
1642
1645
|
url
|
|
1643
1646
|
});
|
|
1644
|
-
$[
|
|
1645
|
-
$[
|
|
1646
|
-
$[
|
|
1647
|
-
$[
|
|
1648
|
-
$[
|
|
1649
|
-
} else t21 = $[
|
|
1647
|
+
$[53] = metaDescription;
|
|
1648
|
+
$[54] = metaTitle;
|
|
1649
|
+
$[55] = t20;
|
|
1650
|
+
$[56] = url;
|
|
1651
|
+
$[57] = t21;
|
|
1652
|
+
} else t21 = $[57];
|
|
1650
1653
|
let t22;
|
|
1651
|
-
if ($[
|
|
1654
|
+
if ($[58] !== t17 || $[59] !== t21) {
|
|
1652
1655
|
t22 = /* @__PURE__ */ jsxs("div", {
|
|
1653
1656
|
className: "space-y-2 pt-2",
|
|
1654
1657
|
children: [
|
|
@@ -1657,10 +1660,10 @@ const SocialPreviewSection = (t0) => {
|
|
|
1657
1660
|
t21
|
|
1658
1661
|
]
|
|
1659
1662
|
});
|
|
1660
|
-
$[
|
|
1661
|
-
$[
|
|
1662
|
-
$[
|
|
1663
|
-
} else t22 = $[
|
|
1663
|
+
$[58] = t17;
|
|
1664
|
+
$[59] = t21;
|
|
1665
|
+
$[60] = t22;
|
|
1666
|
+
} else t22 = $[60];
|
|
1664
1667
|
return t22;
|
|
1665
1668
|
};
|
|
1666
1669
|
const SocialPreviewImage = (t0) => {
|
|
@@ -11,6 +11,7 @@ import { previewPageIframeProps, usePreviewPageFrame } from "../previewPageFrame
|
|
|
11
11
|
import { adoptCanvasDocument, pauseCanvasDocument } from "../../canvas/canvasFrameDocument.js";
|
|
12
12
|
import { forwardCanvasWheel, useCanvasFrameInput } from "../../canvas/useCanvasFrameInput.js";
|
|
13
13
|
import { useActionShortcuts } from "../../provider/useAdminShortcuts.js";
|
|
14
|
+
import { guardStrayCaret } from "../strayCaretGuard.js";
|
|
14
15
|
import { useBlockActionsShortcuts } from "./BlockActionsPopover.js";
|
|
15
16
|
import { FieldOverlayStyles } from "./FieldOverlayStyles.js";
|
|
16
17
|
import { MobilePreviewDrawer } from "./MobilePreviewDrawer.js";
|
|
@@ -60,6 +61,7 @@ const PreviewFrameEffects = () => {
|
|
|
60
61
|
t0 = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
61
62
|
/* @__PURE__ */ jsx(FieldOverlayStyles, {}),
|
|
62
63
|
/* @__PURE__ */ jsx(KeyDownForwarder, {}),
|
|
64
|
+
/* @__PURE__ */ jsx(StrayCaretGuard, {}),
|
|
63
65
|
/* @__PURE__ */ jsx(OverlayTracker, {})
|
|
64
66
|
] });
|
|
65
67
|
$[0] = t0;
|
|
@@ -72,6 +74,27 @@ const KeyDownForwarder = () => {
|
|
|
72
74
|
useActionShortcuts(inIframe ? iframeWindow : null);
|
|
73
75
|
return null;
|
|
74
76
|
};
|
|
77
|
+
const StrayCaretGuard = () => {
|
|
78
|
+
const $ = c(3);
|
|
79
|
+
const { window: iframeWindow } = useFrame();
|
|
80
|
+
let t0;
|
|
81
|
+
let t1;
|
|
82
|
+
if ($[0] !== iframeWindow) {
|
|
83
|
+
t0 = () => {
|
|
84
|
+
if (!iframeWindow) return;
|
|
85
|
+
return guardStrayCaret(iframeWindow.document);
|
|
86
|
+
};
|
|
87
|
+
t1 = [iframeWindow];
|
|
88
|
+
$[0] = iframeWindow;
|
|
89
|
+
$[1] = t0;
|
|
90
|
+
$[2] = t1;
|
|
91
|
+
} else {
|
|
92
|
+
t0 = $[1];
|
|
93
|
+
t1 = $[2];
|
|
94
|
+
}
|
|
95
|
+
React.useEffect(t0, t1);
|
|
96
|
+
return null;
|
|
97
|
+
};
|
|
75
98
|
/** The preview's read-only tree is never editable, whether or not the Canvas shows. */
|
|
76
99
|
const READ_ONLY_ARTIFACT_STUDIO = {
|
|
77
100
|
editing: false,
|
|
@@ -91,7 +114,7 @@ function CuratedBlockShortcuts() {
|
|
|
91
114
|
* when used, pauses with the camera, and draws its editing overlays.
|
|
92
115
|
*/
|
|
93
116
|
function PreviewPageCanvasEffects(t0) {
|
|
94
|
-
const $ = c(
|
|
117
|
+
const $ = c(31);
|
|
95
118
|
const { owner } = t0;
|
|
96
119
|
const { window: frameWindow, iframeElement } = useFrame();
|
|
97
120
|
const { frame, slot, inCanvas } = usePreviewPageFrame();
|
|
@@ -225,33 +248,38 @@ function PreviewPageCanvasEffects(t0) {
|
|
|
225
248
|
if (!placed) return null;
|
|
226
249
|
let t11;
|
|
227
250
|
let t12;
|
|
251
|
+
let t13;
|
|
228
252
|
if ($[24] === Symbol.for("react.memo_cache_sentinel")) {
|
|
229
253
|
t11 = /* @__PURE__ */ jsx(FieldOverlayStyles, {});
|
|
230
|
-
t12 = /* @__PURE__ */ jsx(
|
|
254
|
+
t12 = /* @__PURE__ */ jsx(StrayCaretGuard, {});
|
|
255
|
+
t13 = /* @__PURE__ */ jsx(OverlayTracker, {});
|
|
231
256
|
$[24] = t11;
|
|
232
257
|
$[25] = t12;
|
|
258
|
+
$[26] = t13;
|
|
233
259
|
} else {
|
|
234
260
|
t11 = $[24];
|
|
235
261
|
t12 = $[25];
|
|
262
|
+
t13 = $[26];
|
|
236
263
|
}
|
|
237
|
-
const
|
|
238
|
-
let
|
|
239
|
-
if ($[
|
|
240
|
-
|
|
264
|
+
const t14 = owner?.kind === "page";
|
|
265
|
+
let t15;
|
|
266
|
+
if ($[27] !== iframeElement || $[28] !== owner || $[29] !== t14) {
|
|
267
|
+
t15 = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
241
268
|
t11,
|
|
242
269
|
t12,
|
|
270
|
+
t13,
|
|
243
271
|
/* @__PURE__ */ jsx(Overlays, {
|
|
244
272
|
frame: iframeElement,
|
|
245
273
|
owner,
|
|
246
|
-
canAddBlocks:
|
|
274
|
+
canAddBlocks: t14
|
|
247
275
|
})
|
|
248
276
|
] });
|
|
249
|
-
$[
|
|
250
|
-
$[
|
|
251
|
-
$[28] = t13;
|
|
277
|
+
$[27] = iframeElement;
|
|
278
|
+
$[28] = owner;
|
|
252
279
|
$[29] = t14;
|
|
253
|
-
|
|
254
|
-
|
|
280
|
+
$[30] = t15;
|
|
281
|
+
} else t15 = $[30];
|
|
282
|
+
return t15;
|
|
255
283
|
}
|
|
256
284
|
function _temp(event) {
|
|
257
285
|
if (event.target?.closest?.("a")) event.preventDefault();
|
|
@@ -143,6 +143,8 @@ function SidebarStack(t0) {
|
|
|
143
143
|
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
144
144
|
t1 = {
|
|
145
145
|
ready: false,
|
|
146
|
+
boxes: /* @__PURE__ */ new Map(),
|
|
147
|
+
observer: null,
|
|
146
148
|
front: null,
|
|
147
149
|
behind: null,
|
|
148
150
|
inFront: null
|
|
@@ -156,8 +158,16 @@ function SidebarStack(t0) {
|
|
|
156
158
|
t2 = () => {
|
|
157
159
|
const current = motion.current;
|
|
158
160
|
current.ready = true;
|
|
161
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
162
|
+
const observer = new ResizeObserver(() => measureCards(current));
|
|
163
|
+
current.observer = observer;
|
|
164
|
+
for (const card of current.boxes.keys()) observer.observe(card);
|
|
165
|
+
if (current.inFront?.parentElement) observer.observe(current.inFront.parentElement);
|
|
166
|
+
}
|
|
159
167
|
return () => {
|
|
160
168
|
current.ready = false;
|
|
169
|
+
current.observer?.disconnect();
|
|
170
|
+
current.observer = null;
|
|
161
171
|
};
|
|
162
172
|
};
|
|
163
173
|
t3 = [];
|
|
@@ -233,20 +243,57 @@ function SidebarStack(t0) {
|
|
|
233
243
|
} else t9 = $[12];
|
|
234
244
|
return t9;
|
|
235
245
|
}
|
|
236
|
-
/**
|
|
237
|
-
|
|
238
|
-
|
|
246
|
+
/**
|
|
247
|
+
* Where a card is laid out relative to `stack`, whose box its layers fill. Offsets leave out the
|
|
248
|
+
* transforms that move cards as they come.
|
|
249
|
+
*/
|
|
250
|
+
function layoutBox(card, stack) {
|
|
251
|
+
let left = 0;
|
|
252
|
+
let top = 0;
|
|
253
|
+
let node = card;
|
|
254
|
+
while (node && node !== stack) {
|
|
255
|
+
left += node.offsetLeft;
|
|
256
|
+
top += node.offsetTop;
|
|
257
|
+
const parent = node.offsetParent;
|
|
258
|
+
if (parent && parent !== stack) {
|
|
259
|
+
left += parent.clientLeft;
|
|
260
|
+
top += parent.clientTop;
|
|
261
|
+
}
|
|
262
|
+
node = parent;
|
|
263
|
+
}
|
|
264
|
+
if (node === stack) return {
|
|
265
|
+
left,
|
|
266
|
+
top,
|
|
267
|
+
width: card.offsetWidth,
|
|
268
|
+
height: card.offsetHeight
|
|
269
|
+
};
|
|
270
|
+
const stackRect = stack.getBoundingClientRect();
|
|
239
271
|
const rect = card.getBoundingClientRect();
|
|
272
|
+
return {
|
|
273
|
+
left: rect.left - stackRect.left,
|
|
274
|
+
top: rect.top - stackRect.top,
|
|
275
|
+
width: rect.width,
|
|
276
|
+
height: rect.height
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
/** Notes where each card of the stack is laid out now. */
|
|
280
|
+
function measureCards(motion) {
|
|
281
|
+
const stack = motion.inFront?.parentElement;
|
|
282
|
+
if (!stack) return;
|
|
283
|
+
for (const card of motion.boxes.keys()) if (card.isConnected) motion.boxes.set(card, layoutBox(card, stack));
|
|
284
|
+
}
|
|
285
|
+
/** A still copy of a card, at `box`, so it can move away once the card is gone. */
|
|
286
|
+
function copyCard(card, box) {
|
|
240
287
|
const copy = card.cloneNode(true);
|
|
241
288
|
copy.setAttribute("aria-hidden", "true");
|
|
242
289
|
copy.setAttribute("inert", "");
|
|
243
290
|
Object.assign(copy.style, {
|
|
244
291
|
position: "absolute",
|
|
245
292
|
margin: "0",
|
|
246
|
-
left: `${
|
|
247
|
-
top: `${
|
|
248
|
-
width: `${
|
|
249
|
-
height: `${
|
|
293
|
+
left: `${box.left}px`,
|
|
294
|
+
top: `${box.top}px`,
|
|
295
|
+
width: `${box.width}px`,
|
|
296
|
+
height: `${box.height}px`
|
|
250
297
|
});
|
|
251
298
|
const scrolled = [];
|
|
252
299
|
const walk = (node, path) => {
|
|
@@ -276,6 +323,13 @@ function useStackCard(ref, depth, isView) {
|
|
|
276
323
|
const card = ref.current;
|
|
277
324
|
const motion = stack?.current;
|
|
278
325
|
if (!card || !motion || depth == null) return;
|
|
326
|
+
if (!motion.boxes.has(card)) motion.boxes.set(card, {
|
|
327
|
+
left: 0,
|
|
328
|
+
top: 0,
|
|
329
|
+
width: 0,
|
|
330
|
+
height: 0
|
|
331
|
+
});
|
|
332
|
+
motion.observer?.observe(card);
|
|
279
333
|
const previousFront = motion.front;
|
|
280
334
|
if (isView) motion.front = depth;
|
|
281
335
|
if (motion.ready && previousFront != null && prefersMotion()) {
|
|
@@ -289,10 +343,21 @@ function useStackCard(ref, depth, isView) {
|
|
|
289
343
|
}
|
|
290
344
|
return () => {
|
|
291
345
|
const { behind, inFront } = motion;
|
|
292
|
-
|
|
293
|
-
const
|
|
346
|
+
const box = motion.boxes.get(card);
|
|
347
|
+
const forget = () => {
|
|
348
|
+
motion.boxes.delete(card);
|
|
349
|
+
motion.observer?.unobserve(card);
|
|
350
|
+
};
|
|
351
|
+
if (!motion.ready || !behind || !inFront || !box || !prefersMotion()) {
|
|
352
|
+
queueMicrotask(() => {
|
|
353
|
+
if (!card.isConnected) forget();
|
|
354
|
+
});
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
const { copy, restoreScroll } = copyCard(card, box);
|
|
294
358
|
queueMicrotask(() => {
|
|
295
359
|
if (card.isConnected) return;
|
|
360
|
+
forget();
|
|
296
361
|
const how = motionFor(depth, motion.front ?? depth);
|
|
297
362
|
(how === "front" ? inFront : behind).append(copy);
|
|
298
363
|
restoreScroll();
|
|
@@ -303,6 +368,10 @@ function useStackCard(ref, depth, isView) {
|
|
|
303
368
|
});
|
|
304
369
|
};
|
|
305
370
|
}, []);
|
|
371
|
+
React.useLayoutEffect(() => {
|
|
372
|
+
const motion = stack?.current;
|
|
373
|
+
if (motion) measureCards(motion);
|
|
374
|
+
});
|
|
306
375
|
}
|
|
307
376
|
/**
|
|
308
377
|
* Eases a header's card and content from where they were laid out before `shape` changed to
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
//#region src/features/preview/strayCaretGuard.ts
|
|
2
|
+
/** Where the browser would put the caret for a click at this point. */
|
|
3
|
+
function caretNodeAt(doc, x, y) {
|
|
4
|
+
if (typeof doc.caretPositionFromPoint === "function") return doc.caretPositionFromPoint(x, y)?.offsetNode ?? null;
|
|
5
|
+
return doc.caretRangeFromPoint?.(x, y)?.startContainer ?? null;
|
|
6
|
+
}
|
|
7
|
+
function isEditable(node) {
|
|
8
|
+
return (node?.nodeType === 1 ? node : node?.parentElement ?? null)?.closest("[contenteditable=\"\"], [contenteditable=\"true\"]") != null;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Keep a click beside an editable field from landing in it. On a click over
|
|
12
|
+
* non-editable content, browsers put the caret at the nearest text, and when that
|
|
13
|
+
* text is in a field, they focus it: clicking a block's padding next to a heading
|
|
14
|
+
* starts editing the heading instead of selecting the block. Such a click now only
|
|
15
|
+
* leaves the field being edited, as a click on content without text would.
|
|
16
|
+
*/
|
|
17
|
+
function guardStrayCaret(doc) {
|
|
18
|
+
const onMouseDown = (event) => {
|
|
19
|
+
if (event.button !== 0) return;
|
|
20
|
+
const target = event.target;
|
|
21
|
+
if (!target || isEditable(target)) return;
|
|
22
|
+
if (target.closest?.("input, textarea, select, button")) return;
|
|
23
|
+
if (!isEditable(caretNodeAt(doc, event.clientX, event.clientY))) return;
|
|
24
|
+
event.preventDefault();
|
|
25
|
+
const active = doc.activeElement;
|
|
26
|
+
if (active?.isContentEditable) active.blur();
|
|
27
|
+
doc.getSelection()?.removeAllRanges();
|
|
28
|
+
};
|
|
29
|
+
doc.addEventListener("mousedown", onMouseDown, true);
|
|
30
|
+
return () => doc.removeEventListener("mousedown", onMouseDown, true);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
//#endregion
|
|
34
|
+
export { guardStrayCaret };
|
|
@@ -9,7 +9,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
9
9
|
import { replaceEqualDeep, useQueryClient } from "@tanstack/react-query";
|
|
10
10
|
|
|
11
11
|
//#region src/features/provider/CoreCamoxProvider.tsx
|
|
12
|
-
function CoreCamoxProvider({ apiUrl, authenticationUrl, camoxApp, children, projectUuid, initialAuthenticated = false, initialProject }) {
|
|
12
|
+
function CoreCamoxProvider({ apiUrl, authenticationUrl, camoxApp, children, projectUuid, initialAuthenticated = false, initialProject, sessionless = false }) {
|
|
13
13
|
const queryClient = useQueryClient();
|
|
14
14
|
const authClient = React.useMemo(() => createCamoxAuthClient(apiUrl), [apiUrl]);
|
|
15
15
|
const providedScope = React.useContext(DraftScopeContext);
|
|
@@ -48,14 +48,16 @@ function CoreCamoxProvider({ apiUrl, authenticationUrl, camoxApp, children, proj
|
|
|
48
48
|
apiUrl,
|
|
49
49
|
projectUuid,
|
|
50
50
|
initialAuthenticated,
|
|
51
|
-
exchangingToken
|
|
51
|
+
exchangingToken,
|
|
52
|
+
sessionless
|
|
52
53
|
}), [
|
|
53
54
|
authClient,
|
|
54
55
|
authenticationUrl,
|
|
55
56
|
apiUrl,
|
|
56
57
|
projectUuid,
|
|
57
58
|
initialAuthenticated,
|
|
58
|
-
exchangingToken
|
|
59
|
+
exchangingToken,
|
|
60
|
+
sessionless
|
|
59
61
|
]);
|
|
60
62
|
const [isPreviewHandoff, setIsPreviewHandoff] = React.useState(false);
|
|
61
63
|
React.useEffect(() => {
|
|
@@ -46,6 +46,8 @@ export interface DraftRead {
|
|
|
46
46
|
}
|
|
47
47
|
export declare function createServerApiClient(apiUrl: string, options?: {
|
|
48
48
|
authCookieHeader?: string;
|
|
49
|
+
/** A look token, which reads the draft it was signed for without a session (ADR 0032). */
|
|
50
|
+
lookToken?: string;
|
|
49
51
|
draftId?: string;
|
|
50
52
|
locale?: LocaleView;
|
|
51
53
|
}): RouterClient<Router>;
|