@inshapardaz/likhari-react 0.1.7-dev.79 → 0.1.7-dev.81
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/EditorRoot.d.ts.map +1 -1
- package/dist/EditorRoot.js +2 -2
- package/dist/blocks/PageBreakNode.d.ts +30 -0
- package/dist/blocks/PageBreakNode.d.ts.map +1 -0
- package/dist/blocks/PageBreakNode.js +110 -0
- package/dist/components/Toolbar.d.ts.map +1 -1
- package/dist/components/Toolbar.js +5 -26
- package/dist/i18n/strings.d.ts +3 -7
- package/dist/i18n/strings.d.ts.map +1 -1
- package/dist/i18n/strings.js +6 -21
- package/dist/nodes.d.ts.map +1 -1
- package/dist/nodes.js +2 -4
- package/dist/plugins/PageBreakPlugin.d.ts +3 -0
- package/dist/plugins/PageBreakPlugin.d.ts.map +1 -0
- package/dist/plugins/PageBreakPlugin.js +19 -0
- package/dist/theme/editor.css +29 -21
- package/dist/theme/editorTheme.d.ts.map +1 -1
- package/dist/theme/editorTheme.js +1 -5
- package/package.json +1 -2
- package/dist/components/TableDialog.d.ts +0 -17
- package/dist/components/TableDialog.d.ts.map +0 -1
- package/dist/components/TableDialog.js +0 -33
package/dist/EditorRoot.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditorRoot.d.ts","sourceRoot":"","sources":["../src/EditorRoot.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"EditorRoot.d.ts","sourceRoot":"","sources":["../src/EditorRoot.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAU1D,OAAO,KAAK,EAAe,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAyB,KAAK,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AACvF,OAAO,EAAwB,KAAK,mBAAmB,EAAE,KAAK,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAKzH,OAAO,EAAyB,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAKjE,OAAO,EAAgC,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEnE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,CAAC,QAAQ,EAAE,cAAc,GAAG,YAAY,CAAC,CAAC;IACzD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,aAAa,CAAC,EAAE,uBAAuB,CAAC;IACxC,KAAK,CAAC,EAAE,oBAAoB,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC/B;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAClD;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,KAAK,IAAI,CAAC;IACrD;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC;IACrC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;IAClD,iBAAiB,IAAI,OAAO,CAAC;IAC7B,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,KAAK,IAAI,IAAI,CAAC;CACf;AAQD,eAAO,MAAM,UAAU,uGAmKrB,CAAC"}
|
package/dist/EditorRoot.js
CHANGED
|
@@ -7,7 +7,6 @@ import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin';
|
|
|
7
7
|
import { ListPlugin } from '@lexical/react/LexicalListPlugin';
|
|
8
8
|
import { CheckListPlugin } from '@lexical/react/LexicalCheckListPlugin';
|
|
9
9
|
import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin';
|
|
10
|
-
import { TablePlugin } from '@lexical/react/LexicalTablePlugin';
|
|
11
10
|
import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin';
|
|
12
11
|
import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';
|
|
13
12
|
import { defaultFormatRegistry } from '@inshapardaz/likhari-converters';
|
|
@@ -18,6 +17,7 @@ import { EditorThemeProvider } from './theme/EditorThemeProvider.js';
|
|
|
18
17
|
import { Toolbar } from './components/Toolbar.js';
|
|
19
18
|
import { injectUrduWebFontsCss } from './fonts/index.js';
|
|
20
19
|
import { LinkPastePlugin } from './plugins/LinkPastePlugin.js';
|
|
20
|
+
import { PageBreakPlugin } from './plugins/PageBreakPlugin.js';
|
|
21
21
|
import { ImageOptionsContext } from './image/ImageOptionsContext.js';
|
|
22
22
|
import { PortalTargetContext } from './PortalTargetContext.js';
|
|
23
23
|
import { UiStringsContext, getStrings } from './i18n/index.js';
|
|
@@ -112,5 +112,5 @@ export const EditorRoot = forwardRef(function EditorRoot({ documentId, initialCo
|
|
|
112
112
|
// rather than colliding on a shared one.
|
|
113
113
|
const portalTargetId = useId();
|
|
114
114
|
const portalTargetSelector = `#${CSS.escape(portalTargetId)}`;
|
|
115
|
-
return (_jsx(EditorThemeProvider, { theme: theme, colorScheme: colorScheme, accentColor: accentColor, scopeElementId: portalTargetId, children: _jsxs("div", { className: "likhari-root", dir: dir, ref: rootElementRef, "data-document-id": documentId, style: { height: typeof height === 'number' ? `${height}px` : height }, children: [_jsx("div", { id: portalTargetId, className: "likhari-portal-target" }), _jsx(PortalTargetContext.Provider, { value: portalTargetSelector, children: _jsx(UiStringsContext.Provider, { value: strings, children: _jsx(ImageOptionsContext.Provider, { value: imageOptions, children: _jsxs(LexicalComposer, { initialConfig: initialConfig, children: [_jsx(Toolbar, { config: config, onSave: handleSave, isDirty: isDirty, showSave: showSave, fontOptions: fontOptions, direction: dir, locale: locale }), _jsx("div", { className: "likhari-canvas", children: _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: "likhari-content-editable", dir: dir, "aria-label": strings.editor.contentLabel }), placeholder: _jsx("div", { className: "likhari-placeholder", children: resolvedPlaceholder }), ErrorBoundary: LexicalErrorBoundary }) }), config.history && _jsx(HistoryPlugin, {}), (config.lists.bullet || config.lists.numbered || config.lists.check) && _jsx(ListPlugin, {}), config.lists.check && _jsx(CheckListPlugin, {}), config.links && _jsx(LinkPlugin, {}), config.links && _jsx(LinkPastePlugin, {}), config.
|
|
115
|
+
return (_jsx(EditorThemeProvider, { theme: theme, colorScheme: colorScheme, accentColor: accentColor, scopeElementId: portalTargetId, children: _jsxs("div", { className: "likhari-root", dir: dir, ref: rootElementRef, "data-document-id": documentId, style: { height: typeof height === 'number' ? `${height}px` : height }, children: [_jsx("div", { id: portalTargetId, className: "likhari-portal-target" }), _jsx(PortalTargetContext.Provider, { value: portalTargetSelector, children: _jsx(UiStringsContext.Provider, { value: strings, children: _jsx(ImageOptionsContext.Provider, { value: imageOptions, children: _jsxs(LexicalComposer, { initialConfig: initialConfig, children: [_jsx(Toolbar, { config: config, onSave: handleSave, isDirty: isDirty, showSave: showSave, fontOptions: fontOptions, direction: dir, locale: locale }), _jsx("div", { className: "likhari-canvas", children: _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: "likhari-content-editable", dir: dir, "aria-label": strings.editor.contentLabel }), placeholder: _jsx("div", { className: "likhari-placeholder", children: resolvedPlaceholder }), ErrorBoundary: LexicalErrorBoundary }) }), config.history && _jsx(HistoryPlugin, {}), (config.lists.bullet || config.lists.numbered || config.lists.check) && _jsx(ListPlugin, {}), config.lists.check && _jsx(CheckListPlugin, {}), config.links && _jsx(LinkPlugin, {}), config.links && _jsx(LinkPastePlugin, {}), config.blocks.pageBreak && _jsx(PageBreakPlugin, {}), _jsx(OnChangePlugin, { onChange: handleChange })] }) }) }) })] }) }));
|
|
116
116
|
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type ReactElement } from 'react';
|
|
2
|
+
import { DecoratorNode, type DOMConversionMap, type DOMExportOutput, type EditorConfig, type LexicalCommand, type LexicalNode, type SerializedLexicalNode } from 'lexical';
|
|
3
|
+
export declare const INSERT_PAGE_BREAK_COMMAND: LexicalCommand<void>;
|
|
4
|
+
export type SerializedPageBreakNode = SerializedLexicalNode;
|
|
5
|
+
/**
|
|
6
|
+
* A manual page break — a print/paginated-export concept with no native
|
|
7
|
+
* Lexical node (lexical-editor-spec.md §4.3/§4.6). Renders as a visible
|
|
8
|
+
* dashed marker while editing, and as `page-break-after: always` both live
|
|
9
|
+
* (a print stylesheet, editor.css) and in exported HTML (`exportDOM`).
|
|
10
|
+
*
|
|
11
|
+
* Mirrors @lexical/react's HorizontalRuleNode pattern: `createDOM` returns
|
|
12
|
+
* the actual visible element (the click target `PageBreakComponent` wires
|
|
13
|
+
* selection/delete against), rather than `decorate()` rendering visuals.
|
|
14
|
+
*/
|
|
15
|
+
export declare class PageBreakNode extends DecoratorNode<ReactElement> {
|
|
16
|
+
static getType(): string;
|
|
17
|
+
static clone(node: PageBreakNode): PageBreakNode;
|
|
18
|
+
static importJSON(): PageBreakNode;
|
|
19
|
+
exportJSON(): SerializedPageBreakNode;
|
|
20
|
+
static importDOM(): DOMConversionMap | null;
|
|
21
|
+
exportDOM(): DOMExportOutput;
|
|
22
|
+
createDOM(config: EditorConfig): HTMLElement;
|
|
23
|
+
getTextContent(): string;
|
|
24
|
+
isInline(): false;
|
|
25
|
+
updateDOM(): boolean;
|
|
26
|
+
decorate(): import("react").JSX.Element;
|
|
27
|
+
}
|
|
28
|
+
export declare function $createPageBreakNode(): PageBreakNode;
|
|
29
|
+
export declare function $isPageBreakNode(node: LexicalNode | null | undefined): node is PageBreakNode;
|
|
30
|
+
//# sourceMappingURL=PageBreakNode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PageBreakNode.d.ts","sourceRoot":"","sources":["../../src/blocks/PageBreakNode.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAKlE,OAAO,EAOL,aAAa,EAGb,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,WAAW,EAEhB,KAAK,qBAAqB,EAC3B,MAAM,SAAS,CAAC;AAEjB,eAAO,MAAM,yBAAyB,EAAE,cAAc,CAAC,IAAI,CAA8C,CAAC;AAE1G,MAAM,MAAM,uBAAuB,GAAG,qBAAqB,CAAC;AA2D5D;;;;;;;;;GASG;AACH,qBAAa,aAAc,SAAQ,aAAa,CAAC,YAAY,CAAC;IAC5D,MAAM,CAAC,OAAO,IAAI,MAAM;IAIxB,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,aAAa,GAAG,aAAa;IAIhD,MAAM,CAAC,UAAU,IAAI,aAAa;IAIlC,UAAU,IAAI,uBAAuB;IAIrC,MAAM,CAAC,SAAS,IAAI,gBAAgB,GAAG,IAAI;IAS3C,SAAS,IAAI,eAAe;IAO5B,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW;IAM5C,cAAc,IAAI,MAAM;IAIxB,QAAQ,IAAI,KAAK;IAIjB,SAAS,IAAI,OAAO;IAIpB,QAAQ;CAGT;AAED,wBAAgB,oBAAoB,IAAI,aAAa,CAEpD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,IAAI,aAAa,CAE5F"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect } from 'react';
|
|
3
|
+
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
4
|
+
import { useLexicalNodeSelection } from '@lexical/react/useLexicalNodeSelection';
|
|
5
|
+
import { addClassNamesToElement, mergeRegister, removeClassNamesFromElement } from '@lexical/utils';
|
|
6
|
+
import { useUiStrings } from '../i18n/useStrings.js';
|
|
7
|
+
import { $applyNodeReplacement, $getSelection, $isNodeSelection, CLICK_COMMAND, COMMAND_PRIORITY_LOW, createCommand, DecoratorNode, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, } from 'lexical';
|
|
8
|
+
export const INSERT_PAGE_BREAK_COMMAND = createCommand('INSERT_PAGE_BREAK_COMMAND');
|
|
9
|
+
const SELECTED_CLASS_NAME = 'likhari-page-break-selected';
|
|
10
|
+
function PageBreakComponent({ nodeKey }) {
|
|
11
|
+
const [editor] = useLexicalComposerContext();
|
|
12
|
+
const strings = useUiStrings();
|
|
13
|
+
const [isSelected, setSelected, clearSelection] = useLexicalNodeSelection(nodeKey);
|
|
14
|
+
const onDelete = useCallback((event) => {
|
|
15
|
+
const selection = $getSelection();
|
|
16
|
+
if (isSelected && $isNodeSelection(selection)) {
|
|
17
|
+
event.preventDefault();
|
|
18
|
+
editor.update(() => {
|
|
19
|
+
selection.getNodes().forEach((node) => {
|
|
20
|
+
if ($isPageBreakNode(node))
|
|
21
|
+
node.remove();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return false;
|
|
26
|
+
}, [editor, isSelected]);
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
return mergeRegister(editor.registerCommand(CLICK_COMMAND, (event) => {
|
|
29
|
+
const element = editor.getElementByKey(nodeKey);
|
|
30
|
+
if (event.target !== element)
|
|
31
|
+
return false;
|
|
32
|
+
if (!event.shiftKey)
|
|
33
|
+
clearSelection();
|
|
34
|
+
setSelected(!isSelected);
|
|
35
|
+
return true;
|
|
36
|
+
}, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_DELETE_COMMAND, onDelete, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_BACKSPACE_COMMAND, onDelete, COMMAND_PRIORITY_LOW));
|
|
37
|
+
}, [clearSelection, editor, isSelected, nodeKey, onDelete, setSelected]);
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
const element = editor.getElementByKey(nodeKey);
|
|
40
|
+
if (!element)
|
|
41
|
+
return;
|
|
42
|
+
if (isSelected)
|
|
43
|
+
addClassNamesToElement(element, SELECTED_CLASS_NAME);
|
|
44
|
+
else
|
|
45
|
+
removeClassNamesFromElement(element, SELECTED_CLASS_NAME);
|
|
46
|
+
}, [editor, isSelected, nodeKey]);
|
|
47
|
+
return (_jsxs(_Fragment, { children: [_jsx("span", { className: "likhari-page-break-line", "aria-hidden": "true" }), _jsx("span", { className: "likhari-page-break-label", children: strings.editor.pageBreakLabel }), _jsx("span", { className: "likhari-page-break-line", "aria-hidden": "true" })] }));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* A manual page break — a print/paginated-export concept with no native
|
|
51
|
+
* Lexical node (lexical-editor-spec.md §4.3/§4.6). Renders as a visible
|
|
52
|
+
* dashed marker while editing, and as `page-break-after: always` both live
|
|
53
|
+
* (a print stylesheet, editor.css) and in exported HTML (`exportDOM`).
|
|
54
|
+
*
|
|
55
|
+
* Mirrors @lexical/react's HorizontalRuleNode pattern: `createDOM` returns
|
|
56
|
+
* the actual visible element (the click target `PageBreakComponent` wires
|
|
57
|
+
* selection/delete against), rather than `decorate()` rendering visuals.
|
|
58
|
+
*/
|
|
59
|
+
export class PageBreakNode extends DecoratorNode {
|
|
60
|
+
static getType() {
|
|
61
|
+
return 'page-break';
|
|
62
|
+
}
|
|
63
|
+
static clone(node) {
|
|
64
|
+
return new PageBreakNode(node.__key);
|
|
65
|
+
}
|
|
66
|
+
static importJSON() {
|
|
67
|
+
return $createPageBreakNode();
|
|
68
|
+
}
|
|
69
|
+
exportJSON() {
|
|
70
|
+
return { type: 'page-break', version: 1 };
|
|
71
|
+
}
|
|
72
|
+
static importDOM() {
|
|
73
|
+
return {
|
|
74
|
+
div: (domNode) => {
|
|
75
|
+
if (!domNode.hasAttribute('data-likhari-page-break'))
|
|
76
|
+
return null;
|
|
77
|
+
return { conversion: () => ({ node: $createPageBreakNode() }), priority: 2 };
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
exportDOM() {
|
|
82
|
+
const element = document.createElement('div');
|
|
83
|
+
element.setAttribute('data-likhari-page-break', '');
|
|
84
|
+
element.style.pageBreakAfter = 'always';
|
|
85
|
+
return { element };
|
|
86
|
+
}
|
|
87
|
+
createDOM(config) {
|
|
88
|
+
const element = document.createElement('div');
|
|
89
|
+
addClassNamesToElement(element, config.theme.pageBreak ?? 'likhari-page-break');
|
|
90
|
+
return element;
|
|
91
|
+
}
|
|
92
|
+
getTextContent() {
|
|
93
|
+
return '\n';
|
|
94
|
+
}
|
|
95
|
+
isInline() {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
updateDOM() {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
decorate() {
|
|
102
|
+
return _jsx(PageBreakComponent, { nodeKey: this.__key });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
export function $createPageBreakNode() {
|
|
106
|
+
return $applyNodeReplacement(new PageBreakNode());
|
|
107
|
+
}
|
|
108
|
+
export function $isPageBreakNode(node) {
|
|
109
|
+
return node instanceof PageBreakNode;
|
|
110
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../src/components/Toolbar.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../src/components/Toolbar.tsx"],"names":[],"mappings":"AA6CA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAA6D,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAItG,OAAO,KAAK,EAAE,MAAM,EAAW,MAAM,iBAAiB,CAAC;AAsUvD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,2BAA2B,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sEAAsE;IACtE,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,wFAAwF;IACxF,SAAS,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IAC1B,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAkC,EAAE,SAAiB,EAAE,MAAa,EAAE,EAAE,YAAY,+BAqxBhJ"}
|
|
@@ -10,8 +10,7 @@ import { $isListNode, INSERT_CHECK_LIST_COMMAND, INSERT_ORDERED_LIST_COMMAND, IN
|
|
|
10
10
|
import { $findMatchingParent, $insertNodeToNearestRoot } from '@lexical/utils';
|
|
11
11
|
import { ImageDialog } from '../image/ImageDialog.js';
|
|
12
12
|
import { $createImageNode } from '../image/ImageNode.js';
|
|
13
|
-
import {
|
|
14
|
-
import { INSERT_TABLE_COMMAND } from '@lexical/table';
|
|
13
|
+
import { INSERT_PAGE_BREAK_COMMAND } from '../blocks/PageBreakNode.js';
|
|
15
14
|
import { $createLinkNode, $isLinkNode, TOGGLE_LINK_COMMAND } from '@lexical/link';
|
|
16
15
|
import { LinkDialog } from './LinkDialog.js';
|
|
17
16
|
import { normalizeLinkUrl } from '../utils/linkUrl.js';
|
|
@@ -19,7 +18,7 @@ import { CANVAS_FONT_DEFAULTS, DEFAULT_FONT_OPTIONS, FONT_SIZES_PX } from '../fo
|
|
|
19
18
|
import { setStyleProperty } from '../utils/style.js';
|
|
20
19
|
import { useStrings } from '../i18n/useStrings.js';
|
|
21
20
|
import { usePortalTarget } from '../PortalTargetContext.js';
|
|
22
|
-
import { IconAbc, IconAlignCenter, IconAlignJustified, IconAlignLeft, IconAlignRight, IconArrowBackUp, IconArrowForwardUp, IconBold, IconClearFormatting, IconDeviceFloppy, IconDots, IconExternalLink, IconFeather, IconH1, IconH2, IconH3, IconH4, IconH5, IconH6, IconIndentDecrease, IconIndentIncrease, IconItalic, IconLetterCase, IconLetterCaseLower, IconLetterCaseUpper, IconLink, IconLinkOff, IconList, IconListCheck, IconListNumbers, IconPencil, IconPhoto, IconPilcrow, IconQuote, IconSparkles, IconStrikethrough, IconSubscript, IconSuperscript,
|
|
21
|
+
import { IconAbc, IconAlignCenter, IconAlignJustified, IconAlignLeft, IconAlignRight, IconArrowBackUp, IconArrowForwardUp, IconBold, IconClearFormatting, IconDeviceFloppy, IconDots, IconExternalLink, IconFeather, IconH1, IconH2, IconH3, IconH4, IconH5, IconH6, IconIndentDecrease, IconIndentIncrease, IconItalic, IconLetterCase, IconLetterCaseLower, IconLetterCaseUpper, IconLink, IconLinkOff, IconList, IconListCheck, IconListNumbers, IconPageBreak, IconPencil, IconPhoto, IconPilcrow, IconQuote, IconSparkles, IconStrikethrough, IconSubscript, IconSuperscript, IconTextSize, IconTypography, IconUnderline, IconWand, } from '@tabler/icons-react';
|
|
23
22
|
/** Sentinel for "no inline style": Lexical returns the default it is given when
|
|
24
23
|
* the selection has none, so this tells "unstyled" (show the canvas default)
|
|
25
24
|
* apart from "styled with a value the dropdown doesn't list" (show nothing). */
|
|
@@ -275,26 +274,6 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
275
274
|
});
|
|
276
275
|
closeImageDialog();
|
|
277
276
|
};
|
|
278
|
-
const [tableDialogOpen, setTableDialogOpen] = useState(false);
|
|
279
|
-
const openTableDialog = () => {
|
|
280
|
-
snapshotSelection();
|
|
281
|
-
setTableDialogOpen(true);
|
|
282
|
-
};
|
|
283
|
-
const closeTableDialog = () => {
|
|
284
|
-
setTableDialogOpen(false);
|
|
285
|
-
editor.focus();
|
|
286
|
-
};
|
|
287
|
-
const insertTable = ({ rows, columns, headerRow }) => {
|
|
288
|
-
const saved = menuSelectionRef.current;
|
|
289
|
-
if (saved)
|
|
290
|
-
editor.update(() => $setSelection(saved.clone()), { discrete: true });
|
|
291
|
-
editor.dispatchCommand(INSERT_TABLE_COMMAND, {
|
|
292
|
-
rows: String(rows),
|
|
293
|
-
columns: String(columns),
|
|
294
|
-
includeHeaders: { rows: headerRow, columns: false },
|
|
295
|
-
});
|
|
296
|
-
closeTableDialog();
|
|
297
|
-
};
|
|
298
277
|
/** Applies a font property per `config.font.scope`: to the selection, to
|
|
299
278
|
* every text node in the document, or (for 'both') to the selection when
|
|
300
279
|
* there is a range and to the whole document when there isn't. */
|
|
@@ -448,7 +427,7 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
448
427
|
const showFormattingGroup = headingLevels.length > 0 || config.lists.bullet || config.lists.numbered || config.lists.check || config.blocks.quote;
|
|
449
428
|
const showInlineGroup = fmt.bold || fmt.italic || fmt.underline;
|
|
450
429
|
const showAlignGroup = config.alignment.start || config.alignment.center || config.alignment.justify || config.alignment.left || config.alignment.right;
|
|
451
|
-
const showStubInsertGroup = config.images.linked || config.images.embedded || config.
|
|
430
|
+
const showStubInsertGroup = config.images.linked || config.images.embedded || config.blocks.pageBreak || config.poetry.enabled;
|
|
452
431
|
const showLanguageGroup = config.language.autocorrect || config.language.textCleanup || config.language.spellCheck;
|
|
453
432
|
// The "script & cleanup" and "indent/outdent" groups (UI spec §3.3) render
|
|
454
433
|
// as normal inline toolbar groups whenever there's room, and only move
|
|
@@ -617,7 +596,7 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
617
596
|
restoreSelection();
|
|
618
597
|
openLinkDialog();
|
|
619
598
|
}, onRemove: removeLink, strings: strings }) })] })) : (_jsx(ToolbarButton, { icon: IconLink, title: strings.toolbar.insertLink, onClick: openLinkDialog })) }, "link")),
|
|
620
|
-
showStubInsertGroup && (_jsxs("div", { className: "likhari-toolbar-group likhari-toolbar-group--collapse-tablet", children: [(config.images.linked || config.images.embedded) && (_jsx(ToolbarButton, { icon: IconPhoto, title: strings.toolbar.insertImage, onClick: openImageDialog })), config.
|
|
599
|
+
showStubInsertGroup && (_jsxs("div", { className: "likhari-toolbar-group likhari-toolbar-group--collapse-tablet", children: [(config.images.linked || config.images.embedded) && (_jsx(ToolbarButton, { icon: IconPhoto, title: strings.toolbar.insertImage, onClick: openImageDialog })), config.blocks.pageBreak && (_jsx(ToolbarButton, { icon: IconPageBreak, title: strings.toolbar.insertPageBreak, onClick: () => editor.dispatchCommand(INSERT_PAGE_BREAK_COMMAND, undefined) })), config.poetry.enabled && _jsx(StubButton, { icon: IconFeather, title: strings.toolbar.poetryBlocks, comingSoon: strings.toolbar.comingSoon })] }, "stubInsert")),
|
|
621
600
|
showLanguageGroup && (_jsxs("div", { className: "likhari-toolbar-group likhari-toolbar-group--collapse-tablet", children: [config.language.autocorrect && _jsx(StubButton, { icon: IconWand, title: strings.toolbar.autocorrect, comingSoon: strings.toolbar.comingSoon }), config.language.textCleanup && _jsx(StubButton, { icon: IconSparkles, title: strings.toolbar.textCleanup, comingSoon: strings.toolbar.comingSoon }), config.language.spellCheck && _jsx(StubButton, { icon: IconAbc, title: strings.toolbar.spellChecker, comingSoon: strings.toolbar.comingSoon })] }, "language")),
|
|
622
601
|
];
|
|
623
602
|
return (_jsxs("div", { className: "likhari-toolbar", role: "toolbar", "aria-label": strings.toolbar.ariaLabel, ref: toolbarContainerRef, children: [fixedGroups, movableGroups
|
|
@@ -639,5 +618,5 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
639
618
|
display: 'flex',
|
|
640
619
|
flexWrap: 'nowrap',
|
|
641
620
|
gap: 8,
|
|
642
|
-
}, children: [fixedGroups, movableGroups.map((group) => (_jsx(MovableGroupButtons, { group: group }, group.key)))] }), (config.images.linked || config.images.embedded) && (_jsx(ImageDialog, { mode: "insert", opened: imageDialogOpen, onSubmit: insertImage, onClose: closeImageDialog })), config.
|
|
621
|
+
}, children: [fixedGroups, movableGroups.map((group) => (_jsx(MovableGroupButtons, { group: group }, group.key)))] }), (config.images.linked || config.images.embedded) && (_jsx(ImageDialog, { mode: "insert", opened: imageDialogOpen, onSubmit: insertImage, onClose: closeImageDialog })), config.links && (_jsx(LinkDialog, { opened: linkDialogOpen, initialUrl: state.linkUrl, showTextField: linkNeedsText, onSubmit: applyLink, onRemove: state.isLink ? removeLink : undefined, onClose: closeLinkDialog }))] }));
|
|
643
622
|
}
|
package/dist/i18n/strings.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ export interface Strings {
|
|
|
15
15
|
contentLabel: string;
|
|
16
16
|
/** window.confirm() prompt shown by EditorRef.confirmDiscard() when there are unsaved changes. */
|
|
17
17
|
confirmDiscard: string;
|
|
18
|
+
/** Label shown on a page-break marker's dashed line while editing. */
|
|
19
|
+
pageBreakLabel: string;
|
|
18
20
|
};
|
|
19
21
|
common: {
|
|
20
22
|
cancel: string;
|
|
@@ -40,7 +42,7 @@ export interface Strings {
|
|
|
40
42
|
linkOptions: string;
|
|
41
43
|
insertLink: string;
|
|
42
44
|
insertImage: string;
|
|
43
|
-
|
|
45
|
+
insertPageBreak: string;
|
|
44
46
|
poetryBlocks: string;
|
|
45
47
|
comingSoon: (label: string) => string;
|
|
46
48
|
autocorrect: string;
|
|
@@ -89,12 +91,6 @@ export interface Strings {
|
|
|
89
91
|
invalidUrl: string;
|
|
90
92
|
apply: string;
|
|
91
93
|
};
|
|
92
|
-
tableDialog: {
|
|
93
|
-
title: string;
|
|
94
|
-
rows: string;
|
|
95
|
-
columns: string;
|
|
96
|
-
headerRow: string;
|
|
97
|
-
};
|
|
98
94
|
imageDialog: {
|
|
99
95
|
titleInsert: string;
|
|
100
96
|
titleEdit: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../../src/i18n/strings.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;+DAC+D;AAC/D,MAAM,MAAM,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,cAAc,CAAC;AAElD,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE;QACN,mGAAmG;QACnG,WAAW,EAAE,MAAM,CAAC;QACpB,gDAAgD;QAChD,YAAY,EAAE,MAAM,CAAC;QACrB,kGAAkG;QAClG,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,MAAM,EAAE;QACN,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,OAAO,EAAE;QACP,gEAAgE;QAChE,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,eAAe,EAAE,MAAM,CAAC;QACxB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,qBAAqB,EAAE,MAAM,CAAC;QAC9B,QAAQ,EAAE,MAAM,CAAC;QACjB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,
|
|
1
|
+
{"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../../src/i18n/strings.ts"],"names":[],"mappings":"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"}
|
package/dist/i18n/strings.js
CHANGED
|
@@ -9,6 +9,7 @@ const en = {
|
|
|
9
9
|
placeholder: 'Start writing…',
|
|
10
10
|
contentLabel: 'Editor content',
|
|
11
11
|
confirmDiscard: 'You have unsaved changes. Discard them?',
|
|
12
|
+
pageBreakLabel: 'Page break',
|
|
12
13
|
},
|
|
13
14
|
common: {
|
|
14
15
|
cancel: 'Cancel',
|
|
@@ -33,7 +34,7 @@ const en = {
|
|
|
33
34
|
linkOptions: 'Link options',
|
|
34
35
|
insertLink: 'Insert link (Ctrl+K)',
|
|
35
36
|
insertImage: 'Insert image',
|
|
36
|
-
|
|
37
|
+
insertPageBreak: 'Insert page break',
|
|
37
38
|
poetryBlocks: 'Poetry blocks',
|
|
38
39
|
comingSoon: (label) => `${label} (coming soon)`,
|
|
39
40
|
autocorrect: 'Auto-correct',
|
|
@@ -82,12 +83,6 @@ const en = {
|
|
|
82
83
|
invalidUrl: 'Enter a valid http(s), mailto, tel or relative URL',
|
|
83
84
|
apply: 'Apply',
|
|
84
85
|
},
|
|
85
|
-
tableDialog: {
|
|
86
|
-
title: 'Insert table',
|
|
87
|
-
rows: 'Rows',
|
|
88
|
-
columns: 'Columns',
|
|
89
|
-
headerRow: 'Header row',
|
|
90
|
-
},
|
|
91
86
|
imageDialog: {
|
|
92
87
|
titleInsert: 'Insert image',
|
|
93
88
|
titleEdit: 'Edit image',
|
|
@@ -152,6 +147,7 @@ const ur = {
|
|
|
152
147
|
placeholder: 'لکھنا شروع کریں…',
|
|
153
148
|
contentLabel: 'ایڈیٹر کا مواد',
|
|
154
149
|
confirmDiscard: 'آپ کی غیر محفوظ شدہ تبدیلیاں ہیں۔ کیا انہیں رد کر دیا جائے؟',
|
|
150
|
+
pageBreakLabel: 'صفحے کی تقسیم',
|
|
155
151
|
},
|
|
156
152
|
common: {
|
|
157
153
|
cancel: 'منسوخ کریں',
|
|
@@ -176,7 +172,7 @@ const ur = {
|
|
|
176
172
|
linkOptions: 'لنک کے اختیارات',
|
|
177
173
|
insertLink: 'لنک شامل کریں (Ctrl+K)',
|
|
178
174
|
insertImage: 'تصویر شامل کریں',
|
|
179
|
-
|
|
175
|
+
insertPageBreak: 'صفحے کی تقسیم شامل کریں',
|
|
180
176
|
poetryBlocks: 'شاعری کے بلاکس',
|
|
181
177
|
comingSoon: (label) => `${label} (جلد آ رہا ہے)`,
|
|
182
178
|
autocorrect: 'خودکار تصحیح',
|
|
@@ -225,12 +221,6 @@ const ur = {
|
|
|
225
221
|
invalidUrl: 'براہِ کرم ایک درست http(s)، mailto، tel یا رشتہ دار یو آر ایل درج کریں',
|
|
226
222
|
apply: 'لاگو کریں',
|
|
227
223
|
},
|
|
228
|
-
tableDialog: {
|
|
229
|
-
title: 'جدول شامل کریں',
|
|
230
|
-
rows: 'قطاریں',
|
|
231
|
-
columns: 'کالم',
|
|
232
|
-
headerRow: 'سرِ فہرست قطار',
|
|
233
|
-
},
|
|
234
224
|
imageDialog: {
|
|
235
225
|
titleInsert: 'تصویر شامل کریں',
|
|
236
226
|
titleEdit: 'تصویر میں ترمیم کریں',
|
|
@@ -295,6 +285,7 @@ const paShahmukhi = {
|
|
|
295
285
|
placeholder: 'لکھنا شروع کرو…',
|
|
296
286
|
contentLabel: 'ایڈیٹر دی سامگری',
|
|
297
287
|
confirmDiscard: 'تہاڈیاں کجھ تبدیلیاں سنبھالیاں نئیں گئیاں۔ کی ایہناں نوں رد کر دیئے؟',
|
|
288
|
+
pageBreakLabel: 'صفحے دی ونڈ',
|
|
298
289
|
},
|
|
299
290
|
common: {
|
|
300
291
|
cancel: 'رد کرو',
|
|
@@ -319,7 +310,7 @@ const paShahmukhi = {
|
|
|
319
310
|
linkOptions: 'لنک دے اختیار',
|
|
320
311
|
insertLink: 'لنک پاؤ (Ctrl+K)',
|
|
321
312
|
insertImage: 'تصویر پاؤ',
|
|
322
|
-
|
|
313
|
+
insertPageBreak: 'صفحے دی ونڈ پاؤ',
|
|
323
314
|
poetryBlocks: 'شاعری بلاک',
|
|
324
315
|
comingSoon: (label) => `${label} (چھیتی آ رہا اے)`,
|
|
325
316
|
autocorrect: 'خودکار درستی',
|
|
@@ -368,12 +359,6 @@ const paShahmukhi = {
|
|
|
368
359
|
invalidUrl: 'کِرپا کر کے صحیح http(s)، mailto، tel یا نسبتی یو آر ایل پاؤ',
|
|
369
360
|
apply: 'لاگو کرو',
|
|
370
361
|
},
|
|
371
|
-
tableDialog: {
|
|
372
|
-
title: 'ٹیبل پاؤ',
|
|
373
|
-
rows: 'قطاراں',
|
|
374
|
-
columns: 'کالم',
|
|
375
|
-
headerRow: 'سرکڑی قطار',
|
|
376
|
-
},
|
|
377
362
|
imageDialog: {
|
|
378
363
|
titleInsert: 'تصویر پاؤ',
|
|
379
364
|
titleEdit: 'تصویر وچ تبدیلی کرو',
|
package/dist/nodes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodes.d.ts","sourceRoot":"","sources":["../src/nodes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAQlD;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"nodes.d.ts","sourceRoot":"","sources":["../src/nodes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAQlD;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,EAS5C,CAAC"}
|
package/dist/nodes.js
CHANGED
|
@@ -2,8 +2,8 @@ import { HeadingNode, QuoteNode } from '@lexical/rich-text';
|
|
|
2
2
|
import { ListItemNode, ListNode } from '@lexical/list';
|
|
3
3
|
import { LinkNode } from '@lexical/link';
|
|
4
4
|
import { HorizontalRuleNode } from '@lexical/react/LexicalHorizontalRuleNode';
|
|
5
|
-
import { TableCellNode, TableNode, TableRowNode } from '@lexical/table';
|
|
6
5
|
import { ImageNode } from './image/ImageNode.js';
|
|
6
|
+
import { PageBreakNode } from './blocks/PageBreakNode.js';
|
|
7
7
|
/**
|
|
8
8
|
* Node types registered on the editor at construction time. Per
|
|
9
9
|
* editor-architecture-design.md §2, node registration cannot be conditional
|
|
@@ -20,8 +20,6 @@ export const EDITOR_NODES = [
|
|
|
20
20
|
ListItemNode,
|
|
21
21
|
LinkNode,
|
|
22
22
|
HorizontalRuleNode,
|
|
23
|
-
TableNode,
|
|
24
|
-
TableRowNode,
|
|
25
|
-
TableCellNode,
|
|
26
23
|
ImageNode,
|
|
24
|
+
PageBreakNode,
|
|
27
25
|
];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PageBreakPlugin.d.ts","sourceRoot":"","sources":["../../src/plugins/PageBreakPlugin.tsx"],"names":[],"mappings":"AAMA,+FAA+F;AAC/F,wBAAgB,eAAe,SAiB9B"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
3
|
+
import { $getSelection, $isRangeSelection, COMMAND_PRIORITY_EDITOR } from 'lexical';
|
|
4
|
+
import { $insertNodeToNearestRoot } from '@lexical/utils';
|
|
5
|
+
import { $createPageBreakNode, INSERT_PAGE_BREAK_COMMAND } from '../blocks/PageBreakNode.js';
|
|
6
|
+
/** Registers INSERT_PAGE_BREAK_COMMAND — mirrors @lexical/react's own HorizontalRulePlugin. */
|
|
7
|
+
export function PageBreakPlugin() {
|
|
8
|
+
const [editor] = useLexicalComposerContext();
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
return editor.registerCommand(INSERT_PAGE_BREAK_COMMAND, () => {
|
|
11
|
+
const selection = $getSelection();
|
|
12
|
+
if (!$isRangeSelection(selection))
|
|
13
|
+
return false;
|
|
14
|
+
$insertNodeToNearestRoot($createPageBreakNode());
|
|
15
|
+
return true;
|
|
16
|
+
}, COMMAND_PRIORITY_EDITOR);
|
|
17
|
+
}, [editor]);
|
|
18
|
+
return null;
|
|
19
|
+
}
|
package/dist/theme/editor.css
CHANGED
|
@@ -253,35 +253,43 @@
|
|
|
253
253
|
margin: 1.5em 0;
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
-
/*
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
.likhari-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
256
|
+
/* Page break — a print/export concept with no visual meaning while editing
|
|
257
|
+
on screen, so it gets its own clearly-labeled dashed marker rather than
|
|
258
|
+
masquerading as a horizontal rule. The actual page-break behavior only
|
|
259
|
+
takes effect when printing (lexical-editor-spec.md §4.3/§4.6). */
|
|
260
|
+
.likhari-page-break {
|
|
261
|
+
display: flex;
|
|
262
|
+
align-items: center;
|
|
263
|
+
gap: 8px;
|
|
264
|
+
margin: 1.5em 0;
|
|
265
|
+
font-size: 12px;
|
|
266
|
+
cursor: default;
|
|
264
267
|
}
|
|
265
268
|
|
|
266
|
-
.likhari-
|
|
267
|
-
|
|
269
|
+
.likhari-page-break-line {
|
|
270
|
+
flex: 1 1 auto;
|
|
271
|
+
border-top: 1px dashed var(--editor-line);
|
|
268
272
|
}
|
|
269
273
|
|
|
270
|
-
.likhari-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
min-width: 72px;
|
|
274
|
-
vertical-align: top;
|
|
274
|
+
.likhari-page-break-label {
|
|
275
|
+
color: var(--editor-ink-soft);
|
|
276
|
+
white-space: nowrap;
|
|
275
277
|
}
|
|
276
278
|
|
|
277
|
-
.likhari-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
279
|
+
.likhari-page-break-selected {
|
|
280
|
+
outline: 2px solid var(--editor-accent);
|
|
281
|
+
outline-offset: 2px;
|
|
282
|
+
border-radius: 4px;
|
|
281
283
|
}
|
|
282
284
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
+
@media print {
|
|
286
|
+
.likhari-page-break {
|
|
287
|
+
page-break-after: always;
|
|
288
|
+
/* Hide the on-screen marker itself when actually printing — the
|
|
289
|
+
browser's own pagination (triggered by page-break-after) is what
|
|
290
|
+
matters there, not the editing-time label. */
|
|
291
|
+
visibility: hidden;
|
|
292
|
+
}
|
|
285
293
|
}
|
|
286
294
|
|
|
287
295
|
/* Images — block-level figure; the caption is static text (edited in the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editorTheme.d.ts","sourceRoot":"","sources":["../../src/theme/editorTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"editorTheme.d.ts","sourceRoot":"","sources":["../../src/theme/editorTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,kBA+BzB,CAAC"}
|
|
@@ -33,9 +33,5 @@ export const editorTheme = {
|
|
|
33
33
|
},
|
|
34
34
|
hr: 'likhari-hr',
|
|
35
35
|
image: 'likhari-image-block',
|
|
36
|
-
|
|
37
|
-
tableRow: 'likhari-table-row',
|
|
38
|
-
tableCell: 'likhari-table-cell',
|
|
39
|
-
tableCellHeader: 'likhari-table-cell-header',
|
|
40
|
-
tableCellSelected: 'likhari-table-cell-selected',
|
|
36
|
+
pageBreak: 'likhari-page-break',
|
|
41
37
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inshapardaz/likhari-react",
|
|
3
|
-
"version": "0.1.7-dev.
|
|
3
|
+
"version": "0.1.7-dev.81",
|
|
4
4
|
"description": "React implementation of the Likhari editor, built on @lexical/react.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -37,7 +37,6 @@
|
|
|
37
37
|
"@lexical/react": "^0.20.0",
|
|
38
38
|
"@lexical/rich-text": "^0.20.0",
|
|
39
39
|
"@lexical/selection": "^0.20.0",
|
|
40
|
-
"@lexical/table": "^0.20.0",
|
|
41
40
|
"@lexical/utils": "^0.20.0",
|
|
42
41
|
"@inshapardaz/likhari-converters": "^0.1.0",
|
|
43
42
|
"@inshapardaz/likhari-core": "^0.1.0",
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export interface TableDialogValue {
|
|
2
|
-
rows: number;
|
|
3
|
-
columns: number;
|
|
4
|
-
headerRow: boolean;
|
|
5
|
-
}
|
|
6
|
-
export interface TableDialogProps {
|
|
7
|
-
opened: boolean;
|
|
8
|
-
onSubmit: (value: TableDialogValue) => void;
|
|
9
|
-
onClose: () => void;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Insert-table dialog: rows x columns and an optional header row. Cell
|
|
13
|
-
* merge/split is intentionally not offered anywhere in this dialog or the
|
|
14
|
-
* table it creates — see the comment on `TablePlugin` in `EditorRoot.tsx`.
|
|
15
|
-
*/
|
|
16
|
-
export declare function TableDialog({ opened, onSubmit, onClose }: TableDialogProps): import("react").JSX.Element;
|
|
17
|
-
//# sourceMappingURL=TableDialog.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TableDialog.d.ts","sourceRoot":"","sources":["../../src/components/TableDialog.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC5C,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAOD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,gBAAgB,+BAiD1E"}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useState } from 'react';
|
|
3
|
-
import { Button, Checkbox, Group, Modal, NumberInput } from '@mantine/core';
|
|
4
|
-
import { useUiStrings } from '../i18n/useStrings.js';
|
|
5
|
-
import { usePortalTarget } from '../PortalTargetContext.js';
|
|
6
|
-
const MIN_DIMENSION = 1;
|
|
7
|
-
const MAX_DIMENSION = 20;
|
|
8
|
-
const DEFAULT_ROWS = 3;
|
|
9
|
-
const DEFAULT_COLUMNS = 3;
|
|
10
|
-
/**
|
|
11
|
-
* Insert-table dialog: rows x columns and an optional header row. Cell
|
|
12
|
-
* merge/split is intentionally not offered anywhere in this dialog or the
|
|
13
|
-
* table it creates — see the comment on `TablePlugin` in `EditorRoot.tsx`.
|
|
14
|
-
*/
|
|
15
|
-
export function TableDialog({ opened, onSubmit, onClose }) {
|
|
16
|
-
const strings = useUiStrings();
|
|
17
|
-
const portalTarget = usePortalTarget();
|
|
18
|
-
const [rows, setRows] = useState(DEFAULT_ROWS);
|
|
19
|
-
const [columns, setColumns] = useState(DEFAULT_COLUMNS);
|
|
20
|
-
const [headerRow, setHeaderRow] = useState(true);
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
if (!opened)
|
|
23
|
-
return;
|
|
24
|
-
setRows(DEFAULT_ROWS);
|
|
25
|
-
setColumns(DEFAULT_COLUMNS);
|
|
26
|
-
setHeaderRow(true);
|
|
27
|
-
}, [opened]);
|
|
28
|
-
const handleSubmit = (e) => {
|
|
29
|
-
e.preventDefault();
|
|
30
|
-
onSubmit({ rows, columns, headerRow });
|
|
31
|
-
};
|
|
32
|
-
return (_jsx(Modal, { opened: opened, onClose: onClose, title: strings.tableDialog.title, centered: true, size: "sm", portalProps: { target: portalTarget }, children: _jsxs("form", { onSubmit: handleSubmit, children: [_jsxs(Group, { grow: true, align: "flex-end", children: [_jsx(NumberInput, { label: strings.tableDialog.rows, min: MIN_DIMENSION, max: MAX_DIMENSION, value: rows, onChange: (v) => setRows(typeof v === 'number' ? v : DEFAULT_ROWS), "data-autofocus": true }), _jsx(NumberInput, { label: strings.tableDialog.columns, min: MIN_DIMENSION, max: MAX_DIMENSION, value: columns, onChange: (v) => setColumns(typeof v === 'number' ? v : DEFAULT_COLUMNS) })] }), _jsx(Checkbox, { mt: "sm", label: strings.tableDialog.headerRow, checked: headerRow, onChange: (e) => setHeaderRow(e.currentTarget.checked) }), _jsxs(Group, { justify: "flex-end", gap: "xs", mt: "md", children: [_jsx(Button, { variant: "default", onClick: onClose, children: strings.common.cancel }), _jsx(Button, { type: "submit", children: strings.common.insert })] })] }) }));
|
|
33
|
-
}
|