@yurikilian/lex4 0.3.2 → 1.1.1
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/README.md +71 -4
- package/dist/ast/document-serializer.d.ts.map +1 -1
- package/dist/components/EditorSidebar.d.ts.map +1 -1
- package/dist/components/HeaderFooterActions.d.ts.map +1 -1
- package/dist/components/HeaderFooterToggle.d.ts.map +1 -1
- package/dist/components/HistorySidebar.d.ts.map +1 -1
- package/dist/components/Lex4Editor.d.ts.map +1 -1
- package/dist/components/PageBody.d.ts.map +1 -1
- package/dist/components/PageView.d.ts.map +1 -1
- package/dist/components/Toolbar.d.ts.map +1 -1
- package/dist/components/VariablePanel.d.ts.map +1 -1
- package/dist/components/VariablePicker.d.ts.map +1 -1
- package/dist/constants/dimensions.d.ts +6 -2
- package/dist/constants/dimensions.d.ts.map +1 -1
- package/dist/constants/index.d.ts +1 -1
- package/dist/constants/index.d.ts.map +1 -1
- package/dist/constants/page-layout.d.ts +0 -4
- package/dist/constants/page-layout.d.ts.map +1 -1
- package/dist/extensions/ast-extension.d.ts +9 -0
- package/dist/extensions/ast-extension.d.ts.map +1 -1
- package/dist/extensions/extension-context.d.ts +3 -1
- package/dist/extensions/extension-context.d.ts.map +1 -1
- package/dist/extensions/types.d.ts +12 -0
- package/dist/extensions/types.d.ts.map +1 -1
- package/dist/extensions/variables-extension.d.ts +6 -0
- package/dist/extensions/variables-extension.d.ts.map +1 -1
- package/dist/lex4-editor.cjs +402 -386
- package/dist/lex4-editor.cjs.map +1 -1
- package/dist/lex4-editor.js +402 -386
- package/dist/lex4-editor.js.map +1 -1
- package/dist/lexical/theme.d.ts +1 -1
- package/dist/style.css +789 -695
- package/dist/types/editor-handle.d.ts +12 -7
- package/dist/types/editor-handle.d.ts.map +1 -1
- package/dist/types/editor-props.d.ts +2 -1
- package/dist/types/editor-props.d.ts.map +1 -1
- package/dist/variables/variable-node.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/lex4-editor.cjs
CHANGED
|
@@ -61,7 +61,10 @@ const A4_HEIGHT_MM = 297;
|
|
|
61
61
|
const PX_PER_MM = 96 / 25.4;
|
|
62
62
|
const A4_WIDTH_PX = Math.round(A4_WIDTH_MM * PX_PER_MM);
|
|
63
63
|
const A4_HEIGHT_PX = Math.round(A4_HEIGHT_MM * PX_PER_MM);
|
|
64
|
-
const
|
|
64
|
+
const PAGE_MARGIN_TOP_PX = Math.round(25.4 * PX_PER_MM);
|
|
65
|
+
const PAGE_MARGIN_BOTTOM_PX = Math.round(25.4 * PX_PER_MM);
|
|
66
|
+
const PAGE_MARGIN_LEFT_PX = Math.round(31.75 * PX_PER_MM);
|
|
67
|
+
const PAGE_MARGIN_RIGHT_PX = Math.round(31.75 * PX_PER_MM);
|
|
65
68
|
const MAX_HEADER_RATIO = 0.2;
|
|
66
69
|
const MAX_FOOTER_RATIO = 0.2;
|
|
67
70
|
const MAX_HEADER_HEIGHT_PX = Math.round(A4_HEIGHT_PX * MAX_HEADER_RATIO);
|
|
@@ -1742,21 +1745,21 @@ const EditorSidebar = ({
|
|
|
1742
1745
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1743
1746
|
"aside",
|
|
1744
1747
|
{
|
|
1745
|
-
className: "
|
|
1748
|
+
className: "lex4-sidebar",
|
|
1746
1749
|
"data-testid": testId,
|
|
1747
1750
|
children: [
|
|
1748
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
1751
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-sidebar-header", children: [
|
|
1749
1752
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1750
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "
|
|
1751
|
-
subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "
|
|
1753
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "lex4-sidebar-title", children: title }),
|
|
1754
|
+
subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "lex4-sidebar-subtitle", children: subtitle })
|
|
1752
1755
|
] }),
|
|
1753
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
1756
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-sidebar-actions", children: [
|
|
1754
1757
|
headerActions,
|
|
1755
1758
|
onClose && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1756
1759
|
"button",
|
|
1757
1760
|
{
|
|
1758
1761
|
type: "button",
|
|
1759
|
-
className: "
|
|
1762
|
+
className: "lex4-sidebar-action-btn",
|
|
1760
1763
|
"data-testid": "close-editor-sidebar",
|
|
1761
1764
|
onClick: onClose,
|
|
1762
1765
|
"aria-label": t.sidebar.close,
|
|
@@ -1765,7 +1768,7 @@ const EditorSidebar = ({
|
|
|
1765
1768
|
)
|
|
1766
1769
|
] })
|
|
1767
1770
|
] }),
|
|
1768
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
1771
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-sidebar-body", children })
|
|
1769
1772
|
]
|
|
1770
1773
|
}
|
|
1771
1774
|
);
|
|
@@ -1797,7 +1800,7 @@ const HistorySidebar = () => {
|
|
|
1797
1800
|
"aria-label": t.history.clearHistory,
|
|
1798
1801
|
onMouseDown: (e) => e.preventDefault(),
|
|
1799
1802
|
onClick: () => clearHistory("manual"),
|
|
1800
|
-
className: "
|
|
1803
|
+
className: "lex4-sidebar-action-btn",
|
|
1801
1804
|
"data-testid": "clear-history",
|
|
1802
1805
|
children: /* @__PURE__ */ jsxRuntime.jsx(Trash2, { size: 13 })
|
|
1803
1806
|
}
|
|
@@ -1814,27 +1817,27 @@ const HistorySidebar = () => {
|
|
|
1814
1817
|
children: visibleEntries.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1815
1818
|
"div",
|
|
1816
1819
|
{
|
|
1817
|
-
className: "
|
|
1820
|
+
className: "lex4-history-empty",
|
|
1818
1821
|
"data-testid": "history-empty",
|
|
1819
1822
|
children: t.history.empty
|
|
1820
1823
|
}
|
|
1821
|
-
) : /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "
|
|
1824
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "lex4-history-list", "data-testid": "history-entry-list", children: visibleEntries.map((entry, reversedIndex) => {
|
|
1822
1825
|
const actualIndex = historyEntries.length - reversedIndex - 1;
|
|
1823
1826
|
const isCurrent = actualIndex === historyCursor - 1;
|
|
1824
1827
|
return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1825
1828
|
"button",
|
|
1826
1829
|
{
|
|
1827
1830
|
type: "button",
|
|
1828
|
-
className: `
|
|
1831
|
+
className: `lex4-history-entry ${isCurrent ? "active" : ""}`,
|
|
1829
1832
|
"data-testid": `history-entry-${actualIndex}`,
|
|
1830
1833
|
"data-history-current": isCurrent ? "true" : "false",
|
|
1831
1834
|
onClick: () => jumpToHistoryEntry2(actualIndex),
|
|
1832
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
1833
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
1834
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `
|
|
1835
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
1835
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-history-entry-row", children: [
|
|
1836
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-history-entry-content", children: [
|
|
1837
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `lex4-history-entry-label${isCurrent ? " current" : ""}`, children: entry.label }),
|
|
1838
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-history-entry-source", children: t.regions[entry.source] ?? entry.source })
|
|
1836
1839
|
] }),
|
|
1837
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
1840
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-history-entry-time", children: formatTimestamp(entry.timestamp) })
|
|
1838
1841
|
] })
|
|
1839
1842
|
}
|
|
1840
1843
|
) }, entry.id);
|
|
@@ -1850,11 +1853,11 @@ const HeaderFooterToggle = ({
|
|
|
1850
1853
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1851
1854
|
"label",
|
|
1852
1855
|
{
|
|
1853
|
-
className: "
|
|
1856
|
+
className: "lex4-hf-toggle",
|
|
1854
1857
|
"data-testid": "header-footer-toggle",
|
|
1855
1858
|
children: [
|
|
1856
|
-
/* @__PURE__ */ jsxRuntime.jsx(Rows3, { size: 14, className: "
|
|
1857
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "
|
|
1859
|
+
/* @__PURE__ */ jsxRuntime.jsx(Rows3, { size: 14, className: "lex4-hf-toggle-icon" }),
|
|
1860
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "lex4-hf-toggle-label", children: t.headerFooter.label }),
|
|
1858
1861
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1859
1862
|
"button",
|
|
1860
1863
|
{
|
|
@@ -1863,22 +1866,10 @@ const HeaderFooterToggle = ({
|
|
|
1863
1866
|
"aria-checked": enabled,
|
|
1864
1867
|
onMouseDown: (e) => e.preventDefault(),
|
|
1865
1868
|
onClick: () => onToggle(!enabled),
|
|
1866
|
-
className:
|
|
1867
|
-
|
|
1868
|
-
transition-colors duration-200
|
|
1869
|
-
${enabled ? "bg-blue-500" : "bg-gray-300"}
|
|
1870
|
-
`,
|
|
1869
|
+
className: "lex4-hf-switch",
|
|
1870
|
+
style: { backgroundColor: enabled ? "var(--lex4-color-primary)" : "var(--lex4-color-text-disabled)" },
|
|
1871
1871
|
"data-testid": "header-footer-switch",
|
|
1872
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1873
|
-
"span",
|
|
1874
|
-
{
|
|
1875
|
-
className: `
|
|
1876
|
-
inline-block h-3 w-3 rounded-full bg-white shadow-sm
|
|
1877
|
-
transition-transform duration-200
|
|
1878
|
-
${enabled ? "translate-x-3.5" : "translate-x-0.5"}
|
|
1879
|
-
`
|
|
1880
|
-
}
|
|
1881
|
-
)
|
|
1872
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "lex4-hf-switch-knob" })
|
|
1882
1873
|
}
|
|
1883
1874
|
)
|
|
1884
1875
|
]
|
|
@@ -1920,17 +1911,14 @@ const HeaderFooterActions = ({
|
|
|
1920
1911
|
action();
|
|
1921
1912
|
close();
|
|
1922
1913
|
};
|
|
1923
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef,
|
|
1914
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, style: { position: "relative" }, "data-testid": "header-footer-actions", children: [
|
|
1924
1915
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1925
1916
|
"button",
|
|
1926
1917
|
{
|
|
1927
1918
|
type: "button",
|
|
1928
1919
|
onMouseDown: (e) => e.preventDefault(),
|
|
1929
1920
|
onClick: () => setOpen(!open),
|
|
1930
|
-
className:
|
|
1931
|
-
flex h-7 items-center gap-1 rounded px-1.5 text-xs transition-colors
|
|
1932
|
-
${open ? "bg-blue-50 text-blue-600" : "text-gray-600 hover:bg-gray-100 hover:text-gray-900"}
|
|
1933
|
-
`,
|
|
1921
|
+
className: "lex4-settings-trigger",
|
|
1934
1922
|
"data-testid": "header-footer-menu-trigger",
|
|
1935
1923
|
"aria-expanded": open,
|
|
1936
1924
|
"aria-haspopup": "true",
|
|
@@ -1943,12 +1931,12 @@ const HeaderFooterActions = ({
|
|
|
1943
1931
|
open && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1944
1932
|
"div",
|
|
1945
1933
|
{
|
|
1946
|
-
className: "
|
|
1934
|
+
className: "lex4-settings-menu",
|
|
1947
1935
|
role: "menu",
|
|
1948
1936
|
"data-testid": "header-footer-menu",
|
|
1949
1937
|
children: [
|
|
1950
1938
|
/* @__PURE__ */ jsxRuntime.jsx(SectionLabel, { children: "Page counter" }),
|
|
1951
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
1939
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-settings-counter-grid", "data-testid": "page-counter-mode", children: PAGE_COUNTER_OPTIONS.map(({ value, label }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1952
1940
|
"button",
|
|
1953
1941
|
{
|
|
1954
1942
|
type: "button",
|
|
@@ -1956,10 +1944,7 @@ const HeaderFooterActions = ({
|
|
|
1956
1944
|
"aria-checked": pageCounterMode === value,
|
|
1957
1945
|
onMouseDown: (e) => e.preventDefault(),
|
|
1958
1946
|
onClick: () => onPageCounterModeChange(value),
|
|
1959
|
-
className:
|
|
1960
|
-
rounded px-2 py-1 text-xs text-left transition-colors
|
|
1961
|
-
${pageCounterMode === value ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-600 hover:bg-gray-100"}
|
|
1962
|
-
`,
|
|
1947
|
+
className: "lex4-settings-counter-btn",
|
|
1963
1948
|
"data-testid": `page-counter-${value}`,
|
|
1964
1949
|
children: label
|
|
1965
1950
|
},
|
|
@@ -2032,7 +2017,7 @@ const HeaderFooterActions = ({
|
|
|
2032
2017
|
)
|
|
2033
2018
|
] });
|
|
2034
2019
|
};
|
|
2035
|
-
const SectionLabel = ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
2020
|
+
const SectionLabel = ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-settings-label", children });
|
|
2036
2021
|
const MenuItem = ({ icon, label, onClick, disabled, testId }) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2037
2022
|
"button",
|
|
2038
2023
|
{
|
|
@@ -2041,7 +2026,7 @@ const MenuItem = ({ icon, label, onClick, disabled, testId }) => /* @__PURE__ */
|
|
|
2041
2026
|
onMouseDown: (e) => e.preventDefault(),
|
|
2042
2027
|
onClick,
|
|
2043
2028
|
disabled,
|
|
2044
|
-
className: "
|
|
2029
|
+
className: "lex4-settings-item",
|
|
2045
2030
|
"data-testid": testId,
|
|
2046
2031
|
children: [
|
|
2047
2032
|
icon,
|
|
@@ -2049,7 +2034,7 @@ const MenuItem = ({ icon, label, onClick, disabled, testId }) => /* @__PURE__ */
|
|
|
2049
2034
|
]
|
|
2050
2035
|
}
|
|
2051
2036
|
);
|
|
2052
|
-
const MenuDivider = () => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
2037
|
+
const MenuDivider = () => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-settings-divider" });
|
|
2053
2038
|
function resolveExtensions(extensions) {
|
|
2054
2039
|
const resolved = {
|
|
2055
2040
|
nodes: [],
|
|
@@ -2058,6 +2043,8 @@ function resolveExtensions(extensions) {
|
|
|
2058
2043
|
sidePanels: [],
|
|
2059
2044
|
providers: [],
|
|
2060
2045
|
themeOverrides: {},
|
|
2046
|
+
cssVariables: {},
|
|
2047
|
+
rootClassNames: [],
|
|
2061
2048
|
handleFactories: []
|
|
2062
2049
|
};
|
|
2063
2050
|
for (const ext of extensions) {
|
|
@@ -2069,6 +2056,10 @@ function resolveExtensions(extensions) {
|
|
|
2069
2056
|
if (ext.themeOverrides) {
|
|
2070
2057
|
resolved.themeOverrides = { ...resolved.themeOverrides, ...ext.themeOverrides };
|
|
2071
2058
|
}
|
|
2059
|
+
if (ext.cssVariables) {
|
|
2060
|
+
Object.assign(resolved.cssVariables, ext.cssVariables);
|
|
2061
|
+
}
|
|
2062
|
+
if (ext.rootClassName) resolved.rootClassNames.push(ext.rootClassName);
|
|
2072
2063
|
if (ext.handleMethods) resolved.handleFactories.push(ext.handleMethods);
|
|
2073
2064
|
}
|
|
2074
2065
|
return resolved;
|
|
@@ -2080,14 +2071,27 @@ const EMPTY_RESOLVED = {
|
|
|
2080
2071
|
sidePanels: [],
|
|
2081
2072
|
providers: [],
|
|
2082
2073
|
themeOverrides: {},
|
|
2074
|
+
cssVariables: {},
|
|
2075
|
+
rootClassNames: [],
|
|
2083
2076
|
handleFactories: []
|
|
2084
2077
|
};
|
|
2085
2078
|
const ExtensionResolvedContext = React.createContext(EMPTY_RESOLVED);
|
|
2079
|
+
function arraysEqual(a, b) {
|
|
2080
|
+
if (a.length !== b.length) return false;
|
|
2081
|
+
for (let i = 0; i < a.length; i++) {
|
|
2082
|
+
if (a[i] !== b[i]) return false;
|
|
2083
|
+
}
|
|
2084
|
+
return true;
|
|
2085
|
+
}
|
|
2086
2086
|
const ExtensionProvider = ({ extensions, children }) => {
|
|
2087
|
-
const
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
)
|
|
2087
|
+
const prevNamesRef = React.useRef([]);
|
|
2088
|
+
const resolvedRef = React.useRef(EMPTY_RESOLVED);
|
|
2089
|
+
const currentNames = (extensions ?? []).map((e) => e.name);
|
|
2090
|
+
if (!arraysEqual(currentNames, prevNamesRef.current)) {
|
|
2091
|
+
resolvedRef.current = extensions && extensions.length > 0 ? resolveExtensions(extensions) : EMPTY_RESOLVED;
|
|
2092
|
+
prevNamesRef.current = currentNames;
|
|
2093
|
+
}
|
|
2094
|
+
const resolved = resolvedRef.current;
|
|
2091
2095
|
let wrapped = /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
|
|
2092
2096
|
for (let i = resolved.providers.length - 1; i >= 0; i--) {
|
|
2093
2097
|
const Provider = resolved.providers[i];
|
|
@@ -2394,11 +2398,11 @@ const Toolbar = () => {
|
|
|
2394
2398
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2395
2399
|
"div",
|
|
2396
2400
|
{
|
|
2397
|
-
className: "lex4-toolbar
|
|
2401
|
+
className: "lex4-toolbar",
|
|
2398
2402
|
"data-testid": "toolbar",
|
|
2399
2403
|
children: [
|
|
2400
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
2401
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
2404
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-row", children: [
|
|
2405
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-group", "data-testid": "history-controls", children: [
|
|
2402
2406
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2403
2407
|
ToolbarIconButton,
|
|
2404
2408
|
{
|
|
@@ -2421,12 +2425,12 @@ const Toolbar = () => {
|
|
|
2421
2425
|
)
|
|
2422
2426
|
] }),
|
|
2423
2427
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2424
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
2425
|
-
/* @__PURE__ */ jsxRuntime.jsx(Type, { size: 14, className: "
|
|
2428
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-group-gap", children: [
|
|
2429
|
+
/* @__PURE__ */ jsxRuntime.jsx(Type, { size: 14, className: "lex4-toolbar-icon" }),
|
|
2426
2430
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2427
2431
|
"select",
|
|
2428
2432
|
{
|
|
2429
|
-
className: "
|
|
2433
|
+
className: "lex4-toolbar-select",
|
|
2430
2434
|
"data-testid": "font-selector",
|
|
2431
2435
|
defaultValue: "Calibri",
|
|
2432
2436
|
onChange: handleFontChange,
|
|
@@ -2434,12 +2438,12 @@ const Toolbar = () => {
|
|
|
2434
2438
|
}
|
|
2435
2439
|
)
|
|
2436
2440
|
] }),
|
|
2437
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
2438
|
-
/* @__PURE__ */ jsxRuntime.jsx(ALargeSmall, { size: 14, className: "
|
|
2441
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-group-gap", children: [
|
|
2442
|
+
/* @__PURE__ */ jsxRuntime.jsx(ALargeSmall, { size: 14, className: "lex4-toolbar-icon" }),
|
|
2439
2443
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2440
2444
|
"select",
|
|
2441
2445
|
{
|
|
2442
|
-
className: "
|
|
2446
|
+
className: "lex4-toolbar-select lex4-toolbar-select-narrow",
|
|
2443
2447
|
"data-testid": "font-size-selector",
|
|
2444
2448
|
defaultValue: "12",
|
|
2445
2449
|
onChange: handleFontSizeChange,
|
|
@@ -2448,21 +2452,21 @@ const Toolbar = () => {
|
|
|
2448
2452
|
)
|
|
2449
2453
|
] }),
|
|
2450
2454
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2451
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
2455
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-group", "data-testid": "format-group", children: [
|
|
2452
2456
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.bold, testId: "btn-bold", onClick: handleBold, children: /* @__PURE__ */ jsxRuntime.jsx(Bold, { size: 15 }) }),
|
|
2453
2457
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.italic, testId: "btn-italic", onClick: handleItalic, children: /* @__PURE__ */ jsxRuntime.jsx(Italic, { size: 15 }) }),
|
|
2454
2458
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.underline, testId: "btn-underline", onClick: handleUnderline, children: /* @__PURE__ */ jsxRuntime.jsx(Underline, { size: 15 }) }),
|
|
2455
2459
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.strikethrough, testId: "btn-strike", onClick: handleStrikethrough, children: /* @__PURE__ */ jsxRuntime.jsx(Strikethrough, { size: 15 }) })
|
|
2456
2460
|
] }),
|
|
2457
2461
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2458
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
2462
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-group", "data-testid": "align-group", children: [
|
|
2459
2463
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignLeft, testId: "btn-align-left", onClick: handleAlignLeft, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignStart, { size: 15 }) }),
|
|
2460
2464
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignCenter, testId: "btn-align-center", onClick: handleAlignCenter, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignCenter, { size: 15 }) }),
|
|
2461
2465
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignRight, testId: "btn-align-right", onClick: handleAlignRight, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignEnd, { size: 15 }) }),
|
|
2462
2466
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.justify, testId: "btn-align-justify", onClick: handleAlignJustify, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignJustify, { size: 15 }) })
|
|
2463
2467
|
] }),
|
|
2464
2468
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2465
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
2469
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-group", "data-testid": "list-group", children: [
|
|
2466
2470
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.numberedList, testId: "btn-list-number", onClick: handleListNumber, children: /* @__PURE__ */ jsxRuntime.jsx(ListOrdered, { size: 15 }) }),
|
|
2467
2471
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.bulletList, testId: "btn-list-bullet", onClick: handleListBullet, children: /* @__PURE__ */ jsxRuntime.jsx(List, { size: 15 }) }),
|
|
2468
2472
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.indent, testId: "btn-indent", onClick: handleIndent, children: /* @__PURE__ */ jsxRuntime.jsx(ListIndentIncrease, { size: 15 }) }),
|
|
@@ -2472,7 +2476,7 @@ const Toolbar = () => {
|
|
|
2472
2476
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2473
2477
|
toolbarItems.map((ToolbarItem, idx) => /* @__PURE__ */ jsxRuntime.jsx(ToolbarItem, {}, idx))
|
|
2474
2478
|
] }),
|
|
2475
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
2479
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-toolbar-end", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2476
2480
|
ToolbarIconButton,
|
|
2477
2481
|
{
|
|
2478
2482
|
title: historySidebarOpen ? t.toolbar.closeHistory : t.toolbar.openHistory,
|
|
@@ -2483,7 +2487,7 @@ const Toolbar = () => {
|
|
|
2483
2487
|
}
|
|
2484
2488
|
) })
|
|
2485
2489
|
] }),
|
|
2486
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
2490
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-hf-row", children: [
|
|
2487
2491
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2488
2492
|
HeaderFooterToggle,
|
|
2489
2493
|
{
|
|
@@ -2526,17 +2530,14 @@ const ToolbarIconButton = ({
|
|
|
2526
2530
|
disabled,
|
|
2527
2531
|
onMouseDown: (e) => e.preventDefault(),
|
|
2528
2532
|
onClick,
|
|
2529
|
-
className: `
|
|
2530
|
-
flex h-7 w-7 items-center justify-center rounded transition-colors
|
|
2531
|
-
${disabled ? "cursor-not-allowed text-gray-300" : active ? "bg-blue-50 text-blue-600" : "text-gray-600 hover:bg-gray-100 hover:text-gray-900"}
|
|
2532
|
-
`,
|
|
2533
|
+
className: `lex4-toolbar-btn${active ? " active" : ""}`,
|
|
2533
2534
|
"data-testid": testId,
|
|
2534
2535
|
children
|
|
2535
2536
|
}
|
|
2536
2537
|
);
|
|
2537
|
-
const Divider = () => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
2538
|
+
const Divider = () => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-toolbar-separator" });
|
|
2538
2539
|
function computeBodyHeight(headerHeight, footerHeight) {
|
|
2539
|
-
const verticalMargins =
|
|
2540
|
+
const verticalMargins = PAGE_MARGIN_TOP_PX + PAGE_MARGIN_BOTTOM_PX;
|
|
2540
2541
|
return A4_HEIGHT_PX - headerHeight - footerHeight - verticalMargins;
|
|
2541
2542
|
}
|
|
2542
2543
|
function getTopLevelNodes(state) {
|
|
@@ -2841,33 +2842,33 @@ function usePagination(document2, dispatch) {
|
|
|
2841
2842
|
};
|
|
2842
2843
|
}
|
|
2843
2844
|
const lexicalTheme = {
|
|
2844
|
-
root: "lex4-root
|
|
2845
|
-
paragraph: "lex4-paragraph
|
|
2845
|
+
root: "lex4-root",
|
|
2846
|
+
paragraph: "lex4-paragraph",
|
|
2846
2847
|
heading: {
|
|
2847
|
-
h1: "
|
|
2848
|
-
h2: "
|
|
2849
|
-
h3: "
|
|
2850
|
-
h4: "
|
|
2851
|
-
h5: "
|
|
2848
|
+
h1: "lex4-heading lex4-heading-h1",
|
|
2849
|
+
h2: "lex4-heading lex4-heading-h2",
|
|
2850
|
+
h3: "lex4-heading lex4-heading-h3",
|
|
2851
|
+
h4: "lex4-heading lex4-heading-h4",
|
|
2852
|
+
h5: "lex4-heading lex4-heading-h5"
|
|
2852
2853
|
},
|
|
2853
2854
|
text: {
|
|
2854
|
-
bold: "
|
|
2855
|
-
italic: "italic",
|
|
2856
|
-
underline: "underline",
|
|
2857
|
-
strikethrough: "
|
|
2858
|
-
underlineStrikethrough: "underline
|
|
2855
|
+
bold: "lex4-text-bold",
|
|
2856
|
+
italic: "lex4-text-italic",
|
|
2857
|
+
underline: "lex4-text-underline",
|
|
2858
|
+
strikethrough: "lex4-text-strikethrough",
|
|
2859
|
+
underlineStrikethrough: "lex4-text-underline lex4-text-strikethrough"
|
|
2859
2860
|
},
|
|
2860
2861
|
list: {
|
|
2861
2862
|
nested: {
|
|
2862
|
-
listitem: "
|
|
2863
|
+
listitem: "lex4-listitem-nested"
|
|
2863
2864
|
},
|
|
2864
|
-
ol: "list
|
|
2865
|
-
ul: "list
|
|
2865
|
+
ol: "lex4-list lex4-list-ordered",
|
|
2866
|
+
ul: "lex4-list lex4-list-unordered",
|
|
2866
2867
|
listitem: "lex4-listitem",
|
|
2867
2868
|
listitemChecked: "lex4-listitem-checked",
|
|
2868
2869
|
listitemUnchecked: "lex4-listitem-unchecked"
|
|
2869
2870
|
},
|
|
2870
|
-
quote: "
|
|
2871
|
+
quote: "lex4-quote"
|
|
2871
2872
|
};
|
|
2872
2873
|
const DEFAULT_NODES = [richText.HeadingNode, richText.QuoteNode, list.ListNode, list.ListItemNode];
|
|
2873
2874
|
function createEditorConfig(mode, pageId, extraNodes = [], themeOverrides = {}) {
|
|
@@ -3758,8 +3759,7 @@ const PageBody = ({
|
|
|
3758
3759
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3759
3760
|
"div",
|
|
3760
3761
|
{
|
|
3761
|
-
className: "lex4-page-body
|
|
3762
|
-
style: { overflow: "hidden" },
|
|
3762
|
+
className: "lex4-page-body",
|
|
3763
3763
|
"data-testid": `page-body-${pageId}`,
|
|
3764
3764
|
onFocus,
|
|
3765
3765
|
children: /* @__PURE__ */ jsxRuntime.jsxs(LexicalComposer.LexicalComposer, { initialConfig: config, children: [
|
|
@@ -3769,11 +3769,10 @@ const PageBody = ({
|
|
|
3769
3769
|
contentEditable: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3770
3770
|
LexicalContentEditable.ContentEditable,
|
|
3771
3771
|
{
|
|
3772
|
-
className: "
|
|
3773
|
-
style: { overflow: "visible" }
|
|
3772
|
+
className: "lex4-page-body-editable"
|
|
3774
3773
|
}
|
|
3775
3774
|
),
|
|
3776
|
-
placeholder: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
3775
|
+
placeholder: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-page-placeholder", children: t.body.placeholder }),
|
|
3777
3776
|
ErrorBoundary: LexicalErrorBoundary.LexicalErrorBoundary
|
|
3778
3777
|
}
|
|
3779
3778
|
),
|
|
@@ -3901,7 +3900,7 @@ const PageHeader = ({
|
|
|
3901
3900
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3902
3901
|
"div",
|
|
3903
3902
|
{
|
|
3904
|
-
className: "lex4-page-header
|
|
3903
|
+
className: "lex4-page-header",
|
|
3905
3904
|
style: { maxHeight: MAX_HEADER_HEIGHT_PX, overflow: "clip" },
|
|
3906
3905
|
"data-testid": `page-header-${pageId}`,
|
|
3907
3906
|
children: [
|
|
@@ -3913,10 +3912,10 @@ const PageHeader = ({
|
|
|
3913
3912
|
LexicalContentEditable.ContentEditable,
|
|
3914
3913
|
{
|
|
3915
3914
|
ref: contentRef,
|
|
3916
|
-
className: `
|
|
3915
|
+
className: `lex4-page-hf-editable${hasPageCounter ? " lex4-page-hf-narrow" : ""}`
|
|
3917
3916
|
}
|
|
3918
3917
|
),
|
|
3919
|
-
placeholder: /* @__PURE__ */ jsxRuntime.jsx("div", { className: `
|
|
3918
|
+
placeholder: /* @__PURE__ */ jsxRuntime.jsx("div", { className: `lex4-page-hf-placeholder${hasPageCounter ? " lex4-page-hf-narrow" : ""}`, children: t.header.placeholder }),
|
|
3920
3919
|
ErrorBoundary: LexicalErrorBoundary.LexicalErrorBoundary
|
|
3921
3920
|
}
|
|
3922
3921
|
),
|
|
@@ -3928,7 +3927,7 @@ const PageHeader = ({
|
|
|
3928
3927
|
pageCounterLabel && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3929
3928
|
"div",
|
|
3930
3929
|
{
|
|
3931
|
-
className: "
|
|
3930
|
+
className: "lex4-page-counter",
|
|
3932
3931
|
"data-testid": `page-counter-header-${pageId}`,
|
|
3933
3932
|
children: pageCounterLabel
|
|
3934
3933
|
}
|
|
@@ -3981,7 +3980,7 @@ const PageFooter = ({
|
|
|
3981
3980
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3982
3981
|
"div",
|
|
3983
3982
|
{
|
|
3984
|
-
className: "lex4-page-footer
|
|
3983
|
+
className: "lex4-page-footer",
|
|
3985
3984
|
style: { maxHeight: MAX_FOOTER_HEIGHT_PX, overflow: "clip" },
|
|
3986
3985
|
"data-testid": `page-footer-${pageId}`,
|
|
3987
3986
|
children: [
|
|
@@ -3993,10 +3992,10 @@ const PageFooter = ({
|
|
|
3993
3992
|
LexicalContentEditable.ContentEditable,
|
|
3994
3993
|
{
|
|
3995
3994
|
ref: contentRef,
|
|
3996
|
-
className: `
|
|
3995
|
+
className: `lex4-page-hf-editable${hasPageCounter ? " lex4-page-hf-narrow" : ""}`
|
|
3997
3996
|
}
|
|
3998
3997
|
),
|
|
3999
|
-
placeholder: /* @__PURE__ */ jsxRuntime.jsx("div", { className: `
|
|
3998
|
+
placeholder: /* @__PURE__ */ jsxRuntime.jsx("div", { className: `lex4-page-hf-placeholder${hasPageCounter ? " lex4-page-hf-narrow" : ""}`, children: t.footer.placeholder }),
|
|
4000
3999
|
ErrorBoundary: LexicalErrorBoundary.LexicalErrorBoundary
|
|
4001
4000
|
}
|
|
4002
4001
|
),
|
|
@@ -4008,7 +4007,7 @@ const PageFooter = ({
|
|
|
4008
4007
|
pageCounterLabel && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4009
4008
|
"div",
|
|
4010
4009
|
{
|
|
4011
|
-
className: "
|
|
4010
|
+
className: "lex4-page-counter",
|
|
4012
4011
|
"data-testid": `page-counter-footer-${pageId}`,
|
|
4013
4012
|
children: pageCounterLabel
|
|
4014
4013
|
}
|
|
@@ -4066,11 +4065,14 @@ const PageView = React.memo(({
|
|
|
4066
4065
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4067
4066
|
"div",
|
|
4068
4067
|
{
|
|
4069
|
-
className: "lex4-page
|
|
4068
|
+
className: "lex4-page",
|
|
4070
4069
|
style: {
|
|
4071
4070
|
width: A4_WIDTH_PX,
|
|
4072
4071
|
height: A4_HEIGHT_PX,
|
|
4073
|
-
|
|
4072
|
+
paddingTop: PAGE_MARGIN_TOP_PX,
|
|
4073
|
+
paddingBottom: PAGE_MARGIN_BOTTOM_PX,
|
|
4074
|
+
paddingLeft: PAGE_MARGIN_LEFT_PX,
|
|
4075
|
+
paddingRight: PAGE_MARGIN_RIGHT_PX
|
|
4074
4076
|
},
|
|
4075
4077
|
"data-testid": `page-${pageIndex}`,
|
|
4076
4078
|
"data-page-id": pageId,
|
|
@@ -4351,7 +4353,7 @@ const DocumentView = () => {
|
|
|
4351
4353
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4352
4354
|
"div",
|
|
4353
4355
|
{
|
|
4354
|
-
className: "lex4-document-view
|
|
4356
|
+
className: "lex4-document-view",
|
|
4355
4357
|
"data-testid": "document-view",
|
|
4356
4358
|
tabIndex: -1,
|
|
4357
4359
|
children: document2.pages.map((page, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -4370,6 +4372,250 @@ const DocumentView = () => {
|
|
|
4370
4372
|
}
|
|
4371
4373
|
);
|
|
4372
4374
|
};
|
|
4375
|
+
const AST_VERSION = "1.0.0";
|
|
4376
|
+
const IS_BOLD = 1;
|
|
4377
|
+
const IS_ITALIC = 2;
|
|
4378
|
+
const IS_STRIKETHROUGH = 4;
|
|
4379
|
+
const IS_UNDERLINE = 8;
|
|
4380
|
+
function decodeFormatBitmask(format) {
|
|
4381
|
+
const marks = {};
|
|
4382
|
+
if (format & IS_BOLD) marks.bold = true;
|
|
4383
|
+
if (format & IS_ITALIC) marks.italic = true;
|
|
4384
|
+
if (format & IS_UNDERLINE) marks.underline = true;
|
|
4385
|
+
if (format & IS_STRIKETHROUGH) marks.strikethrough = true;
|
|
4386
|
+
return marks;
|
|
4387
|
+
}
|
|
4388
|
+
function extractFontFamily(style) {
|
|
4389
|
+
const match = style.match(/font-family:\s*([^;]+)/);
|
|
4390
|
+
return match ? match[1].trim().replace(/['"]/g, "") : void 0;
|
|
4391
|
+
}
|
|
4392
|
+
function extractFontSizePt(style) {
|
|
4393
|
+
const match = style.match(/font-size:\s*(\d+(?:\.\d+)?)\s*pt/);
|
|
4394
|
+
return match ? parseFloat(match[1]) : void 0;
|
|
4395
|
+
}
|
|
4396
|
+
function buildTextMarks(format, style) {
|
|
4397
|
+
const formatMarks = decodeFormatBitmask(format);
|
|
4398
|
+
const fontFamily = style ? extractFontFamily(style) : void 0;
|
|
4399
|
+
const fontSize = style ? extractFontSizePt(style) : void 0;
|
|
4400
|
+
const marks = {
|
|
4401
|
+
...formatMarks,
|
|
4402
|
+
...fontFamily ? { fontFamily } : {},
|
|
4403
|
+
...fontSize ? { fontSize } : {}
|
|
4404
|
+
};
|
|
4405
|
+
return Object.keys(marks).length > 0 ? marks : void 0;
|
|
4406
|
+
}
|
|
4407
|
+
function mapInlineNode(node) {
|
|
4408
|
+
switch (node.type) {
|
|
4409
|
+
case "text":
|
|
4410
|
+
return mapTextNode(node);
|
|
4411
|
+
case "variable-node":
|
|
4412
|
+
return mapVariableNode(node);
|
|
4413
|
+
case "linebreak":
|
|
4414
|
+
return mapLineBreak();
|
|
4415
|
+
default:
|
|
4416
|
+
return { type: "text", text: "" };
|
|
4417
|
+
}
|
|
4418
|
+
}
|
|
4419
|
+
function mapTextNode(node) {
|
|
4420
|
+
const marks = buildTextMarks(node.format, node.style);
|
|
4421
|
+
return {
|
|
4422
|
+
type: "text",
|
|
4423
|
+
text: node.text,
|
|
4424
|
+
...marks ? { marks } : {}
|
|
4425
|
+
};
|
|
4426
|
+
}
|
|
4427
|
+
function mapVariableNode(node) {
|
|
4428
|
+
return {
|
|
4429
|
+
type: "variable",
|
|
4430
|
+
key: node.variableKey
|
|
4431
|
+
};
|
|
4432
|
+
}
|
|
4433
|
+
function mapLineBreak() {
|
|
4434
|
+
return { type: "linebreak" };
|
|
4435
|
+
}
|
|
4436
|
+
function mapInlineNodes(nodes) {
|
|
4437
|
+
return nodes.map(mapInlineNode);
|
|
4438
|
+
}
|
|
4439
|
+
const ALIGN_LEFT = 1;
|
|
4440
|
+
const ALIGN_CENTER = 2;
|
|
4441
|
+
const ALIGN_RIGHT = 3;
|
|
4442
|
+
const ALIGN_JUSTIFY = 4;
|
|
4443
|
+
function decodeAlignment(format) {
|
|
4444
|
+
if (typeof format === "string") {
|
|
4445
|
+
if (["left", "center", "right", "justify"].includes(format)) {
|
|
4446
|
+
return format;
|
|
4447
|
+
}
|
|
4448
|
+
return void 0;
|
|
4449
|
+
}
|
|
4450
|
+
if (typeof format !== "number" || format === 0) return void 0;
|
|
4451
|
+
switch (format) {
|
|
4452
|
+
case ALIGN_LEFT:
|
|
4453
|
+
return "left";
|
|
4454
|
+
case ALIGN_CENTER:
|
|
4455
|
+
return "center";
|
|
4456
|
+
case ALIGN_RIGHT:
|
|
4457
|
+
return "right";
|
|
4458
|
+
case ALIGN_JUSTIFY:
|
|
4459
|
+
return "justify";
|
|
4460
|
+
default:
|
|
4461
|
+
return void 0;
|
|
4462
|
+
}
|
|
4463
|
+
}
|
|
4464
|
+
function mapBlockNode(node) {
|
|
4465
|
+
switch (node.type) {
|
|
4466
|
+
case "paragraph":
|
|
4467
|
+
return mapParagraph(node);
|
|
4468
|
+
case "heading":
|
|
4469
|
+
return mapHeading(node);
|
|
4470
|
+
case "list":
|
|
4471
|
+
return mapList(node);
|
|
4472
|
+
case "quote":
|
|
4473
|
+
return mapBlockQuote(node);
|
|
4474
|
+
default:
|
|
4475
|
+
return {
|
|
4476
|
+
type: "paragraph",
|
|
4477
|
+
children: mapInlineChildren(node)
|
|
4478
|
+
};
|
|
4479
|
+
}
|
|
4480
|
+
}
|
|
4481
|
+
function mapParagraph(node) {
|
|
4482
|
+
const alignment = decodeAlignment(node.format);
|
|
4483
|
+
const indent = node.indent && node.indent > 0 ? node.indent : void 0;
|
|
4484
|
+
return {
|
|
4485
|
+
type: "paragraph",
|
|
4486
|
+
...alignment ? { alignment } : {},
|
|
4487
|
+
...indent ? { indent } : {},
|
|
4488
|
+
children: mapInlineChildren(node)
|
|
4489
|
+
};
|
|
4490
|
+
}
|
|
4491
|
+
function mapHeading(node) {
|
|
4492
|
+
var _a;
|
|
4493
|
+
const alignment = decodeAlignment(node.format);
|
|
4494
|
+
const tagMatch = (_a = node.tag) == null ? void 0 : _a.match(/^h(\d)$/);
|
|
4495
|
+
const level = tagMatch ? parseInt(tagMatch[1], 10) : 1;
|
|
4496
|
+
return {
|
|
4497
|
+
type: "heading",
|
|
4498
|
+
level,
|
|
4499
|
+
...alignment ? { alignment } : {},
|
|
4500
|
+
children: mapInlineChildren(node)
|
|
4501
|
+
};
|
|
4502
|
+
}
|
|
4503
|
+
function mapList(node) {
|
|
4504
|
+
const listType = node.listType === "number" ? "ordered" : "unordered";
|
|
4505
|
+
const items = (node.children ?? []).filter((c) => c.type === "listitem").map(mapListItem);
|
|
4506
|
+
return {
|
|
4507
|
+
type: "list",
|
|
4508
|
+
listType,
|
|
4509
|
+
items
|
|
4510
|
+
};
|
|
4511
|
+
}
|
|
4512
|
+
function mapListItem(node) {
|
|
4513
|
+
const inlineChildren = [];
|
|
4514
|
+
let nestedList;
|
|
4515
|
+
for (const child of node.children ?? []) {
|
|
4516
|
+
if (child.type === "list") {
|
|
4517
|
+
nestedList = mapList(child);
|
|
4518
|
+
} else {
|
|
4519
|
+
const mapped = mapInlineNodes([child]);
|
|
4520
|
+
inlineChildren.push(...mapped);
|
|
4521
|
+
}
|
|
4522
|
+
}
|
|
4523
|
+
return {
|
|
4524
|
+
type: "list-item",
|
|
4525
|
+
children: inlineChildren,
|
|
4526
|
+
...nestedList ? { nestedList } : {}
|
|
4527
|
+
};
|
|
4528
|
+
}
|
|
4529
|
+
function mapBlockQuote(node) {
|
|
4530
|
+
return {
|
|
4531
|
+
type: "blockquote",
|
|
4532
|
+
children: mapInlineChildren(node)
|
|
4533
|
+
};
|
|
4534
|
+
}
|
|
4535
|
+
function mapInlineChildren(node) {
|
|
4536
|
+
if (!node.children || node.children.length === 0) return [];
|
|
4537
|
+
return mapInlineNodes(node.children);
|
|
4538
|
+
}
|
|
4539
|
+
function mapBlockNodes(nodes) {
|
|
4540
|
+
return nodes.map(mapBlockNode);
|
|
4541
|
+
}
|
|
4542
|
+
function mapEditorStateToContent(state) {
|
|
4543
|
+
if (!state || !state.root || !state.root.children) {
|
|
4544
|
+
return null;
|
|
4545
|
+
}
|
|
4546
|
+
const blocks = mapBlockNodes(state.root.children);
|
|
4547
|
+
return { blocks };
|
|
4548
|
+
}
|
|
4549
|
+
function mapEditorStateToBlocks(state) {
|
|
4550
|
+
if (!state || !state.root || !state.root.children) {
|
|
4551
|
+
return [];
|
|
4552
|
+
}
|
|
4553
|
+
return mapBlockNodes(state.root.children);
|
|
4554
|
+
}
|
|
4555
|
+
const MARGIN_TOP_MM = Math.round(PAGE_MARGIN_TOP_PX / PX_PER_MM * 10) / 10;
|
|
4556
|
+
const MARGIN_BOTTOM_MM = Math.round(PAGE_MARGIN_BOTTOM_PX / PX_PER_MM * 10) / 10;
|
|
4557
|
+
const MARGIN_LEFT_MM = Math.round(PAGE_MARGIN_LEFT_PX / PX_PER_MM * 10) / 10;
|
|
4558
|
+
const MARGIN_RIGHT_MM = Math.round(PAGE_MARGIN_RIGHT_PX / PX_PER_MM * 10) / 10;
|
|
4559
|
+
function serializeDocument(document2, variableDefinitions = []) {
|
|
4560
|
+
const pages = document2.pages.map(
|
|
4561
|
+
(page, index) => serializePage(page, index)
|
|
4562
|
+
);
|
|
4563
|
+
const metadata = buildMetadata(variableDefinitions);
|
|
4564
|
+
return {
|
|
4565
|
+
version: AST_VERSION,
|
|
4566
|
+
page: {
|
|
4567
|
+
format: "A4",
|
|
4568
|
+
widthMm: 210,
|
|
4569
|
+
heightMm: 297,
|
|
4570
|
+
margins: {
|
|
4571
|
+
topMm: MARGIN_TOP_MM,
|
|
4572
|
+
rightMm: MARGIN_RIGHT_MM,
|
|
4573
|
+
bottomMm: MARGIN_BOTTOM_MM,
|
|
4574
|
+
leftMm: MARGIN_LEFT_MM
|
|
4575
|
+
}
|
|
4576
|
+
},
|
|
4577
|
+
headerFooter: {
|
|
4578
|
+
enabled: document2.headerFooterEnabled,
|
|
4579
|
+
pageCounterMode: document2.pageCounterMode,
|
|
4580
|
+
defaultHeader: document2.pages.length > 0 ? mapEditorStateToContent(document2.pages[0].headerState) : null,
|
|
4581
|
+
defaultFooter: document2.pages.length > 0 ? mapEditorStateToContent(document2.pages[0].footerState) : null
|
|
4582
|
+
},
|
|
4583
|
+
pages,
|
|
4584
|
+
metadata
|
|
4585
|
+
};
|
|
4586
|
+
}
|
|
4587
|
+
function serializePage(page, pageIndex) {
|
|
4588
|
+
return {
|
|
4589
|
+
pageIndex,
|
|
4590
|
+
body: mapEditorStateToBlocks(page.bodyState),
|
|
4591
|
+
header: mapEditorStateToContent(page.headerState),
|
|
4592
|
+
footer: mapEditorStateToContent(page.footerState)
|
|
4593
|
+
};
|
|
4594
|
+
}
|
|
4595
|
+
function buildMetadata(variableDefinitions) {
|
|
4596
|
+
const variables = {};
|
|
4597
|
+
for (const def of variableDefinitions) {
|
|
4598
|
+
variables[def.key] = {
|
|
4599
|
+
key: def.key,
|
|
4600
|
+
label: def.label,
|
|
4601
|
+
...def.description ? { description: def.description } : {},
|
|
4602
|
+
...def.valueType ? { valueType: def.valueType } : {},
|
|
4603
|
+
...def.group ? { group: def.group } : {}
|
|
4604
|
+
};
|
|
4605
|
+
}
|
|
4606
|
+
return { variables };
|
|
4607
|
+
}
|
|
4608
|
+
function buildSavePayload(ast, options) {
|
|
4609
|
+
return {
|
|
4610
|
+
document: ast,
|
|
4611
|
+
...(options == null ? void 0 : options.exportTarget) ? { exportTarget: options.exportTarget } : {},
|
|
4612
|
+
...(options == null ? void 0 : options.documentId) ? { documentId: options.documentId } : {},
|
|
4613
|
+
...(options == null ? void 0 : options.metadata) ? { metadata: options.metadata } : {}
|
|
4614
|
+
};
|
|
4615
|
+
}
|
|
4616
|
+
function serializeDocumentJson(ast) {
|
|
4617
|
+
return JSON.stringify(ast, null, 2);
|
|
4618
|
+
}
|
|
4373
4619
|
function selectEntireDocument(rootElement, selectionBuffer) {
|
|
4374
4620
|
if (!rootElement || !selectionBuffer) {
|
|
4375
4621
|
return;
|
|
@@ -4393,6 +4639,7 @@ function isFormFieldTarget(target) {
|
|
|
4393
4639
|
}
|
|
4394
4640
|
const EditorChrome = ({
|
|
4395
4641
|
captureHistoryShortcutsOnWindow,
|
|
4642
|
+
onSave,
|
|
4396
4643
|
className
|
|
4397
4644
|
}) => {
|
|
4398
4645
|
const {
|
|
@@ -4403,7 +4650,7 @@ const EditorChrome = ({
|
|
|
4403
4650
|
undo,
|
|
4404
4651
|
redo
|
|
4405
4652
|
} = useDocument();
|
|
4406
|
-
const { sidePanels } = useExtensions();
|
|
4653
|
+
const { sidePanels, cssVariables, rootClassNames } = useExtensions();
|
|
4407
4654
|
const rootRef = React.useRef(null);
|
|
4408
4655
|
const selectionBufferRef = React.useRef(null);
|
|
4409
4656
|
const clearGlobalSelection = React.useCallback(() => {
|
|
@@ -4465,12 +4712,22 @@ const EditorChrome = ({
|
|
|
4465
4712
|
});
|
|
4466
4713
|
return;
|
|
4467
4714
|
}
|
|
4715
|
+
if (key === "s" && onSave) {
|
|
4716
|
+
event.preventDefault();
|
|
4717
|
+
event.stopPropagation();
|
|
4718
|
+
const ast = serializeDocument(document2);
|
|
4719
|
+
const json = serializeDocumentJson(ast);
|
|
4720
|
+
onSave({ document: document2, ast, json });
|
|
4721
|
+
return;
|
|
4722
|
+
}
|
|
4468
4723
|
if (handleHistoryShortcut(event)) {
|
|
4469
4724
|
return;
|
|
4470
4725
|
}
|
|
4471
4726
|
}, [
|
|
4727
|
+
document2,
|
|
4472
4728
|
dispatch,
|
|
4473
4729
|
handleHistoryShortcut,
|
|
4730
|
+
onSave,
|
|
4474
4731
|
setGlobalSelectionActive
|
|
4475
4732
|
]);
|
|
4476
4733
|
const handleMouseDownCapture = React.useCallback((event) => {
|
|
@@ -4488,9 +4745,13 @@ const EditorChrome = ({
|
|
|
4488
4745
|
const editableRoots = ((_a = rootRef.current) == null ? void 0 : _a.querySelectorAll(
|
|
4489
4746
|
'[data-testid^="page-body-"] [data-lexical-editor="true"]'
|
|
4490
4747
|
)) ?? [];
|
|
4748
|
+
const root = rootRef.current;
|
|
4749
|
+
const styles = root ? getComputedStyle(root) : null;
|
|
4750
|
+
const selBg = (styles == null ? void 0 : styles.getPropertyValue("--lex4-color-selection-bg").trim()) || GLOBAL_SELECTION_BACKGROUND;
|
|
4751
|
+
const selFg = (styles == null ? void 0 : styles.getPropertyValue("--lex4-color-selection-text").trim()) || GLOBAL_SELECTION_FOREGROUND;
|
|
4491
4752
|
editableRoots.forEach((editableRoot) => {
|
|
4492
|
-
editableRoot.style.backgroundColor = globalSelectionActive ?
|
|
4493
|
-
editableRoot.style.color = globalSelectionActive ?
|
|
4753
|
+
editableRoot.style.backgroundColor = globalSelectionActive ? selBg : "";
|
|
4754
|
+
editableRoot.style.color = globalSelectionActive ? selFg : "";
|
|
4494
4755
|
editableRoot.style.caretColor = globalSelectionActive ? "transparent" : "";
|
|
4495
4756
|
});
|
|
4496
4757
|
}, [globalSelectionActive, document2.pages.length]);
|
|
@@ -4523,11 +4784,14 @@ const EditorChrome = ({
|
|
|
4523
4784
|
window.removeEventListener("beforeinput", handleWindowBeforeInput, { capture: true });
|
|
4524
4785
|
};
|
|
4525
4786
|
}, [captureHistoryShortcutsOnWindow, clearGlobalSelection, handleHistoryShortcut, redo, undo]);
|
|
4787
|
+
const rootClassName = ["lex4-editor", ...rootClassNames, className].filter(Boolean).join(" ");
|
|
4788
|
+
const extensionStyle = Object.keys(cssVariables).length > 0 ? cssVariables : void 0;
|
|
4526
4789
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4527
4790
|
"div",
|
|
4528
4791
|
{
|
|
4529
4792
|
ref: rootRef,
|
|
4530
|
-
className:
|
|
4793
|
+
className: rootClassName,
|
|
4794
|
+
style: extensionStyle,
|
|
4531
4795
|
"data-testid": "lex4-editor",
|
|
4532
4796
|
"data-global-selection-active": globalSelectionActive ? "true" : "false",
|
|
4533
4797
|
onKeyDownCapture: handleKeyDownCapture,
|
|
@@ -4541,12 +4805,12 @@ const EditorChrome = ({
|
|
|
4541
4805
|
"data-testid": "global-selection-buffer",
|
|
4542
4806
|
readOnly: true,
|
|
4543
4807
|
tabIndex: -1,
|
|
4544
|
-
className: "
|
|
4808
|
+
className: "lex4-selection-buffer"
|
|
4545
4809
|
}
|
|
4546
4810
|
),
|
|
4547
4811
|
/* @__PURE__ */ jsxRuntime.jsx(Toolbar, {}),
|
|
4548
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
4549
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
4812
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-canvas", children: [
|
|
4813
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-canvas-scroll", children: /* @__PURE__ */ jsxRuntime.jsx(DocumentView, {}) }),
|
|
4550
4814
|
sidePanels.map((Panel, idx) => /* @__PURE__ */ jsxRuntime.jsx(Panel, {}, idx)),
|
|
4551
4815
|
/* @__PURE__ */ jsxRuntime.jsx(HistorySidebar, {})
|
|
4552
4816
|
] })
|
|
@@ -4554,7 +4818,7 @@ const EditorChrome = ({
|
|
|
4554
4818
|
}
|
|
4555
4819
|
);
|
|
4556
4820
|
};
|
|
4557
|
-
const EditorWithHandle = React.forwardRef(({ captureHistoryShortcutsOnWindow, className }, ref) => {
|
|
4821
|
+
const EditorWithHandle = React.forwardRef(({ captureHistoryShortcutsOnWindow, onSave, className }, ref) => {
|
|
4558
4822
|
const { document: doc, activeEditor } = useDocument();
|
|
4559
4823
|
const { handleFactories } = useExtensions();
|
|
4560
4824
|
const getDocument = React.useCallback(() => doc, [doc]);
|
|
@@ -4572,6 +4836,7 @@ const EditorWithHandle = React.forwardRef(({ captureHistoryShortcutsOnWindow, cl
|
|
|
4572
4836
|
EditorChrome,
|
|
4573
4837
|
{
|
|
4574
4838
|
captureHistoryShortcutsOnWindow,
|
|
4839
|
+
onSave,
|
|
4575
4840
|
className
|
|
4576
4841
|
}
|
|
4577
4842
|
);
|
|
@@ -4581,6 +4846,7 @@ const Lex4Editor = React.forwardRef(({
|
|
|
4581
4846
|
captureHistoryShortcutsOnWindow = true,
|
|
4582
4847
|
initialDocument,
|
|
4583
4848
|
onDocumentChange,
|
|
4849
|
+
onSave,
|
|
4584
4850
|
extensions,
|
|
4585
4851
|
translations,
|
|
4586
4852
|
className
|
|
@@ -4595,6 +4861,7 @@ const Lex4Editor = React.forwardRef(({
|
|
|
4595
4861
|
{
|
|
4596
4862
|
ref,
|
|
4597
4863
|
captureHistoryShortcutsOnWindow,
|
|
4864
|
+
onSave,
|
|
4598
4865
|
className
|
|
4599
4866
|
}
|
|
4600
4867
|
)
|
|
@@ -4667,247 +4934,6 @@ function useHeaderFooter(maxHeight, onHeightChange) {
|
|
|
4667
4934
|
}, []);
|
|
4668
4935
|
return { attachRef };
|
|
4669
4936
|
}
|
|
4670
|
-
const AST_VERSION = "1.0.0";
|
|
4671
|
-
const IS_BOLD = 1;
|
|
4672
|
-
const IS_ITALIC = 2;
|
|
4673
|
-
const IS_STRIKETHROUGH = 4;
|
|
4674
|
-
const IS_UNDERLINE = 8;
|
|
4675
|
-
function decodeFormatBitmask(format) {
|
|
4676
|
-
const marks = {};
|
|
4677
|
-
if (format & IS_BOLD) marks.bold = true;
|
|
4678
|
-
if (format & IS_ITALIC) marks.italic = true;
|
|
4679
|
-
if (format & IS_UNDERLINE) marks.underline = true;
|
|
4680
|
-
if (format & IS_STRIKETHROUGH) marks.strikethrough = true;
|
|
4681
|
-
return marks;
|
|
4682
|
-
}
|
|
4683
|
-
function extractFontFamily(style) {
|
|
4684
|
-
const match = style.match(/font-family:\s*([^;]+)/);
|
|
4685
|
-
return match ? match[1].trim().replace(/['"]/g, "") : void 0;
|
|
4686
|
-
}
|
|
4687
|
-
function extractFontSizePt(style) {
|
|
4688
|
-
const match = style.match(/font-size:\s*(\d+(?:\.\d+)?)\s*pt/);
|
|
4689
|
-
return match ? parseFloat(match[1]) : void 0;
|
|
4690
|
-
}
|
|
4691
|
-
function buildTextMarks(format, style) {
|
|
4692
|
-
const formatMarks = decodeFormatBitmask(format);
|
|
4693
|
-
const fontFamily = style ? extractFontFamily(style) : void 0;
|
|
4694
|
-
const fontSize = style ? extractFontSizePt(style) : void 0;
|
|
4695
|
-
const marks = {
|
|
4696
|
-
...formatMarks,
|
|
4697
|
-
...fontFamily ? { fontFamily } : {},
|
|
4698
|
-
...fontSize ? { fontSize } : {}
|
|
4699
|
-
};
|
|
4700
|
-
return Object.keys(marks).length > 0 ? marks : void 0;
|
|
4701
|
-
}
|
|
4702
|
-
function mapInlineNode(node) {
|
|
4703
|
-
switch (node.type) {
|
|
4704
|
-
case "text":
|
|
4705
|
-
return mapTextNode(node);
|
|
4706
|
-
case "variable-node":
|
|
4707
|
-
return mapVariableNode(node);
|
|
4708
|
-
case "linebreak":
|
|
4709
|
-
return mapLineBreak();
|
|
4710
|
-
default:
|
|
4711
|
-
return { type: "text", text: "" };
|
|
4712
|
-
}
|
|
4713
|
-
}
|
|
4714
|
-
function mapTextNode(node) {
|
|
4715
|
-
const marks = buildTextMarks(node.format, node.style);
|
|
4716
|
-
return {
|
|
4717
|
-
type: "text",
|
|
4718
|
-
text: node.text,
|
|
4719
|
-
...marks ? { marks } : {}
|
|
4720
|
-
};
|
|
4721
|
-
}
|
|
4722
|
-
function mapVariableNode(node) {
|
|
4723
|
-
return {
|
|
4724
|
-
type: "variable",
|
|
4725
|
-
key: node.variableKey
|
|
4726
|
-
};
|
|
4727
|
-
}
|
|
4728
|
-
function mapLineBreak() {
|
|
4729
|
-
return { type: "linebreak" };
|
|
4730
|
-
}
|
|
4731
|
-
function mapInlineNodes(nodes) {
|
|
4732
|
-
return nodes.map(mapInlineNode);
|
|
4733
|
-
}
|
|
4734
|
-
const ALIGN_LEFT = 1;
|
|
4735
|
-
const ALIGN_CENTER = 2;
|
|
4736
|
-
const ALIGN_RIGHT = 3;
|
|
4737
|
-
const ALIGN_JUSTIFY = 4;
|
|
4738
|
-
function decodeAlignment(format) {
|
|
4739
|
-
if (typeof format === "string") {
|
|
4740
|
-
if (["left", "center", "right", "justify"].includes(format)) {
|
|
4741
|
-
return format;
|
|
4742
|
-
}
|
|
4743
|
-
return void 0;
|
|
4744
|
-
}
|
|
4745
|
-
if (typeof format !== "number" || format === 0) return void 0;
|
|
4746
|
-
switch (format) {
|
|
4747
|
-
case ALIGN_LEFT:
|
|
4748
|
-
return "left";
|
|
4749
|
-
case ALIGN_CENTER:
|
|
4750
|
-
return "center";
|
|
4751
|
-
case ALIGN_RIGHT:
|
|
4752
|
-
return "right";
|
|
4753
|
-
case ALIGN_JUSTIFY:
|
|
4754
|
-
return "justify";
|
|
4755
|
-
default:
|
|
4756
|
-
return void 0;
|
|
4757
|
-
}
|
|
4758
|
-
}
|
|
4759
|
-
function mapBlockNode(node) {
|
|
4760
|
-
switch (node.type) {
|
|
4761
|
-
case "paragraph":
|
|
4762
|
-
return mapParagraph(node);
|
|
4763
|
-
case "heading":
|
|
4764
|
-
return mapHeading(node);
|
|
4765
|
-
case "list":
|
|
4766
|
-
return mapList(node);
|
|
4767
|
-
case "quote":
|
|
4768
|
-
return mapBlockQuote(node);
|
|
4769
|
-
default:
|
|
4770
|
-
return {
|
|
4771
|
-
type: "paragraph",
|
|
4772
|
-
children: mapInlineChildren(node)
|
|
4773
|
-
};
|
|
4774
|
-
}
|
|
4775
|
-
}
|
|
4776
|
-
function mapParagraph(node) {
|
|
4777
|
-
const alignment = decodeAlignment(node.format);
|
|
4778
|
-
const indent = node.indent && node.indent > 0 ? node.indent : void 0;
|
|
4779
|
-
return {
|
|
4780
|
-
type: "paragraph",
|
|
4781
|
-
...alignment ? { alignment } : {},
|
|
4782
|
-
...indent ? { indent } : {},
|
|
4783
|
-
children: mapInlineChildren(node)
|
|
4784
|
-
};
|
|
4785
|
-
}
|
|
4786
|
-
function mapHeading(node) {
|
|
4787
|
-
var _a;
|
|
4788
|
-
const alignment = decodeAlignment(node.format);
|
|
4789
|
-
const tagMatch = (_a = node.tag) == null ? void 0 : _a.match(/^h(\d)$/);
|
|
4790
|
-
const level = tagMatch ? parseInt(tagMatch[1], 10) : 1;
|
|
4791
|
-
return {
|
|
4792
|
-
type: "heading",
|
|
4793
|
-
level,
|
|
4794
|
-
...alignment ? { alignment } : {},
|
|
4795
|
-
children: mapInlineChildren(node)
|
|
4796
|
-
};
|
|
4797
|
-
}
|
|
4798
|
-
function mapList(node) {
|
|
4799
|
-
const listType = node.listType === "number" ? "ordered" : "unordered";
|
|
4800
|
-
const items = (node.children ?? []).filter((c) => c.type === "listitem").map(mapListItem);
|
|
4801
|
-
return {
|
|
4802
|
-
type: "list",
|
|
4803
|
-
listType,
|
|
4804
|
-
items
|
|
4805
|
-
};
|
|
4806
|
-
}
|
|
4807
|
-
function mapListItem(node) {
|
|
4808
|
-
const inlineChildren = [];
|
|
4809
|
-
let nestedList;
|
|
4810
|
-
for (const child of node.children ?? []) {
|
|
4811
|
-
if (child.type === "list") {
|
|
4812
|
-
nestedList = mapList(child);
|
|
4813
|
-
} else {
|
|
4814
|
-
const mapped = mapInlineNodes([child]);
|
|
4815
|
-
inlineChildren.push(...mapped);
|
|
4816
|
-
}
|
|
4817
|
-
}
|
|
4818
|
-
return {
|
|
4819
|
-
type: "list-item",
|
|
4820
|
-
children: inlineChildren,
|
|
4821
|
-
...nestedList ? { nestedList } : {}
|
|
4822
|
-
};
|
|
4823
|
-
}
|
|
4824
|
-
function mapBlockQuote(node) {
|
|
4825
|
-
return {
|
|
4826
|
-
type: "blockquote",
|
|
4827
|
-
children: mapInlineChildren(node)
|
|
4828
|
-
};
|
|
4829
|
-
}
|
|
4830
|
-
function mapInlineChildren(node) {
|
|
4831
|
-
if (!node.children || node.children.length === 0) return [];
|
|
4832
|
-
return mapInlineNodes(node.children);
|
|
4833
|
-
}
|
|
4834
|
-
function mapBlockNodes(nodes) {
|
|
4835
|
-
return nodes.map(mapBlockNode);
|
|
4836
|
-
}
|
|
4837
|
-
function mapEditorStateToContent(state) {
|
|
4838
|
-
if (!state || !state.root || !state.root.children) {
|
|
4839
|
-
return null;
|
|
4840
|
-
}
|
|
4841
|
-
const blocks = mapBlockNodes(state.root.children);
|
|
4842
|
-
return { blocks };
|
|
4843
|
-
}
|
|
4844
|
-
function mapEditorStateToBlocks(state) {
|
|
4845
|
-
if (!state || !state.root || !state.root.children) {
|
|
4846
|
-
return [];
|
|
4847
|
-
}
|
|
4848
|
-
return mapBlockNodes(state.root.children);
|
|
4849
|
-
}
|
|
4850
|
-
const MARGIN_MM = Math.round(PAGE_MARGIN_PX / PX_PER_MM * 10) / 10;
|
|
4851
|
-
function serializeDocument(document2, variableDefinitions = []) {
|
|
4852
|
-
const pages = document2.pages.map(
|
|
4853
|
-
(page, index) => serializePage(page, index)
|
|
4854
|
-
);
|
|
4855
|
-
const metadata = buildMetadata(variableDefinitions);
|
|
4856
|
-
return {
|
|
4857
|
-
version: AST_VERSION,
|
|
4858
|
-
page: {
|
|
4859
|
-
format: "A4",
|
|
4860
|
-
widthMm: 210,
|
|
4861
|
-
heightMm: 297,
|
|
4862
|
-
margins: {
|
|
4863
|
-
topMm: MARGIN_MM,
|
|
4864
|
-
rightMm: MARGIN_MM,
|
|
4865
|
-
bottomMm: MARGIN_MM,
|
|
4866
|
-
leftMm: MARGIN_MM
|
|
4867
|
-
}
|
|
4868
|
-
},
|
|
4869
|
-
headerFooter: {
|
|
4870
|
-
enabled: document2.headerFooterEnabled,
|
|
4871
|
-
pageCounterMode: document2.pageCounterMode,
|
|
4872
|
-
defaultHeader: document2.pages.length > 0 ? mapEditorStateToContent(document2.pages[0].headerState) : null,
|
|
4873
|
-
defaultFooter: document2.pages.length > 0 ? mapEditorStateToContent(document2.pages[0].footerState) : null
|
|
4874
|
-
},
|
|
4875
|
-
pages,
|
|
4876
|
-
metadata
|
|
4877
|
-
};
|
|
4878
|
-
}
|
|
4879
|
-
function serializePage(page, pageIndex) {
|
|
4880
|
-
return {
|
|
4881
|
-
pageIndex,
|
|
4882
|
-
body: mapEditorStateToBlocks(page.bodyState),
|
|
4883
|
-
header: mapEditorStateToContent(page.headerState),
|
|
4884
|
-
footer: mapEditorStateToContent(page.footerState)
|
|
4885
|
-
};
|
|
4886
|
-
}
|
|
4887
|
-
function buildMetadata(variableDefinitions) {
|
|
4888
|
-
const variables = {};
|
|
4889
|
-
for (const def of variableDefinitions) {
|
|
4890
|
-
variables[def.key] = {
|
|
4891
|
-
key: def.key,
|
|
4892
|
-
label: def.label,
|
|
4893
|
-
...def.description ? { description: def.description } : {},
|
|
4894
|
-
...def.valueType ? { valueType: def.valueType } : {},
|
|
4895
|
-
...def.group ? { group: def.group } : {}
|
|
4896
|
-
};
|
|
4897
|
-
}
|
|
4898
|
-
return { variables };
|
|
4899
|
-
}
|
|
4900
|
-
function buildSavePayload(ast, options) {
|
|
4901
|
-
return {
|
|
4902
|
-
document: ast,
|
|
4903
|
-
...(options == null ? void 0 : options.exportTarget) ? { exportTarget: options.exportTarget } : {},
|
|
4904
|
-
...(options == null ? void 0 : options.documentId) ? { documentId: options.documentId } : {},
|
|
4905
|
-
...(options == null ? void 0 : options.metadata) ? { metadata: options.metadata } : {}
|
|
4906
|
-
};
|
|
4907
|
-
}
|
|
4908
|
-
function serializeDocumentJson(ast) {
|
|
4909
|
-
return JSON.stringify(ast, null, 2);
|
|
4910
|
-
}
|
|
4911
4937
|
function astExtension() {
|
|
4912
4938
|
return {
|
|
4913
4939
|
name: "ast",
|
|
@@ -5033,7 +5059,7 @@ function VariableChip({ variableKey }) {
|
|
|
5033
5059
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5034
5060
|
"span",
|
|
5035
5061
|
{
|
|
5036
|
-
className: "lex4-variable-chip
|
|
5062
|
+
className: "lex4-variable-chip",
|
|
5037
5063
|
"data-testid": `variable-chip-${variableKey}`,
|
|
5038
5064
|
title: variableKey,
|
|
5039
5065
|
children: label
|
|
@@ -5106,12 +5132,12 @@ const VariablePicker = ({ onInsert, disabled = false }) => {
|
|
|
5106
5132
|
document.addEventListener("mousedown", handler);
|
|
5107
5133
|
return () => document.removeEventListener("mousedown", handler);
|
|
5108
5134
|
}, [open]);
|
|
5109
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: "
|
|
5135
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: "lex4-variable-picker", children: [
|
|
5110
5136
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5111
5137
|
"button",
|
|
5112
5138
|
{
|
|
5113
5139
|
type: "button",
|
|
5114
|
-
className: "
|
|
5140
|
+
className: "lex4-variable-picker-btn",
|
|
5115
5141
|
"data-testid": "variable-picker-button",
|
|
5116
5142
|
disabled: disabled || definitions.length === 0,
|
|
5117
5143
|
onClick: () => setOpen(!open),
|
|
@@ -5122,14 +5148,13 @@ const VariablePicker = ({ onInsert, disabled = false }) => {
|
|
|
5122
5148
|
open && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5123
5149
|
"div",
|
|
5124
5150
|
{
|
|
5125
|
-
className: "
|
|
5151
|
+
className: "lex4-variable-picker-dropdown",
|
|
5126
5152
|
"data-testid": "variable-picker-dropdown",
|
|
5127
5153
|
children: [
|
|
5128
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
5154
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-variable-picker-search", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5129
5155
|
"input",
|
|
5130
5156
|
{
|
|
5131
5157
|
type: "text",
|
|
5132
|
-
className: "w-full rounded border border-gray-200 px-2 py-1 text-xs\n focus:border-blue-400 focus:outline-none",
|
|
5133
5158
|
placeholder: "Search variables...",
|
|
5134
5159
|
"data-testid": "variable-picker-search",
|
|
5135
5160
|
value: filter,
|
|
@@ -5137,20 +5162,20 @@ const VariablePicker = ({ onInsert, disabled = false }) => {
|
|
|
5137
5162
|
autoFocus: true
|
|
5138
5163
|
}
|
|
5139
5164
|
) }),
|
|
5140
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
5141
|
-
Object.keys(grouped).length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
5165
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-variable-picker-list", children: [
|
|
5166
|
+
Object.keys(grouped).length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-variable-picker-empty", children: "No variables found" }),
|
|
5142
5167
|
Object.entries(grouped).map(([group, defs]) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
5143
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
5168
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-variable-picker-group-label", children: group }),
|
|
5144
5169
|
defs.map((def) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5145
5170
|
"button",
|
|
5146
5171
|
{
|
|
5147
5172
|
type: "button",
|
|
5148
|
-
className: "
|
|
5173
|
+
className: "lex4-variable-picker-option",
|
|
5149
5174
|
"data-testid": `variable-option-${def.key}`,
|
|
5150
5175
|
onClick: () => handleInsert(def.key),
|
|
5151
5176
|
children: [
|
|
5152
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "
|
|
5153
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "
|
|
5177
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "lex4-variable-picker-key", children: `{{${def.key}}}` }),
|
|
5178
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "lex4-variable-picker-label", children: def.label })
|
|
5154
5179
|
]
|
|
5155
5180
|
},
|
|
5156
5181
|
def.key
|
|
@@ -5208,20 +5233,20 @@ const VariablePanel = ({ open, onClose }) => {
|
|
|
5208
5233
|
"button",
|
|
5209
5234
|
{
|
|
5210
5235
|
type: "button",
|
|
5211
|
-
className: "
|
|
5236
|
+
className: "lex4-sidebar-action-btn",
|
|
5212
5237
|
title: t.variables.refreshVariables,
|
|
5213
5238
|
"data-testid": "btn-refresh-variables",
|
|
5214
5239
|
children: /* @__PURE__ */ jsxRuntime.jsx(RefreshCw, { size: 12 })
|
|
5215
5240
|
}
|
|
5216
5241
|
),
|
|
5217
5242
|
children: [
|
|
5218
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
5219
|
-
/* @__PURE__ */ jsxRuntime.jsx(Search, { size: 14, className: "
|
|
5243
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-variable-search-container", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-variable-search-wrapper", children: [
|
|
5244
|
+
/* @__PURE__ */ jsxRuntime.jsx(Search, { size: 14, className: "lex4-variable-search-icon" }),
|
|
5220
5245
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5221
5246
|
"input",
|
|
5222
5247
|
{
|
|
5223
5248
|
type: "text",
|
|
5224
|
-
className: "
|
|
5249
|
+
className: "lex4-variable-search-input",
|
|
5225
5250
|
placeholder: t.variables.searchPlaceholder,
|
|
5226
5251
|
"data-testid": "variable-panel-search",
|
|
5227
5252
|
value: filter,
|
|
@@ -5229,25 +5254,19 @@ const VariablePanel = ({ open, onClose }) => {
|
|
|
5229
5254
|
}
|
|
5230
5255
|
)
|
|
5231
5256
|
] }) }),
|
|
5232
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
5233
|
-
Object.keys(grouped).length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
5234
|
-
Object.entries(grouped).map(([group, defs]) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
5257
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-variable-list", children: [
|
|
5258
|
+
Object.keys(grouped).length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-variable-list-empty", children: t.variables.noVariablesFound }),
|
|
5259
|
+
Object.entries(grouped).map(([group, defs]) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-variable-group", children: /* @__PURE__ */ jsxRuntime.jsx("div", { children: defs.map((def) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5235
5260
|
"button",
|
|
5236
5261
|
{
|
|
5237
5262
|
type: "button",
|
|
5238
|
-
className: "
|
|
5263
|
+
className: "lex4-variable-list-item",
|
|
5239
5264
|
"data-testid": `variable-panel-${def.key}`,
|
|
5240
5265
|
onClick: () => handleInsert(def.key),
|
|
5241
5266
|
disabled: !activeEditor,
|
|
5242
5267
|
children: [
|
|
5243
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5244
|
-
|
|
5245
|
-
{
|
|
5246
|
-
className: "inline-flex items-center rounded-full border border-blue-300 bg-white\n px-2 py-0.5 text-[11px] font-medium text-blue-700\n group-hover:border-blue-400 group-hover:bg-blue-50",
|
|
5247
|
-
children: def.label
|
|
5248
|
-
}
|
|
5249
|
-
),
|
|
5250
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-semibold uppercase tracking-wider text-gray-400", children: group })
|
|
5268
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "lex4-variable-badge", children: def.label }),
|
|
5269
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "lex4-variable-group-label", children: group })
|
|
5251
5270
|
]
|
|
5252
5271
|
},
|
|
5253
5272
|
def.key
|
|
@@ -5301,10 +5320,7 @@ const VariablePanelToggle = () => {
|
|
|
5301
5320
|
"aria-label": panelOpen ? t.variables.closePanel : t.variables.openPanel,
|
|
5302
5321
|
onMouseDown: (e) => e.preventDefault(),
|
|
5303
5322
|
onClick: () => setPanelOpen(!panelOpen),
|
|
5304
|
-
className: `
|
|
5305
|
-
flex h-7 w-7 items-center justify-center rounded transition-colors
|
|
5306
|
-
${panelOpen ? "bg-blue-50 text-blue-600" : "text-gray-600 hover:bg-gray-100 hover:text-gray-900"}
|
|
5307
|
-
`,
|
|
5323
|
+
className: `lex4-toolbar-btn${panelOpen ? " active" : ""}`,
|
|
5308
5324
|
"data-testid": "toggle-variable-panel",
|
|
5309
5325
|
children: /* @__PURE__ */ jsxRuntime.jsx(Braces, { size: 15 })
|
|
5310
5326
|
}
|