@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.css +5 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +15 -2
- package/dist/index.d.ts +15 -2
- package/dist/index.js +122 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +120 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.css
CHANGED
|
@@ -198,6 +198,10 @@
|
|
|
198
198
|
background: transparent;
|
|
199
199
|
min-height: 100vh;
|
|
200
200
|
}
|
|
201
|
+
.ink-page-wrap--single {
|
|
202
|
+
min-height: unset;
|
|
203
|
+
padding: 0;
|
|
204
|
+
}
|
|
201
205
|
.ink-page-card {
|
|
202
206
|
background: var(--ink-page);
|
|
203
207
|
box-shadow: var(--ink-shadow);
|
|
@@ -216,7 +220,7 @@
|
|
|
216
220
|
display: block;
|
|
217
221
|
width: calc(100% + var(--ink-padding-left, 28mm) + var(--ink-padding-right, 28mm));
|
|
218
222
|
margin-left: calc(-1 * var(--ink-padding-left, 28mm));
|
|
219
|
-
background:
|
|
223
|
+
background: transparent;
|
|
220
224
|
border-top: 2px solid var(--ink-border-line);
|
|
221
225
|
border-bottom: 2px solid var(--ink-border-line);
|
|
222
226
|
box-sizing: border-box;
|
package/dist/index.css.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/styles/floating-toolbar.css","../src/styles/themes.css","../src/styles/page.css"],"sourcesContent":["/* Sticky wrapper — keeps toolbar floating in canvas while page scrolls beneath */\n.ink-floating-toolbar-wrap {\n position: sticky;\n top: 16px;\n z-index: 100;\n width: fit-content;\n margin-bottom: 16px;\n align-self: center;\n}\n\n/* Pill-shaped floating bar */\n.ink-floating-toolbar {\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 6px 12px;\n background: var(--ink-page, #f5f4ed);\n border: 1px solid var(--ink-toolbar-border, #d4d0c4);\n border-radius: 12px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n white-space: nowrap;\n}\n\n.ink-toolbar-sep {\n display: inline-block;\n width: 1px;\n height: 20px;\n background: var(--ink-toolbar-border, #d4d0c4);\n margin: 0 6px;\n align-self: center;\n flex-shrink: 0;\n}\n\n.ink-toolbar-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 30px;\n height: 30px;\n border: none;\n border-radius: 4px;\n background: transparent;\n cursor: pointer;\n color: var(--ink-text-muted, #6b6a64);\n transition: background 0.1s, color 0.1s;\n flex-shrink: 0;\n}\n\n.ink-toolbar-btn:hover {\n background: var(--ink-toolbar-border, #d4d0c4);\n color: var(--ink-text, #141413);\n}\n\n.ink-toolbar-btn--active {\n color: var(--ink-accent, #1b365d);\n}\n\n/* Popover container — parent must be position:relative */\n.ink-popover-anchor {\n position: relative;\n display: inline-flex;\n}\n\n.ink-popover {\n position: absolute;\n top: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n background: var(--ink-page, #f5f4ed);\n border: 1px solid var(--ink-toolbar-border, #d4d0c4);\n border-radius: 8px;\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);\n padding: 12px;\n z-index: 200;\n min-width: 160px;\n}\n\n.ink-popover--right {\n left: auto;\n right: 0;\n transform: none;\n}\n\n/* Font picker list */\n.ink-font-picker {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.ink-font-option {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 8px;\n border: none;\n border-radius: 4px;\n background: transparent;\n cursor: pointer;\n color: var(--ink-text, #141413);\n text-align: left;\n width: 100%;\n transition: background 0.1s;\n}\n\n.ink-font-option:hover {\n background: var(--ink-toolbar-border, #d4d0c4);\n}\n\n.ink-font-option--active {\n background: var(--ink-toolbar-border, #d4d0c4);\n font-weight: 600;\n}\n\n/* Color panel rows */\n.ink-color-panel {\n display: flex;\n flex-direction: column;\n gap: 10px;\n min-width: 220px;\n}\n\n.ink-color-row {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.ink-color-label {\n font-size: 11px;\n color: var(--ink-text-muted, #6b6a64);\n width: 46px;\n flex-shrink: 0;\n}\n\n.ink-swatches {\n display: flex;\n gap: 4px;\n align-items: center;\n flex-wrap: nowrap;\n}\n\n.ink-swatch {\n width: 20px;\n height: 20px;\n border-radius: 50%;\n border: 2px solid transparent;\n cursor: pointer;\n flex-shrink: 0;\n transition: transform 0.1s, border-color 0.1s;\n}\n\n.ink-swatch:hover {\n transform: scale(1.15);\n}\n\n.ink-swatch--active {\n border-color: var(--ink-accent, #1b365d);\n}\n\n.ink-color-custom {\n width: 22px;\n height: 22px;\n border-radius: 50%;\n border: 2px solid var(--ink-toolbar-border, #d4d0c4);\n cursor: pointer;\n padding: 0;\n background: none;\n overflow: hidden;\n flex-shrink: 0;\n}\n\n.ink-color-custom input[type=\"color\"] {\n width: 200%;\n height: 200%;\n margin: -50%;\n border: none;\n padding: 0;\n cursor: pointer;\n background: none;\n}\n",".ink-page-wrap[data-theme=\"parchment\"] {\n --ink-bg: #e0ddd4;\n --ink-page: #f5f4ed;\n --ink-shadow: 0 4px 24px rgba(0, 0, 0, 0.05);\n --ink-border-line: #c8c4b8;\n --ink-accent: #1b365d;\n --ink-text: #141413;\n --ink-text-muted: #6b6a64;\n --ink-toolbar-bg: #edeae0;\n --ink-toolbar-border: #d4d0c4;\n --ink-font-body: Charter, Georgia, 'Palatino Linotype', serif;\n}\n\n.ink-page-wrap[data-theme=\"minimal\"] {\n --ink-bg: #e8e8e8;\n --ink-page: #ffffff;\n --ink-shadow: 0 2px 12px rgba(0, 0, 0, 0.18);\n --ink-border-line: #d0d0d0;\n --ink-accent: #2563eb;\n --ink-text: #111111;\n --ink-text-muted: #888888;\n --ink-toolbar-bg: #f5f5f5;\n --ink-toolbar-border: #e0e0e0;\n --ink-font-body: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n}\n","@import './themes.css';\r\n\r\n.ink-page-wrap {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n padding: 32px 0;\r\n background: transparent;\r\n min-height: 100vh;\r\n}\r\n\r\n.ink-page-card {\r\n background: var(--ink-page);\r\n box-shadow: var(--ink-shadow);\r\n box-sizing: border-box;\r\n font-family: var(--ink-font-body);\r\n color: var(--ink-text);\r\n}\r\n\r\n.ink-page-card .ProseMirror {\r\n outline: none;\r\n width: var(--ink-body-width, 100%);\r\n min-height: var(--ink-body-height, 600px);\r\n line-height: 1.7;\r\n padding-top: 28px;\r\n}\r\n\r\n\r\n/* Page gap widget — injected by ProseMirror plugin at each page boundary */\r\n.ink-page-gap {\r\n display: block;\r\n width: calc(100% + var(--ink-padding-left, 28mm) + var(--ink-padding-right, 28mm));\r\n margin-left: calc(-1 * var(--ink-padding-left, 28mm));\r\n background:
|
|
1
|
+
{"version":3,"sources":["../src/styles/floating-toolbar.css","../src/styles/themes.css","../src/styles/page.css"],"sourcesContent":["/* Sticky wrapper — keeps toolbar floating in canvas while page scrolls beneath */\n.ink-floating-toolbar-wrap {\n position: sticky;\n top: 16px;\n z-index: 100;\n width: fit-content;\n margin-bottom: 16px;\n align-self: center;\n}\n\n/* Pill-shaped floating bar */\n.ink-floating-toolbar {\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 6px 12px;\n background: var(--ink-page, #f5f4ed);\n border: 1px solid var(--ink-toolbar-border, #d4d0c4);\n border-radius: 12px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n white-space: nowrap;\n}\n\n.ink-toolbar-sep {\n display: inline-block;\n width: 1px;\n height: 20px;\n background: var(--ink-toolbar-border, #d4d0c4);\n margin: 0 6px;\n align-self: center;\n flex-shrink: 0;\n}\n\n.ink-toolbar-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 30px;\n height: 30px;\n border: none;\n border-radius: 4px;\n background: transparent;\n cursor: pointer;\n color: var(--ink-text-muted, #6b6a64);\n transition: background 0.1s, color 0.1s;\n flex-shrink: 0;\n}\n\n.ink-toolbar-btn:hover {\n background: var(--ink-toolbar-border, #d4d0c4);\n color: var(--ink-text, #141413);\n}\n\n.ink-toolbar-btn--active {\n color: var(--ink-accent, #1b365d);\n}\n\n/* Popover container — parent must be position:relative */\n.ink-popover-anchor {\n position: relative;\n display: inline-flex;\n}\n\n.ink-popover {\n position: absolute;\n top: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n background: var(--ink-page, #f5f4ed);\n border: 1px solid var(--ink-toolbar-border, #d4d0c4);\n border-radius: 8px;\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);\n padding: 12px;\n z-index: 200;\n min-width: 160px;\n}\n\n.ink-popover--right {\n left: auto;\n right: 0;\n transform: none;\n}\n\n/* Font picker list */\n.ink-font-picker {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.ink-font-option {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 8px;\n border: none;\n border-radius: 4px;\n background: transparent;\n cursor: pointer;\n color: var(--ink-text, #141413);\n text-align: left;\n width: 100%;\n transition: background 0.1s;\n}\n\n.ink-font-option:hover {\n background: var(--ink-toolbar-border, #d4d0c4);\n}\n\n.ink-font-option--active {\n background: var(--ink-toolbar-border, #d4d0c4);\n font-weight: 600;\n}\n\n/* Color panel rows */\n.ink-color-panel {\n display: flex;\n flex-direction: column;\n gap: 10px;\n min-width: 220px;\n}\n\n.ink-color-row {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.ink-color-label {\n font-size: 11px;\n color: var(--ink-text-muted, #6b6a64);\n width: 46px;\n flex-shrink: 0;\n}\n\n.ink-swatches {\n display: flex;\n gap: 4px;\n align-items: center;\n flex-wrap: nowrap;\n}\n\n.ink-swatch {\n width: 20px;\n height: 20px;\n border-radius: 50%;\n border: 2px solid transparent;\n cursor: pointer;\n flex-shrink: 0;\n transition: transform 0.1s, border-color 0.1s;\n}\n\n.ink-swatch:hover {\n transform: scale(1.15);\n}\n\n.ink-swatch--active {\n border-color: var(--ink-accent, #1b365d);\n}\n\n.ink-color-custom {\n width: 22px;\n height: 22px;\n border-radius: 50%;\n border: 2px solid var(--ink-toolbar-border, #d4d0c4);\n cursor: pointer;\n padding: 0;\n background: none;\n overflow: hidden;\n flex-shrink: 0;\n}\n\n.ink-color-custom input[type=\"color\"] {\n width: 200%;\n height: 200%;\n margin: -50%;\n border: none;\n padding: 0;\n cursor: pointer;\n background: none;\n}\n",".ink-page-wrap[data-theme=\"parchment\"] {\n --ink-bg: #e0ddd4;\n --ink-page: #f5f4ed;\n --ink-shadow: 0 4px 24px rgba(0, 0, 0, 0.05);\n --ink-border-line: #c8c4b8;\n --ink-accent: #1b365d;\n --ink-text: #141413;\n --ink-text-muted: #6b6a64;\n --ink-toolbar-bg: #edeae0;\n --ink-toolbar-border: #d4d0c4;\n --ink-font-body: Charter, Georgia, 'Palatino Linotype', serif;\n}\n\n.ink-page-wrap[data-theme=\"minimal\"] {\n --ink-bg: #e8e8e8;\n --ink-page: #ffffff;\n --ink-shadow: 0 2px 12px rgba(0, 0, 0, 0.18);\n --ink-border-line: #d0d0d0;\n --ink-accent: #2563eb;\n --ink-text: #111111;\n --ink-text-muted: #888888;\n --ink-toolbar-bg: #f5f5f5;\n --ink-toolbar-border: #e0e0e0;\n --ink-font-body: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n}\n","@import './themes.css';\r\n\r\n.ink-page-wrap {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n padding: 32px 0;\r\n background: transparent;\r\n min-height: 100vh;\r\n}\r\n\r\n/* Single-page mode: no min-height, no padding — consumer controls layout */\r\n.ink-page-wrap--single {\r\n min-height: unset;\r\n padding: 0;\r\n}\r\n\r\n.ink-page-card {\r\n background: var(--ink-page);\r\n box-shadow: var(--ink-shadow);\r\n box-sizing: border-box;\r\n font-family: var(--ink-font-body);\r\n color: var(--ink-text);\r\n}\r\n\r\n.ink-page-card .ProseMirror {\r\n outline: none;\r\n width: var(--ink-body-width, 100%);\r\n min-height: var(--ink-body-height, 600px);\r\n line-height: 1.7;\r\n padding-top: 28px;\r\n}\r\n\r\n\r\n/* Page gap widget — injected by ProseMirror plugin at each page boundary */\r\n.ink-page-gap {\r\n display: block;\r\n width: calc(100% + var(--ink-padding-left, 28mm) + var(--ink-padding-right, 28mm));\r\n margin-left: calc(-1 * var(--ink-padding-left, 28mm));\r\n background: transparent;\r\n border-top: 2px solid var(--ink-border-line);\r\n border-bottom: 2px solid var(--ink-border-line);\r\n box-sizing: border-box;\r\n pointer-events: none;\r\n user-select: none;\r\n -webkit-user-select: none;\r\n}\r\n\r\n/* Lock paragraph line-height — zero margins so ruled lines stay on grid */\r\n.ink-page-card .ProseMirror p {\r\n line-height: 28px;\r\n margin: 0;\r\n padding: 0;\r\n}\r\n\r\n\r\n/* Ruled lines — toggled by ink-ruled class on .ink-page-card */\r\n.ink-page-card.ink-ruled .ProseMirror {\r\n background-image: repeating-linear-gradient(\r\n to bottom,\r\n transparent 0px,\r\n transparent 27px,\r\n var(--ink-border-line, #c8c4b8) 27px,\r\n var(--ink-border-line, #c8c4b8) 28px\r\n );\r\n background-size: 100% 28px;\r\n background-position-y: 28px;\r\n background-attachment: local;\r\n}\r\n"],"mappings":"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","names":[]}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
+
import { Extension } from '@tiptap/core';
|
|
3
4
|
|
|
4
5
|
type PageSize = 'A4' | 'Letter';
|
|
5
6
|
type Theme = 'parchment' | 'minimal';
|
|
@@ -24,7 +25,19 @@ interface InkEditorProps {
|
|
|
24
25
|
initialColors?: Partial<ThemeColors>;
|
|
25
26
|
toolbarStart?: ReactNode[];
|
|
26
27
|
toolbarEnd?: ReactNode[];
|
|
28
|
+
/** Single-page mode: disables multi-page gap widgets. Use with onOverflow. */
|
|
29
|
+
singlePage?: boolean;
|
|
30
|
+
/** Called when content overflows one page. fitsJson = content that fits, overflowJson = spilled content. */
|
|
31
|
+
onOverflow?: (fitsJson: object, overflowJson: object) => void;
|
|
32
|
+
/** Seed content (Tiptap JSON doc) — used to pre-fill a page, e.g. overflow from previous page. */
|
|
33
|
+
initialContent?: object;
|
|
27
34
|
}
|
|
28
|
-
declare function InkEditor({ pageSize, onChange, theme, toolbar, initialFont, initialColors, toolbarStart, toolbarEnd, }: InkEditorProps): react_jsx_runtime.JSX.Element;
|
|
35
|
+
declare function InkEditor({ pageSize, onChange, theme, toolbar, initialFont, initialColors, toolbarStart, toolbarEnd, singlePage, onOverflow, initialContent, }: InkEditorProps): react_jsx_runtime.JSX.Element;
|
|
29
36
|
|
|
30
|
-
|
|
37
|
+
interface SinglePageOverflowOptions {
|
|
38
|
+
pageSize: PageSize;
|
|
39
|
+
onOverflow: (fitsJson: object, overflowJson: object) => void;
|
|
40
|
+
}
|
|
41
|
+
declare const SinglePageOverflow: Extension<SinglePageOverflowOptions, any>;
|
|
42
|
+
|
|
43
|
+
export { type FontKey, InkEditor, type InkEditorProps, MINIMAL_DEFAULTS, PARCHMENT_DEFAULTS, type PageSize, SinglePageOverflow, type Theme, type ThemeColors, type ToolbarKey };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
+
import { Extension } from '@tiptap/core';
|
|
3
4
|
|
|
4
5
|
type PageSize = 'A4' | 'Letter';
|
|
5
6
|
type Theme = 'parchment' | 'minimal';
|
|
@@ -24,7 +25,19 @@ interface InkEditorProps {
|
|
|
24
25
|
initialColors?: Partial<ThemeColors>;
|
|
25
26
|
toolbarStart?: ReactNode[];
|
|
26
27
|
toolbarEnd?: ReactNode[];
|
|
28
|
+
/** Single-page mode: disables multi-page gap widgets. Use with onOverflow. */
|
|
29
|
+
singlePage?: boolean;
|
|
30
|
+
/** Called when content overflows one page. fitsJson = content that fits, overflowJson = spilled content. */
|
|
31
|
+
onOverflow?: (fitsJson: object, overflowJson: object) => void;
|
|
32
|
+
/** Seed content (Tiptap JSON doc) — used to pre-fill a page, e.g. overflow from previous page. */
|
|
33
|
+
initialContent?: object;
|
|
27
34
|
}
|
|
28
|
-
declare function InkEditor({ pageSize, onChange, theme, toolbar, initialFont, initialColors, toolbarStart, toolbarEnd, }: InkEditorProps): react_jsx_runtime.JSX.Element;
|
|
35
|
+
declare function InkEditor({ pageSize, onChange, theme, toolbar, initialFont, initialColors, toolbarStart, toolbarEnd, singlePage, onOverflow, initialContent, }: InkEditorProps): react_jsx_runtime.JSX.Element;
|
|
29
36
|
|
|
30
|
-
|
|
37
|
+
interface SinglePageOverflowOptions {
|
|
38
|
+
pageSize: PageSize;
|
|
39
|
+
onOverflow: (fitsJson: object, overflowJson: object) => void;
|
|
40
|
+
}
|
|
41
|
+
declare const SinglePageOverflow: Extension<SinglePageOverflowOptions, any>;
|
|
42
|
+
|
|
43
|
+
export { type FontKey, InkEditor, type InkEditorProps, MINIMAL_DEFAULTS, PARCHMENT_DEFAULTS, type PageSize, SinglePageOverflow, type Theme, type ThemeColors, type ToolbarKey };
|
package/dist/index.js
CHANGED
|
@@ -32,7 +32,8 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
InkEditor: () => InkEditor,
|
|
34
34
|
MINIMAL_DEFAULTS: () => MINIMAL_DEFAULTS,
|
|
35
|
-
PARCHMENT_DEFAULTS: () => PARCHMENT_DEFAULTS
|
|
35
|
+
PARCHMENT_DEFAULTS: () => PARCHMENT_DEFAULTS,
|
|
36
|
+
SinglePageOverflow: () => SinglePageOverflow
|
|
36
37
|
});
|
|
37
38
|
module.exports = __toCommonJS(index_exports);
|
|
38
39
|
|
|
@@ -2262,6 +2263,103 @@ var TabIndent = Extension.create({
|
|
|
2262
2263
|
}
|
|
2263
2264
|
});
|
|
2264
2265
|
|
|
2266
|
+
// src/extensions/SinglePageOverflow.ts
|
|
2267
|
+
var import_state3 = require("@tiptap/pm/state");
|
|
2268
|
+
var pluginKey2 = new import_state3.PluginKey("singlePageOverflow");
|
|
2269
|
+
function getBodyHeightPx2(view, pageSize) {
|
|
2270
|
+
const card = view.dom.closest(".ink-page-card");
|
|
2271
|
+
if (card) {
|
|
2272
|
+
const style = window.getComputedStyle(card);
|
|
2273
|
+
const paddingTop = parseFloat(style.paddingTop);
|
|
2274
|
+
const paddingBottom = parseFloat(style.paddingBottom);
|
|
2275
|
+
const totalHeight = card.offsetHeight || 0;
|
|
2276
|
+
const bodyPx = totalHeight - paddingTop - paddingBottom;
|
|
2277
|
+
if (bodyPx > 0) return Math.floor(bodyPx / 28) * 28;
|
|
2278
|
+
}
|
|
2279
|
+
const d = PAGE_DIMENSIONS[pageSize];
|
|
2280
|
+
const PX_PER_MM2 = 3.7795;
|
|
2281
|
+
return Math.floor((d.heightMm - d.paddingTopMm - d.paddingBottomMm) * PX_PER_MM2 / 28) * 28;
|
|
2282
|
+
}
|
|
2283
|
+
function splitAtOverflow(doc, view, bodyHeightPx) {
|
|
2284
|
+
let baseY = null;
|
|
2285
|
+
let splitPos = null;
|
|
2286
|
+
doc.forEach((node, offset) => {
|
|
2287
|
+
if (splitPos !== null) return;
|
|
2288
|
+
const pos = offset + 1;
|
|
2289
|
+
if (pos >= doc.content.size) return;
|
|
2290
|
+
let bottom;
|
|
2291
|
+
try {
|
|
2292
|
+
const coords = view.coordsAtPos(pos);
|
|
2293
|
+
if (baseY === null) baseY = coords.top;
|
|
2294
|
+
const endPos = offset + node.nodeSize - 1;
|
|
2295
|
+
bottom = endPos > pos ? view.coordsAtPos(endPos).bottom : coords.bottom;
|
|
2296
|
+
} catch {
|
|
2297
|
+
return;
|
|
2298
|
+
}
|
|
2299
|
+
const relBottom = bottom - (baseY ?? bottom);
|
|
2300
|
+
if (relBottom > bodyHeightPx) {
|
|
2301
|
+
splitPos = offset;
|
|
2302
|
+
}
|
|
2303
|
+
});
|
|
2304
|
+
if (splitPos === null) return null;
|
|
2305
|
+
const schema = doc.type.schema;
|
|
2306
|
+
const fitsContent = doc.slice(0, splitPos).content;
|
|
2307
|
+
const overflowContent = doc.slice(splitPos).content;
|
|
2308
|
+
const fitsJson = schema.nodeFromJSON({ type: "doc", content: fitsContent.toJSON() ?? [] }).toJSON();
|
|
2309
|
+
const overflowJson = schema.nodeFromJSON({ type: "doc", content: overflowContent.toJSON() ?? [] }).toJSON();
|
|
2310
|
+
return { fitsJson, overflowJson };
|
|
2311
|
+
}
|
|
2312
|
+
var SinglePageOverflow = Extension.create({
|
|
2313
|
+
name: "singlePageOverflow",
|
|
2314
|
+
addOptions() {
|
|
2315
|
+
return {
|
|
2316
|
+
pageSize: "A4",
|
|
2317
|
+
onOverflow: () => {
|
|
2318
|
+
}
|
|
2319
|
+
};
|
|
2320
|
+
},
|
|
2321
|
+
addProseMirrorPlugins() {
|
|
2322
|
+
const { pageSize, onOverflow } = this.options;
|
|
2323
|
+
let rafId = null;
|
|
2324
|
+
function scheduleCheck(view) {
|
|
2325
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
2326
|
+
rafId = requestAnimationFrame(() => {
|
|
2327
|
+
rafId = null;
|
|
2328
|
+
if (view.isDestroyed) return;
|
|
2329
|
+
const bodyHeightPx = getBodyHeightPx2(view, pageSize);
|
|
2330
|
+
const result = splitAtOverflow(view.state.doc, view, bodyHeightPx);
|
|
2331
|
+
if (!result) return;
|
|
2332
|
+
const { fitsJson, overflowJson } = result;
|
|
2333
|
+
const schema = view.state.schema;
|
|
2334
|
+
const fitsDoc = schema.nodeFromJSON(fitsJson);
|
|
2335
|
+
const tr = view.state.tr.replaceWith(0, view.state.doc.content.size, fitsDoc.content);
|
|
2336
|
+
tr.setMeta("addToHistory", false);
|
|
2337
|
+
tr.setMeta("singlePageTrim", true);
|
|
2338
|
+
view.dispatch(tr);
|
|
2339
|
+
onOverflow(fitsJson, overflowJson);
|
|
2340
|
+
});
|
|
2341
|
+
}
|
|
2342
|
+
return [
|
|
2343
|
+
new import_state3.Plugin({
|
|
2344
|
+
key: pluginKey2,
|
|
2345
|
+
view(editorView) {
|
|
2346
|
+
return {
|
|
2347
|
+
update(view, prevState) {
|
|
2348
|
+
if (view.state.doc.eq(prevState.doc) || view.state.tr?.getMeta?.("singlePageTrim")) return;
|
|
2349
|
+
if (view.state.doc.content.size !== prevState.doc.content.size || !view.state.doc.eq(prevState.doc)) {
|
|
2350
|
+
scheduleCheck(view);
|
|
2351
|
+
}
|
|
2352
|
+
},
|
|
2353
|
+
destroy() {
|
|
2354
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
2355
|
+
}
|
|
2356
|
+
};
|
|
2357
|
+
}
|
|
2358
|
+
})
|
|
2359
|
+
];
|
|
2360
|
+
}
|
|
2361
|
+
});
|
|
2362
|
+
|
|
2265
2363
|
// src/components/PagedEditorContent.tsx
|
|
2266
2364
|
var import_react4 = require("@tiptap/react");
|
|
2267
2365
|
|
|
@@ -2581,7 +2679,8 @@ function PagedEditorContent({
|
|
|
2581
2679
|
colors,
|
|
2582
2680
|
onColorsChange,
|
|
2583
2681
|
toolbarStart,
|
|
2584
|
-
toolbarEnd
|
|
2682
|
+
toolbarEnd,
|
|
2683
|
+
singlePage = false
|
|
2585
2684
|
}) {
|
|
2586
2685
|
const widthPx = getPageWidthPx(pageSize);
|
|
2587
2686
|
const bodyWidthPx = getBodyWidthPx(pageSize);
|
|
@@ -2592,7 +2691,7 @@ function PagedEditorContent({
|
|
|
2592
2691
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2593
2692
|
"div",
|
|
2594
2693
|
{
|
|
2595
|
-
className: "ink-page-wrap"
|
|
2694
|
+
className: `ink-page-wrap${singlePage ? " ink-page-wrap--single" : ""}`,
|
|
2596
2695
|
"data-theme": theme,
|
|
2597
2696
|
style: {
|
|
2598
2697
|
"--ink-bg": colors.canvasBg,
|
|
@@ -2624,7 +2723,8 @@ function PagedEditorContent({
|
|
|
2624
2723
|
className: `ink-page-card${ruled ? " ink-ruled" : ""}`,
|
|
2625
2724
|
style: {
|
|
2626
2725
|
width: widthPx,
|
|
2627
|
-
|
|
2726
|
+
// In singlePage mode: fixed height + overflow hidden so content never visually spills
|
|
2727
|
+
...singlePage ? { height: pageHeightPx, overflow: "hidden" } : { minHeight: pageHeightPx },
|
|
2628
2728
|
padding: `${dims.paddingTopMm}mm ${dims.paddingRightMm}mm ${dims.paddingBottomMm}mm ${dims.paddingLeftMm}mm`,
|
|
2629
2729
|
["--ink-padding-top"]: `${dims.paddingTopMm}mm`,
|
|
2630
2730
|
["--ink-padding-right"]: `${dims.paddingRightMm}mm`,
|
|
@@ -2651,7 +2751,10 @@ function InkEditor({
|
|
|
2651
2751
|
initialFont = "cursive",
|
|
2652
2752
|
initialColors,
|
|
2653
2753
|
toolbarStart,
|
|
2654
|
-
toolbarEnd
|
|
2754
|
+
toolbarEnd,
|
|
2755
|
+
singlePage = false,
|
|
2756
|
+
onOverflow,
|
|
2757
|
+
initialContent
|
|
2655
2758
|
}) {
|
|
2656
2759
|
const [ruled, setRuled] = (0, import_react6.useState)(false);
|
|
2657
2760
|
const [font, setFont] = (0, import_react6.useState)(initialFont);
|
|
@@ -2659,14 +2762,17 @@ function InkEditor({
|
|
|
2659
2762
|
...theme === "minimal" ? MINIMAL_DEFAULTS : PARCHMENT_DEFAULTS,
|
|
2660
2763
|
...initialColors
|
|
2661
2764
|
});
|
|
2765
|
+
const extensions = [
|
|
2766
|
+
import_starter_kit.default,
|
|
2767
|
+
import_extension_text_align.default.configure({ types: ["heading", "paragraph"] }),
|
|
2768
|
+
import_extension_underline.default,
|
|
2769
|
+
TabIndent,
|
|
2770
|
+
...singlePage ? [SinglePageOverflow.configure({ pageSize, onOverflow: onOverflow ?? (() => {
|
|
2771
|
+
}) })] : [PageLayout.configure({ pageSize })]
|
|
2772
|
+
];
|
|
2662
2773
|
const editor = (0, import_react5.useEditor)({
|
|
2663
|
-
extensions
|
|
2664
|
-
|
|
2665
|
-
PageLayout.configure({ pageSize }),
|
|
2666
|
-
import_extension_text_align.default.configure({ types: ["heading", "paragraph"] }),
|
|
2667
|
-
import_extension_underline.default,
|
|
2668
|
-
TabIndent
|
|
2669
|
-
],
|
|
2774
|
+
extensions,
|
|
2775
|
+
content: initialContent ?? void 0,
|
|
2670
2776
|
onUpdate({ editor: editor2 }) {
|
|
2671
2777
|
onChange?.(editor2.getJSON());
|
|
2672
2778
|
}
|
|
@@ -2690,7 +2796,8 @@ function InkEditor({
|
|
|
2690
2796
|
colors,
|
|
2691
2797
|
onColorsChange: setColors,
|
|
2692
2798
|
toolbarStart,
|
|
2693
|
-
toolbarEnd
|
|
2799
|
+
toolbarEnd,
|
|
2800
|
+
singlePage
|
|
2694
2801
|
}
|
|
2695
2802
|
);
|
|
2696
2803
|
}
|
|
@@ -2698,6 +2805,7 @@ function InkEditor({
|
|
|
2698
2805
|
0 && (module.exports = {
|
|
2699
2806
|
InkEditor,
|
|
2700
2807
|
MINIMAL_DEFAULTS,
|
|
2701
|
-
PARCHMENT_DEFAULTS
|
|
2808
|
+
PARCHMENT_DEFAULTS,
|
|
2809
|
+
SinglePageOverflow
|
|
2702
2810
|
});
|
|
2703
2811
|
//# sourceMappingURL=index.js.map
|