@linloir/limr 1.0.0 → 1.0.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/README.en.md +36 -8
- package/README.md +36 -8
- package/benchmarks/results/layout.json +2593 -0
- package/benchmarks/results/markstream-code.json +1823 -0
- package/benchmarks/results/markstream-reading-repeat.json +1152 -0
- package/benchmarks/results/markstream.json +12486 -0
- package/benchmarks/results/streaming-browser.json +77 -0
- package/benchmarks/results/streaming.json +357 -0
- package/dist/base.css +83 -3
- package/dist/{chunk-TTISGBST.js → chunk-BG5QUQFR.js} +327 -72
- package/dist/chunk-BG5QUQFR.js.map +1 -0
- package/dist/chunk-BVHHOVMT.js +179 -0
- package/dist/chunk-BVHHOVMT.js.map +1 -0
- package/dist/chunk-FJZCQY2S.js +155 -0
- package/dist/chunk-FJZCQY2S.js.map +1 -0
- package/dist/chunk-FSI5OTBW.js +1 -0
- package/dist/{chunk-N77VD2YR.js → chunk-GU2RPESF.js} +145 -83
- package/dist/chunk-GU2RPESF.js.map +1 -0
- package/dist/{chunk-3ILUZKDB.js → chunk-SUAAUGAX.js} +1280 -501
- package/dist/chunk-SUAAUGAX.js.map +1 -0
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +13 -5
- package/dist/extensions/index.d.ts +30 -5
- package/dist/extensions/index.js +15 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +27 -8
- package/dist/{engine-43u8B4yt.d.ts → knuth-plass-C8mgFm7W.d.ts} +67 -1
- package/dist/knuth-plass-layout-CHQCWKB5.js +449 -0
- package/dist/knuth-plass-layout-CHQCWKB5.js.map +1 -0
- package/dist/react/index.d.ts +5 -4
- package/dist/react/index.js +5 -3
- package/dist/styles.css +83 -3
- package/dist/{translations-DHnYMg4h.d.ts → translations-BXzSwLBJ.d.ts} +39 -2
- package/docs/en/README.md +8 -6
- package/docs/en/annotations.md +3 -1
- package/docs/en/api.md +9 -1
- package/docs/en/architecture.md +11 -3
- package/docs/en/extensions.md +53 -4
- package/docs/en/getting-started.md +2 -0
- package/docs/en/integration.md +26 -2
- package/docs/en/modules.md +9 -5
- package/docs/en/performance.md +42 -2
- package/docs/en/styles.md +21 -2
- package/docs/en/syntax.md +118 -15
- package/docs/zh-CN/README.md +8 -6
- package/docs/zh-CN/annotations.md +3 -1
- package/docs/zh-CN/api.md +9 -1
- package/docs/zh-CN/architecture.md +11 -3
- package/docs/zh-CN/extensions.md +55 -4
- package/docs/zh-CN/getting-started.md +2 -0
- package/docs/zh-CN/integration.md +26 -2
- package/docs/zh-CN/modules.md +9 -5
- package/docs/zh-CN/performance.md +42 -2
- package/docs/zh-CN/styles.md +21 -2
- package/docs/zh-CN/syntax.md +120 -15
- package/package.json +9 -1
- package/skills/limr-plugin-development/references/contract.md +9 -3
- package/skills/limr-use/references/integration.md +11 -3
- package/skills/limr-use/references/syntax.md +8 -5
- package/dist/chunk-3ILUZKDB.js.map +0 -1
- package/dist/chunk-N77VD2YR.js.map +0 -1
- package/dist/chunk-TTISGBST.js.map +0 -1
- package/dist/chunk-V2OG4Y3F.js +0 -1
- /package/dist/{chunk-V2OG4Y3F.js.map → chunk-FSI5OTBW.js.map} +0 -0
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
highlightPalette,
|
|
10
10
|
highlightSelection,
|
|
11
11
|
scrollWithMotion,
|
|
12
|
-
sourceRangeStartRect,
|
|
13
12
|
useAppearance,
|
|
14
13
|
useDocument,
|
|
15
14
|
useDocumentSelector,
|
|
@@ -19,20 +18,26 @@ import {
|
|
|
19
18
|
useSelection,
|
|
20
19
|
useStoreSelector,
|
|
21
20
|
useTheme
|
|
22
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-SUAAUGAX.js";
|
|
23
22
|
import {
|
|
24
23
|
annotationReferenceRange,
|
|
25
24
|
defaultHighlight,
|
|
26
|
-
intersects,
|
|
27
25
|
mapText,
|
|
28
|
-
rangeOf,
|
|
29
26
|
resolveAnnotationAnchors,
|
|
30
27
|
sameRange,
|
|
31
28
|
selectionFromRange
|
|
32
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-BG5QUQFR.js";
|
|
30
|
+
import {
|
|
31
|
+
atomicSelectionText,
|
|
32
|
+
sourceRangeStartRect
|
|
33
|
+
} from "./chunk-BVHHOVMT.js";
|
|
34
|
+
import {
|
|
35
|
+
intersects,
|
|
36
|
+
rangeOf
|
|
37
|
+
} from "./chunk-FJZCQY2S.js";
|
|
33
38
|
|
|
34
39
|
// src/components/Reader.tsx
|
|
35
|
-
import { useEffect as useEffect7, useId as useId2, useRef as
|
|
40
|
+
import { useEffect as useEffect7, useId as useId2, useRef as useRef6, useState as useState6 } from "react";
|
|
36
41
|
|
|
37
42
|
// src/components/TableOfContents.tsx
|
|
38
43
|
import { useEffect as useEffect2, useRef } from "react";
|
|
@@ -43,7 +48,8 @@ function useOverflowFade(ref, runtime, contentSelector, beforeMeasure) {
|
|
|
43
48
|
useEffect(() => {
|
|
44
49
|
const host = ref.current;
|
|
45
50
|
if (!host) return;
|
|
46
|
-
let frame = 0
|
|
51
|
+
let frame = 0;
|
|
52
|
+
const transitions = /* @__PURE__ */ new Map();
|
|
47
53
|
const measure = () => {
|
|
48
54
|
frame = 0;
|
|
49
55
|
beforeMeasure?.();
|
|
@@ -68,8 +74,12 @@ function useOverflowFade(ref, runtime, contentSelector, beforeMeasure) {
|
|
|
68
74
|
};
|
|
69
75
|
set("--limr-fade-start", top - box.top);
|
|
70
76
|
set("--limr-fade-end", bottom - box.top);
|
|
71
|
-
|
|
72
|
-
|
|
77
|
+
const now = performance.now();
|
|
78
|
+
for (const [target, properties] of transitions) {
|
|
79
|
+
for (const [property, end2] of properties) if (end2 <= now || !host.contains(target)) properties.delete(property);
|
|
80
|
+
if (!properties.size) transitions.delete(target);
|
|
81
|
+
}
|
|
82
|
+
if (transitions.size) schedule();
|
|
73
83
|
};
|
|
74
84
|
const schedule = () => {
|
|
75
85
|
if (!frame) frame = requestAnimationFrame(measure);
|
|
@@ -78,12 +88,23 @@ function useOverflowFade(ref, runtime, contentSelector, beforeMeasure) {
|
|
|
78
88
|
cancelAnimationFrame(frame);
|
|
79
89
|
measure();
|
|
80
90
|
};
|
|
81
|
-
const start = () => {
|
|
82
|
-
|
|
91
|
+
const start = (event) => {
|
|
92
|
+
const target = event.target;
|
|
93
|
+
if (!(target instanceof Element) || !/^(top|bottom|left|right|height|max-height|min-height|width|max-width|transform|translate|grid-template-rows|padding.*|margin.*)$/.test(event.propertyName)) return;
|
|
94
|
+
const css = getComputedStyle(target), properties = css.transitionProperty.split(",").map((value) => value.trim());
|
|
95
|
+
const index = Math.max(0, properties.indexOf(event.propertyName));
|
|
96
|
+
const milliseconds = (value) => {
|
|
97
|
+
const list = value.split(",");
|
|
98
|
+
const item = list[index % list.length].trim();
|
|
99
|
+
return parseFloat(item) * (item.endsWith("ms") ? 1 : 1e3);
|
|
100
|
+
};
|
|
101
|
+
const pending = transitions.get(target) ?? /* @__PURE__ */ new Map();
|
|
102
|
+
pending.set(event.propertyName, performance.now() + milliseconds(css.transitionDuration) + milliseconds(css.transitionDelay) + 34);
|
|
103
|
+
transitions.set(target, pending);
|
|
83
104
|
schedule();
|
|
84
105
|
};
|
|
85
|
-
const end = () => {
|
|
86
|
-
|
|
106
|
+
const end = (event) => {
|
|
107
|
+
if (event.target instanceof Element) transitions.get(event.target)?.delete(event.propertyName);
|
|
87
108
|
schedule();
|
|
88
109
|
};
|
|
89
110
|
host.addEventListener("transitionrun", start);
|
|
@@ -95,7 +116,10 @@ function useOverflowFade(ref, runtime, contentSelector, beforeMeasure) {
|
|
|
95
116
|
if (records.some((record) => {
|
|
96
117
|
const element = record.target instanceof Element ? record.target : record.target.parentElement;
|
|
97
118
|
return element && element !== host && !element.closest(".limr-highlight-layer,.limr-paint-layer");
|
|
98
|
-
}))
|
|
119
|
+
})) {
|
|
120
|
+
if (beforeMeasure) refresh();
|
|
121
|
+
else schedule();
|
|
122
|
+
}
|
|
99
123
|
});
|
|
100
124
|
mutation.observe(host, { subtree: true, childList: true, characterData: true, attributes: true, attributeFilter: ["style", "class"] });
|
|
101
125
|
const unsubscribe = [runtime.layout.subscribe(schedule), runtime.viewport.subscribe(refresh), runtime.documentOffset.subscribe(schedule), runtime.configuration.subscribe(schedule)];
|
|
@@ -187,7 +211,7 @@ function TableOfContents({ title, maxDepth = 6, followActive = true, topInset =
|
|
|
187
211
|
}
|
|
188
212
|
|
|
189
213
|
// src/components/AnnotationSidebar.tsx
|
|
190
|
-
import { useCallback, useEffect as useEffect4, useMemo, useRef as useRef2, useState as useState2, useSyncExternalStore } from "react";
|
|
214
|
+
import { memo, useCallback, useEffect as useEffect4, useMemo, useRef as useRef2, useState as useState2, useSyncExternalStore } from "react";
|
|
191
215
|
import { flushSync } from "react-dom";
|
|
192
216
|
|
|
193
217
|
// src/components/AnnotationContent.tsx
|
|
@@ -273,6 +297,19 @@ var alignSidebar = (items, { activeId, gap, height, prioritizeActive }) => {
|
|
|
273
297
|
}
|
|
274
298
|
return new Map(items.map((item, index) => [item.id, positions[index]]));
|
|
275
299
|
};
|
|
300
|
+
var SidebarCardBody = memo(function SidebarCardBody2({ occurrence, annotation, annotations, reference, active, title, toggleLabel, Preview, activate }) {
|
|
301
|
+
return /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
302
|
+
reference && /* @__PURE__ */ jsx3("div", { className: "limr-sidebar-reference", title: reference, children: /* @__PURE__ */ jsx3("p", { className: "limr-sidebar-excerpt", children: reference }) }),
|
|
303
|
+
/* @__PURE__ */ jsxs3("div", { className: "limr-sidebar-card-body", children: [
|
|
304
|
+
/* @__PURE__ */ jsxs3("button", { type: "button", className: "limr-sidebar-card-heading", onClick: () => activate(occurrence.id), "aria-expanded": active, children: [
|
|
305
|
+
title,
|
|
306
|
+
/* @__PURE__ */ jsx3("span", { className: "limr-sidebar-toggle", children: /* @__PURE__ */ jsx3("span", { className: "limr-button-label limr-underline", children: toggleLabel }, String(active)) })
|
|
307
|
+
] }),
|
|
308
|
+
Preview && annotation && /* @__PURE__ */ jsx3(Collapse, { open: !active, keepMounted: true, className: "limr-sidebar-preview-panel", children: /* @__PURE__ */ jsx3("div", { className: "limr-sidebar-preview", children: /* @__PURE__ */ jsx3(Preview, { annotation, data: annotation.data, occurrence, annotations, referenceText: reference }) }) }),
|
|
309
|
+
/* @__PURE__ */ jsx3(Collapse, { open: active, className: "limr-sidebar-expansion", children: /* @__PURE__ */ jsx3("div", { className: "limr-sidebar-card-content", children: /* @__PURE__ */ jsx3(AnnotationGroup, { occurrence, presentation: "sidebar", enabled: active }) }) })
|
|
310
|
+
] })
|
|
311
|
+
] });
|
|
312
|
+
});
|
|
276
313
|
function AnnotationSidebar({ sync = "document", gap = 14, positioner = alignSidebar, renderCard, className, style }) {
|
|
277
314
|
const runtime = useRuntime();
|
|
278
315
|
const document2 = useDocument();
|
|
@@ -452,7 +489,7 @@ function AnnotationSidebar({ sync = "document", gap = 14, positioner = alignSide
|
|
|
452
489
|
useIsomorphicLayoutEffect(() => {
|
|
453
490
|
if (sync === "document") runtime.documentOffset.set(displacement);
|
|
454
491
|
}, [runtime, displacement, sync]);
|
|
455
|
-
const lockCard = (id) => {
|
|
492
|
+
const lockCard = useCallback((id) => {
|
|
456
493
|
if (locked?.id === id) return;
|
|
457
494
|
const card = cards.current.get(id);
|
|
458
495
|
if (card && rail.current) {
|
|
@@ -460,7 +497,14 @@ function AnnotationSidebar({ sync = "document", gap = 14, positioner = alignSide
|
|
|
460
497
|
const top = card.getBoundingClientRect().top - origin;
|
|
461
498
|
setCardLock({ id, top });
|
|
462
499
|
}
|
|
463
|
-
};
|
|
500
|
+
}, [locked?.id]);
|
|
501
|
+
const activateCard = useCallback((id) => {
|
|
502
|
+
const state = runtime.interaction.get();
|
|
503
|
+
const hovering = state.hovered === id || cards.current.get(id)?.matches(":hover");
|
|
504
|
+
lockCard(id);
|
|
505
|
+
runtime.activate(state.active === id ? null : id, "sidebar");
|
|
506
|
+
if (hovering) runtime.hover(id, "sidebar");
|
|
507
|
+
}, [runtime, lockCard]);
|
|
464
508
|
return /* @__PURE__ */ jsx3("aside", { ref: rail, "aria-label": locale.annotations, className: `limr-sidebar ${className ?? ""}`, "data-sync": sync, "data-releasing": releasing ? "" : void 0, "data-limr-theme": theme, "data-limr-appearance": appearance, style, children: items.map((occurrence) => {
|
|
465
509
|
const annotation = decorations.annotations.get(occurrence.annotationIds[0]);
|
|
466
510
|
const definition = runtime.annotationTypes.get(annotation?.type ?? "citation");
|
|
@@ -485,12 +529,7 @@ function AnnotationSidebar({ sync = "document", gap = 14, positioner = alignSide
|
|
|
485
529
|
} : { marginBlockEnd: gap }
|
|
486
530
|
};
|
|
487
531
|
const collapseOnContentClick = occurrence.annotationIds.every((id) => runtime.annotationTypes.get(decorations.annotations.get(id)?.type ?? "")?.sidebar?.collapseOnContentClick);
|
|
488
|
-
const activate = () =>
|
|
489
|
-
const hovering = runtime.interaction.get().hovered === occurrence.id || cards.current.get(occurrence.id)?.matches(":hover");
|
|
490
|
-
lockCard(occurrence.id);
|
|
491
|
-
runtime.activate(isActive ? null : occurrence.id, "sidebar");
|
|
492
|
-
if (hovering) runtime.hover(occurrence.id, "sidebar");
|
|
493
|
-
};
|
|
532
|
+
const activate = () => activateCard(occurrence.id);
|
|
494
533
|
return /* @__PURE__ */ jsx3(
|
|
495
534
|
"div",
|
|
496
535
|
{
|
|
@@ -520,17 +559,7 @@ function AnnotationSidebar({ sync = "document", gap = 14, positioner = alignSide
|
|
|
520
559
|
onClick: (event) => {
|
|
521
560
|
if ((!isActive || collapseOnContentClick) && !renderCard && !event.defaultPrevented && !event.target.closest('button,a,input,select,textarea,summary,[role="button"],[role="link"],[contenteditable="true"],[data-limr-card-interactive]') && window.getSelection()?.isCollapsed !== false) activate();
|
|
522
561
|
},
|
|
523
|
-
children: renderCard ? renderCard({ occurrence, active: isActive, activate }) : /* @__PURE__ */
|
|
524
|
-
references.get(occurrence.id) && /* @__PURE__ */ jsx3("div", { className: "limr-sidebar-reference", title: references.get(occurrence.id), children: /* @__PURE__ */ jsx3("p", { className: "limr-sidebar-excerpt", children: references.get(occurrence.id) }) }),
|
|
525
|
-
/* @__PURE__ */ jsxs3("div", { className: "limr-sidebar-card-body", children: [
|
|
526
|
-
/* @__PURE__ */ jsxs3("button", { type: "button", className: "limr-sidebar-card-heading", onClick: activate, "aria-expanded": isActive, children: [
|
|
527
|
-
definition?.label ?? annotation?.type ?? "Reference",
|
|
528
|
-
/* @__PURE__ */ jsx3("span", { className: "limr-sidebar-toggle", children: /* @__PURE__ */ jsx3("span", { className: "limr-button-label limr-underline", children: isActive ? locale.collapse : locale.expand }, String(isActive)) })
|
|
529
|
-
] }),
|
|
530
|
-
Preview && annotation && /* @__PURE__ */ jsx3(Collapse, { open: !isActive, keepMounted: true, className: "limr-sidebar-preview-panel", children: /* @__PURE__ */ jsx3("div", { className: "limr-sidebar-preview", children: /* @__PURE__ */ jsx3(Preview, { annotation, data: annotation.data, occurrence, annotations: annotationGroups.get(occurrence.id), referenceText: references.get(occurrence.id) ?? "" }) }) }),
|
|
531
|
-
/* @__PURE__ */ jsx3(Collapse, { open: isActive, className: "limr-sidebar-expansion", children: /* @__PURE__ */ jsx3("div", { className: "limr-sidebar-card-content", children: /* @__PURE__ */ jsx3(AnnotationGroup, { occurrence, presentation: "sidebar", enabled: isActive }) }) })
|
|
532
|
-
] })
|
|
533
|
-
] })
|
|
562
|
+
children: renderCard ? renderCard({ occurrence, active: isActive, activate }) : /* @__PURE__ */ jsx3(SidebarCardBody, { occurrence, annotation, annotations: annotationGroups.get(occurrence.id), reference: references.get(occurrence.id) ?? "", active: isActive, title: definition?.label ?? annotation?.type ?? "Reference", toggleLabel: isActive ? locale.collapse : locale.expand, Preview, activate: activateCard })
|
|
534
563
|
},
|
|
535
564
|
occurrence.id
|
|
536
565
|
);
|
|
@@ -849,9 +878,33 @@ function AnnotationOverlay({ disabled = false, portalRoot, previewWidth = 340, m
|
|
|
849
878
|
}
|
|
850
879
|
|
|
851
880
|
// src/components/SelectionToolbar.tsx
|
|
852
|
-
import { useEffect as useEffect6, useId, useMemo as useMemo2, useRef as
|
|
881
|
+
import { useEffect as useEffect6, useId, useMemo as useMemo2, useRef as useRef5, useState as useState5 } from "react";
|
|
853
882
|
import { autoUpdate as autoUpdate2, FloatingPortal as FloatingPortal2, offset as offset2, shift as shift2, useFloating as useFloating2 } from "@floating-ui/react";
|
|
854
|
-
|
|
883
|
+
|
|
884
|
+
// src/components/ToolFaces.tsx
|
|
885
|
+
import { useRef as useRef4, useState as useState4 } from "react";
|
|
886
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
887
|
+
function ToolFaces({ state, children }) {
|
|
888
|
+
const ref = useRef4(null);
|
|
889
|
+
const [width, setWidth] = useState4();
|
|
890
|
+
useIsomorphicLayoutEffect(() => {
|
|
891
|
+
const element = ref.current;
|
|
892
|
+
if (!element) return;
|
|
893
|
+
const faces = [...element.querySelectorAll(".limr-tool-face")];
|
|
894
|
+
const measure = () => {
|
|
895
|
+
const face = faces.find((face2) => face2.hasAttribute("data-visible"));
|
|
896
|
+
if (face) setWidth(face.offsetWidth);
|
|
897
|
+
};
|
|
898
|
+
measure();
|
|
899
|
+
const observer = new ResizeObserver(measure);
|
|
900
|
+
faces.forEach((face) => observer.observe(face));
|
|
901
|
+
return () => observer.disconnect();
|
|
902
|
+
}, [state]);
|
|
903
|
+
return /* @__PURE__ */ jsx5("span", { className: "limr-tool-faces", ref, style: { width }, children });
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
// src/components/SelectionToolbar.tsx
|
|
907
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
855
908
|
var defaults = [highlightPalette(), highlightSelection(), copyText(), deleteAnnotations()];
|
|
856
909
|
function SelectionToolbar({ actions, portalRoot, maxPanelHeight = 260, className = "", style, render }) {
|
|
857
910
|
const runtime = useRuntime();
|
|
@@ -870,15 +923,15 @@ function SelectionToolbar({ actions, portalRoot, maxPanelHeight = 260, className
|
|
|
870
923
|
const order = (action) => action.placement === "start" ? -1 : action.placement === "end" ? 1 : 0;
|
|
871
924
|
return [...map.values()].sort((a, b) => order(a) - order(b));
|
|
872
925
|
}, [config.extensions, actions]);
|
|
873
|
-
const [busy, setBusy] =
|
|
874
|
-
const busyRef =
|
|
875
|
-
const [error, setError] =
|
|
876
|
-
const [expanded, setExpanded] =
|
|
877
|
-
const [success, setSuccess] =
|
|
878
|
-
const [deleteHintOpen, setDeleteHintOpen] =
|
|
879
|
-
const [preferredHighlight, setPreferredHighlight] =
|
|
880
|
-
const closeTimer =
|
|
881
|
-
const successTimer =
|
|
926
|
+
const [busy, setBusy] = useState5(null);
|
|
927
|
+
const busyRef = useRef5(false);
|
|
928
|
+
const [error, setError] = useState5(null);
|
|
929
|
+
const [expanded, setExpanded] = useState5(null);
|
|
930
|
+
const [success, setSuccess] = useState5(null);
|
|
931
|
+
const [deleteHintOpen, setDeleteHintOpen] = useState5(false);
|
|
932
|
+
const [preferredHighlight, setPreferredHighlight] = useState5(defaultHighlight);
|
|
933
|
+
const closeTimer = useRef5(void 0);
|
|
934
|
+
const successTimer = useRef5(void 0);
|
|
882
935
|
const panelId = useId();
|
|
883
936
|
const documentSnapshot = runtime.document.getSnapshot();
|
|
884
937
|
const effectiveSelection = useMemo2(() => {
|
|
@@ -886,9 +939,15 @@ function SelectionToolbar({ actions, portalRoot, maxPanelHeight = 260, className
|
|
|
886
939
|
if (interaction.editing && active?.annotationIds.includes(interaction.editing)) return null;
|
|
887
940
|
const range = paint?.range ?? (hiddenActive ? active?.range : void 0);
|
|
888
941
|
return range ? selectionFromRange(documentSnapshot, range, {
|
|
889
|
-
text: paint ? runtime.highlightReference?.text ?? annotationReferenceText(documentSnapshot, { id: paint.id, annotationIds: [], range }) : annotationReferenceText(documentSnapshot, active)
|
|
942
|
+
text: atomicSelectionText(runtime, [range]) ?? (paint ? runtime.highlightReference?.text ?? annotationReferenceText(documentSnapshot, { id: paint.id, annotationIds: [], range }) : annotationReferenceText(documentSnapshot, active))
|
|
890
943
|
}) : null;
|
|
891
944
|
}, [documentSnapshot, paint, active, selection, interaction.editing, hiddenActive]);
|
|
945
|
+
const blockReference = useMemo2(() => {
|
|
946
|
+
const ranges = effectiveSelection?.raw.ranges;
|
|
947
|
+
if (ranges?.length !== 1) return null;
|
|
948
|
+
const { start, end } = ranges[0];
|
|
949
|
+
return runtime.content?.querySelector(`[data-limr-atomic="block"][data-source-start="${start}"][data-source-end="${end}"]`) ?? null;
|
|
950
|
+
}, [runtime, effectiveSelection]);
|
|
892
951
|
const annotations = useMemo2(() => effectiveSelection ? [...decorations.annotations.values()].filter((annotation) => resolveAnnotationAnchors(annotation, documentSnapshot).some((anchor) => [...effectiveSelection.raw.ranges, ...effectiveSelection.syntax.ranges].some((range) => sameRange(anchor.range, range)))) : [], [decorations, effectiveSelection, documentSnapshot]);
|
|
893
952
|
const highlight = paint ? decorations.annotations.get(paint.annotationId) : annotations.find((annotation) => annotation.type === "highlight");
|
|
894
953
|
const highlightAppearance = highlight?.data ?? preferredHighlight;
|
|
@@ -903,7 +962,8 @@ function SelectionToolbar({ actions, portalRoot, maxPanelHeight = 260, className
|
|
|
903
962
|
signal: runtime.signal,
|
|
904
963
|
clearSelection: () => runtime.clearSelection()
|
|
905
964
|
} : null;
|
|
906
|
-
const
|
|
965
|
+
const readOnly = highlight?.data?.readOnly === true;
|
|
966
|
+
const available = context ? readOnly ? [defaults[2]] : combined.filter((action) => action.visible?.(context) ?? true) : [];
|
|
907
967
|
const expandedAction = available.find((action) => action.id === expanded && action.renderExpanded);
|
|
908
968
|
const hasPanels = available.some((action) => action.renderExpanded);
|
|
909
969
|
const open = !!context && effectiveSelection.settled && available.length > 0;
|
|
@@ -911,16 +971,16 @@ function SelectionToolbar({ actions, portalRoot, maxPanelHeight = 260, className
|
|
|
911
971
|
open,
|
|
912
972
|
strategy: "fixed",
|
|
913
973
|
placement: "bottom",
|
|
914
|
-
middleware: [offset2(10), { name: "toolbarSpace", options: { hasPanels, maxPanelHeight }, fn({ rects, placement: placement2, elements }) {
|
|
974
|
+
middleware: [offset2(10), { name: "toolbarSpace", options: { hasPanels, maxPanelHeight, blockReference }, fn({ rects, placement: placement2, elements }) {
|
|
915
975
|
const viewport = window.visualViewport;
|
|
916
976
|
const root = runtime.configuration.get().scrollRoot?.getBoundingClientRect();
|
|
917
977
|
const top = Math.max(viewport?.offsetTop ?? 0, root?.top ?? 0);
|
|
918
978
|
const bottom = Math.min((viewport?.offsetTop ?? 0) + (viewport?.height ?? window.innerHeight), root?.bottom ?? Infinity);
|
|
919
979
|
const above = Math.max(0, rects.reference.y - top - 20), below = Math.max(0, bottom - rects.reference.y - rects.reference.height - 20);
|
|
920
|
-
const row = (elements.floating.querySelector(".limr-toolbar-actions")?.getBoundingClientRect().height ?? 34) + (elements.floating.querySelector(".limr-toolbar-delete-hint")?.getBoundingClientRect().height ?? 0);
|
|
980
|
+
const row = (elements.floating.querySelector(".limr-toolbar-actions")?.getBoundingClientRect().height ?? 34) + (elements.floating.querySelector(".limr-toolbar-delete-hint,.limr-toolbar-readonly-hint")?.getBoundingClientRect().height ?? 0);
|
|
921
981
|
const limit = Math.max(0, parseFloat(getComputedStyle(elements.floating).getPropertyValue("--limr-toolbar-panel-max-height")) || maxPanelHeight);
|
|
922
982
|
const needed = row + (hasPanels ? limit : 0) + 24;
|
|
923
|
-
const next = below >= needed || below >= above ? "bottom" : "top";
|
|
983
|
+
const next = blockReference || below >= needed || below >= above ? "bottom" : "top";
|
|
924
984
|
const room = next === "bottom" ? below : above;
|
|
925
985
|
elements.floating.style.setProperty("--limr-toolbar-panel-height", `${Math.max(0, Math.min(limit, room - row - 24))}px`);
|
|
926
986
|
elements.floating.style.setProperty("--limr-toolbar-available-height", `${room}px`);
|
|
@@ -929,9 +989,9 @@ function SelectionToolbar({ actions, portalRoot, maxPanelHeight = 260, className
|
|
|
929
989
|
whileElementsMounted: autoUpdate2
|
|
930
990
|
});
|
|
931
991
|
useEffect6(() => {
|
|
932
|
-
const reference = selection ? runtime.selectionRange : paint ? runtime.highlightReference : active ? runtime.anchors.get(active.id) : null;
|
|
933
|
-
if (reference) refs.setPositionReference({ getBoundingClientRect: () => reference.getBoundingClientRect(), getClientRects: () => reference.getClientRects(), contextElement: runtime.content ?? void 0 });
|
|
934
|
-
}, [runtime, refs, selection, paint, active]);
|
|
992
|
+
const reference = blockReference ?? (selection ? runtime.selectionRange : paint ? runtime.highlightReference : active ? runtime.anchors.get(active.id) : null);
|
|
993
|
+
if (reference) refs.setPositionReference({ getBoundingClientRect: () => reference.getBoundingClientRect(), getClientRects: () => reference.getClientRects(), contextElement: blockReference ?? runtime.content ?? void 0 });
|
|
994
|
+
}, [runtime, refs, blockReference, selection, paint, active]);
|
|
935
995
|
const selectionKey = effectiveSelection?.raw.ranges.map((range) => `${range.start}-${range.end}`).join(",") ?? "";
|
|
936
996
|
useEffect6(() => {
|
|
937
997
|
setError(null);
|
|
@@ -1014,7 +1074,7 @@ function SelectionToolbar({ actions, portalRoot, maxPanelHeight = 260, className
|
|
|
1014
1074
|
};
|
|
1015
1075
|
const annotationCount = annotations.filter((annotation) => annotation.type !== "highlight").length;
|
|
1016
1076
|
const hint = available.some((action) => action.id === "delete-annotations") && annotationCount > 1 ? context.locale.deleteAnnotationsHint.replace("{count}", String(annotationCount)) : null;
|
|
1017
|
-
return /* @__PURE__ */
|
|
1077
|
+
return /* @__PURE__ */ jsx6(FloatingPortal2, { root: portalRoot, children: /* @__PURE__ */ jsx6(
|
|
1018
1078
|
"div",
|
|
1019
1079
|
{
|
|
1020
1080
|
ref: refs.setFloating,
|
|
@@ -1027,6 +1087,7 @@ function SelectionToolbar({ actions, portalRoot, maxPanelHeight = 260, className
|
|
|
1027
1087
|
"data-limr-appearance": appearance,
|
|
1028
1088
|
"data-placement": placement,
|
|
1029
1089
|
"data-highlight": highlight?.id,
|
|
1090
|
+
"data-readonly": readOnly || void 0,
|
|
1030
1091
|
"data-expanded": expandedAction?.id,
|
|
1031
1092
|
onMouseDown: (event) => {
|
|
1032
1093
|
if (!(event.target instanceof Element) || !event.target.closest("input,textarea,select,[contenteditable]")) event.preventDefault();
|
|
@@ -1058,7 +1119,7 @@ function SelectionToolbar({ actions, portalRoot, maxPanelHeight = 260, className
|
|
|
1058
1119
|
event.preventDefault();
|
|
1059
1120
|
},
|
|
1060
1121
|
children: /* @__PURE__ */ jsxs5("div", { className: "limr-toolbar-surface", "data-ready": isPositioned || void 0, children: [
|
|
1061
|
-
/* @__PURE__ */
|
|
1122
|
+
/* @__PURE__ */ jsx6("div", { className: "limr-toolbar-actions", children: render && !readOnly ? render({ context, actions: available, run }) : available.map((action, index) => /* @__PURE__ */ jsx6(
|
|
1062
1123
|
"div",
|
|
1063
1124
|
{
|
|
1064
1125
|
className: "limr-toolbar-item",
|
|
@@ -1079,7 +1140,7 @@ function SelectionToolbar({ actions, portalRoot, maxPanelHeight = 260, className
|
|
|
1079
1140
|
setError(cause instanceof Error ? cause.message : String(cause));
|
|
1080
1141
|
}
|
|
1081
1142
|
},
|
|
1082
|
-
children: action.render ? action.render(actionContext(action)) : /* @__PURE__ */
|
|
1143
|
+
children: action.render ? action.render(actionContext(action)) : /* @__PURE__ */ jsx6(
|
|
1083
1144
|
"button",
|
|
1084
1145
|
{
|
|
1085
1146
|
className: "limr-toolbar-action",
|
|
@@ -1103,33 +1164,34 @@ function SelectionToolbar({ actions, portalRoot, maxPanelHeight = 260, className
|
|
|
1103
1164
|
onBlur: (event) => {
|
|
1104
1165
|
if (action.id === "delete-annotations" && !event.currentTarget.matches(":hover")) setDeleteHintOpen(false);
|
|
1105
1166
|
},
|
|
1106
|
-
children: [
|
|
1167
|
+
children: /* @__PURE__ */ jsxs5(ToolFaces, { state: label(action), children: [
|
|
1107
1168
|
/* @__PURE__ */ jsxs5("span", { className: "limr-tool-face", "data-visible": success !== action.id || void 0, "aria-hidden": "true", children: [
|
|
1108
|
-
/* @__PURE__ */
|
|
1109
|
-
/* @__PURE__ */
|
|
1169
|
+
/* @__PURE__ */ jsx6("span", { className: "limr-tool-icon", children: typeof action.icon === "function" ? action.icon(context) : action.icon }, typeof action.label === "function" ? action.label(context) : action.label),
|
|
1170
|
+
/* @__PURE__ */ jsx6("span", { className: "limr-tool-label limr-underline", children: typeof action.label === "function" ? action.label(context) : action.label })
|
|
1110
1171
|
] }),
|
|
1111
1172
|
action.successLabel && /* @__PURE__ */ jsxs5("span", { className: "limr-tool-face", "data-visible": success === action.id || void 0, "aria-hidden": "true", children: [
|
|
1112
|
-
/* @__PURE__ */
|
|
1113
|
-
/* @__PURE__ */
|
|
1173
|
+
/* @__PURE__ */ jsx6("span", { className: "limr-tool-icon", children: action.successIcon ?? (typeof action.icon === "function" ? action.icon(context) : action.icon) }),
|
|
1174
|
+
/* @__PURE__ */ jsx6("span", { className: "limr-tool-label limr-underline", children: typeof action.successLabel === "function" ? action.successLabel(context) : action.successLabel })
|
|
1114
1175
|
] })
|
|
1115
|
-
]
|
|
1176
|
+
] })
|
|
1116
1177
|
}
|
|
1117
1178
|
)
|
|
1118
1179
|
},
|
|
1119
1180
|
action.id
|
|
1120
1181
|
)) }),
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1182
|
+
readOnly && /* @__PURE__ */ jsx6("p", { className: "limr-toolbar-readonly-hint", children: context.locale.inlineHighlightHint ?? "Markdown inline highlight, editing unavailable" }),
|
|
1183
|
+
expandedAction && /* @__PURE__ */ jsx6("div", { id: panelId, className: "limr-toolbar-panel", role: "group", "aria-label": label(expandedAction), children: /* @__PURE__ */ jsx6(OverlayScrollArea, { active: true, label: label(expandedAction), children: expandedAction.renderExpanded(actionContext(expandedAction)) }) }, expandedAction.id),
|
|
1184
|
+
hint && /* @__PURE__ */ jsx6(Collapse, { open: deleteHintOpen, keepMounted: true, className: "limr-toolbar-delete-warning", children: /* @__PURE__ */ jsx6("p", { id: `${panelId}-delete`, className: "limr-toolbar-delete-hint", children: hint }) }),
|
|
1185
|
+
error && /* @__PURE__ */ jsx6("span", { role: "alert", className: "limr-action-error", children: error })
|
|
1124
1186
|
] }, selectionKey)
|
|
1125
1187
|
}
|
|
1126
1188
|
) });
|
|
1127
1189
|
}
|
|
1128
1190
|
|
|
1129
1191
|
// src/components/Reader.tsx
|
|
1130
|
-
import { Fragment as Fragment3, jsx as
|
|
1192
|
+
import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1131
1193
|
function Reader({ actions, toc = true, sidebar = true, followOutput = false, sidebarBreakpoint = 1120, fillHeight = true, className, style, ...provider }) {
|
|
1132
|
-
return /* @__PURE__ */
|
|
1194
|
+
return /* @__PURE__ */ jsx7(DocumentProvider, { ...provider, children: /* @__PURE__ */ jsx7(ReaderLayout, { actions, toc, sidebar, followOutput, sidebarBreakpoint, fillHeight, className, style }) });
|
|
1133
1195
|
}
|
|
1134
1196
|
function ReaderLayout({ actions, toc, sidebar, followOutput, sidebarBreakpoint, fillHeight, className, style }) {
|
|
1135
1197
|
const runtime = useRuntime();
|
|
@@ -1137,12 +1199,12 @@ function ReaderLayout({ actions, toc, sidebar, followOutput, sidebarBreakpoint,
|
|
|
1137
1199
|
const layout = useStoreSelector(runtime.layout, (value) => value);
|
|
1138
1200
|
const appearance = useAppearance();
|
|
1139
1201
|
const theme = useTheme();
|
|
1140
|
-
const ref =
|
|
1141
|
-
const tocRail =
|
|
1142
|
-
const content =
|
|
1202
|
+
const ref = useRef6(null);
|
|
1203
|
+
const tocRail = useRef6(null);
|
|
1204
|
+
const content = useRef6(null);
|
|
1143
1205
|
useOverflowFade(content, runtime, ":scope > .limr-prose");
|
|
1144
|
-
const [width, setWidth] =
|
|
1145
|
-
const [availableHeight, setAvailableHeight] =
|
|
1206
|
+
const [width, setWidth] = useState6(0);
|
|
1207
|
+
const [availableHeight, setAvailableHeight] = useState6(0);
|
|
1146
1208
|
useIsomorphicLayoutEffect(() => {
|
|
1147
1209
|
if (!fillHeight || !ref.current) return;
|
|
1148
1210
|
const origin = ref.current.getBoundingClientRect().top - runtime.getViewportTop() - (scrollRoot?.clientTop ?? 0) + runtime.getScrollTop();
|
|
@@ -1203,25 +1265,25 @@ function ReaderLayout({ actions, toc, sidebar, followOutput, sidebarBreakpoint,
|
|
|
1203
1265
|
const sidebarVisible = !!sidebar && width >= sidebarBreakpoint;
|
|
1204
1266
|
return /* @__PURE__ */ jsxs6("div", { ref, className: `limr-reader ${className ?? ""}`, style: { "--limr-reader-available-height": fillHeight ? `${availableHeight}px` : void 0, ...style }, "data-fill-height": fillHeight || void 0, "data-sidebar": sidebarVisible || void 0, "data-toc": toc && width >= 800 || void 0, "data-limr-theme": theme, "data-limr-appearance": appearance, children: [
|
|
1205
1267
|
toc && /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
1206
|
-
/* @__PURE__ */
|
|
1207
|
-
/* @__PURE__ */
|
|
1268
|
+
/* @__PURE__ */ jsx7("div", { ref: tocRail, className: "limr-reader-toc", children: /* @__PURE__ */ jsx7(TableOfContents, {}) }),
|
|
1269
|
+
/* @__PURE__ */ jsx7(MobileContents, {})
|
|
1208
1270
|
] }),
|
|
1209
|
-
/* @__PURE__ */
|
|
1210
|
-
sidebarVisible && /* @__PURE__ */
|
|
1211
|
-
/* @__PURE__ */
|
|
1212
|
-
/* @__PURE__ */
|
|
1271
|
+
/* @__PURE__ */ jsx7("main", { ref: content, className: "limr-reader-content", children: /* @__PURE__ */ jsx7(Markdown, { followOutput }) }),
|
|
1272
|
+
sidebarVisible && /* @__PURE__ */ jsx7(AnnotationSidebar, {}),
|
|
1273
|
+
/* @__PURE__ */ jsx7(AnnotationOverlay, { disabled: sidebarVisible }),
|
|
1274
|
+
/* @__PURE__ */ jsx7(SelectionToolbar, { actions })
|
|
1213
1275
|
] });
|
|
1214
1276
|
}
|
|
1215
1277
|
function MobileContents() {
|
|
1216
1278
|
const locale = useLocale();
|
|
1217
|
-
const [open, setOpen] =
|
|
1279
|
+
const [open, setOpen] = useState6(false);
|
|
1218
1280
|
const id = useId2();
|
|
1219
1281
|
return /* @__PURE__ */ jsxs6("div", { className: "limr-reader-mobile-toc", children: [
|
|
1220
1282
|
/* @__PURE__ */ jsxs6("button", { type: "button", className: "limr-mobile-toc-toggle", "aria-expanded": open, "aria-controls": id, onClick: () => setOpen((value) => !value), children: [
|
|
1221
|
-
/* @__PURE__ */
|
|
1222
|
-
/* @__PURE__ */
|
|
1283
|
+
/* @__PURE__ */ jsx7("span", { children: locale.contents }),
|
|
1284
|
+
/* @__PURE__ */ jsx7("svg", { viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx7("path", { d: "m6 8 4 4 4-4" }) })
|
|
1223
1285
|
] }),
|
|
1224
|
-
/* @__PURE__ */
|
|
1286
|
+
/* @__PURE__ */ jsx7("div", { id, children: /* @__PURE__ */ jsx7(Collapse, { open, keepMounted: true, children: /* @__PURE__ */ jsx7(TableOfContents, {}) }) })
|
|
1225
1287
|
] });
|
|
1226
1288
|
}
|
|
1227
1289
|
|
|
@@ -1235,4 +1297,4 @@ export {
|
|
|
1235
1297
|
SelectionToolbar,
|
|
1236
1298
|
Reader
|
|
1237
1299
|
};
|
|
1238
|
-
//# sourceMappingURL=chunk-
|
|
1300
|
+
//# sourceMappingURL=chunk-GU2RPESF.js.map
|