@sethumadhavan004/ink-editor 0.0.3 → 0.0.4

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
 
@@ -2559,7 +2656,8 @@ function PagedEditorContent({
2559
2656
  colors,
2560
2657
  onColorsChange,
2561
2658
  toolbarStart,
2562
- toolbarEnd
2659
+ toolbarEnd,
2660
+ singlePage = false
2563
2661
  }) {
2564
2662
  const widthPx = getPageWidthPx(pageSize);
2565
2663
  const bodyWidthPx = getBodyWidthPx(pageSize);
@@ -2570,7 +2668,7 @@ function PagedEditorContent({
2570
2668
  return /* @__PURE__ */ jsxs4(
2571
2669
  "div",
2572
2670
  {
2573
- className: "ink-page-wrap",
2671
+ className: `ink-page-wrap${singlePage ? " ink-page-wrap--single" : ""}`,
2574
2672
  "data-theme": theme,
2575
2673
  style: {
2576
2674
  "--ink-bg": colors.canvasBg,
@@ -2602,7 +2700,8 @@ function PagedEditorContent({
2602
2700
  className: `ink-page-card${ruled ? " ink-ruled" : ""}`,
2603
2701
  style: {
2604
2702
  width: widthPx,
2605
- minHeight: pageHeightPx,
2703
+ // In singlePage mode: fixed height + overflow hidden so content never visually spills
2704
+ ...singlePage ? { height: pageHeightPx, overflow: "hidden" } : { minHeight: pageHeightPx },
2606
2705
  padding: `${dims.paddingTopMm}mm ${dims.paddingRightMm}mm ${dims.paddingBottomMm}mm ${dims.paddingLeftMm}mm`,
2607
2706
  ["--ink-padding-top"]: `${dims.paddingTopMm}mm`,
2608
2707
  ["--ink-padding-right"]: `${dims.paddingRightMm}mm`,
@@ -2629,7 +2728,10 @@ function InkEditor({
2629
2728
  initialFont = "cursive",
2630
2729
  initialColors,
2631
2730
  toolbarStart,
2632
- toolbarEnd
2731
+ toolbarEnd,
2732
+ singlePage = false,
2733
+ onOverflow,
2734
+ initialContent
2633
2735
  }) {
2634
2736
  const [ruled, setRuled] = useState2(false);
2635
2737
  const [font, setFont] = useState2(initialFont);
@@ -2637,14 +2739,17 @@ function InkEditor({
2637
2739
  ...theme === "minimal" ? MINIMAL_DEFAULTS : PARCHMENT_DEFAULTS,
2638
2740
  ...initialColors
2639
2741
  });
2742
+ const extensions = [
2743
+ StarterKit,
2744
+ TextAlign.configure({ types: ["heading", "paragraph"] }),
2745
+ Underline2,
2746
+ TabIndent,
2747
+ ...singlePage ? [SinglePageOverflow.configure({ pageSize, onOverflow: onOverflow ?? (() => {
2748
+ }) })] : [PageLayout.configure({ pageSize })]
2749
+ ];
2640
2750
  const editor = useEditor({
2641
- extensions: [
2642
- StarterKit,
2643
- PageLayout.configure({ pageSize }),
2644
- TextAlign.configure({ types: ["heading", "paragraph"] }),
2645
- Underline2,
2646
- TabIndent
2647
- ],
2751
+ extensions,
2752
+ content: initialContent ?? void 0,
2648
2753
  onUpdate({ editor: editor2 }) {
2649
2754
  onChange?.(editor2.getJSON());
2650
2755
  }
@@ -2668,13 +2773,15 @@ function InkEditor({
2668
2773
  colors,
2669
2774
  onColorsChange: setColors,
2670
2775
  toolbarStart,
2671
- toolbarEnd
2776
+ toolbarEnd,
2777
+ singlePage
2672
2778
  }
2673
2779
  );
2674
2780
  }
2675
2781
  export {
2676
2782
  InkEditor,
2677
2783
  MINIMAL_DEFAULTS,
2678
- PARCHMENT_DEFAULTS
2784
+ PARCHMENT_DEFAULTS,
2785
+ SinglePageOverflow
2679
2786
  };
2680
2787
  //# sourceMappingURL=index.mjs.map