@doxi/react 0.11.0
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/LICENSE +21 -0
- package/README.md +60 -0
- package/dist/DoxivaEditor.d.ts +20 -0
- package/dist/DoxivaEditor.d.ts.map +1 -0
- package/dist/DoxivaEditor.js +448 -0
- package/dist/DoxivaEditor.js.map +1 -0
- package/dist/Editor.d.ts +21 -0
- package/dist/Editor.d.ts.map +1 -0
- package/dist/Editor.js +49 -0
- package/dist/Editor.js.map +1 -0
- package/dist/HeaderFooterPopover.d.ts +49 -0
- package/dist/HeaderFooterPopover.d.ts.map +1 -0
- package/dist/HeaderFooterPopover.js +139 -0
- package/dist/HeaderFooterPopover.js.map +1 -0
- package/dist/ImagePopover.d.ts +23 -0
- package/dist/ImagePopover.d.ts.map +1 -0
- package/dist/ImagePopover.js +59 -0
- package/dist/ImagePopover.js.map +1 -0
- package/dist/LinkPopover.d.ts +25 -0
- package/dist/LinkPopover.d.ts.map +1 -0
- package/dist/LinkPopover.js +67 -0
- package/dist/LinkPopover.js.map +1 -0
- package/dist/PageSettingsPopover.d.ts +33 -0
- package/dist/PageSettingsPopover.d.ts.map +1 -0
- package/dist/PageSettingsPopover.js +48 -0
- package/dist/PageSettingsPopover.js.map +1 -0
- package/dist/TablePicker.d.ts +27 -0
- package/dist/TablePicker.d.ts.map +1 -0
- package/dist/TablePicker.js +38 -0
- package/dist/TablePicker.js.map +1 -0
- package/dist/Toolbar.d.ts +103 -0
- package/dist/Toolbar.d.ts.map +1 -0
- package/dist/Toolbar.js +161 -0
- package/dist/Toolbar.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/toolbar-builders/alignment.d.ts +4 -0
- package/dist/toolbar-builders/alignment.d.ts.map +1 -0
- package/dist/toolbar-builders/alignment.js +56 -0
- package/dist/toolbar-builders/alignment.js.map +1 -0
- package/dist/toolbar-builders/blocks.d.ts +4 -0
- package/dist/toolbar-builders/blocks.d.ts.map +1 -0
- package/dist/toolbar-builders/blocks.js +39 -0
- package/dist/toolbar-builders/blocks.js.map +1 -0
- package/dist/toolbar-builders/font-size.d.ts +4 -0
- package/dist/toolbar-builders/font-size.d.ts.map +1 -0
- package/dist/toolbar-builders/font-size.js +41 -0
- package/dist/toolbar-builders/font-size.js.map +1 -0
- package/dist/toolbar-builders/headings.d.ts +4 -0
- package/dist/toolbar-builders/headings.d.ts.map +1 -0
- package/dist/toolbar-builders/headings.js +18 -0
- package/dist/toolbar-builders/headings.js.map +1 -0
- package/dist/toolbar-builders/history.d.ts +3 -0
- package/dist/toolbar-builders/history.d.ts.map +1 -0
- package/dist/toolbar-builders/history.js +13 -0
- package/dist/toolbar-builders/history.js.map +1 -0
- package/dist/toolbar-builders/images.d.ts +4 -0
- package/dist/toolbar-builders/images.d.ts.map +1 -0
- package/dist/toolbar-builders/images.js +8 -0
- package/dist/toolbar-builders/images.js.map +1 -0
- package/dist/toolbar-builders/line-height.d.ts +4 -0
- package/dist/toolbar-builders/line-height.d.ts.map +1 -0
- package/dist/toolbar-builders/line-height.js +46 -0
- package/dist/toolbar-builders/line-height.js.map +1 -0
- package/dist/toolbar-builders/links.d.ts +4 -0
- package/dist/toolbar-builders/links.d.ts.map +1 -0
- package/dist/toolbar-builders/links.js +19 -0
- package/dist/toolbar-builders/links.js.map +1 -0
- package/dist/toolbar-builders/lists.d.ts +4 -0
- package/dist/toolbar-builders/lists.d.ts.map +1 -0
- package/dist/toolbar-builders/lists.js +38 -0
- package/dist/toolbar-builders/lists.js.map +1 -0
- package/dist/toolbar-builders/marks.d.ts +4 -0
- package/dist/toolbar-builders/marks.d.ts.map +1 -0
- package/dist/toolbar-builders/marks.js +41 -0
- package/dist/toolbar-builders/marks.js.map +1 -0
- package/dist/toolbar-builders/system.d.ts +12 -0
- package/dist/toolbar-builders/system.d.ts.map +1 -0
- package/dist/toolbar-builders/system.js +28 -0
- package/dist/toolbar-builders/system.js.map +1 -0
- package/dist/toolbar-builders/tables.d.ts +4 -0
- package/dist/toolbar-builders/tables.d.ts.map +1 -0
- package/dist/toolbar-builders/tables.js +235 -0
- package/dist/toolbar-builders/tables.js.map +1 -0
- package/dist/toolbar-builders/typography.d.ts +4 -0
- package/dist/toolbar-builders/typography.d.ts.map +1 -0
- package/dist/toolbar-builders/typography.js +123 -0
- package/dist/toolbar-builders/typography.js.map +1 -0
- package/dist/types.d.ts +85 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +28 -0
- package/dist/types.js.map +1 -0
- package/dist/useDoxivaEditor.d.ts +10 -0
- package/dist/useDoxivaEditor.d.ts.map +1 -0
- package/dist/useDoxivaEditor.js +30 -0
- package/dist/useDoxivaEditor.js.map +1 -0
- package/package.json +48 -0
package/dist/Editor.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { EditorView } from '@doxi/core';
|
|
3
|
+
import { useEffect, useRef } from 'react';
|
|
4
|
+
export function Editor(props) {
|
|
5
|
+
const mountRef = useRef(null);
|
|
6
|
+
const viewRef = useRef(null);
|
|
7
|
+
const editorRef = useRef(props.editor);
|
|
8
|
+
editorRef.current = props.editor;
|
|
9
|
+
const onMountRef = useRef(props.onMount);
|
|
10
|
+
onMountRef.current = props.onMount;
|
|
11
|
+
// Mount/unmount effect — runs once per component lifetime.
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
const mount = mountRef.current;
|
|
14
|
+
if (!mount)
|
|
15
|
+
return;
|
|
16
|
+
const view = new EditorView(mount, {
|
|
17
|
+
state: editorRef.current.state,
|
|
18
|
+
renderer: props.renderer,
|
|
19
|
+
...(props.editable !== undefined ? { editable: props.editable } : {}),
|
|
20
|
+
...(props.paginated ? { paginated: props.paginated } : {}),
|
|
21
|
+
...(props.ariaLabel !== undefined ? { ariaLabel: props.ariaLabel } : {}),
|
|
22
|
+
dispatchTransaction(tr) {
|
|
23
|
+
editorRef.current.dispatch(tr);
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
viewRef.current = view;
|
|
27
|
+
const cleanupFn = onMountRef.current ? onMountRef.current(view) : undefined;
|
|
28
|
+
return () => {
|
|
29
|
+
if (cleanupFn)
|
|
30
|
+
cleanupFn();
|
|
31
|
+
view.destroy();
|
|
32
|
+
viewRef.current = null;
|
|
33
|
+
};
|
|
34
|
+
// The view's renderer/editable/paginated are captured at mount. To change
|
|
35
|
+
// any of these, the host should remount the component (key prop).
|
|
36
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
37
|
+
}, []);
|
|
38
|
+
// updateState effect — runs when editor.state changes.
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
const view = viewRef.current;
|
|
41
|
+
if (!view)
|
|
42
|
+
return;
|
|
43
|
+
if (view.state !== props.editor.state) {
|
|
44
|
+
view.updateState(props.editor.state);
|
|
45
|
+
}
|
|
46
|
+
}, [props.editor.state]);
|
|
47
|
+
return _jsx("div", { ref: mountRef, className: "dx-react-editor-mount" });
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=Editor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Editor.js","sourceRoot":"","sources":["../src/Editor.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAkC,MAAM,YAAY,CAAA;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAqBzC,MAAM,UAAU,MAAM,CAAC,KAAkB;IACvC,MAAM,QAAQ,GAAG,MAAM,CAAwB,IAAI,CAAC,CAAA;IACpD,MAAM,OAAO,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAA;IAC/C,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IACtC,SAAS,CAAC,OAAO,GAAG,KAAK,CAAC,MAAM,CAAA;IAChC,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACxC,UAAU,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAA;IAElC,2DAA2D;IAC3D,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAA;QAC9B,IAAI,CAAC,KAAK;YAAE,OAAM;QAClB,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,KAAK,EAAE;YACjC,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,KAAK;YAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrE,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,GAAG,CAAC,KAAK,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACxE,mBAAmB,CAAC,EAAE;gBACpB,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;YAChC,CAAC;SACF,CAAC,CAAA;QACF,OAAO,CAAC,OAAO,GAAG,IAAI,CAAA;QACtB,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QAC3E,OAAO,GAAG,EAAE;YACV,IAAI,SAAS;gBAAE,SAAS,EAAE,CAAA;YAC1B,IAAI,CAAC,OAAO,EAAE,CAAA;YACd,OAAO,CAAC,OAAO,GAAG,IAAI,CAAA;QACxB,CAAC,CAAA;QACD,0EAA0E;QAC1E,kEAAkE;QAClE,uDAAuD;IACzD,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,uDAAuD;IACvD,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAA;QAC5B,IAAI,CAAC,IAAI;YAAE,OAAM;QACjB,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACtC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACtC,CAAC;IACH,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;IAExB,OAAO,cAAK,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAC,uBAAuB,GAAG,CAAA;AACjE,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type EditorState, type Transaction } from '@doxi/core';
|
|
2
|
+
import { type JSX } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Header/footer settings popover for the bundled `<DoxivaEditor>` (v0.11).
|
|
5
|
+
* Also exported as a standalone component for power users who roll their
|
|
6
|
+
* own toolbar via `<Toolbar>` + the popover `id` map.
|
|
7
|
+
*
|
|
8
|
+
* The popover lets the user:
|
|
9
|
+
* - Type plain text for the header and/or footer.
|
|
10
|
+
* - Toggle a "Page N of M" stamp that interleaves page_var atoms
|
|
11
|
+
* (kind='pageNumber' + kind='totalPages') with the user-typed text.
|
|
12
|
+
* - Enable/disable the header and footer slots entirely (CSS-only — hides
|
|
13
|
+
* the slot DOM via `.no-header` / `.no-footer` on `.app-editor-wrap`).
|
|
14
|
+
* - Set the slot min-height via host-side CSS custom properties
|
|
15
|
+
* (`--dx-header-height` / `--dx-footer-height`).
|
|
16
|
+
*
|
|
17
|
+
* Apply dispatches two SetPageMetaSteps in a single transaction so the
|
|
18
|
+
* header + footer text are committed atomically and the history can undo
|
|
19
|
+
* them as one entry.
|
|
20
|
+
*
|
|
21
|
+
* Chrome changes (enable / height) commit LIVE on every change — they are
|
|
22
|
+
* pure CSS, not part of the prosemirror document model, so there's no
|
|
23
|
+
* history entry to batch and the preview reflects edits immediately. Apply
|
|
24
|
+
* just closes the popover for the text path.
|
|
25
|
+
*
|
|
26
|
+
* KNOWN UX GAP (v0.10): The core LayoutEngine does not subtract the
|
|
27
|
+
* configured header/footer slot height from the page content area. Setting
|
|
28
|
+
* a height much larger than the default ~24 px will visually overlap the
|
|
29
|
+
* last lines of body content with the footer on long pages. Fixing it
|
|
30
|
+
* requires a core change to LayoutEngine.layout() — tracked for v0.11/v1.0.
|
|
31
|
+
*/
|
|
32
|
+
/** Pure-CSS page chrome state owned by the host App and threaded through
|
|
33
|
+
* the popover. Not part of the prosemirror document. */
|
|
34
|
+
export interface PageChromeState {
|
|
35
|
+
readonly headerEnabled: boolean;
|
|
36
|
+
readonly footerEnabled: boolean;
|
|
37
|
+
readonly headerHeightPx: number;
|
|
38
|
+
readonly footerHeightPx: number;
|
|
39
|
+
}
|
|
40
|
+
export declare const DEFAULT_PAGE_CHROME: PageChromeState;
|
|
41
|
+
export interface HeaderFooterPopoverProps {
|
|
42
|
+
state: EditorState;
|
|
43
|
+
dispatch: (tr: Transaction) => void;
|
|
44
|
+
close: () => void;
|
|
45
|
+
chrome: PageChromeState;
|
|
46
|
+
onChromeChange: (next: PageChromeState) => void;
|
|
47
|
+
}
|
|
48
|
+
export declare function HeaderFooterPopover(props: HeaderFooterPopoverProps): JSX.Element;
|
|
49
|
+
//# sourceMappingURL=HeaderFooterPopover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HeaderFooterPopover.d.ts","sourceRoot":"","sources":["../src/HeaderFooterPopover.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA4C,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAA;AACzG,OAAO,EAAY,KAAK,GAAG,EAAE,MAAM,OAAO,CAAA;AAE1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH;yDACyD;AACzD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;IAC/B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;IAC/B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;CAChC;AAED,eAAO,MAAM,mBAAmB,EAAE,eAKjC,CAAA;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,WAAW,CAAA;IAClB,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAA;IACnC,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,MAAM,EAAE,eAAe,CAAA;IACvB,cAAc,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAA;CAChD;AAoFD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,GAAG,GAAG,CAAC,OAAO,CAqKhF"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment, SetPageMetaStep, defaultSchema } from '@doxi/core';
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
export const DEFAULT_PAGE_CHROME = {
|
|
5
|
+
headerEnabled: true,
|
|
6
|
+
footerEnabled: true,
|
|
7
|
+
headerHeightPx: 24,
|
|
8
|
+
footerHeightPx: 24,
|
|
9
|
+
};
|
|
10
|
+
/** Build a single-paragraph fragment from plain text (empty → Fragment.empty). */
|
|
11
|
+
function fragmentFromText(text) {
|
|
12
|
+
if (!text.trim())
|
|
13
|
+
return Fragment.empty;
|
|
14
|
+
return Fragment.from([
|
|
15
|
+
defaultSchema.node('paragraph', null, [defaultSchema.text(text)]),
|
|
16
|
+
]);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Build a fragment of the shape "{userText} — Page {pageNumber} of {totalPages}"
|
|
20
|
+
* (when userText is non-empty) or "Page {pageNumber} of {totalPages}" (when
|
|
21
|
+
* userText is empty). Mirrors the exact node shape produced by
|
|
22
|
+
* __doxivaDebug.setHeaderWithPageNumber so the per-page substitution rendered
|
|
23
|
+
* by the page-slots view picks them up.
|
|
24
|
+
*/
|
|
25
|
+
function fragmentWithPageNumbers(text) {
|
|
26
|
+
const prefix = text.trim();
|
|
27
|
+
const nodes = prefix
|
|
28
|
+
? [
|
|
29
|
+
defaultSchema.text(prefix + ' — '),
|
|
30
|
+
defaultSchema.text('Page '),
|
|
31
|
+
defaultSchema.node('page_var', { kind: 'pageNumber' }),
|
|
32
|
+
defaultSchema.text(' of '),
|
|
33
|
+
defaultSchema.node('page_var', { kind: 'totalPages' }),
|
|
34
|
+
]
|
|
35
|
+
: [
|
|
36
|
+
defaultSchema.text('Page '),
|
|
37
|
+
defaultSchema.node('page_var', { kind: 'pageNumber' }),
|
|
38
|
+
defaultSchema.text(' of '),
|
|
39
|
+
defaultSchema.node('page_var', { kind: 'totalPages' }),
|
|
40
|
+
];
|
|
41
|
+
return Fragment.from([defaultSchema.node('paragraph', null, nodes)]);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Recover the plain-text portion from a header/footer fragment. Concatenates
|
|
45
|
+
* text nodes of the first paragraph; skips page_var atoms (those are
|
|
46
|
+
* controlled by the checkbox state). If the text ends with the " — " marker
|
|
47
|
+
* we use as a separator before "Page N of M", trim it off so re-opening the
|
|
48
|
+
* popover after an Apply doesn't accumulate extra " — " markers each round.
|
|
49
|
+
*/
|
|
50
|
+
function textFromFragment(f) {
|
|
51
|
+
if (f.size === 0)
|
|
52
|
+
return '';
|
|
53
|
+
const first = f.children[0];
|
|
54
|
+
if (!first || !first.content)
|
|
55
|
+
return '';
|
|
56
|
+
let out = '';
|
|
57
|
+
for (let i = 0; i < first.content.childCount; i++) {
|
|
58
|
+
const c = first.content.child(i);
|
|
59
|
+
if (c.text)
|
|
60
|
+
out += c.text;
|
|
61
|
+
}
|
|
62
|
+
// Strip the trailing " — Page " bridge text (from a previous round-trip).
|
|
63
|
+
// If we leave it, applying twice grows the prefix unbounded.
|
|
64
|
+
if (out.endsWith(' — Page '))
|
|
65
|
+
out = out.slice(0, -' — Page '.length);
|
|
66
|
+
if (out.endsWith('Page '))
|
|
67
|
+
out = out.slice(0, -'Page '.length);
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
/** Does this fragment contain at least one page_var atom anywhere? */
|
|
71
|
+
function hasPageVar(f) {
|
|
72
|
+
if (f.size === 0)
|
|
73
|
+
return false;
|
|
74
|
+
for (let pi = 0; pi < f.childCount; pi++) {
|
|
75
|
+
const p = f.child(pi);
|
|
76
|
+
if (!p.content)
|
|
77
|
+
continue;
|
|
78
|
+
for (let i = 0; i < p.content.childCount; i++) {
|
|
79
|
+
if (p.content.child(i).type.name === 'page_var')
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
/** Clamp a number-input value into the chrome height domain (0..400 px). */
|
|
86
|
+
function clampHeight(n) {
|
|
87
|
+
if (!Number.isFinite(n))
|
|
88
|
+
return 0;
|
|
89
|
+
if (n < 0)
|
|
90
|
+
return 0;
|
|
91
|
+
if (n > 400)
|
|
92
|
+
return 400;
|
|
93
|
+
return Math.round(n);
|
|
94
|
+
}
|
|
95
|
+
export function HeaderFooterPopover(props) {
|
|
96
|
+
const meta = props.state.pageMeta;
|
|
97
|
+
const [headerText, setHeaderText] = useState(textFromFragment(meta.header));
|
|
98
|
+
const [footerText, setFooterText] = useState(textFromFragment(meta.footer));
|
|
99
|
+
const [headerPageNum, setHeaderPageNum] = useState(hasPageVar(meta.header));
|
|
100
|
+
const [footerPageNum, setFooterPageNum] = useState(hasPageVar(meta.footer));
|
|
101
|
+
// Chrome state is owned by the host — read directly from props.chrome,
|
|
102
|
+
// commit changes live via props.onChromeChange. No local mirror.
|
|
103
|
+
const chrome = props.chrome;
|
|
104
|
+
const setHeaderEnabled = (v) => {
|
|
105
|
+
props.onChromeChange({ ...chrome, headerEnabled: v });
|
|
106
|
+
};
|
|
107
|
+
const setFooterEnabled = (v) => {
|
|
108
|
+
props.onChromeChange({ ...chrome, footerEnabled: v });
|
|
109
|
+
};
|
|
110
|
+
const setHeaderHeight = (v) => {
|
|
111
|
+
props.onChromeChange({ ...chrome, headerHeightPx: clampHeight(v) });
|
|
112
|
+
};
|
|
113
|
+
const setFooterHeight = (v) => {
|
|
114
|
+
props.onChromeChange({ ...chrome, footerHeightPx: clampHeight(v) });
|
|
115
|
+
};
|
|
116
|
+
const apply = () => {
|
|
117
|
+
const headerFrag = headerPageNum
|
|
118
|
+
? fragmentWithPageNumbers(headerText)
|
|
119
|
+
: fragmentFromText(headerText);
|
|
120
|
+
const footerFrag = footerPageNum
|
|
121
|
+
? fragmentWithPageNumbers(footerText)
|
|
122
|
+
: fragmentFromText(footerText);
|
|
123
|
+
// Both steps in a single transaction → atomic, one history entry.
|
|
124
|
+
const tr = props.state.tr
|
|
125
|
+
.step(new SetPageMetaStep('header', headerFrag))
|
|
126
|
+
.step(new SetPageMetaStep('footer', footerFrag));
|
|
127
|
+
props.dispatch(tr);
|
|
128
|
+
props.close();
|
|
129
|
+
};
|
|
130
|
+
const clear = () => {
|
|
131
|
+
const tr = props.state.tr
|
|
132
|
+
.step(new SetPageMetaStep('header', Fragment.empty))
|
|
133
|
+
.step(new SetPageMetaStep('footer', Fragment.empty));
|
|
134
|
+
props.dispatch(tr);
|
|
135
|
+
props.close();
|
|
136
|
+
};
|
|
137
|
+
return (_jsxs("div", { className: "dx-toolbar-popover dx-header-footer-popover", role: "dialog", "aria-label": "Header and footer settings", onMouseDown: (e) => e.stopPropagation(), children: [_jsxs("label", { children: ["Header:", _jsx("input", { type: "text", "data-testid": "header-text", value: headerText, placeholder: "Header text", onChange: (e) => setHeaderText(e.target.value) })] }), _jsxs("label", { className: "dx-header-footer-checkbox", children: [_jsx("input", { type: "checkbox", "data-testid": "header-pagenum", checked: headerPageNum, onChange: (e) => setHeaderPageNum(e.target.checked) }), "Show \"Page N of M\" in header"] }), _jsxs("fieldset", { className: "dx-header-footer-section", children: [_jsx("legend", { children: "Header" }), _jsxs("label", { className: "dx-header-footer-checkbox", children: [_jsx("input", { type: "checkbox", "data-testid": "header-enabled", checked: chrome.headerEnabled, onChange: (e) => setHeaderEnabled(e.target.checked) }), "Enabled"] }), _jsxs("label", { children: ["Height (px):", _jsx("input", { type: "number", "data-testid": "header-height", min: 0, max: 400, value: chrome.headerHeightPx, onChange: (e) => setHeaderHeight(Number(e.target.value)) })] })] }), _jsxs("label", { children: ["Footer:", _jsx("input", { type: "text", "data-testid": "footer-text", value: footerText, placeholder: "Footer text", onChange: (e) => setFooterText(e.target.value) })] }), _jsxs("label", { className: "dx-header-footer-checkbox", children: [_jsx("input", { type: "checkbox", "data-testid": "footer-pagenum", checked: footerPageNum, onChange: (e) => setFooterPageNum(e.target.checked) }), "Show \"Page N of M\" in footer"] }), _jsxs("fieldset", { className: "dx-header-footer-section", children: [_jsx("legend", { children: "Footer" }), _jsxs("label", { className: "dx-header-footer-checkbox", children: [_jsx("input", { type: "checkbox", "data-testid": "footer-enabled", checked: chrome.footerEnabled, onChange: (e) => setFooterEnabled(e.target.checked) }), "Enabled"] }), _jsxs("label", { children: ["Height (px):", _jsx("input", { type: "number", "data-testid": "footer-height", min: 0, max: 400, value: chrome.footerHeightPx, onChange: (e) => setFooterHeight(Number(e.target.value)) })] })] }), _jsxs("div", { className: "dx-header-footer-actions", children: [_jsx("button", { type: "button", "data-testid": "header-footer-apply", onMouseDown: (e) => e.preventDefault(), onClick: apply, children: "Apply" }), _jsx("button", { type: "button", "data-testid": "header-footer-clear", onMouseDown: (e) => e.preventDefault(), onClick: clear, children: "Clear" }), _jsx("button", { type: "button", "data-testid": "header-footer-cancel", onMouseDown: (e) => e.preventDefault(), onClick: props.close, children: "Cancel" })] })] }));
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=HeaderFooterPopover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HeaderFooterPopover.js","sourceRoot":"","sources":["../src/HeaderFooterPopover.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type EditorState, type Transaction } from '@doxi/core';
|
|
2
|
+
import { type JSX } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Insert-image popover. Rendered by the {@link Toolbar} when its `image`
|
|
5
|
+
* popover is open. Props supplied by the toolbar:
|
|
6
|
+
* - `state` — current editor state (used to read the schema).
|
|
7
|
+
* - `dispatch` — apply a transaction to the editor.
|
|
8
|
+
* - `close` — close the popover (called after apply / Escape).
|
|
9
|
+
*
|
|
10
|
+
* UX details:
|
|
11
|
+
* - The URL input autofocuses + selects-all on mount.
|
|
12
|
+
* - Enter (inside the URL input) applies; Escape closes.
|
|
13
|
+
* - Apply with an empty or whitespace-only URL is a no-op except
|
|
14
|
+
* that the popover closes. No error UI in v0.3d.
|
|
15
|
+
* - `onMouseDown` is stopped from propagating so clicking inside the
|
|
16
|
+
* popover doesn't trigger the toolbar's click-outside-to-close.
|
|
17
|
+
*/
|
|
18
|
+
export declare function ImagePopover(props: {
|
|
19
|
+
state: EditorState;
|
|
20
|
+
dispatch: (tr: Transaction) => void;
|
|
21
|
+
close: () => void;
|
|
22
|
+
}): JSX.Element;
|
|
23
|
+
//# sourceMappingURL=ImagePopover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImagePopover.d.ts","sourceRoot":"","sources":["../src/ImagePopover.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAA;AAC5E,OAAO,EAA+B,KAAK,GAAG,EAAE,MAAM,OAAO,CAAA;AAE7D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAClC,KAAK,EAAE,WAAW,CAAA;IAClB,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAA;IACnC,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB,GAAG,GAAG,CAAC,OAAO,CA0Ed"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { insertImage } from '@doxi/core';
|
|
3
|
+
import { useEffect, useRef, useState } from 'react';
|
|
4
|
+
/**
|
|
5
|
+
* Insert-image popover. Rendered by the {@link Toolbar} when its `image`
|
|
6
|
+
* popover is open. Props supplied by the toolbar:
|
|
7
|
+
* - `state` — current editor state (used to read the schema).
|
|
8
|
+
* - `dispatch` — apply a transaction to the editor.
|
|
9
|
+
* - `close` — close the popover (called after apply / Escape).
|
|
10
|
+
*
|
|
11
|
+
* UX details:
|
|
12
|
+
* - The URL input autofocuses + selects-all on mount.
|
|
13
|
+
* - Enter (inside the URL input) applies; Escape closes.
|
|
14
|
+
* - Apply with an empty or whitespace-only URL is a no-op except
|
|
15
|
+
* that the popover closes. No error UI in v0.3d.
|
|
16
|
+
* - `onMouseDown` is stopped from propagating so clicking inside the
|
|
17
|
+
* popover doesn't trigger the toolbar's click-outside-to-close.
|
|
18
|
+
*/
|
|
19
|
+
export function ImagePopover(props) {
|
|
20
|
+
const [src, setSrc] = useState('');
|
|
21
|
+
const [alt, setAlt] = useState('');
|
|
22
|
+
const srcRef = useRef(null);
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
const el = srcRef.current;
|
|
25
|
+
if (!el)
|
|
26
|
+
return;
|
|
27
|
+
el.focus();
|
|
28
|
+
el.select();
|
|
29
|
+
}, []);
|
|
30
|
+
const apply = () => {
|
|
31
|
+
const trimmed = src.trim();
|
|
32
|
+
if (trimmed === '') {
|
|
33
|
+
props.close();
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
insertImage(props.state.schema, { src: trimmed, alt })(props.state, props.dispatch);
|
|
37
|
+
props.close();
|
|
38
|
+
};
|
|
39
|
+
return (_jsxs("div", { className: "dx-toolbar-popover dx-toolbar-image-popover", role: "dialog", "aria-label": "Insert image", onMouseDown: (e) => e.stopPropagation(), children: [_jsx("input", { ref: srcRef, type: "url", "data-testid": "image-input-src", placeholder: "https://example.com/image.jpg", value: src, onChange: (e) => setSrc(e.target.value), onKeyDown: (e) => {
|
|
40
|
+
if (e.key === 'Enter') {
|
|
41
|
+
e.preventDefault();
|
|
42
|
+
apply();
|
|
43
|
+
}
|
|
44
|
+
else if (e.key === 'Escape') {
|
|
45
|
+
e.preventDefault();
|
|
46
|
+
props.close();
|
|
47
|
+
}
|
|
48
|
+
} }), _jsx("input", { type: "text", "data-testid": "image-input-alt", placeholder: "Alt text (optional)", value: alt, onChange: (e) => setAlt(e.target.value), onKeyDown: (e) => {
|
|
49
|
+
if (e.key === 'Enter') {
|
|
50
|
+
e.preventDefault();
|
|
51
|
+
apply();
|
|
52
|
+
}
|
|
53
|
+
else if (e.key === 'Escape') {
|
|
54
|
+
e.preventDefault();
|
|
55
|
+
props.close();
|
|
56
|
+
}
|
|
57
|
+
} }), _jsx("div", { className: "dx-toolbar-image-actions", children: _jsx("button", { type: "button", "data-testid": "image-apply", onMouseDown: (e) => e.preventDefault(), onClick: apply, children: "Apply" }) })] }));
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=ImagePopover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImagePopover.js","sourceRoot":"","sources":["../src/ImagePopover.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type EditorState, type Transaction } from '@doxi/core';
|
|
2
|
+
import { type JSX } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* The link editor popover. Rendered by the {@link Toolbar} when its `link`
|
|
5
|
+
* popover is open. Props supplied by the toolbar:
|
|
6
|
+
* - `state` — current editor state (used to read the existing link).
|
|
7
|
+
* - `dispatch` — apply a transaction to the editor.
|
|
8
|
+
* - `close` — close the popover (called after apply / remove / Escape).
|
|
9
|
+
*
|
|
10
|
+
* UX details:
|
|
11
|
+
* - The URL input autofocuses + selects-all on mount so the user can
|
|
12
|
+
* immediately type / paste.
|
|
13
|
+
* - Enter applies; Escape closes without changes.
|
|
14
|
+
* - Apply with an empty URL removes any existing link (so a user can
|
|
15
|
+
* clear an accidental link without hunting for the Remove button).
|
|
16
|
+
* - Remove only appears when the cursor is on an existing link.
|
|
17
|
+
* - `onMouseDown` is stopped from propagating so clicking inside the
|
|
18
|
+
* popover doesn't trigger the toolbar's click-outside-to-close.
|
|
19
|
+
*/
|
|
20
|
+
export declare function LinkPopover(props: {
|
|
21
|
+
state: EditorState;
|
|
22
|
+
dispatch: (tr: Transaction) => void;
|
|
23
|
+
close: () => void;
|
|
24
|
+
}): JSX.Element;
|
|
25
|
+
//# sourceMappingURL=LinkPopover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LinkPopover.d.ts","sourceRoot":"","sources":["../src/LinkPopover.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiC,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAA;AAC9F,OAAO,EAA+B,KAAK,GAAG,EAAE,MAAM,OAAO,CAAA;AAE7D;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE;IACjC,KAAK,EAAE,WAAW,CAAA;IAClB,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAA;IACnC,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB,GAAG,GAAG,CAAC,OAAO,CAkFd"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { getLinkAt, setLink, unsetLink } from '@doxi/core';
|
|
3
|
+
import { useEffect, useRef, useState } from 'react';
|
|
4
|
+
/**
|
|
5
|
+
* The link editor popover. Rendered by the {@link Toolbar} when its `link`
|
|
6
|
+
* popover is open. Props supplied by the toolbar:
|
|
7
|
+
* - `state` — current editor state (used to read the existing link).
|
|
8
|
+
* - `dispatch` — apply a transaction to the editor.
|
|
9
|
+
* - `close` — close the popover (called after apply / remove / Escape).
|
|
10
|
+
*
|
|
11
|
+
* UX details:
|
|
12
|
+
* - The URL input autofocuses + selects-all on mount so the user can
|
|
13
|
+
* immediately type / paste.
|
|
14
|
+
* - Enter applies; Escape closes without changes.
|
|
15
|
+
* - Apply with an empty URL removes any existing link (so a user can
|
|
16
|
+
* clear an accidental link without hunting for the Remove button).
|
|
17
|
+
* - Remove only appears when the cursor is on an existing link.
|
|
18
|
+
* - `onMouseDown` is stopped from propagating so clicking inside the
|
|
19
|
+
* popover doesn't trigger the toolbar's click-outside-to-close.
|
|
20
|
+
*/
|
|
21
|
+
export function LinkPopover(props) {
|
|
22
|
+
const linkType = props.state.schema.marks.link;
|
|
23
|
+
const initial = linkType ? getLinkAt(props.state, linkType) : null;
|
|
24
|
+
const initialHref = initial ? String(initial.attrs.href ?? '') : '';
|
|
25
|
+
const [href, setHref] = useState(initialHref);
|
|
26
|
+
const inputRef = useRef(null);
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
const el = inputRef.current;
|
|
29
|
+
if (!el)
|
|
30
|
+
return;
|
|
31
|
+
el.focus();
|
|
32
|
+
el.select();
|
|
33
|
+
}, []);
|
|
34
|
+
const apply = () => {
|
|
35
|
+
if (!linkType) {
|
|
36
|
+
props.close();
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const trimmed = href.trim();
|
|
40
|
+
if (trimmed === '') {
|
|
41
|
+
unsetLink(linkType)(props.state, props.dispatch);
|
|
42
|
+
props.close();
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
setLink(linkType, { href: trimmed })(props.state, props.dispatch);
|
|
46
|
+
props.close();
|
|
47
|
+
};
|
|
48
|
+
const remove = () => {
|
|
49
|
+
if (!linkType) {
|
|
50
|
+
props.close();
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
unsetLink(linkType)(props.state, props.dispatch);
|
|
54
|
+
props.close();
|
|
55
|
+
};
|
|
56
|
+
return (_jsxs("div", { className: "dx-toolbar-popover dx-toolbar-link-popover", role: "dialog", "aria-label": "Insert link", onMouseDown: (e) => e.stopPropagation(), children: [_jsx("input", { ref: inputRef, type: "url", "data-testid": "link-input", placeholder: "https://example.com", value: href, onChange: (e) => setHref(e.target.value), onKeyDown: (e) => {
|
|
57
|
+
if (e.key === 'Enter') {
|
|
58
|
+
e.preventDefault();
|
|
59
|
+
apply();
|
|
60
|
+
}
|
|
61
|
+
else if (e.key === 'Escape') {
|
|
62
|
+
e.preventDefault();
|
|
63
|
+
props.close();
|
|
64
|
+
}
|
|
65
|
+
} }), _jsx("button", { type: "button", "data-testid": "link-apply", onMouseDown: (e) => e.preventDefault(), onClick: apply, children: "Apply" }), initial && (_jsx("button", { type: "button", "data-testid": "link-remove", onMouseDown: (e) => e.preventDefault(), onClick: remove, children: "Remove" }))] }));
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=LinkPopover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LinkPopover.js","sourceRoot":"","sources":["../src/LinkPopover.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { EditorState, PageConfig, Transaction } from '@doxi/core';
|
|
2
|
+
import { type JSX } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Page settings popover for the bundled `<DoxivaEditor>` (v0.11). Also
|
|
5
|
+
* exported as a standalone component for power users who roll their own
|
|
6
|
+
* toolbar via `<Toolbar>` + the popover `id` map.
|
|
7
|
+
*
|
|
8
|
+
* The popover lets the user pick from a small set of size + orientation +
|
|
9
|
+
* margin presets. Custom dimensions are deferred to v1.0.
|
|
10
|
+
*/
|
|
11
|
+
export type PageSizeId = 'letter' | 'a4' | 'legal' | 'a5';
|
|
12
|
+
export type Orientation = 'portrait' | 'landscape';
|
|
13
|
+
export type MarginPreset = 'normal' | 'narrow' | 'wide';
|
|
14
|
+
export interface PageSettings {
|
|
15
|
+
readonly size: PageSizeId;
|
|
16
|
+
readonly orientation: Orientation;
|
|
17
|
+
readonly margins: MarginPreset;
|
|
18
|
+
}
|
|
19
|
+
export declare const DEFAULT_PAGE_SETTINGS: PageSettings;
|
|
20
|
+
/**
|
|
21
|
+
* Project the host-app's preset selection onto the PageConfig shape that
|
|
22
|
+
* @doxi/core's layout engine consumes.
|
|
23
|
+
*/
|
|
24
|
+
export declare function pageConfigFromSettings(s: PageSettings): PageConfig;
|
|
25
|
+
export interface PageSettingsPopoverProps {
|
|
26
|
+
state: EditorState;
|
|
27
|
+
dispatch: (tr: Transaction) => void;
|
|
28
|
+
close: () => void;
|
|
29
|
+
current: PageSettings;
|
|
30
|
+
onChange: (next: PageSettings) => void;
|
|
31
|
+
}
|
|
32
|
+
export declare function PageSettingsPopover(props: PageSettingsPopoverProps): JSX.Element;
|
|
33
|
+
//# sourceMappingURL=PageSettingsPopover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PageSettingsPopover.d.ts","sourceRoot":"","sources":["../src/PageSettingsPopover.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AACtE,OAAO,EAAY,KAAK,GAAG,EAAE,MAAM,OAAO,CAAA;AAE1C;;;;;;;GAOG;AAEH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,IAAI,GAAG,OAAO,GAAG,IAAI,CAAA;AACzD,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,WAAW,CAAA;AAClD,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAA;AAEvD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAA;CAC/B;AAqBD,eAAO,MAAM,qBAAqB,EAAE,YAInC,CAAA;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,YAAY,GAAG,UAAU,CAQlE;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,WAAW,CAAA;IAClB,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAA;IACnC,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,OAAO,EAAE,YAAY,CAAA;IACrB,QAAQ,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAA;CACvC;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,GAAG,GAAG,CAAC,OAAO,CAyEhF"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Concrete pixel dimensions per preset. Letter/A4 line up with what
|
|
5
|
+
* @doxi/core's resolveDimensions returns for its built-in named sizes, so
|
|
6
|
+
* the default ('letter' + 'portrait' + 'normal') is bit-for-bit identical to
|
|
7
|
+
* DEFAULT_PAGE_CONFIG.
|
|
8
|
+
*/
|
|
9
|
+
const SIZE_PX = {
|
|
10
|
+
letter: { w: 816, h: 1056 },
|
|
11
|
+
a4: { w: 794, h: 1123 },
|
|
12
|
+
legal: { w: 816, h: 1344 },
|
|
13
|
+
a5: { w: 559, h: 794 },
|
|
14
|
+
};
|
|
15
|
+
const MARGIN_PX = {
|
|
16
|
+
normal: 96,
|
|
17
|
+
narrow: 48,
|
|
18
|
+
wide: 144,
|
|
19
|
+
};
|
|
20
|
+
export const DEFAULT_PAGE_SETTINGS = {
|
|
21
|
+
size: 'letter',
|
|
22
|
+
orientation: 'portrait',
|
|
23
|
+
margins: 'normal',
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Project the host-app's preset selection onto the PageConfig shape that
|
|
27
|
+
* @doxi/core's layout engine consumes.
|
|
28
|
+
*/
|
|
29
|
+
export function pageConfigFromSettings(s) {
|
|
30
|
+
const base = SIZE_PX[s.size];
|
|
31
|
+
const { w, h } = s.orientation === 'landscape' ? { w: base.h, h: base.w } : base;
|
|
32
|
+
const m = MARGIN_PX[s.margins];
|
|
33
|
+
return {
|
|
34
|
+
size: { widthPx: w, heightPx: h },
|
|
35
|
+
margins: { topPx: m, rightPx: m, bottomPx: m, leftPx: m },
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export function PageSettingsPopover(props) {
|
|
39
|
+
const [size, setSize] = useState(props.current.size);
|
|
40
|
+
const [orientation, setOrientation] = useState(props.current.orientation);
|
|
41
|
+
const [margins, setMargins] = useState(props.current.margins);
|
|
42
|
+
const apply = () => {
|
|
43
|
+
props.onChange({ size, orientation, margins });
|
|
44
|
+
props.close();
|
|
45
|
+
};
|
|
46
|
+
return (_jsxs("div", { className: "dx-toolbar-popover dx-page-settings-popover", role: "dialog", "aria-label": "Page settings", onMouseDown: (e) => e.stopPropagation(), children: [_jsxs("label", { children: ["Size:", _jsxs("select", { value: size, onChange: (e) => setSize(e.target.value), "data-testid": "page-size", children: [_jsx("option", { value: "letter", children: "Letter (8.5 \u00D7 11 in)" }), _jsx("option", { value: "a4", children: "A4 (210 \u00D7 297 mm)" }), _jsx("option", { value: "legal", children: "Legal (8.5 \u00D7 14 in)" }), _jsx("option", { value: "a5", children: "A5 (148 \u00D7 210 mm)" })] })] }), _jsxs("label", { children: ["Orientation:", _jsxs("select", { value: orientation, onChange: (e) => setOrientation(e.target.value), "data-testid": "page-orientation", children: [_jsx("option", { value: "portrait", children: "Portrait" }), _jsx("option", { value: "landscape", children: "Landscape" })] })] }), _jsxs("label", { children: ["Margins:", _jsxs("select", { value: margins, onChange: (e) => setMargins(e.target.value), "data-testid": "page-margins", children: [_jsx("option", { value: "normal", children: "Normal (96 px)" }), _jsx("option", { value: "narrow", children: "Narrow (48 px)" }), _jsx("option", { value: "wide", children: "Wide (144 px)" })] })] }), _jsxs("div", { className: "dx-page-settings-actions", children: [_jsx("button", { type: "button", "data-testid": "page-settings-apply", onMouseDown: (e) => e.preventDefault(), onClick: apply, children: "Apply" }), _jsx("button", { type: "button", "data-testid": "page-settings-cancel", onMouseDown: (e) => e.preventDefault(), onClick: props.close, children: "Cancel" })] })] }));
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=PageSettingsPopover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PageSettingsPopover.js","sourceRoot":"","sources":["../src/PageSettingsPopover.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAY,MAAM,OAAO,CAAA;AAqB1C;;;;;GAKG;AACH,MAAM,OAAO,GAAiD;IAC5D,MAAM,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE;IAC3B,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE;IACvB,KAAK,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE;IAC1B,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE;CACvB,CAAA;AAED,MAAM,SAAS,GAAiC;IAC9C,MAAM,EAAE,EAAE;IACV,MAAM,EAAE,EAAE;IACV,IAAI,EAAE,GAAG;CACV,CAAA;AAED,MAAM,CAAC,MAAM,qBAAqB,GAAiB;IACjD,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,UAAU;IACvB,OAAO,EAAE,QAAQ;CAClB,CAAA;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,CAAe;IACpD,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;IAC5B,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;IAChF,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;IAC9B,OAAO;QACL,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE;QACjC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;KAC1D,CAAA;AACH,CAAC;AAUD,MAAM,UAAU,mBAAmB,CAAC,KAA+B;IACjE,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAa,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IAChE,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAc,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IACtF,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAe,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAE3E,MAAM,KAAK,GAAG,GAAS,EAAE;QACvB,KAAK,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAA;QAC9C,KAAK,CAAC,KAAK,EAAE,CAAA;IACf,CAAC,CAAA;IAED,OAAO,CACL,eACE,SAAS,EAAC,6CAA6C,EACvD,IAAI,EAAC,QAAQ,gBACF,eAAe,EAC1B,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,EAAE,aAEvC,qCAEE,kBACE,KAAK,EAAE,IAAI,EACX,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAmB,CAAC,iBAC1C,WAAW,aAEvB,iBAAQ,KAAK,EAAC,QAAQ,0CAA8B,EACpD,iBAAQ,KAAK,EAAC,IAAI,uCAA2B,EAC7C,iBAAQ,KAAK,EAAC,OAAO,yCAA6B,EAClD,iBAAQ,KAAK,EAAC,IAAI,uCAA2B,IACtC,IACH,EACR,4CAEE,kBACE,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,KAAoB,CAAC,iBAClD,kBAAkB,aAE9B,iBAAQ,KAAK,EAAC,UAAU,yBAAkB,EAC1C,iBAAQ,KAAK,EAAC,WAAW,0BAAmB,IACrC,IACH,EACR,wCAEE,kBACE,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,KAAqB,CAAC,iBAC/C,cAAc,aAE1B,iBAAQ,KAAK,EAAC,QAAQ,+BAAwB,EAC9C,iBAAQ,KAAK,EAAC,QAAQ,+BAAwB,EAC9C,iBAAQ,KAAK,EAAC,MAAM,8BAAuB,IACpC,IACH,EACR,eAAK,SAAS,EAAC,0BAA0B,aACvC,iBACE,IAAI,EAAC,QAAQ,iBACD,qBAAqB,EACjC,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,EAAE,EACtC,OAAO,EAAE,KAAK,sBAGP,EACT,iBACE,IAAI,EAAC,QAAQ,iBACD,sBAAsB,EAClC,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,EAAE,EACtC,OAAO,EAAE,KAAK,CAAC,KAAK,uBAGb,IACL,IACF,CACP,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type EditorState, type Transaction } from '@doxi/core';
|
|
2
|
+
import { type JSX } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Insert-table popover content. Rendered by the {@link Toolbar} when its
|
|
5
|
+
* `table` popover is open. Props supplied by the toolbar:
|
|
6
|
+
* - `state` — current editor state (read schema, run the command).
|
|
7
|
+
* - `dispatch` — apply a transaction.
|
|
8
|
+
* - `close` — close the popover after committing.
|
|
9
|
+
*
|
|
10
|
+
* UX:
|
|
11
|
+
* - 8×8 grid of hoverable cells. Hover highlights the top-left
|
|
12
|
+
* (r+1) × (c+1) rectangle. Click commits an insertTable command at
|
|
13
|
+
* that size and closes the popover.
|
|
14
|
+
* - Label below the grid mirrors the current hover size, or
|
|
15
|
+
* "Insert table" when nothing is hovered.
|
|
16
|
+
* - `onMouseDown` is stopped from propagating so the toolbar's
|
|
17
|
+
* click-outside-to-close handler doesn't close the popover on
|
|
18
|
+
* a grid click before our `onClick` fires.
|
|
19
|
+
* - Escape close is handled by the Toolbar's popover container (its
|
|
20
|
+
* own keydown listener at the window level), mirroring LinkPopover.
|
|
21
|
+
*/
|
|
22
|
+
export declare function TablePicker(props: {
|
|
23
|
+
state: EditorState;
|
|
24
|
+
dispatch: (tr: Transaction) => void;
|
|
25
|
+
close: () => void;
|
|
26
|
+
}): JSX.Element;
|
|
27
|
+
//# sourceMappingURL=TablePicker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TablePicker.d.ts","sourceRoot":"","sources":["../src/TablePicker.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAA;AAC5E,OAAO,EAAY,KAAK,GAAG,EAAE,MAAM,OAAO,CAAA;AAK1C;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE;IACjC,KAAK,EAAE,WAAW,CAAA;IAClB,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAA;IACnC,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB,GAAG,GAAG,CAAC,OAAO,CAyCd"}
|