docblocks-react-ui 0.3.1 → 0.4.1
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/CHANGELOG.md +118 -0
- package/README.md +9 -2
- package/dist/{Editor-BvKqUGXH.mjs → Editor-CUToaW9z.mjs} +495 -283
- package/dist/{constants-D4FTL0ph.mjs → constants-BaAj3jDA.mjs} +52 -1
- package/dist/{index-DG0lJy_t.d.mts → index-BQRTt8x2.d.mts} +22 -10
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +8 -4
- package/dist/mermaid/index.mjs +2 -2
- package/dist/pdf/index.d.mts +1 -1
- package/dist/pdf/index.mjs +318 -51
- package/dist/styles.css +54 -0
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as ChevronLeft, c as isSafeDownloadHref, d as cn, i as ChevronRight, l as preventDefault, n as X, o as assertNever, r as TriangleAlert, s as clamp, t as isEmbeddablePdfUrl, u as stopPropagation } from "./constants-BaAj3jDA.mjs";
|
|
2
2
|
import { useStore } from "zustand";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { Component, Fragment, createContext, memo, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
@@ -2023,40 +2023,6 @@ function ChevronDown(props) {
|
|
|
2023
2023
|
});
|
|
2024
2024
|
}
|
|
2025
2025
|
//#endregion
|
|
2026
|
-
//#region src/shared/ui/icons/ChevronLeft.tsx
|
|
2027
|
-
function ChevronLeft(props) {
|
|
2028
|
-
return /* @__PURE__ */ jsx("svg", {
|
|
2029
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
2030
|
-
width: 24,
|
|
2031
|
-
height: 24,
|
|
2032
|
-
viewBox: "0 0 24 24",
|
|
2033
|
-
fill: "none",
|
|
2034
|
-
stroke: "currentColor",
|
|
2035
|
-
strokeWidth: 2,
|
|
2036
|
-
strokeLinecap: "round",
|
|
2037
|
-
strokeLinejoin: "round",
|
|
2038
|
-
...props,
|
|
2039
|
-
children: /* @__PURE__ */ jsx("path", { d: "m15 18-6-6 6-6" })
|
|
2040
|
-
});
|
|
2041
|
-
}
|
|
2042
|
-
//#endregion
|
|
2043
|
-
//#region src/shared/ui/icons/ChevronRight.tsx
|
|
2044
|
-
function ChevronRight(props) {
|
|
2045
|
-
return /* @__PURE__ */ jsx("svg", {
|
|
2046
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
2047
|
-
width: 24,
|
|
2048
|
-
height: 24,
|
|
2049
|
-
viewBox: "0 0 24 24",
|
|
2050
|
-
fill: "none",
|
|
2051
|
-
stroke: "currentColor",
|
|
2052
|
-
strokeWidth: 2,
|
|
2053
|
-
strokeLinecap: "round",
|
|
2054
|
-
strokeLinejoin: "round",
|
|
2055
|
-
...props,
|
|
2056
|
-
children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" })
|
|
2057
|
-
});
|
|
2058
|
-
}
|
|
2059
|
-
//#endregion
|
|
2060
2026
|
//#region src/shared/ui/icons/ChevronUp.tsx
|
|
2061
2027
|
function ChevronUp(props) {
|
|
2062
2028
|
return /* @__PURE__ */ jsx("svg", {
|
|
@@ -3767,23 +3733,6 @@ function Underline(props) {
|
|
|
3767
3733
|
});
|
|
3768
3734
|
}
|
|
3769
3735
|
//#endregion
|
|
3770
|
-
//#region src/shared/ui/icons/X.tsx
|
|
3771
|
-
function X(props) {
|
|
3772
|
-
return /* @__PURE__ */ jsxs("svg", {
|
|
3773
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
3774
|
-
width: 24,
|
|
3775
|
-
height: 24,
|
|
3776
|
-
viewBox: "0 0 24 24",
|
|
3777
|
-
fill: "none",
|
|
3778
|
-
stroke: "currentColor",
|
|
3779
|
-
strokeWidth: 2,
|
|
3780
|
-
strokeLinecap: "round",
|
|
3781
|
-
strokeLinejoin: "round",
|
|
3782
|
-
...props,
|
|
3783
|
-
children: [/* @__PURE__ */ jsx("path", { d: "M18 6 6 18" }), /* @__PURE__ */ jsx("path", { d: "m6 6 12 12" })]
|
|
3784
|
-
});
|
|
3785
|
-
}
|
|
3786
|
-
//#endregion
|
|
3787
3736
|
//#region src/shared/ui/icons/Zap.tsx
|
|
3788
3737
|
function Zap(props) {
|
|
3789
3738
|
return /* @__PURE__ */ jsx("svg", {
|
|
@@ -4137,7 +4086,11 @@ var blocks_default$1 = {
|
|
|
4137
4086
|
"wrap": "Wrap long lines",
|
|
4138
4087
|
"rendering": "rendering…",
|
|
4139
4088
|
"pdfPreviewUnavailable": "PDF preview unavailable ({error}). Showing the built-in viewer.",
|
|
4140
|
-
"pdfLoading": "loading preview…"
|
|
4089
|
+
"pdfLoading": "loading preview…",
|
|
4090
|
+
"pdfPrevPage": "Previous page",
|
|
4091
|
+
"pdfNextPage": "Next page",
|
|
4092
|
+
"pdfFullscreen": "Expand to fullscreen",
|
|
4093
|
+
"pdfCloseFullscreen": "Close fullscreen"
|
|
4141
4094
|
},
|
|
4142
4095
|
image: {
|
|
4143
4096
|
"placeholder": "image",
|
|
@@ -4149,7 +4102,13 @@ var blocks_default$1 = {
|
|
|
4149
4102
|
embed: {
|
|
4150
4103
|
"zoomIn": "Zoom in",
|
|
4151
4104
|
"zoomOut": "Zoom out",
|
|
4152
|
-
"zoomReset": "Reset zoom"
|
|
4105
|
+
"zoomReset": "Reset zoom",
|
|
4106
|
+
"resizeHeight": "Resize embed height",
|
|
4107
|
+
"editUrl": "Edit URL",
|
|
4108
|
+
"saveUrl": "Save URL",
|
|
4109
|
+
"cancelEdit": "Cancel",
|
|
4110
|
+
"srcPlaceholder": "Embed URL (https://…)",
|
|
4111
|
+
"unsafeHint": "Only absolute http(s):// URLs are supported."
|
|
4153
4112
|
},
|
|
4154
4113
|
syncEmbed: {
|
|
4155
4114
|
"broken": "The master document for this synced block is unavailable.",
|
|
@@ -4479,7 +4438,7 @@ var slash_default$1 = {
|
|
|
4479
4438
|
"code": "Code block",
|
|
4480
4439
|
"codeMermaid": "Code block (mermaid)",
|
|
4481
4440
|
"divider": "Divider",
|
|
4482
|
-
"
|
|
4441
|
+
"file": "File",
|
|
4483
4442
|
"embed": "Embed",
|
|
4484
4443
|
"database": "Database",
|
|
4485
4444
|
"frame": "Frame",
|
|
@@ -4507,7 +4466,7 @@ var slash_default$1 = {
|
|
|
4507
4466
|
},
|
|
4508
4467
|
embed: {
|
|
4509
4468
|
"urlPlaceholder": "Embed URL (https://…)",
|
|
4510
|
-
"unsafeHint": "Only absolute
|
|
4469
|
+
"unsafeHint": "Only absolute http(s):// URLs are supported."
|
|
4511
4470
|
}
|
|
4512
4471
|
};
|
|
4513
4472
|
//#endregion
|
|
@@ -4579,7 +4538,11 @@ var blocks_default = {
|
|
|
4579
4538
|
"wrap": "Переносить длинные строки",
|
|
4580
4539
|
"rendering": "Рисование…",
|
|
4581
4540
|
"pdfPreviewUnavailable": "Превью PDF недоступно ({error}). Показан встроенный просмотрщик.",
|
|
4582
|
-
"pdfLoading": "Загрузка превью…"
|
|
4541
|
+
"pdfLoading": "Загрузка превью…",
|
|
4542
|
+
"pdfPrevPage": "Предыдущая страница",
|
|
4543
|
+
"pdfNextPage": "Следующая страница",
|
|
4544
|
+
"pdfFullscreen": "Развернуть на весь экран",
|
|
4545
|
+
"pdfCloseFullscreen": "Закрыть полноэкранный режим"
|
|
4583
4546
|
},
|
|
4584
4547
|
image: {
|
|
4585
4548
|
"placeholder": "изображение",
|
|
@@ -4591,7 +4554,13 @@ var blocks_default = {
|
|
|
4591
4554
|
embed: {
|
|
4592
4555
|
"zoomIn": "Приблизить",
|
|
4593
4556
|
"zoomOut": "Отдалить",
|
|
4594
|
-
"zoomReset": "Сбросить масштаб"
|
|
4557
|
+
"zoomReset": "Сбросить масштаб",
|
|
4558
|
+
"resizeHeight": "Изменить высоту встраивания",
|
|
4559
|
+
"editUrl": "Изменить ссылку",
|
|
4560
|
+
"saveUrl": "Сохранить ссылку",
|
|
4561
|
+
"cancelEdit": "Отмена",
|
|
4562
|
+
"srcPlaceholder": "URL встраивания (https://…)",
|
|
4563
|
+
"unsafeHint": "Поддерживаются только абсолютные URL http(s)://."
|
|
4595
4564
|
},
|
|
4596
4565
|
syncEmbed: {
|
|
4597
4566
|
"broken": "Мастер-документ для этого синхронизируемого блока недоступен.",
|
|
@@ -4921,7 +4890,7 @@ var slash_default = {
|
|
|
4921
4890
|
"code": "Блок кода",
|
|
4922
4891
|
"codeMermaid": "Блок кода (mermaid)",
|
|
4923
4892
|
"divider": "Разделитель",
|
|
4924
|
-
"
|
|
4893
|
+
"file": "Файл",
|
|
4925
4894
|
"embed": "Встраивание",
|
|
4926
4895
|
"database": "База данных",
|
|
4927
4896
|
"frame": "Фрейм",
|
|
@@ -4949,7 +4918,7 @@ var slash_default = {
|
|
|
4949
4918
|
},
|
|
4950
4919
|
embed: {
|
|
4951
4920
|
"urlPlaceholder": "URL встраивания (https://…)",
|
|
4952
|
-
"unsafeHint": "
|
|
4921
|
+
"unsafeHint": "Поддерживаются только абсолютные URL http(s)://."
|
|
4953
4922
|
}
|
|
4954
4923
|
};
|
|
4955
4924
|
//#endregion
|
|
@@ -9575,6 +9544,7 @@ function GridBody({ blockId, bridge, tableId, filter, columnOrder, hiddenColumns
|
|
|
9575
9544
|
"data-slot": "docblocks/block",
|
|
9576
9545
|
"data-block-type": "database",
|
|
9577
9546
|
"data-block-id": blockId,
|
|
9547
|
+
className: "min-h-0 flex-1",
|
|
9578
9548
|
children: /* @__PURE__ */ jsx(CardContent, {
|
|
9579
9549
|
"data-slot": "docblocks/database",
|
|
9580
9550
|
"data-state": "loading",
|
|
@@ -9590,7 +9560,7 @@ function GridBody({ blockId, bridge, tableId, filter, columnOrder, hiddenColumns
|
|
|
9590
9560
|
"data-slot": "docblocks/block",
|
|
9591
9561
|
"data-block-type": "database",
|
|
9592
9562
|
"data-block-id": blockId,
|
|
9593
|
-
className: "\n my-(--docblocks-block-spacing) rounded-(--docblocks-radius)
|
|
9563
|
+
className: "\n my-(--docblocks-block-spacing) min-h-0 flex-1 rounded-(--docblocks-radius)\n border-(length:--docblocks-table-border-width) border-(--docblocks-table-border-color) outline-none\n ",
|
|
9594
9564
|
children: /* @__PURE__ */ jsxs(CardContent, {
|
|
9595
9565
|
"data-slot": "docblocks/database",
|
|
9596
9566
|
"data-state": "broken",
|
|
@@ -9682,10 +9652,10 @@ function GridBody({ blockId, bridge, tableId, filter, columnOrder, hiddenColumns
|
|
|
9682
9652
|
"data-block-type": "database",
|
|
9683
9653
|
"data-block-id": blockId,
|
|
9684
9654
|
"data-state": "ready",
|
|
9685
|
-
className: "\n my-(--docblocks-block-spacing) rounded-(--docblocks-radius)
|
|
9655
|
+
className: "\n my-(--docblocks-block-spacing) flex min-h-0 flex-1 flex-col rounded-(--docblocks-radius)\n border-(length:--docblocks-table-border-width) border-(--docblocks-table-border-color) outline-none\n ",
|
|
9686
9656
|
children: /* @__PURE__ */ jsxs(CardContent, {
|
|
9687
9657
|
"data-slot": "docblocks/database",
|
|
9688
|
-
className: "flex flex-col gap-(--docblocks-block-spacing) p-(--docblocks-block-spacing)",
|
|
9658
|
+
className: "flex min-h-0 flex-1 flex-col gap-(--docblocks-block-spacing) p-(--docblocks-block-spacing)",
|
|
9689
9659
|
children: [
|
|
9690
9660
|
/* @__PURE__ */ jsxs("div", {
|
|
9691
9661
|
"data-slot": "docblocks/database-toolbar",
|
|
@@ -9792,6 +9762,7 @@ function GridBody({ blockId, bridge, tableId, filter, columnOrder, hiddenColumns
|
|
|
9792
9762
|
}),
|
|
9793
9763
|
/* @__PURE__ */ jsxs(ScrollArea, {
|
|
9794
9764
|
"data-slot": "docblocks/database-grid",
|
|
9765
|
+
className: "min-h-0 flex-1",
|
|
9795
9766
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
9796
9767
|
ref: tableRef,
|
|
9797
9768
|
"data-slot": "docblocks/database-table",
|
|
@@ -10393,22 +10364,16 @@ function FrameSlashPicker({ onCommit, onCancel }) {
|
|
|
10393
10364
|
//#endregion
|
|
10394
10365
|
//#region src/editing/slash/SlashEmbedForm.tsx
|
|
10395
10366
|
/**
|
|
10396
|
-
* The slash `Embed` form (the embed-creation affordance):
|
|
10397
|
-
*
|
|
10398
|
-
* render as an iframe
|
|
10399
|
-
*
|
|
10400
|
-
*
|
|
10401
|
-
*
|
|
10402
|
-
*
|
|
10403
|
-
*/
|
|
10404
|
-
/** The embed's kind
|
|
10405
|
-
const
|
|
10406
|
-
"iframe",
|
|
10407
|
-
"github",
|
|
10408
|
-
"figma",
|
|
10409
|
-
"loom",
|
|
10410
|
-
"html"
|
|
10411
|
-
];
|
|
10367
|
+
* The slash `Embed` form (the embed-creation affordance): a URL input
|
|
10368
|
+
* (auto-focused) only — the kind stands the `iframe` default (the renderer's
|
|
10369
|
+
* hint; all kinds render as an iframe). The menu stands open over the phrase
|
|
10370
|
+
* while the form stands; the commit (the URL's Enter, or the check) lands the
|
|
10371
|
+
* phrase strip + the `insertBlock('embed', { kind: "iframe", src })` in the
|
|
10372
|
+
* caller's transact. An empty (or whitespace-only) URL commits nothing (the
|
|
10373
|
+
* menu stands open on the phrase — the Image / Database contract).
|
|
10374
|
+
*/
|
|
10375
|
+
/** The embed's kind (the renderer's hint — the form stands the URL only). */
|
|
10376
|
+
const EMBED_KIND_IFRAME = "iframe";
|
|
10412
10377
|
/** The form's i18n scope: the package's instance stands the provider's seat
|
|
10413
10378
|
* over the form (the form stands also outside the editor's scope). */
|
|
10414
10379
|
function SlashEmbedForm(props) {
|
|
@@ -10418,7 +10383,6 @@ function SlashEmbedForm(props) {
|
|
|
10418
10383
|
function SlashEmbedFormInner({ onCommit, onCancel }) {
|
|
10419
10384
|
const { t } = useTranslation("slash");
|
|
10420
10385
|
const [url, setUrl] = useState("");
|
|
10421
|
-
const [kind, setKind] = useState("iframe");
|
|
10422
10386
|
const urlInputRef = useRef(null);
|
|
10423
10387
|
useEffect(() => {
|
|
10424
10388
|
urlInputRef.current?.focus();
|
|
@@ -10426,18 +10390,15 @@ function SlashEmbedFormInner({ onCommit, onCancel }) {
|
|
|
10426
10390
|
const commit = () => {
|
|
10427
10391
|
const trimmed = url.trim();
|
|
10428
10392
|
if (trimmed.length === 0) return;
|
|
10429
|
-
if (!isSafeEmbedSrc(
|
|
10430
|
-
onCommit(
|
|
10431
|
-
kind,
|
|
10432
|
-
src: trimmed
|
|
10433
|
-
});
|
|
10393
|
+
if (!isSafeEmbedSrc(EMBED_KIND_IFRAME, trimmed)) return;
|
|
10394
|
+
onCommit(trimmed);
|
|
10434
10395
|
};
|
|
10435
10396
|
const stopFormKey = (event) => {
|
|
10436
10397
|
event.stopPropagation();
|
|
10437
10398
|
if (event.key === "Escape") onCancel();
|
|
10438
10399
|
};
|
|
10439
|
-
const canCommit = url.trim().length > 0 && isSafeEmbedSrc(
|
|
10440
|
-
const unsafeHint = url.trim().length > 0 && !isSafeEmbedSrc(
|
|
10400
|
+
const canCommit = url.trim().length > 0 && isSafeEmbedSrc(EMBED_KIND_IFRAME, url.trim());
|
|
10401
|
+
const unsafeHint = url.trim().length > 0 && !isSafeEmbedSrc(EMBED_KIND_IFRAME, url.trim()) ? t("embed.unsafeHint") : null;
|
|
10441
10402
|
const onUrlKeyDown = (event) => {
|
|
10442
10403
|
stopFormKey(event);
|
|
10443
10404
|
if (event.key === "Enter") {
|
|
@@ -10446,51 +10407,36 @@ function SlashEmbedFormInner({ onCommit, onCancel }) {
|
|
|
10446
10407
|
}
|
|
10447
10408
|
};
|
|
10448
10409
|
const onUrlChange = (event) => setUrl(event.target.value);
|
|
10449
|
-
const onKindChange = (event) => setKind(event.target.value);
|
|
10450
10410
|
return /* @__PURE__ */ jsxs("div", {
|
|
10451
10411
|
"data-slot": "docblocks/slash-embed-form",
|
|
10452
10412
|
className: "flex w-56 flex-col gap-2 p-1",
|
|
10453
|
-
children: [
|
|
10454
|
-
|
|
10413
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
10414
|
+
className: "flex items-center gap-1",
|
|
10415
|
+
children: [/* @__PURE__ */ jsx(Input, {
|
|
10455
10416
|
size: "sm",
|
|
10456
10417
|
ref: urlInputRef,
|
|
10457
10418
|
type: "text",
|
|
10458
10419
|
"data-slot": "docblocks/slash-embed-url",
|
|
10459
|
-
className: "rounded-sm",
|
|
10420
|
+
className: "h-7 flex-1 rounded-sm",
|
|
10460
10421
|
placeholder: t("embed.urlPlaceholder"),
|
|
10461
10422
|
value: url,
|
|
10462
10423
|
onKeyDown: onUrlKeyDown,
|
|
10463
10424
|
onChange: onUrlChange
|
|
10464
|
-
}),
|
|
10465
|
-
|
|
10466
|
-
|
|
10467
|
-
|
|
10468
|
-
|
|
10469
|
-
|
|
10470
|
-
|
|
10471
|
-
|
|
10472
|
-
|
|
10473
|
-
|
|
10474
|
-
|
|
10475
|
-
|
|
10476
|
-
|
|
10477
|
-
|
|
10478
|
-
|
|
10479
|
-
variant: "outline",
|
|
10480
|
-
size: "icon",
|
|
10481
|
-
className: "size-7 cursor-default rounded-sm bg-transparent disabled:cursor-default dark:bg-transparent",
|
|
10482
|
-
disabled: !canCommit,
|
|
10483
|
-
onMouseDown: preventDefault,
|
|
10484
|
-
onClick: commit,
|
|
10485
|
-
children: /* @__PURE__ */ jsx(Check, { className: "size-4" })
|
|
10486
|
-
})]
|
|
10487
|
-
}),
|
|
10488
|
-
unsafeHint !== null && /* @__PURE__ */ jsx("p", {
|
|
10489
|
-
"data-slot": "docblocks/slash-embed-hint",
|
|
10490
|
-
className: "px-1 text-xs text-destructive",
|
|
10491
|
-
children: unsafeHint
|
|
10492
|
-
})
|
|
10493
|
-
]
|
|
10425
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
10426
|
+
"data-slot": "docblocks/slash-embed-insert",
|
|
10427
|
+
variant: "outline",
|
|
10428
|
+
size: "icon",
|
|
10429
|
+
className: "\n size-7 shrink-0 cursor-default rounded-sm bg-transparent\n disabled:cursor-default\n dark:bg-transparent\n ",
|
|
10430
|
+
disabled: !canCommit,
|
|
10431
|
+
onMouseDown: preventDefault,
|
|
10432
|
+
onClick: commit,
|
|
10433
|
+
children: /* @__PURE__ */ jsx(Check, { className: "size-4" })
|
|
10434
|
+
})]
|
|
10435
|
+
}), unsafeHint !== null && /* @__PURE__ */ jsx("p", {
|
|
10436
|
+
"data-slot": "docblocks/slash-embed-hint",
|
|
10437
|
+
className: "px-1 text-xs text-destructive",
|
|
10438
|
+
children: unsafeHint
|
|
10439
|
+
})]
|
|
10494
10440
|
});
|
|
10495
10441
|
}
|
|
10496
10442
|
/** The v1 command list (filterable by the typed query). The `label` is the
|
|
@@ -10577,8 +10523,8 @@ const SLASH_COMMANDS = [
|
|
|
10577
10523
|
type: "divider"
|
|
10578
10524
|
},
|
|
10579
10525
|
{
|
|
10580
|
-
label: "
|
|
10581
|
-
labelKey: "blocks.
|
|
10526
|
+
label: "File",
|
|
10527
|
+
labelKey: "blocks.file",
|
|
10582
10528
|
icon: Image,
|
|
10583
10529
|
type: "image"
|
|
10584
10530
|
},
|
|
@@ -11263,7 +11209,7 @@ function useSlashMenu(rootRef) {
|
|
|
11263
11209
|
doc,
|
|
11264
11210
|
rootRef
|
|
11265
11211
|
]);
|
|
11266
|
-
const commitEmbed = useCallback((
|
|
11212
|
+
const commitEmbed = useCallback((src) => {
|
|
11267
11213
|
const pending = pendingEmbedRef.current;
|
|
11268
11214
|
pendingEmbedRef.current = null;
|
|
11269
11215
|
setEmbedForm(false);
|
|
@@ -11284,8 +11230,8 @@ function useSlashMenu(rootRef) {
|
|
|
11284
11230
|
doc.deleteText(blockId, slashOffset, queryEnd);
|
|
11285
11231
|
}
|
|
11286
11232
|
const embedId = doc.insertBlock("embed", {
|
|
11287
|
-
kind:
|
|
11288
|
-
src
|
|
11233
|
+
kind: "iframe",
|
|
11234
|
+
src,
|
|
11289
11235
|
...ind
|
|
11290
11236
|
}, {
|
|
11291
11237
|
parent: parentId,
|
|
@@ -11897,15 +11843,18 @@ function NotPublishedPlaceholder() {
|
|
|
11897
11843
|
//#endregion
|
|
11898
11844
|
//#region src/editor-provider/constants.ts
|
|
11899
11845
|
/**
|
|
11900
|
-
* The
|
|
11901
|
-
*
|
|
11902
|
-
*
|
|
11903
|
-
*
|
|
11904
|
-
*
|
|
11905
|
-
*
|
|
11906
|
-
*
|
|
11907
|
-
|
|
11908
|
-
|
|
11846
|
+
* The embed sandbox (the default when no `embedSandbox` policy is supplied):
|
|
11847
|
+
* the embedded content runs with its own origin's grants (`allow-same-origin`
|
|
11848
|
+
* — the real-app requirement: a dashboard's own storage / cookies stand,
|
|
11849
|
+
* so the app boots like in a plain tab) + scripts, forms, and popups.
|
|
11850
|
+
* The frame's document stands a separate document either way: a
|
|
11851
|
+
* cross-origin embed cannot reach the parent's DOM or state. The one
|
|
11852
|
+
* posture consequence: a same-origin URL (the page's own origin) reaches
|
|
11853
|
+
* the parent over `window.parent` — the document author's own choice to
|
|
11854
|
+
* embed it. The `embedSandbox` policy stands the restriction (the
|
|
11855
|
+
* opaque-origin stand — no `allow-same-origin` — for the untrusted embeds).
|
|
11856
|
+
*/
|
|
11857
|
+
const DEFAULT_EMBED_SANDBOX = "allow-scripts allow-same-origin allow-forms allow-popups";
|
|
11909
11858
|
const defaultEmbedSandbox = () => DEFAULT_EMBED_SANDBOX;
|
|
11910
11859
|
//#endregion
|
|
11911
11860
|
//#region src/editor-provider/context.ts
|
|
@@ -12738,20 +12687,34 @@ function DatabaseBlock({ id, block }) {
|
|
|
12738
12687
|
* only (all kinds render as an iframe; per-kind card renderers come later),
|
|
12739
12688
|
* so an unknown kind (newer data) still renders the same iframe. `src` is a
|
|
12740
12689
|
* URL, not a blob key: the consumer's blob resolver does not apply. The
|
|
12741
|
-
* iframe stands a `sandbox` attribute — the
|
|
12742
|
-
*
|
|
12743
|
-
*
|
|
12744
|
-
*
|
|
12745
|
-
*
|
|
12690
|
+
* iframe stands a `sandbox` attribute — the default grants the same-origin
|
|
12691
|
+
* (the embedded app's own storage / cookies stand, so the real apps boot
|
|
12692
|
+
* like in a plain tab) or the consumer's `embedSandbox` policy (the
|
|
12693
|
+
* opaque-origin's restriction over the untrusted, `null` for the fully
|
|
12694
|
+
* trusted). The block is not text-editable, so the wrapper carries no gutter
|
|
12746
12695
|
* handle.
|
|
12747
12696
|
*
|
|
12748
|
-
*
|
|
12697
|
+
* Height (the stretched stand): the wrapper's height stands the
|
|
12698
|
+
* `--docblocks-embed-height` token (the default — the minimum). The
|
|
12699
|
+
* bottom-edge resize handle (the hover reveal, the keyboard's arrows)
|
|
12700
|
+
* stretches it over the minimum; the stretched px stand the block's
|
|
12701
|
+
* `height` attr (the null idiom: null / absent = the token's default), so
|
|
12702
|
+
* the reload restores it and the panes share it over the wire (the commit
|
|
12703
|
+
* stands the gesture's rest — one write per drag, one per key press).
|
|
12704
|
+
*
|
|
12705
|
+
* Pan/zoom (the persisted view): the iframe stands a CSS
|
|
12749
12706
|
* `translate(x, y) scale(s)` transform (the wrapper clips the overflow). The
|
|
12750
|
-
*
|
|
12751
|
-
*
|
|
12752
|
-
*
|
|
12707
|
+
* view stands the block's `zoom` / `panX` / `panY` attrs (the null idiom:
|
|
12708
|
+
* null / absent = the identity) — the reload restores the view and the wire
|
|
12709
|
+
* carries it over the panes (the panes share the persisted view; a pane's
|
|
12710
|
+
* gesture writes over the doc, the others adopt it). The write is debounced
|
|
12711
|
+
* over the gesture's bursts (one doc write per rest). The controls:
|
|
12753
12712
|
*
|
|
12754
12713
|
* - the hover toolbar (zoom in / out, the percent, reset) — always stands;
|
|
12714
|
+
* - the toolbar's URL edit (the editing mode's stand): the panel over the
|
|
12715
|
+
* toolbar changes the `src` (the safe non-empty's write — the unsafe's
|
|
12716
|
+
* rejection over the slash form's rule; the iframe's navigation over the
|
|
12717
|
+
* new src, the view's / the height's attrs stand untouched);
|
|
12755
12718
|
* - the wheel — `ctrl`/`cmd` zooms at the cursor, a plain wheel pans
|
|
12756
12719
|
* vertically (content opposite to the delta, the canvas idiom);
|
|
12757
12720
|
* - the modifier drag — a `space` / `alt`-held pointer drag pans (the iframe
|
|
@@ -12771,12 +12734,36 @@ const EMBED_MAX_SCALE = 4;
|
|
|
12771
12734
|
const EMBED_ZOOM_STEP = 1.2;
|
|
12772
12735
|
/** The wheel's continuous zoom factor (the exponential of the delta, the canvas pinch idiom). */
|
|
12773
12736
|
const EMBED_WHEEL_ZOOM = .002;
|
|
12737
|
+
/** The view's persist debounce (the gesture's bursts stand one doc write per rest). */
|
|
12738
|
+
const EMBED_PERSIST_DEBOUNCE_MS = 250;
|
|
12739
|
+
/** The height's fallback minimum (px): the `--docblocks-embed-height` token's default (the non-CSS environment's stand — jsdom). */
|
|
12740
|
+
const EMBED_MIN_HEIGHT = 300;
|
|
12741
|
+
/** The resize handle's key step (px per arrow press). */
|
|
12742
|
+
const EMBED_RESIZE_KEY_STEP = 16;
|
|
12774
12743
|
/** The identity view: the iframe at its natural size, filling the wrapper. */
|
|
12775
12744
|
const EMBED_VIEW_IDENTITY = {
|
|
12776
12745
|
scale: 1,
|
|
12777
12746
|
x: 0,
|
|
12778
12747
|
y: 0
|
|
12779
12748
|
};
|
|
12749
|
+
/** The view over the block's persisted attrs (the null idiom's restore). */
|
|
12750
|
+
function viewOfAttrs(zoom, panX, panY) {
|
|
12751
|
+
return {
|
|
12752
|
+
scale: zoom ?? 1,
|
|
12753
|
+
x: panX ?? 0,
|
|
12754
|
+
y: panY ?? 0
|
|
12755
|
+
};
|
|
12756
|
+
}
|
|
12757
|
+
/**
|
|
12758
|
+
* The view's wire stand: the gesture's floating-point's residue must not
|
|
12759
|
+
* stand a non-identity's persist (the zoom-out/in's round-trip lands the
|
|
12760
|
+
* 0.9999…'s "identity"). The zoom's round to the label's 1%'s precision,
|
|
12761
|
+
* the pan's to the 0.1 px (the sub-pixel's residue stands the identity).
|
|
12762
|
+
*/
|
|
12763
|
+
function roundViewValue(value, places) {
|
|
12764
|
+
const factor = 10 ** places;
|
|
12765
|
+
return Math.round(value * factor) / factor;
|
|
12766
|
+
}
|
|
12780
12767
|
/**
|
|
12781
12768
|
* Clamp the pan against the scaled embed's overflow. The embed cannot be
|
|
12782
12769
|
* dragged past the container: at `scale <= 1` it fits (or is smaller) and
|
|
@@ -12802,17 +12789,61 @@ function zoomAtPoint(view, cx, cy, nextScale) {
|
|
|
12802
12789
|
y: cy - (cy - view.y) * factor
|
|
12803
12790
|
};
|
|
12804
12791
|
}
|
|
12792
|
+
/**
|
|
12793
|
+
* The height's wire stand: the token's minimum over the wrapper (the
|
|
12794
|
+
* themed token's stand), the fallback's default over the non-CSS's stand
|
|
12795
|
+
* (jsdom's empty computed value).
|
|
12796
|
+
*/
|
|
12797
|
+
function readEmbedMinHeight(wrapper) {
|
|
12798
|
+
const raw = getComputedStyle(wrapper).getPropertyValue("--docblocks-embed-height");
|
|
12799
|
+
const value = Number.parseFloat(raw);
|
|
12800
|
+
return Number.isFinite(value) && value > 0 ? value : EMBED_MIN_HEIGHT;
|
|
12801
|
+
}
|
|
12805
12802
|
function EmbedBlock({ id, block }) {
|
|
12806
12803
|
const { t } = useTranslation("blocks");
|
|
12807
12804
|
const { kind, src, title } = block.attrs;
|
|
12808
|
-
const { embedSandbox } = useEditorContext();
|
|
12805
|
+
const { doc, embedSandbox, viewMode } = useEditorContext();
|
|
12809
12806
|
const sandbox = embedSandbox(src);
|
|
12810
12807
|
const wrapperRef = useRef(null);
|
|
12811
|
-
const [view, setView] = useState(
|
|
12808
|
+
const [view, setView] = useState(() => viewOfAttrs(block.attrs.zoom, block.attrs.panX, block.attrs.panY));
|
|
12812
12809
|
const viewRef = useRef(view);
|
|
12813
12810
|
viewRef.current = view;
|
|
12811
|
+
const [height, setHeight] = useState(block.attrs.height ?? null);
|
|
12812
|
+
const heightRef = useRef(height);
|
|
12813
|
+
heightRef.current = height;
|
|
12814
|
+
const [tokenMin, setTokenMin] = useState(EMBED_MIN_HEIGHT);
|
|
12815
|
+
const resizeSession = useRef(null);
|
|
12814
12816
|
const [panModifier, setPanModifier] = useState(false);
|
|
12815
12817
|
const panSession = useRef(null);
|
|
12818
|
+
const [editOpen, setEditOpen] = useState(false);
|
|
12819
|
+
const [draft, setDraft] = useState(src);
|
|
12820
|
+
const editInputRef = useRef(null);
|
|
12821
|
+
/** The edit's open: the draft stands the block's own src (the cancel's restore). */
|
|
12822
|
+
const openEdit = () => {
|
|
12823
|
+
setDraft(src);
|
|
12824
|
+
setEditOpen(true);
|
|
12825
|
+
};
|
|
12826
|
+
const closeEdit = () => setEditOpen(false);
|
|
12827
|
+
useEffect(() => {
|
|
12828
|
+
if (editOpen) editInputRef.current?.focus();
|
|
12829
|
+
}, [editOpen]);
|
|
12830
|
+
const trimmedDraft = draft.trim();
|
|
12831
|
+
const canSave = trimmedDraft.length > 0 && isSafeEmbedSrc(kind, trimmedDraft);
|
|
12832
|
+
const editHint = trimmedDraft.length > 0 && !isSafeEmbedSrc(kind, trimmedDraft) ? t("embed.unsafeHint") : null;
|
|
12833
|
+
/** The edit's commit: the safe non-empty draft stands the `src`'s write.
|
|
12834
|
+
* The unchanged draft writes nothing (no updatedAt's stamp, no wire update). */
|
|
12835
|
+
const commitEdit = () => {
|
|
12836
|
+
if (!canSave) return;
|
|
12837
|
+
if (trimmedDraft !== src) doc.updateBlock(id, { src: trimmedDraft });
|
|
12838
|
+
setEditOpen(false);
|
|
12839
|
+
};
|
|
12840
|
+
const onEditKeyDown = (event) => {
|
|
12841
|
+
event.stopPropagation();
|
|
12842
|
+
if (event.key === "Enter") {
|
|
12843
|
+
event.preventDefault();
|
|
12844
|
+
commitEdit();
|
|
12845
|
+
} else if (event.key === "Escape") closeEdit();
|
|
12846
|
+
};
|
|
12816
12847
|
useEffect(() => {
|
|
12817
12848
|
const isPanModifier = (event) => event.code === "Space" || event.key === "Alt";
|
|
12818
12849
|
const onKeyDown = (event) => {
|
|
@@ -12879,6 +12910,125 @@ function EmbedBlock({ id, block }) {
|
|
|
12879
12910
|
const zoomOut = () => zoomBy(1 / EMBED_ZOOM_STEP);
|
|
12880
12911
|
const resetView = () => setView(EMBED_VIEW_IDENTITY);
|
|
12881
12912
|
const atIdentity = view.scale === EMBED_VIEW_IDENTITY.scale && view.x === 0 && view.y === 0;
|
|
12913
|
+
/**
|
|
12914
|
+
* The persisted view's write (the debounce over the gesture's bursts): the
|
|
12915
|
+
* non-identity view stands the block's attrs (the zoom / panX / panY — the
|
|
12916
|
+
* null idiom: the identity parts stand `null`, the reader's restore), so
|
|
12917
|
+
* the reload / the new tab's embed stands the same view. The values stand
|
|
12918
|
+
* the wire's precision (the 1%'s zoom, the 0.1 px's pan — the rounding's
|
|
12919
|
+
* guard over the floating-point's residue). The no-op stand: a view equal
|
|
12920
|
+
* to the block's own attrs writes nothing (no updatedAt's stamp, no wire
|
|
12921
|
+
* update).
|
|
12922
|
+
*/
|
|
12923
|
+
useEffect(() => {
|
|
12924
|
+
const zoom = roundViewValue(view.scale, 2);
|
|
12925
|
+
const x = roundViewValue(view.x, 1);
|
|
12926
|
+
const y = roundViewValue(view.y, 1);
|
|
12927
|
+
if (zoom === (block.attrs.zoom ?? 1) && x === (block.attrs.panX ?? 0) && y === (block.attrs.panY ?? 0)) return;
|
|
12928
|
+
const timer = window.setTimeout(() => {
|
|
12929
|
+
doc.updateBlock(id, {
|
|
12930
|
+
zoom: zoom === 1 ? null : zoom,
|
|
12931
|
+
panX: x === 0 ? null : x,
|
|
12932
|
+
panY: y === 0 ? null : y
|
|
12933
|
+
});
|
|
12934
|
+
}, EMBED_PERSIST_DEBOUNCE_MS);
|
|
12935
|
+
return () => window.clearTimeout(timer);
|
|
12936
|
+
}, [
|
|
12937
|
+
view,
|
|
12938
|
+
block.attrs,
|
|
12939
|
+
doc,
|
|
12940
|
+
id
|
|
12941
|
+
]);
|
|
12942
|
+
/**
|
|
12943
|
+
* The remote's stand: the panes share the persisted view over the wire — a
|
|
12944
|
+
* pane's peer lands a view different from the local's (the block's attrs
|
|
12945
|
+
* stand the peer's write), so the local's view adopts it. Own writes land
|
|
12946
|
+
* equal to the local's view and stand no adopt. The adopt clamps the
|
|
12947
|
+
* restored pan to the current wrapper (a stale pan over a narrower pane's
|
|
12948
|
+
* clip must not blank the embed).
|
|
12949
|
+
*/
|
|
12950
|
+
useEffect(() => {
|
|
12951
|
+
const scale = block.attrs.zoom ?? 1;
|
|
12952
|
+
const x = block.attrs.panX ?? 0;
|
|
12953
|
+
const y = block.attrs.panY ?? 0;
|
|
12954
|
+
const v = viewRef.current;
|
|
12955
|
+
if (scale === v.scale && x === v.x && y === v.y) return;
|
|
12956
|
+
const rect = wrapperRef.current?.getBoundingClientRect();
|
|
12957
|
+
const clamped = rect === void 0 || rect.width === 0 || rect.height === 0 ? {
|
|
12958
|
+
x,
|
|
12959
|
+
y
|
|
12960
|
+
} : clampEmbedPan(scale, x, y, rect.width, rect.height);
|
|
12961
|
+
setView({
|
|
12962
|
+
scale,
|
|
12963
|
+
x: clamped.x,
|
|
12964
|
+
y: clamped.y
|
|
12965
|
+
});
|
|
12966
|
+
}, [block.attrs]);
|
|
12967
|
+
/** The token's minimum's measure (the themed's stand) over the mount. */
|
|
12968
|
+
useLayoutEffect(() => {
|
|
12969
|
+
const wrapper = wrapperRef.current;
|
|
12970
|
+
if (wrapper === null) return;
|
|
12971
|
+
setTokenMin(readEmbedMinHeight(wrapper));
|
|
12972
|
+
}, []);
|
|
12973
|
+
/**
|
|
12974
|
+
* The remote's stand over the height: the panes share the stretched stand
|
|
12975
|
+
* over the wire — a pane's peer lands a height different from the local's
|
|
12976
|
+
* (the block's `height` attr's stand the peer's write), so the local's
|
|
12977
|
+
* state adopts it. Own commits land equal to the local's state and stand
|
|
12978
|
+
* no adopt.
|
|
12979
|
+
*/
|
|
12980
|
+
useEffect(() => {
|
|
12981
|
+
const attrHeight = block.attrs.height ?? null;
|
|
12982
|
+
if (attrHeight === heightRef.current) return;
|
|
12983
|
+
setHeight(attrHeight);
|
|
12984
|
+
}, [block.attrs]);
|
|
12985
|
+
const onResizePointerDown = (event) => {
|
|
12986
|
+
if (event.button !== 0) return;
|
|
12987
|
+
event.stopPropagation();
|
|
12988
|
+
const wrapper = wrapperRef.current;
|
|
12989
|
+
if (wrapper === null) return;
|
|
12990
|
+
const min = readEmbedMinHeight(wrapper);
|
|
12991
|
+
const rect = wrapper.getBoundingClientRect();
|
|
12992
|
+
event.target.setPointerCapture?.(event.pointerId);
|
|
12993
|
+
resizeSession.current = {
|
|
12994
|
+
pointerId: event.pointerId,
|
|
12995
|
+
startY: event.clientY,
|
|
12996
|
+
startHeight: rect.height,
|
|
12997
|
+
min,
|
|
12998
|
+
lastHeight: rect.height
|
|
12999
|
+
};
|
|
13000
|
+
};
|
|
13001
|
+
const onResizePointerMove = (event) => {
|
|
13002
|
+
const session = resizeSession.current;
|
|
13003
|
+
if (session === null || event.pointerId !== session.pointerId) return;
|
|
13004
|
+
const next = Math.max(session.startHeight + (event.clientY - session.startY), session.min);
|
|
13005
|
+
session.lastHeight = next;
|
|
13006
|
+
setHeight(next);
|
|
13007
|
+
};
|
|
13008
|
+
const endResize = (event) => {
|
|
13009
|
+
const session = resizeSession.current;
|
|
13010
|
+
if (session === null || event.pointerId !== session.pointerId) return;
|
|
13011
|
+
event.target.releasePointerCapture?.(event.pointerId);
|
|
13012
|
+
resizeSession.current = null;
|
|
13013
|
+
const committed = Math.round(session.lastHeight);
|
|
13014
|
+
if (committed <= session.min) {
|
|
13015
|
+
if ((block.attrs.height ?? null) !== null) doc.updateBlock(id, { height: null });
|
|
13016
|
+
} else if (committed !== (block.attrs.height ?? null)) doc.updateBlock(id, { height: committed });
|
|
13017
|
+
};
|
|
13018
|
+
const onResizeKeyDown = (event) => {
|
|
13019
|
+
const wrapper = wrapperRef.current;
|
|
13020
|
+
if (wrapper === null) return;
|
|
13021
|
+
const min = readEmbedMinHeight(wrapper);
|
|
13022
|
+
const delta = event.key === "ArrowDown" ? EMBED_RESIZE_KEY_STEP : event.key === "ArrowUp" ? -16 : null;
|
|
13023
|
+
if (delta === null) return;
|
|
13024
|
+
event.preventDefault();
|
|
13025
|
+
const current = Math.max(heightRef.current ?? min, min);
|
|
13026
|
+
const next = Math.max(current + delta, min);
|
|
13027
|
+
setHeight(next <= min ? null : next);
|
|
13028
|
+
if (next <= min) {
|
|
13029
|
+
if ((block.attrs.height ?? null) !== null) doc.updateBlock(id, { height: null });
|
|
13030
|
+
} else if (next !== (block.attrs.height ?? null)) doc.updateBlock(id, { height: next });
|
|
13031
|
+
};
|
|
12882
13032
|
const onPointerDown = (event) => {
|
|
12883
13033
|
if (!panModifier || event.button !== 0) return;
|
|
12884
13034
|
if (event.target.closest("button") !== null) return;
|
|
@@ -12920,71 +13070,151 @@ function EmbedBlock({ id, block }) {
|
|
|
12920
13070
|
"data-block-id": id,
|
|
12921
13071
|
"data-kind": kind,
|
|
12922
13072
|
className: "\n group relative my-(--docblocks-block-spacing) h-(--docblocks-embed-height) overflow-hidden\n rounded-(--docblocks-radius) border-(length:--docblocks-divider-border-width)\n border-(--docblocks-divider-border-color) outline-none\n ",
|
|
12923
|
-
style: {
|
|
13073
|
+
style: {
|
|
13074
|
+
...height !== null ? { height: Math.max(height, tokenMin) } : {},
|
|
13075
|
+
cursor: panModifier ? panSession.current !== null ? "grabbing" : "grab" : void 0
|
|
13076
|
+
},
|
|
12924
13077
|
onPointerDown,
|
|
12925
13078
|
onPointerMove,
|
|
12926
13079
|
onPointerUp: endPan,
|
|
12927
13080
|
onPointerCancel: endPan,
|
|
12928
|
-
children: [
|
|
12929
|
-
|
|
12930
|
-
|
|
12931
|
-
|
|
12932
|
-
|
|
12933
|
-
|
|
12934
|
-
|
|
12935
|
-
|
|
12936
|
-
|
|
12937
|
-
|
|
12938
|
-
|
|
12939
|
-
|
|
12940
|
-
|
|
12941
|
-
|
|
12942
|
-
|
|
12943
|
-
|
|
12944
|
-
|
|
12945
|
-
|
|
12946
|
-
|
|
12947
|
-
|
|
12948
|
-
|
|
12949
|
-
|
|
12950
|
-
|
|
12951
|
-
|
|
12952
|
-
|
|
12953
|
-
|
|
12954
|
-
|
|
12955
|
-
|
|
12956
|
-
|
|
12957
|
-
|
|
12958
|
-
|
|
12959
|
-
|
|
12960
|
-
|
|
12961
|
-
|
|
12962
|
-
|
|
12963
|
-
|
|
12964
|
-
|
|
12965
|
-
|
|
12966
|
-
|
|
12967
|
-
|
|
12968
|
-
|
|
12969
|
-
|
|
12970
|
-
|
|
12971
|
-
|
|
12972
|
-
|
|
12973
|
-
|
|
12974
|
-
|
|
12975
|
-
|
|
12976
|
-
|
|
12977
|
-
|
|
12978
|
-
|
|
12979
|
-
|
|
12980
|
-
|
|
12981
|
-
|
|
12982
|
-
|
|
12983
|
-
|
|
12984
|
-
|
|
12985
|
-
|
|
12986
|
-
|
|
12987
|
-
|
|
13081
|
+
children: [
|
|
13082
|
+
isSafeEmbedSrc(kind, src) ? /* @__PURE__ */ jsx("iframe", {
|
|
13083
|
+
"data-slot": "docblocks/embed",
|
|
13084
|
+
src,
|
|
13085
|
+
title: title ?? kind,
|
|
13086
|
+
loading: "lazy",
|
|
13087
|
+
sandbox: sandbox ?? void 0,
|
|
13088
|
+
className: "block h-full w-full border-0",
|
|
13089
|
+
style: {
|
|
13090
|
+
transform: `translate(${view.x}px, ${view.y}px) scale(${view.scale})`,
|
|
13091
|
+
transformOrigin: "0 0",
|
|
13092
|
+
pointerEvents: panModifier ? "none" : "auto"
|
|
13093
|
+
}
|
|
13094
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
13095
|
+
"data-slot": "docblocks/embed-blocked",
|
|
13096
|
+
className: "\n flex h-full w-full items-center justify-center p-4 text-center text-sm text-(--docblocks-muted-text-color)\n ",
|
|
13097
|
+
children: title ?? kind
|
|
13098
|
+
}),
|
|
13099
|
+
/* @__PURE__ */ jsxs("div", {
|
|
13100
|
+
"data-slot": "docblocks/embed-toolbar",
|
|
13101
|
+
className: "\n pointer-events-none absolute top-1.5 right-1.5 z-10 flex items-center gap-0.5 rounded-(--docblocks-radius)\n border-(length:--docblocks-divider-border-width) border-(--docblocks-divider-border-color)\n bg-(--docblocks-page-card-background) p-0.5 text-(--docblocks-text-color) opacity-0\n shadow-(--docblocks-formatbar-shadow) transition-opacity\n group-focus-within:pointer-events-auto group-focus-within:opacity-100\n group-hover:pointer-events-auto group-hover:opacity-100\n ",
|
|
13102
|
+
children: [
|
|
13103
|
+
/* @__PURE__ */ jsx(Button, {
|
|
13104
|
+
"data-slot": "docblocks/embed-zoom-out",
|
|
13105
|
+
variant: "ghost",
|
|
13106
|
+
size: "icon",
|
|
13107
|
+
"aria-label": t("embed.zoomOut"),
|
|
13108
|
+
className: "size-6 cursor-default rounded-sm text-(--docblocks-text-color) disabled:opacity-50",
|
|
13109
|
+
disabled: view.scale <= EMBED_MIN_SCALE,
|
|
13110
|
+
onMouseDown: preventDefault,
|
|
13111
|
+
onClick: zoomOut,
|
|
13112
|
+
children: /* @__PURE__ */ jsx(Minus, { className: "size-4" })
|
|
13113
|
+
}),
|
|
13114
|
+
/* @__PURE__ */ jsxs("span", {
|
|
13115
|
+
"data-slot": "docblocks/embed-zoom",
|
|
13116
|
+
className: "min-w-10 px-1 text-center text-xs text-(--docblocks-text-color) tabular-nums",
|
|
13117
|
+
children: [Math.round(view.scale * 100), "%"]
|
|
13118
|
+
}),
|
|
13119
|
+
/* @__PURE__ */ jsx(Button, {
|
|
13120
|
+
"data-slot": "docblocks/embed-zoom-in",
|
|
13121
|
+
variant: "ghost",
|
|
13122
|
+
size: "icon",
|
|
13123
|
+
"aria-label": t("embed.zoomIn"),
|
|
13124
|
+
className: "size-6 cursor-default rounded-sm text-(--docblocks-text-color) disabled:opacity-50",
|
|
13125
|
+
disabled: view.scale >= EMBED_MAX_SCALE,
|
|
13126
|
+
onMouseDown: preventDefault,
|
|
13127
|
+
onClick: zoomIn,
|
|
13128
|
+
children: /* @__PURE__ */ jsx(Plus, { className: "size-4" })
|
|
13129
|
+
}),
|
|
13130
|
+
/* @__PURE__ */ jsx(Button, {
|
|
13131
|
+
"data-slot": "docblocks/embed-zoom-reset",
|
|
13132
|
+
variant: "ghost",
|
|
13133
|
+
size: "icon",
|
|
13134
|
+
"aria-label": t("embed.zoomReset"),
|
|
13135
|
+
className: "size-6 cursor-default rounded-sm text-(--docblocks-text-color) disabled:opacity-50",
|
|
13136
|
+
disabled: atIdentity,
|
|
13137
|
+
onMouseDown: preventDefault,
|
|
13138
|
+
onClick: resetView,
|
|
13139
|
+
children: /* @__PURE__ */ jsx(RotateCcw, { className: "size-4" })
|
|
13140
|
+
}),
|
|
13141
|
+
!viewMode && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
|
|
13142
|
+
className: "mx-0.5 h-4 w-px bg-(--docblocks-divider-border-color)",
|
|
13143
|
+
"aria-hidden": true
|
|
13144
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
13145
|
+
"data-slot": "docblocks/embed-edit-url",
|
|
13146
|
+
variant: "ghost",
|
|
13147
|
+
size: "icon",
|
|
13148
|
+
"aria-label": t("embed.editUrl"),
|
|
13149
|
+
className: "size-6 cursor-default rounded-sm text-(--docblocks-text-color)",
|
|
13150
|
+
onMouseDown: preventDefault,
|
|
13151
|
+
onClick: openEdit,
|
|
13152
|
+
children: /* @__PURE__ */ jsx(Pen, { className: "size-4" })
|
|
13153
|
+
})] })
|
|
13154
|
+
]
|
|
13155
|
+
}),
|
|
13156
|
+
!viewMode && editOpen && /* @__PURE__ */ jsxs("div", {
|
|
13157
|
+
"data-slot": "docblocks/embed-edit",
|
|
13158
|
+
className: "\n absolute top-8 right-1.5 z-10 flex w-56 flex-col gap-1.5 rounded-(--docblocks-radius)\n border-(length:--docblocks-divider-border-width) border-(--docblocks-divider-border-color)\n bg-(--docblocks-page-card-background) p-1.5 text-(--docblocks-text-color)\n shadow-(--docblocks-formatbar-shadow)\n ",
|
|
13159
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
13160
|
+
className: "flex items-center gap-1",
|
|
13161
|
+
children: [
|
|
13162
|
+
/* @__PURE__ */ jsx(Input, {
|
|
13163
|
+
size: "sm",
|
|
13164
|
+
ref: editInputRef,
|
|
13165
|
+
type: "text",
|
|
13166
|
+
"data-slot": "docblocks/embed-edit-input",
|
|
13167
|
+
className: "h-7 flex-1 rounded-sm",
|
|
13168
|
+
placeholder: t("embed.srcPlaceholder"),
|
|
13169
|
+
value: draft,
|
|
13170
|
+
onChange: (event) => setDraft(event.target.value),
|
|
13171
|
+
onKeyDown: onEditKeyDown
|
|
13172
|
+
}),
|
|
13173
|
+
/* @__PURE__ */ jsx(Button, {
|
|
13174
|
+
"data-slot": "docblocks/embed-edit-save",
|
|
13175
|
+
variant: "ghost",
|
|
13176
|
+
size: "icon",
|
|
13177
|
+
"aria-label": t("embed.saveUrl"),
|
|
13178
|
+
className: "size-7 shrink-0 cursor-default rounded-sm text-(--docblocks-text-color) disabled:opacity-50",
|
|
13179
|
+
disabled: !canSave,
|
|
13180
|
+
onMouseDown: preventDefault,
|
|
13181
|
+
onClick: commitEdit,
|
|
13182
|
+
children: /* @__PURE__ */ jsx(Check, { className: "size-4" })
|
|
13183
|
+
}),
|
|
13184
|
+
/* @__PURE__ */ jsx(Button, {
|
|
13185
|
+
"data-slot": "docblocks/embed-edit-cancel",
|
|
13186
|
+
variant: "ghost",
|
|
13187
|
+
size: "icon",
|
|
13188
|
+
"aria-label": t("embed.cancelEdit"),
|
|
13189
|
+
className: "size-7 shrink-0 cursor-default rounded-sm text-(--docblocks-text-color)",
|
|
13190
|
+
onMouseDown: preventDefault,
|
|
13191
|
+
onClick: closeEdit,
|
|
13192
|
+
children: /* @__PURE__ */ jsx(X, { className: "size-4" })
|
|
13193
|
+
})
|
|
13194
|
+
]
|
|
13195
|
+
}), editHint !== null && /* @__PURE__ */ jsx("p", {
|
|
13196
|
+
"data-slot": "docblocks/embed-edit-hint",
|
|
13197
|
+
className: "px-1 text-xs text-destructive",
|
|
13198
|
+
children: editHint
|
|
13199
|
+
})]
|
|
13200
|
+
}),
|
|
13201
|
+
!viewMode && /* @__PURE__ */ jsx("div", {
|
|
13202
|
+
"data-slot": "docblocks/embed-resize",
|
|
13203
|
+
role: "slider",
|
|
13204
|
+
"aria-orientation": "vertical",
|
|
13205
|
+
"aria-valuemin": tokenMin,
|
|
13206
|
+
"aria-valuenow": Math.max(height ?? tokenMin, tokenMin),
|
|
13207
|
+
"aria-label": t("embed.resizeHeight"),
|
|
13208
|
+
tabIndex: 0,
|
|
13209
|
+
className: "\n absolute inset-x-0 bottom-0 z-10 flex h-2 cursor-row-resize items-end justify-center opacity-0\n transition-opacity outline-none\n group-focus-within:opacity-100\n group-hover:opacity-100\n ",
|
|
13210
|
+
onPointerDown: onResizePointerDown,
|
|
13211
|
+
onPointerMove: onResizePointerMove,
|
|
13212
|
+
onPointerUp: endResize,
|
|
13213
|
+
onPointerCancel: endResize,
|
|
13214
|
+
onKeyDown: onResizeKeyDown,
|
|
13215
|
+
children: /* @__PURE__ */ jsx("div", { className: "mb-0.5 h-0.5 w-10 rounded-full bg-(--docblocks-divider-border-color)" })
|
|
13216
|
+
})
|
|
13217
|
+
]
|
|
12988
13218
|
});
|
|
12989
13219
|
}
|
|
12990
13220
|
//#endregion
|
|
@@ -18092,7 +18322,8 @@ function TextBlock({ id, block, tag, nested, collapsible = false, flat = false,
|
|
|
18092
18322
|
size: "icon",
|
|
18093
18323
|
onClick: (event) => deleteBlock(event.currentTarget, id),
|
|
18094
18324
|
onMouseDown: onControlMouseDown,
|
|
18095
|
-
className: cn("absolute top-[calc((var(--docblocks-line-box-height)-var(--docblocks-gutter-size))/2)]
|
|
18325
|
+
className: cn("absolute top-[calc((var(--docblocks-line-box-height)-var(--docblocks-gutter-size))/2)]", "cursor-pointer rounded-full opacity-0 group-hover:opacity-100", "text-(--docblocks-gutter-color)", "size-5", selected && "opacity-100"),
|
|
18326
|
+
style: { right: "var(--docblocks-gutter-left)" },
|
|
18096
18327
|
children: /* @__PURE__ */ jsx(Trash, {})
|
|
18097
18328
|
}),
|
|
18098
18329
|
block.type === "list-item" && block.attrs.list === "task" && /* @__PURE__ */ jsx(Checkbox, {
|
|
@@ -18660,67 +18891,36 @@ function TitleMenu({ slot, ariaLabel, open, onOpenChange, onCommit }) {
|
|
|
18660
18891
|
//#endregion
|
|
18661
18892
|
//#region src/canvas/FrameBlock.tsx
|
|
18662
18893
|
/**
|
|
18663
|
-
* The canvas frame's renderer: the
|
|
18664
|
-
* frame
|
|
18665
|
-
* geometry + the selection + the move/resize preview;
|
|
18666
|
-
*
|
|
18667
|
-
*
|
|
18668
|
-
*
|
|
18669
|
-
* the
|
|
18670
|
-
*
|
|
18671
|
-
*
|
|
18672
|
-
*
|
|
18673
|
-
*
|
|
18674
|
-
|
|
18675
|
-
|
|
18676
|
-
* chip (the container's idiom) stands over the shared CanvasTitleChip.
|
|
18677
|
-
* The frame-chain's cycle guard: a frame rendered inside another frame's
|
|
18678
|
-
* window carries the chain's ids and excludes the chain + itself from its
|
|
18679
|
-
* window's content (the chain grows strictly down the nesting — the
|
|
18680
|
-
* recursion is finite, no depth limit needed).
|
|
18681
|
-
*/
|
|
18682
|
-
/** The frame chain's stand of a direct surface child (no window above).
|
|
18683
|
-
* The stable module constant stands the default — the memo's identity
|
|
18684
|
-
* comparison bails over the resting items. */
|
|
18685
|
-
const EMPTY_FRAME_CHAIN = /* @__PURE__ */ new Set();
|
|
18686
|
-
function FrameBlock({ id, movePreview = null, resizeBox = null, selected = false, frameChain = EMPTY_FRAME_CHAIN }) {
|
|
18894
|
+
* The canvas frame's renderer: the frame's boundary — the rectangle that
|
|
18895
|
+
* defines the region the page-frame block renders. The CanvasItem's wrapper
|
|
18896
|
+
* carries the geometry + the selection + the move/resize preview; the box
|
|
18897
|
+
* stands the container's thin rounded border (the selection's color on the
|
|
18898
|
+
* selection) over the canvas's own background. The frame renders the
|
|
18899
|
+
* boundary only — no content copy: the canvas's own figures stand behind the
|
|
18900
|
+
* transparent box (the canvas frame is a region marker, not a window), and
|
|
18901
|
+
* the content's mirror (the surface's children clipped to the frame's
|
|
18902
|
+
* region) stands on the page-frame block's side (FramePageBlock). The
|
|
18903
|
+
* frame's title chip (the container's idiom) stands over the shared
|
|
18904
|
+
* CanvasTitleChip.
|
|
18905
|
+
*/
|
|
18906
|
+
function FrameBlock({ id, selected = false }) {
|
|
18687
18907
|
const { t } = useTranslation("canvas");
|
|
18688
|
-
const {
|
|
18908
|
+
const { parentType } = useBlockContext();
|
|
18689
18909
|
const block = useBlock(id);
|
|
18690
18910
|
if (parentType !== "surface" || block === void 0 || block.type !== "frame") return /* @__PURE__ */ jsx(PlaceholderBlock, { type: "frame" });
|
|
18691
|
-
const committed = effectiveGeometry(block);
|
|
18692
|
-
const effective = {
|
|
18693
|
-
x: (resizeBox?.x ?? committed.x) + (movePreview?.dx ?? 0),
|
|
18694
|
-
y: (resizeBox?.y ?? committed.y) + (movePreview?.dy ?? 0),
|
|
18695
|
-
w: resizeBox?.w ?? committed.w,
|
|
18696
|
-
h: resizeBox?.h ?? committed.h
|
|
18697
|
-
};
|
|
18698
|
-
const offset = frameWindowOffset(effective);
|
|
18699
18911
|
const selectedColor = "var(--docblocks-canvas-selection-border-color)";
|
|
18700
|
-
const ringColor = selected ? selectedColor : "var(--docblocks-canvas-group-border-color)";
|
|
18701
|
-
const boxStyle = {
|
|
18702
|
-
backgroundColor: "var(--docblocks-canvas-background)",
|
|
18703
|
-
...frameDotBackground(effective.x - effective.w / 2, effective.y - effective.h / 2),
|
|
18704
|
-
boxShadow: `inset 0 0 0 1px ${ringColor}`,
|
|
18705
|
-
outline: selected ? `var(--docblocks-canvas-selection-border-width) solid ${selectedColor}` : void 0,
|
|
18706
|
-
outlineOffset: 1
|
|
18707
|
-
};
|
|
18708
|
-
const excludedIds = useMemo(() => [...frameChain, id], [frameChain, id]);
|
|
18709
|
-
const childFrameChain = useMemo(() => /* @__PURE__ */ new Set([...frameChain, id]), [frameChain, id]);
|
|
18710
18912
|
return /* @__PURE__ */ jsxs("div", {
|
|
18711
18913
|
"data-slot": "docblocks/frame",
|
|
18712
18914
|
"data-block-id": id,
|
|
18713
18915
|
className: "h-full w-full",
|
|
18714
18916
|
children: [/* @__PURE__ */ jsx("div", {
|
|
18715
|
-
"data-slot": "docblocks/frame-
|
|
18716
|
-
className: "absolute inset-0
|
|
18717
|
-
style:
|
|
18718
|
-
|
|
18719
|
-
|
|
18720
|
-
|
|
18721
|
-
|
|
18722
|
-
frameChain: childFrameChain
|
|
18723
|
-
})
|
|
18917
|
+
"data-slot": "docblocks/frame-boundary",
|
|
18918
|
+
className: "absolute inset-0 rounded-(--docblocks-radius)",
|
|
18919
|
+
style: {
|
|
18920
|
+
boxShadow: `inset 0 0 0 1px ${selected ? selectedColor : "var(--docblocks-canvas-group-border-color)"}`,
|
|
18921
|
+
outline: selected ? `var(--docblocks-canvas-selection-border-width) solid ${selectedColor}` : void 0,
|
|
18922
|
+
outlineOffset: 1
|
|
18923
|
+
}
|
|
18724
18924
|
}), /* @__PURE__ */ jsx(CanvasTitleChip, {
|
|
18725
18925
|
id,
|
|
18726
18926
|
title: block.attrs?.title ?? "",
|
|
@@ -22768,7 +22968,7 @@ const CANVAS_ITEM_LABEL_KEYS = {
|
|
|
22768
22968
|
* order, the line can stand over or under a figure); `interactive`
|
|
22769
22969
|
* toggles the line's hit path (the page view's surface stands it inert).
|
|
22770
22970
|
*/
|
|
22771
|
-
const CanvasItem = memo(function CanvasItem({ id, pendingConnector = null, movePreview = null, resizeBox = null, interactive = true, kbFocused = false
|
|
22971
|
+
const CanvasItem = memo(function CanvasItem({ id, pendingConnector = null, movePreview = null, resizeBox = null, interactive = true, kbFocused = false }) {
|
|
22772
22972
|
const { t } = useTranslation("canvas");
|
|
22773
22973
|
const { store, renderers } = useEditorContext();
|
|
22774
22974
|
const { siblings } = useBlockContext();
|
|
@@ -22803,10 +23003,7 @@ const CanvasItem = memo(function CanvasItem({ id, pendingConnector = null, moveP
|
|
|
22803
23003
|
tag: "div"
|
|
22804
23004
|
}) : block.type === "frame" ? /* @__PURE__ */ jsx(FrameBlock, {
|
|
22805
23005
|
id,
|
|
22806
|
-
|
|
22807
|
-
resizeBox,
|
|
22808
|
-
selected,
|
|
22809
|
-
frameChain
|
|
23006
|
+
selected
|
|
22810
23007
|
}) : block.type === "group" ? /* @__PURE__ */ jsx(GroupBlock, {
|
|
22811
23008
|
id,
|
|
22812
23009
|
block,
|
|
@@ -22853,7 +23050,7 @@ const CanvasItem = memo(function CanvasItem({ id, pendingConnector = null, moveP
|
|
|
22853
23050
|
style,
|
|
22854
23051
|
children: content
|
|
22855
23052
|
});
|
|
22856
|
-
}, (prev, next) => prev.id === next.id && prev.pendingConnector === next.pendingConnector && prev.movePreview === next.movePreview && prev.resizeBox === next.resizeBox && prev.interactive === next.interactive && prev.kbFocused === next.kbFocused
|
|
23053
|
+
}, (prev, next) => prev.id === next.id && prev.pendingConnector === next.pendingConnector && prev.movePreview === next.movePreview && prev.resizeBox === next.resizeBox && prev.interactive === next.interactive && prev.kbFocused === next.kbFocused);
|
|
22857
23054
|
//#endregion
|
|
22858
23055
|
//#region src/canvas/ConnectorArrowDefs.tsx
|
|
22859
23056
|
/** The surface's arrowhead defs (the hidden 0x0 svg): the marker ids stand
|
|
@@ -22968,7 +23165,7 @@ function ConnectorArrowDefs({ id }) {
|
|
|
22968
23165
|
* context providers are not DOM nodes, so several surfaces merge onto the
|
|
22969
23166
|
* same canvas in root order (the later surface paints on top: the DOM
|
|
22970
23167
|
* order is the z-order). */
|
|
22971
|
-
function SurfaceLayer({ id, children, pendingConnector, movePreview, resizePreview, endpointDrag, endpointPreview, showPorts, endpointSnap, kbFocusId = null, inert = false, excludedIds
|
|
23168
|
+
function SurfaceLayer({ id, children, pendingConnector, movePreview, resizePreview, endpointDrag, endpointPreview, showPorts, endpointSnap, kbFocusId = null, inert = false, excludedIds }) {
|
|
22972
23169
|
const contextValue = useBlockContextValue(id, children, "surface");
|
|
22973
23170
|
const session = useMemo(() => ({
|
|
22974
23171
|
movePreview,
|
|
@@ -23001,8 +23198,7 @@ function SurfaceLayer({ id, children, pendingConnector, movePreview, resizePrevi
|
|
|
23001
23198
|
pendingConnector,
|
|
23002
23199
|
movePreview: movePreview !== null && movePreview.ids.includes(childId) ? movePreview : null,
|
|
23003
23200
|
resizeBox: resizePreview !== null && resizePreview.id === childId ? resizePreview.box : null,
|
|
23004
|
-
kbFocused: kbFocusId === childId
|
|
23005
|
-
frameChain
|
|
23201
|
+
kbFocused: kbFocusId === childId
|
|
23006
23202
|
}, childId)),
|
|
23007
23203
|
showPorts && /* @__PURE__ */ jsx(PortDots, {
|
|
23008
23204
|
id,
|
|
@@ -23097,8 +23293,7 @@ function PortDots({ id, snapped }) {
|
|
|
23097
23293
|
//#endregion
|
|
23098
23294
|
//#region src/canvas/FrameWindowContent.tsx
|
|
23099
23295
|
const EMPTY_IDS$1 = [];
|
|
23100
|
-
|
|
23101
|
-
function FrameWindowContent({ surfaceId, offset, excludedIds = EMPTY_IDS$1, frameChain = EMPTY_CHAIN, className }) {
|
|
23296
|
+
function FrameWindowContent({ surfaceId, offset, excludedIds = EMPTY_IDS$1, className }) {
|
|
23102
23297
|
const surface = useBlock(surfaceId);
|
|
23103
23298
|
const children = surface !== void 0 && surface.type === "surface" ? surface.children ?? EMPTY_IDS$1 : EMPTY_IDS$1;
|
|
23104
23299
|
return /* @__PURE__ */ jsx("div", {
|
|
@@ -23124,8 +23319,7 @@ function FrameWindowContent({ surfaceId, offset, excludedIds = EMPTY_IDS$1, fram
|
|
|
23124
23319
|
endpointSnap: null,
|
|
23125
23320
|
kbFocusId: null,
|
|
23126
23321
|
inert: true,
|
|
23127
|
-
excludedIds
|
|
23128
|
-
frameChain
|
|
23322
|
+
excludedIds
|
|
23129
23323
|
}), /* @__PURE__ */ jsx(ConnectorLabelChips, { children })]
|
|
23130
23324
|
})
|
|
23131
23325
|
});
|
|
@@ -23134,11 +23328,13 @@ function FrameWindowContent({ surfaceId, offset, excludedIds = EMPTY_IDS$1, fram
|
|
|
23134
23328
|
//#region src/blocks/FramePageBlock.tsx
|
|
23135
23329
|
/**
|
|
23136
23330
|
* The page-frame block's renderer: the inline window into the referenced
|
|
23137
|
-
* canvas frame's surface — the
|
|
23138
|
-
*
|
|
23139
|
-
*
|
|
23140
|
-
*
|
|
23141
|
-
* 1:1 (no fit/zoom controls — the v1 boundary). The
|
|
23331
|
+
* canvas frame's surface — the content's mirror (FrameWindowContent over
|
|
23332
|
+
* the window's offset; the box's background the canvas's own background +
|
|
23333
|
+
* the dot grid phase-aligned to the world's grid; the container's thin
|
|
23334
|
+
* rounded border), inlined in the page flow at
|
|
23335
|
+
* 1:1 (no fit/zoom controls — the v1 boundary). The canvas frame stands the
|
|
23336
|
+
* boundary only (a region marker) — this page block is the sole renderer
|
|
23337
|
+
* of the frame's content. The box's height is the
|
|
23142
23338
|
* referenced frame's 1:1; the width is the frame's width clipped to the
|
|
23143
23339
|
* row's measured width (the window's center stays at the frame's center —
|
|
23144
23340
|
* a narrow row clips the wide window horizontally, the offset and the dot
|
|
@@ -23232,7 +23428,6 @@ function FramePageWindow({ id, frameId, surfaceId, referenced }) {
|
|
|
23232
23428
|
};
|
|
23233
23429
|
const title = referenced.attrs?.title ?? "";
|
|
23234
23430
|
const excludedIds = useMemo(() => [frameId], [frameId]);
|
|
23235
|
-
const frameChain = useMemo(() => /* @__PURE__ */ new Set([frameId]), [frameId]);
|
|
23236
23431
|
return /* @__PURE__ */ jsx("div", {
|
|
23237
23432
|
ref: rowRef,
|
|
23238
23433
|
"data-slot": "docblocks/frame-page",
|
|
@@ -23250,8 +23445,7 @@ function FramePageWindow({ id, frameId, surfaceId, referenced }) {
|
|
|
23250
23445
|
children: /* @__PURE__ */ jsx(FrameWindowContent, {
|
|
23251
23446
|
surfaceId,
|
|
23252
23447
|
offset,
|
|
23253
|
-
excludedIds
|
|
23254
|
-
frameChain
|
|
23448
|
+
excludedIds
|
|
23255
23449
|
})
|
|
23256
23450
|
})
|
|
23257
23451
|
});
|
|
@@ -27766,6 +27960,15 @@ function positionAtPoint(doc, root, x, y) {
|
|
|
27766
27960
|
* soft-break lines) itself — a permanent capture listener, independent of
|
|
27767
27961
|
* the session (the real pointer's third press starts no session: the
|
|
27768
27962
|
* pointer's detail stands 3 and the session guard returns).
|
|
27963
|
+
*
|
|
27964
|
+
* The iframe's focus exception: a press while the document's focus stands
|
|
27965
|
+
* in a frame (the embed's iframe) tears the session down and lets the
|
|
27966
|
+
* mousedown's default stand — the default's focus move out of the frame
|
|
27967
|
+
* is the editor's document's focus, and suppressing it would seat the
|
|
27968
|
+
* caret over the unfocused document (no visible caret, the keys' no-
|
|
27969
|
+
* stand). The browser's native caret's seat stands the press; a double
|
|
27970
|
+
* press over the focused frame stands the same stand over the detail's
|
|
27971
|
+
* check.
|
|
27769
27972
|
*/
|
|
27770
27973
|
function useCrossDrag(rootRef, doc) {
|
|
27771
27974
|
const sessionRef = useRef(null);
|
|
@@ -27799,12 +28002,19 @@ function useCrossDrag(rootRef, doc) {
|
|
|
27799
28002
|
if (session === null || root === null || event.button !== 0) return;
|
|
27800
28003
|
const target = event.target instanceof Element ? event.target : null;
|
|
27801
28004
|
if (target === null || !root.contains(target)) return;
|
|
27802
|
-
|
|
28005
|
+
const tearDown = () => {
|
|
27803
28006
|
sessionRef.current = null;
|
|
27804
28007
|
window.removeEventListener("pointermove", move);
|
|
27805
28008
|
window.removeEventListener("pointerup", end);
|
|
27806
28009
|
window.removeEventListener("pointercancel", end);
|
|
27807
28010
|
window.removeEventListener("mousedown", mousedown, true);
|
|
28011
|
+
};
|
|
28012
|
+
if (event.detail >= 2) {
|
|
28013
|
+
tearDown();
|
|
28014
|
+
return;
|
|
28015
|
+
}
|
|
28016
|
+
if (document.activeElement instanceof HTMLIFrameElement) {
|
|
28017
|
+
tearDown();
|
|
27808
28018
|
return;
|
|
27809
28019
|
}
|
|
27810
28020
|
event.preventDefault();
|
|
@@ -27846,6 +28056,7 @@ function useCrossDrag(rootRef, doc) {
|
|
|
27846
28056
|
if (target === null || !root.contains(target)) return;
|
|
27847
28057
|
const inner = target.closest("[data-slot=\"docblocks/block-content\"]");
|
|
27848
28058
|
if (inner === null || inner.closest("[data-slot=\"docblocks/editor\"]") !== root) return;
|
|
28059
|
+
if (document.activeElement instanceof HTMLIFrameElement) return;
|
|
27849
28060
|
const blockId = inner.dataset.blockId;
|
|
27850
28061
|
const head = locatePosition(inner, 0);
|
|
27851
28062
|
const tail = locatePosition(inner, doc.getTextLength(blockId));
|
|
@@ -28357,7 +28568,8 @@ const RowItem = memo(function RowItem({ node, layoutSlide, isDragged, animated,
|
|
|
28357
28568
|
size: "icon",
|
|
28358
28569
|
onClick: (event) => deleteBlock(event.currentTarget, node.id),
|
|
28359
28570
|
onMouseDown: onHandleMouseDown,
|
|
28360
|
-
className: cn("absolute top-[calc((var(--docblocks-line-box-height)-var(--docblocks-gutter-size))/2)]
|
|
28571
|
+
className: cn("absolute top-[calc((var(--docblocks-line-box-height)-var(--docblocks-gutter-size))/2)]", "cursor-pointer rounded-full opacity-0 group-hover:opacity-100", "text-(--docblocks-gutter-color)", "size-5", selected && "opacity-100"),
|
|
28572
|
+
style: { right: "var(--docblocks-gutter-left)" },
|
|
28361
28573
|
children: /* @__PURE__ */ jsx(Trash, {})
|
|
28362
28574
|
}),
|
|
28363
28575
|
/* @__PURE__ */ jsx(BlockNodeView, {
|