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