@sethumadhavan004/ink-editor 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.css +5 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +19 -2
- package/dist/index.d.ts +19 -2
- package/dist/index.js +183 -57
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +181 -56
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2224,6 +2224,103 @@ var TabIndent = Extension.create({
|
|
|
2224
2224
|
}
|
|
2225
2225
|
});
|
|
2226
2226
|
|
|
2227
|
+
// src/extensions/SinglePageOverflow.ts
|
|
2228
|
+
import { Plugin as Plugin3, PluginKey as PluginKey3 } from "@tiptap/pm/state";
|
|
2229
|
+
var pluginKey2 = new PluginKey3("singlePageOverflow");
|
|
2230
|
+
function getBodyHeightPx2(view, pageSize) {
|
|
2231
|
+
const card = view.dom.closest(".ink-page-card");
|
|
2232
|
+
if (card) {
|
|
2233
|
+
const style = window.getComputedStyle(card);
|
|
2234
|
+
const paddingTop = parseFloat(style.paddingTop);
|
|
2235
|
+
const paddingBottom = parseFloat(style.paddingBottom);
|
|
2236
|
+
const totalHeight = card.offsetHeight || 0;
|
|
2237
|
+
const bodyPx = totalHeight - paddingTop - paddingBottom;
|
|
2238
|
+
if (bodyPx > 0) return Math.floor(bodyPx / 28) * 28;
|
|
2239
|
+
}
|
|
2240
|
+
const d = PAGE_DIMENSIONS[pageSize];
|
|
2241
|
+
const PX_PER_MM2 = 3.7795;
|
|
2242
|
+
return Math.floor((d.heightMm - d.paddingTopMm - d.paddingBottomMm) * PX_PER_MM2 / 28) * 28;
|
|
2243
|
+
}
|
|
2244
|
+
function splitAtOverflow(doc, view, bodyHeightPx) {
|
|
2245
|
+
let baseY = null;
|
|
2246
|
+
let splitPos = null;
|
|
2247
|
+
doc.forEach((node, offset) => {
|
|
2248
|
+
if (splitPos !== null) return;
|
|
2249
|
+
const pos = offset + 1;
|
|
2250
|
+
if (pos >= doc.content.size) return;
|
|
2251
|
+
let bottom;
|
|
2252
|
+
try {
|
|
2253
|
+
const coords = view.coordsAtPos(pos);
|
|
2254
|
+
if (baseY === null) baseY = coords.top;
|
|
2255
|
+
const endPos = offset + node.nodeSize - 1;
|
|
2256
|
+
bottom = endPos > pos ? view.coordsAtPos(endPos).bottom : coords.bottom;
|
|
2257
|
+
} catch {
|
|
2258
|
+
return;
|
|
2259
|
+
}
|
|
2260
|
+
const relBottom = bottom - (baseY ?? bottom);
|
|
2261
|
+
if (relBottom > bodyHeightPx) {
|
|
2262
|
+
splitPos = offset;
|
|
2263
|
+
}
|
|
2264
|
+
});
|
|
2265
|
+
if (splitPos === null) return null;
|
|
2266
|
+
const schema = doc.type.schema;
|
|
2267
|
+
const fitsContent = doc.slice(0, splitPos).content;
|
|
2268
|
+
const overflowContent = doc.slice(splitPos).content;
|
|
2269
|
+
const fitsJson = schema.nodeFromJSON({ type: "doc", content: fitsContent.toJSON() ?? [] }).toJSON();
|
|
2270
|
+
const overflowJson = schema.nodeFromJSON({ type: "doc", content: overflowContent.toJSON() ?? [] }).toJSON();
|
|
2271
|
+
return { fitsJson, overflowJson };
|
|
2272
|
+
}
|
|
2273
|
+
var SinglePageOverflow = Extension.create({
|
|
2274
|
+
name: "singlePageOverflow",
|
|
2275
|
+
addOptions() {
|
|
2276
|
+
return {
|
|
2277
|
+
pageSize: "A4",
|
|
2278
|
+
onOverflow: () => {
|
|
2279
|
+
}
|
|
2280
|
+
};
|
|
2281
|
+
},
|
|
2282
|
+
addProseMirrorPlugins() {
|
|
2283
|
+
const { pageSize, onOverflow } = this.options;
|
|
2284
|
+
let rafId = null;
|
|
2285
|
+
function scheduleCheck(view) {
|
|
2286
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
2287
|
+
rafId = requestAnimationFrame(() => {
|
|
2288
|
+
rafId = null;
|
|
2289
|
+
if (view.isDestroyed) return;
|
|
2290
|
+
const bodyHeightPx = getBodyHeightPx2(view, pageSize);
|
|
2291
|
+
const result = splitAtOverflow(view.state.doc, view, bodyHeightPx);
|
|
2292
|
+
if (!result) return;
|
|
2293
|
+
const { fitsJson, overflowJson } = result;
|
|
2294
|
+
const schema = view.state.schema;
|
|
2295
|
+
const fitsDoc = schema.nodeFromJSON(fitsJson);
|
|
2296
|
+
const tr = view.state.tr.replaceWith(0, view.state.doc.content.size, fitsDoc.content);
|
|
2297
|
+
tr.setMeta("addToHistory", false);
|
|
2298
|
+
tr.setMeta("singlePageTrim", true);
|
|
2299
|
+
view.dispatch(tr);
|
|
2300
|
+
onOverflow(fitsJson, overflowJson);
|
|
2301
|
+
});
|
|
2302
|
+
}
|
|
2303
|
+
return [
|
|
2304
|
+
new Plugin3({
|
|
2305
|
+
key: pluginKey2,
|
|
2306
|
+
view(editorView) {
|
|
2307
|
+
return {
|
|
2308
|
+
update(view, prevState) {
|
|
2309
|
+
if (view.state.doc.eq(prevState.doc) || view.state.tr?.getMeta?.("singlePageTrim")) return;
|
|
2310
|
+
if (view.state.doc.content.size !== prevState.doc.content.size || !view.state.doc.eq(prevState.doc)) {
|
|
2311
|
+
scheduleCheck(view);
|
|
2312
|
+
}
|
|
2313
|
+
},
|
|
2314
|
+
destroy() {
|
|
2315
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
2316
|
+
}
|
|
2317
|
+
};
|
|
2318
|
+
}
|
|
2319
|
+
})
|
|
2320
|
+
];
|
|
2321
|
+
}
|
|
2322
|
+
});
|
|
2323
|
+
|
|
2227
2324
|
// src/components/PagedEditorContent.tsx
|
|
2228
2325
|
import { EditorContent } from "@tiptap/react";
|
|
2229
2326
|
|
|
@@ -2322,7 +2419,7 @@ var COLOR_LABELS = {
|
|
|
2322
2419
|
accentColor: "Accent"
|
|
2323
2420
|
};
|
|
2324
2421
|
var COLOR_KEYS = Object.keys(SWATCHES);
|
|
2325
|
-
function ColorPanel({ colors, onChange, open, onToggle, onClose }) {
|
|
2422
|
+
function ColorPanel({ colors, onChange, open, onToggle, onClose, hiddenKeys = [] }) {
|
|
2326
2423
|
const ref = useRef2(null);
|
|
2327
2424
|
useEffect2(() => {
|
|
2328
2425
|
if (!open) return;
|
|
@@ -2347,7 +2444,7 @@ function ColorPanel({ colors, onChange, open, onToggle, onClose }) {
|
|
|
2347
2444
|
children: /* @__PURE__ */ jsx2(Palette, { size: 16 })
|
|
2348
2445
|
}
|
|
2349
2446
|
),
|
|
2350
|
-
open && /* @__PURE__ */ jsx2("div", { className: "ink-popover ink-popover--right ink-color-panel", role: "dialog", "aria-label": "Color customization", children: COLOR_KEYS.map((key) => /* @__PURE__ */ jsxs2("div", { className: "ink-color-row", children: [
|
|
2447
|
+
open && /* @__PURE__ */ jsx2("div", { className: "ink-popover ink-popover--right ink-color-panel", role: "dialog", "aria-label": "Color customization", children: COLOR_KEYS.filter((k) => !hiddenKeys.includes(k)).map((key) => /* @__PURE__ */ jsxs2("div", { className: "ink-color-row", children: [
|
|
2351
2448
|
/* @__PURE__ */ jsx2("span", { className: "ink-color-label", children: COLOR_LABELS[key] }),
|
|
2352
2449
|
/* @__PURE__ */ jsxs2("div", { className: "ink-swatches", children: [
|
|
2353
2450
|
SWATCHES[key].map((swatch) => /* @__PURE__ */ jsx2(
|
|
@@ -2391,7 +2488,8 @@ function FloatingToolbar({
|
|
|
2391
2488
|
colors,
|
|
2392
2489
|
onColorsChange,
|
|
2393
2490
|
toolbarStart,
|
|
2394
|
-
toolbarEnd
|
|
2491
|
+
toolbarEnd,
|
|
2492
|
+
hiddenColorKeys
|
|
2395
2493
|
}) {
|
|
2396
2494
|
const [openPanel, setOpenPanel] = useState(null);
|
|
2397
2495
|
useEffect3(() => {
|
|
@@ -2535,7 +2633,8 @@ function FloatingToolbar({
|
|
|
2535
2633
|
onChange: onColorsChange,
|
|
2536
2634
|
open: openPanel === "color",
|
|
2537
2635
|
onToggle: () => togglePanel("color"),
|
|
2538
|
-
onClose: () => setOpenPanel(null)
|
|
2636
|
+
onClose: () => setOpenPanel(null),
|
|
2637
|
+
hiddenKeys: hiddenColorKeys
|
|
2539
2638
|
}
|
|
2540
2639
|
),
|
|
2541
2640
|
toolbarEnd && toolbarEnd.length > 0 && /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
@@ -2559,7 +2658,9 @@ function PagedEditorContent({
|
|
|
2559
2658
|
colors,
|
|
2560
2659
|
onColorsChange,
|
|
2561
2660
|
toolbarStart,
|
|
2562
|
-
toolbarEnd
|
|
2661
|
+
toolbarEnd,
|
|
2662
|
+
singlePage = false,
|
|
2663
|
+
hiddenColorKeys
|
|
2563
2664
|
}) {
|
|
2564
2665
|
const widthPx = getPageWidthPx(pageSize);
|
|
2565
2666
|
const bodyWidthPx = getBodyWidthPx(pageSize);
|
|
@@ -2567,52 +2668,62 @@ function PagedEditorContent({
|
|
|
2567
2668
|
const pageHeightPx = Math.round(dims.heightMm * 3.7795);
|
|
2568
2669
|
const hasToolbar = toolbar.length > 0;
|
|
2569
2670
|
const bodyHeightPx = getBodyHeightPx(pageSize);
|
|
2671
|
+
const cssVars = {
|
|
2672
|
+
"--ink-bg": colors.canvasBg,
|
|
2673
|
+
"--ink-page": colors.paperColor,
|
|
2674
|
+
"--ink-text": colors.textColor,
|
|
2675
|
+
"--ink-border-line": colors.lineColor,
|
|
2676
|
+
"--ink-accent": colors.accentColor,
|
|
2677
|
+
"--ink-font-body": FONTS[font].family
|
|
2678
|
+
};
|
|
2679
|
+
const toolbar_el = editor && hasToolbar ? /* @__PURE__ */ jsx4(
|
|
2680
|
+
FloatingToolbar,
|
|
2681
|
+
{
|
|
2682
|
+
editor,
|
|
2683
|
+
buttons: toolbar,
|
|
2684
|
+
ruled,
|
|
2685
|
+
onToggleRuled,
|
|
2686
|
+
font,
|
|
2687
|
+
onFontChange,
|
|
2688
|
+
colors,
|
|
2689
|
+
onColorsChange,
|
|
2690
|
+
toolbarStart,
|
|
2691
|
+
toolbarEnd,
|
|
2692
|
+
hiddenColorKeys
|
|
2693
|
+
}
|
|
2694
|
+
) : null;
|
|
2695
|
+
const card_el = /* @__PURE__ */ jsx4(
|
|
2696
|
+
"div",
|
|
2697
|
+
{
|
|
2698
|
+
className: `ink-page-card${ruled ? " ink-ruled" : ""}`,
|
|
2699
|
+
style: {
|
|
2700
|
+
width: widthPx,
|
|
2701
|
+
...singlePage ? { height: pageHeightPx, overflow: "hidden" } : { minHeight: pageHeightPx },
|
|
2702
|
+
padding: `${dims.paddingTopMm}mm ${dims.paddingRightMm}mm ${dims.paddingBottomMm}mm ${dims.paddingLeftMm}mm`,
|
|
2703
|
+
["--ink-padding-top"]: `${dims.paddingTopMm}mm`,
|
|
2704
|
+
["--ink-padding-right"]: `${dims.paddingRightMm}mm`,
|
|
2705
|
+
["--ink-padding-left"]: `${dims.paddingLeftMm}mm`,
|
|
2706
|
+
["--ink-body-width"]: `${bodyWidthPx}px`,
|
|
2707
|
+
["--ink-body-height"]: `${bodyHeightPx}px`
|
|
2708
|
+
},
|
|
2709
|
+
children: /* @__PURE__ */ jsx4(EditorContent, { editor })
|
|
2710
|
+
}
|
|
2711
|
+
);
|
|
2712
|
+
if (singlePage) {
|
|
2713
|
+
return /* @__PURE__ */ jsxs4("div", { "data-theme": theme, style: cssVars, children: [
|
|
2714
|
+
toolbar_el,
|
|
2715
|
+
card_el
|
|
2716
|
+
] });
|
|
2717
|
+
}
|
|
2570
2718
|
return /* @__PURE__ */ jsxs4(
|
|
2571
2719
|
"div",
|
|
2572
2720
|
{
|
|
2573
2721
|
className: "ink-page-wrap",
|
|
2574
2722
|
"data-theme": theme,
|
|
2575
|
-
style:
|
|
2576
|
-
"--ink-bg": colors.canvasBg,
|
|
2577
|
-
"--ink-page": colors.paperColor,
|
|
2578
|
-
"--ink-text": colors.textColor,
|
|
2579
|
-
"--ink-border-line": colors.lineColor,
|
|
2580
|
-
"--ink-accent": colors.accentColor,
|
|
2581
|
-
"--ink-font-body": FONTS[font].family
|
|
2582
|
-
},
|
|
2723
|
+
style: cssVars,
|
|
2583
2724
|
children: [
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
{
|
|
2587
|
-
editor,
|
|
2588
|
-
buttons: toolbar,
|
|
2589
|
-
ruled,
|
|
2590
|
-
onToggleRuled,
|
|
2591
|
-
font,
|
|
2592
|
-
onFontChange,
|
|
2593
|
-
colors,
|
|
2594
|
-
onColorsChange,
|
|
2595
|
-
toolbarStart,
|
|
2596
|
-
toolbarEnd
|
|
2597
|
-
}
|
|
2598
|
-
),
|
|
2599
|
-
/* @__PURE__ */ jsx4(
|
|
2600
|
-
"div",
|
|
2601
|
-
{
|
|
2602
|
-
className: `ink-page-card${ruled ? " ink-ruled" : ""}`,
|
|
2603
|
-
style: {
|
|
2604
|
-
width: widthPx,
|
|
2605
|
-
minHeight: pageHeightPx,
|
|
2606
|
-
padding: `${dims.paddingTopMm}mm ${dims.paddingRightMm}mm ${dims.paddingBottomMm}mm ${dims.paddingLeftMm}mm`,
|
|
2607
|
-
["--ink-padding-top"]: `${dims.paddingTopMm}mm`,
|
|
2608
|
-
["--ink-padding-right"]: `${dims.paddingRightMm}mm`,
|
|
2609
|
-
["--ink-padding-left"]: `${dims.paddingLeftMm}mm`,
|
|
2610
|
-
["--ink-body-width"]: `${bodyWidthPx}px`,
|
|
2611
|
-
["--ink-body-height"]: `${bodyHeightPx}px`
|
|
2612
|
-
},
|
|
2613
|
-
children: /* @__PURE__ */ jsx4(EditorContent, { editor })
|
|
2614
|
-
}
|
|
2615
|
-
)
|
|
2725
|
+
toolbar_el,
|
|
2726
|
+
card_el
|
|
2616
2727
|
]
|
|
2617
2728
|
}
|
|
2618
2729
|
);
|
|
@@ -2629,7 +2740,12 @@ function InkEditor({
|
|
|
2629
2740
|
initialFont = "cursive",
|
|
2630
2741
|
initialColors,
|
|
2631
2742
|
toolbarStart,
|
|
2632
|
-
toolbarEnd
|
|
2743
|
+
toolbarEnd,
|
|
2744
|
+
singlePage = false,
|
|
2745
|
+
onOverflow,
|
|
2746
|
+
initialContent,
|
|
2747
|
+
onColorsChange,
|
|
2748
|
+
hiddenColorKeys
|
|
2633
2749
|
}) {
|
|
2634
2750
|
const [ruled, setRuled] = useState2(false);
|
|
2635
2751
|
const [font, setFont] = useState2(initialFont);
|
|
@@ -2637,14 +2753,17 @@ function InkEditor({
|
|
|
2637
2753
|
...theme === "minimal" ? MINIMAL_DEFAULTS : PARCHMENT_DEFAULTS,
|
|
2638
2754
|
...initialColors
|
|
2639
2755
|
});
|
|
2756
|
+
const extensions = [
|
|
2757
|
+
StarterKit,
|
|
2758
|
+
TextAlign.configure({ types: ["heading", "paragraph"] }),
|
|
2759
|
+
Underline2,
|
|
2760
|
+
TabIndent,
|
|
2761
|
+
...singlePage ? [SinglePageOverflow.configure({ pageSize, onOverflow: onOverflow ?? (() => {
|
|
2762
|
+
}) })] : [PageLayout.configure({ pageSize })]
|
|
2763
|
+
];
|
|
2640
2764
|
const editor = useEditor({
|
|
2641
|
-
extensions
|
|
2642
|
-
|
|
2643
|
-
PageLayout.configure({ pageSize }),
|
|
2644
|
-
TextAlign.configure({ types: ["heading", "paragraph"] }),
|
|
2645
|
-
Underline2,
|
|
2646
|
-
TabIndent
|
|
2647
|
-
],
|
|
2765
|
+
extensions,
|
|
2766
|
+
content: initialContent ?? void 0,
|
|
2648
2767
|
onUpdate({ editor: editor2 }) {
|
|
2649
2768
|
onChange?.(editor2.getJSON());
|
|
2650
2769
|
}
|
|
@@ -2666,15 +2785,21 @@ function InkEditor({
|
|
|
2666
2785
|
font,
|
|
2667
2786
|
onFontChange: setFont,
|
|
2668
2787
|
colors,
|
|
2669
|
-
onColorsChange:
|
|
2788
|
+
onColorsChange: (c) => {
|
|
2789
|
+
setColors(c);
|
|
2790
|
+
onColorsChange?.(c);
|
|
2791
|
+
},
|
|
2670
2792
|
toolbarStart,
|
|
2671
|
-
toolbarEnd
|
|
2793
|
+
toolbarEnd,
|
|
2794
|
+
singlePage,
|
|
2795
|
+
hiddenColorKeys
|
|
2672
2796
|
}
|
|
2673
2797
|
);
|
|
2674
2798
|
}
|
|
2675
2799
|
export {
|
|
2676
2800
|
InkEditor,
|
|
2677
2801
|
MINIMAL_DEFAULTS,
|
|
2678
|
-
PARCHMENT_DEFAULTS
|
|
2802
|
+
PARCHMENT_DEFAULTS,
|
|
2803
|
+
SinglePageOverflow
|
|
2679
2804
|
};
|
|
2680
2805
|
//# sourceMappingURL=index.mjs.map
|