@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.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
- editor && hasToolbar && /* @__PURE__ */ jsx4(
2585
- FloatingToolbar,
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
- StarterKit,
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: setColors,
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