@yurikilian/lex4 0.3.2 → 1.0.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/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/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/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 +390 -383
- package/dist/lex4-editor.cjs.map +1 -1
- package/dist/lex4-editor.js +390 -383
- 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
|
@@ -1742,21 +1742,21 @@ const EditorSidebar = ({
|
|
|
1742
1742
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1743
1743
|
"aside",
|
|
1744
1744
|
{
|
|
1745
|
-
className: "
|
|
1745
|
+
className: "lex4-sidebar",
|
|
1746
1746
|
"data-testid": testId,
|
|
1747
1747
|
children: [
|
|
1748
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
1748
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-sidebar-header", children: [
|
|
1749
1749
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1750
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "
|
|
1751
|
-
subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "
|
|
1750
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "lex4-sidebar-title", children: title }),
|
|
1751
|
+
subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "lex4-sidebar-subtitle", children: subtitle })
|
|
1752
1752
|
] }),
|
|
1753
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
1753
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-sidebar-actions", children: [
|
|
1754
1754
|
headerActions,
|
|
1755
1755
|
onClose && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1756
1756
|
"button",
|
|
1757
1757
|
{
|
|
1758
1758
|
type: "button",
|
|
1759
|
-
className: "
|
|
1759
|
+
className: "lex4-sidebar-action-btn",
|
|
1760
1760
|
"data-testid": "close-editor-sidebar",
|
|
1761
1761
|
onClick: onClose,
|
|
1762
1762
|
"aria-label": t.sidebar.close,
|
|
@@ -1765,7 +1765,7 @@ const EditorSidebar = ({
|
|
|
1765
1765
|
)
|
|
1766
1766
|
] })
|
|
1767
1767
|
] }),
|
|
1768
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
1768
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-sidebar-body", children })
|
|
1769
1769
|
]
|
|
1770
1770
|
}
|
|
1771
1771
|
);
|
|
@@ -1797,7 +1797,7 @@ const HistorySidebar = () => {
|
|
|
1797
1797
|
"aria-label": t.history.clearHistory,
|
|
1798
1798
|
onMouseDown: (e) => e.preventDefault(),
|
|
1799
1799
|
onClick: () => clearHistory("manual"),
|
|
1800
|
-
className: "
|
|
1800
|
+
className: "lex4-sidebar-action-btn",
|
|
1801
1801
|
"data-testid": "clear-history",
|
|
1802
1802
|
children: /* @__PURE__ */ jsxRuntime.jsx(Trash2, { size: 13 })
|
|
1803
1803
|
}
|
|
@@ -1814,27 +1814,27 @@ const HistorySidebar = () => {
|
|
|
1814
1814
|
children: visibleEntries.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1815
1815
|
"div",
|
|
1816
1816
|
{
|
|
1817
|
-
className: "
|
|
1817
|
+
className: "lex4-history-empty",
|
|
1818
1818
|
"data-testid": "history-empty",
|
|
1819
1819
|
children: t.history.empty
|
|
1820
1820
|
}
|
|
1821
|
-
) : /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "
|
|
1821
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "lex4-history-list", "data-testid": "history-entry-list", children: visibleEntries.map((entry, reversedIndex) => {
|
|
1822
1822
|
const actualIndex = historyEntries.length - reversedIndex - 1;
|
|
1823
1823
|
const isCurrent = actualIndex === historyCursor - 1;
|
|
1824
1824
|
return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1825
1825
|
"button",
|
|
1826
1826
|
{
|
|
1827
1827
|
type: "button",
|
|
1828
|
-
className: `
|
|
1828
|
+
className: `lex4-history-entry ${isCurrent ? "active" : ""}`,
|
|
1829
1829
|
"data-testid": `history-entry-${actualIndex}`,
|
|
1830
1830
|
"data-history-current": isCurrent ? "true" : "false",
|
|
1831
1831
|
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: "
|
|
1832
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-history-entry-row", children: [
|
|
1833
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-history-entry-content", children: [
|
|
1834
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `lex4-history-entry-label${isCurrent ? " current" : ""}`, children: entry.label }),
|
|
1835
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-history-entry-source", children: t.regions[entry.source] ?? entry.source })
|
|
1836
1836
|
] }),
|
|
1837
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
1837
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-history-entry-time", children: formatTimestamp(entry.timestamp) })
|
|
1838
1838
|
] })
|
|
1839
1839
|
}
|
|
1840
1840
|
) }, entry.id);
|
|
@@ -1850,11 +1850,11 @@ const HeaderFooterToggle = ({
|
|
|
1850
1850
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1851
1851
|
"label",
|
|
1852
1852
|
{
|
|
1853
|
-
className: "
|
|
1853
|
+
className: "lex4-hf-toggle",
|
|
1854
1854
|
"data-testid": "header-footer-toggle",
|
|
1855
1855
|
children: [
|
|
1856
|
-
/* @__PURE__ */ jsxRuntime.jsx(Rows3, { size: 14, className: "
|
|
1857
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "
|
|
1856
|
+
/* @__PURE__ */ jsxRuntime.jsx(Rows3, { size: 14, className: "lex4-hf-toggle-icon" }),
|
|
1857
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "lex4-hf-toggle-label", children: t.headerFooter.label }),
|
|
1858
1858
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1859
1859
|
"button",
|
|
1860
1860
|
{
|
|
@@ -1863,22 +1863,10 @@ const HeaderFooterToggle = ({
|
|
|
1863
1863
|
"aria-checked": enabled,
|
|
1864
1864
|
onMouseDown: (e) => e.preventDefault(),
|
|
1865
1865
|
onClick: () => onToggle(!enabled),
|
|
1866
|
-
className:
|
|
1867
|
-
|
|
1868
|
-
transition-colors duration-200
|
|
1869
|
-
${enabled ? "bg-blue-500" : "bg-gray-300"}
|
|
1870
|
-
`,
|
|
1866
|
+
className: "lex4-hf-switch",
|
|
1867
|
+
style: { backgroundColor: enabled ? "var(--lex4-color-primary)" : "var(--lex4-color-text-disabled)" },
|
|
1871
1868
|
"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
|
-
)
|
|
1869
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "lex4-hf-switch-knob" })
|
|
1882
1870
|
}
|
|
1883
1871
|
)
|
|
1884
1872
|
]
|
|
@@ -1920,17 +1908,14 @@ const HeaderFooterActions = ({
|
|
|
1920
1908
|
action();
|
|
1921
1909
|
close();
|
|
1922
1910
|
};
|
|
1923
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef,
|
|
1911
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, style: { position: "relative" }, "data-testid": "header-footer-actions", children: [
|
|
1924
1912
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1925
1913
|
"button",
|
|
1926
1914
|
{
|
|
1927
1915
|
type: "button",
|
|
1928
1916
|
onMouseDown: (e) => e.preventDefault(),
|
|
1929
1917
|
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
|
-
`,
|
|
1918
|
+
className: "lex4-settings-trigger",
|
|
1934
1919
|
"data-testid": "header-footer-menu-trigger",
|
|
1935
1920
|
"aria-expanded": open,
|
|
1936
1921
|
"aria-haspopup": "true",
|
|
@@ -1943,12 +1928,12 @@ const HeaderFooterActions = ({
|
|
|
1943
1928
|
open && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1944
1929
|
"div",
|
|
1945
1930
|
{
|
|
1946
|
-
className: "
|
|
1931
|
+
className: "lex4-settings-menu",
|
|
1947
1932
|
role: "menu",
|
|
1948
1933
|
"data-testid": "header-footer-menu",
|
|
1949
1934
|
children: [
|
|
1950
1935
|
/* @__PURE__ */ jsxRuntime.jsx(SectionLabel, { children: "Page counter" }),
|
|
1951
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
1936
|
+
/* @__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
1937
|
"button",
|
|
1953
1938
|
{
|
|
1954
1939
|
type: "button",
|
|
@@ -1956,10 +1941,7 @@ const HeaderFooterActions = ({
|
|
|
1956
1941
|
"aria-checked": pageCounterMode === value,
|
|
1957
1942
|
onMouseDown: (e) => e.preventDefault(),
|
|
1958
1943
|
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
|
-
`,
|
|
1944
|
+
className: "lex4-settings-counter-btn",
|
|
1963
1945
|
"data-testid": `page-counter-${value}`,
|
|
1964
1946
|
children: label
|
|
1965
1947
|
},
|
|
@@ -2032,7 +2014,7 @@ const HeaderFooterActions = ({
|
|
|
2032
2014
|
)
|
|
2033
2015
|
] });
|
|
2034
2016
|
};
|
|
2035
|
-
const SectionLabel = ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
2017
|
+
const SectionLabel = ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-settings-label", children });
|
|
2036
2018
|
const MenuItem = ({ icon, label, onClick, disabled, testId }) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2037
2019
|
"button",
|
|
2038
2020
|
{
|
|
@@ -2041,7 +2023,7 @@ const MenuItem = ({ icon, label, onClick, disabled, testId }) => /* @__PURE__ */
|
|
|
2041
2023
|
onMouseDown: (e) => e.preventDefault(),
|
|
2042
2024
|
onClick,
|
|
2043
2025
|
disabled,
|
|
2044
|
-
className: "
|
|
2026
|
+
className: "lex4-settings-item",
|
|
2045
2027
|
"data-testid": testId,
|
|
2046
2028
|
children: [
|
|
2047
2029
|
icon,
|
|
@@ -2049,7 +2031,7 @@ const MenuItem = ({ icon, label, onClick, disabled, testId }) => /* @__PURE__ */
|
|
|
2049
2031
|
]
|
|
2050
2032
|
}
|
|
2051
2033
|
);
|
|
2052
|
-
const MenuDivider = () => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
2034
|
+
const MenuDivider = () => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-settings-divider" });
|
|
2053
2035
|
function resolveExtensions(extensions) {
|
|
2054
2036
|
const resolved = {
|
|
2055
2037
|
nodes: [],
|
|
@@ -2058,6 +2040,8 @@ function resolveExtensions(extensions) {
|
|
|
2058
2040
|
sidePanels: [],
|
|
2059
2041
|
providers: [],
|
|
2060
2042
|
themeOverrides: {},
|
|
2043
|
+
cssVariables: {},
|
|
2044
|
+
rootClassNames: [],
|
|
2061
2045
|
handleFactories: []
|
|
2062
2046
|
};
|
|
2063
2047
|
for (const ext of extensions) {
|
|
@@ -2069,6 +2053,10 @@ function resolveExtensions(extensions) {
|
|
|
2069
2053
|
if (ext.themeOverrides) {
|
|
2070
2054
|
resolved.themeOverrides = { ...resolved.themeOverrides, ...ext.themeOverrides };
|
|
2071
2055
|
}
|
|
2056
|
+
if (ext.cssVariables) {
|
|
2057
|
+
Object.assign(resolved.cssVariables, ext.cssVariables);
|
|
2058
|
+
}
|
|
2059
|
+
if (ext.rootClassName) resolved.rootClassNames.push(ext.rootClassName);
|
|
2072
2060
|
if (ext.handleMethods) resolved.handleFactories.push(ext.handleMethods);
|
|
2073
2061
|
}
|
|
2074
2062
|
return resolved;
|
|
@@ -2080,14 +2068,27 @@ const EMPTY_RESOLVED = {
|
|
|
2080
2068
|
sidePanels: [],
|
|
2081
2069
|
providers: [],
|
|
2082
2070
|
themeOverrides: {},
|
|
2071
|
+
cssVariables: {},
|
|
2072
|
+
rootClassNames: [],
|
|
2083
2073
|
handleFactories: []
|
|
2084
2074
|
};
|
|
2085
2075
|
const ExtensionResolvedContext = React.createContext(EMPTY_RESOLVED);
|
|
2076
|
+
function arraysEqual(a, b) {
|
|
2077
|
+
if (a.length !== b.length) return false;
|
|
2078
|
+
for (let i = 0; i < a.length; i++) {
|
|
2079
|
+
if (a[i] !== b[i]) return false;
|
|
2080
|
+
}
|
|
2081
|
+
return true;
|
|
2082
|
+
}
|
|
2086
2083
|
const ExtensionProvider = ({ extensions, children }) => {
|
|
2087
|
-
const
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
)
|
|
2084
|
+
const prevNamesRef = React.useRef([]);
|
|
2085
|
+
const resolvedRef = React.useRef(EMPTY_RESOLVED);
|
|
2086
|
+
const currentNames = (extensions ?? []).map((e) => e.name);
|
|
2087
|
+
if (!arraysEqual(currentNames, prevNamesRef.current)) {
|
|
2088
|
+
resolvedRef.current = extensions && extensions.length > 0 ? resolveExtensions(extensions) : EMPTY_RESOLVED;
|
|
2089
|
+
prevNamesRef.current = currentNames;
|
|
2090
|
+
}
|
|
2091
|
+
const resolved = resolvedRef.current;
|
|
2091
2092
|
let wrapped = /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
|
|
2092
2093
|
for (let i = resolved.providers.length - 1; i >= 0; i--) {
|
|
2093
2094
|
const Provider = resolved.providers[i];
|
|
@@ -2394,11 +2395,11 @@ const Toolbar = () => {
|
|
|
2394
2395
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2395
2396
|
"div",
|
|
2396
2397
|
{
|
|
2397
|
-
className: "lex4-toolbar
|
|
2398
|
+
className: "lex4-toolbar",
|
|
2398
2399
|
"data-testid": "toolbar",
|
|
2399
2400
|
children: [
|
|
2400
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
2401
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
2401
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-row", children: [
|
|
2402
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-group", "data-testid": "history-controls", children: [
|
|
2402
2403
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2403
2404
|
ToolbarIconButton,
|
|
2404
2405
|
{
|
|
@@ -2421,12 +2422,12 @@ const Toolbar = () => {
|
|
|
2421
2422
|
)
|
|
2422
2423
|
] }),
|
|
2423
2424
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2424
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
2425
|
-
/* @__PURE__ */ jsxRuntime.jsx(Type, { size: 14, className: "
|
|
2425
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-group-gap", children: [
|
|
2426
|
+
/* @__PURE__ */ jsxRuntime.jsx(Type, { size: 14, className: "lex4-toolbar-icon" }),
|
|
2426
2427
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2427
2428
|
"select",
|
|
2428
2429
|
{
|
|
2429
|
-
className: "
|
|
2430
|
+
className: "lex4-toolbar-select",
|
|
2430
2431
|
"data-testid": "font-selector",
|
|
2431
2432
|
defaultValue: "Calibri",
|
|
2432
2433
|
onChange: handleFontChange,
|
|
@@ -2434,12 +2435,12 @@ const Toolbar = () => {
|
|
|
2434
2435
|
}
|
|
2435
2436
|
)
|
|
2436
2437
|
] }),
|
|
2437
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
2438
|
-
/* @__PURE__ */ jsxRuntime.jsx(ALargeSmall, { size: 14, className: "
|
|
2438
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-group-gap", children: [
|
|
2439
|
+
/* @__PURE__ */ jsxRuntime.jsx(ALargeSmall, { size: 14, className: "lex4-toolbar-icon" }),
|
|
2439
2440
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2440
2441
|
"select",
|
|
2441
2442
|
{
|
|
2442
|
-
className: "
|
|
2443
|
+
className: "lex4-toolbar-select lex4-toolbar-select-narrow",
|
|
2443
2444
|
"data-testid": "font-size-selector",
|
|
2444
2445
|
defaultValue: "12",
|
|
2445
2446
|
onChange: handleFontSizeChange,
|
|
@@ -2448,21 +2449,21 @@ const Toolbar = () => {
|
|
|
2448
2449
|
)
|
|
2449
2450
|
] }),
|
|
2450
2451
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2451
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
2452
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-group", "data-testid": "format-group", children: [
|
|
2452
2453
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.bold, testId: "btn-bold", onClick: handleBold, children: /* @__PURE__ */ jsxRuntime.jsx(Bold, { size: 15 }) }),
|
|
2453
2454
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.italic, testId: "btn-italic", onClick: handleItalic, children: /* @__PURE__ */ jsxRuntime.jsx(Italic, { size: 15 }) }),
|
|
2454
2455
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.underline, testId: "btn-underline", onClick: handleUnderline, children: /* @__PURE__ */ jsxRuntime.jsx(Underline, { size: 15 }) }),
|
|
2455
2456
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.strikethrough, testId: "btn-strike", onClick: handleStrikethrough, children: /* @__PURE__ */ jsxRuntime.jsx(Strikethrough, { size: 15 }) })
|
|
2456
2457
|
] }),
|
|
2457
2458
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2458
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
2459
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-group", "data-testid": "align-group", children: [
|
|
2459
2460
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignLeft, testId: "btn-align-left", onClick: handleAlignLeft, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignStart, { size: 15 }) }),
|
|
2460
2461
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignCenter, testId: "btn-align-center", onClick: handleAlignCenter, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignCenter, { size: 15 }) }),
|
|
2461
2462
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignRight, testId: "btn-align-right", onClick: handleAlignRight, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignEnd, { size: 15 }) }),
|
|
2462
2463
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.justify, testId: "btn-align-justify", onClick: handleAlignJustify, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignJustify, { size: 15 }) })
|
|
2463
2464
|
] }),
|
|
2464
2465
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2465
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
2466
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-toolbar-group", "data-testid": "list-group", children: [
|
|
2466
2467
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.numberedList, testId: "btn-list-number", onClick: handleListNumber, children: /* @__PURE__ */ jsxRuntime.jsx(ListOrdered, { size: 15 }) }),
|
|
2467
2468
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.bulletList, testId: "btn-list-bullet", onClick: handleListBullet, children: /* @__PURE__ */ jsxRuntime.jsx(List, { size: 15 }) }),
|
|
2468
2469
|
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.indent, testId: "btn-indent", onClick: handleIndent, children: /* @__PURE__ */ jsxRuntime.jsx(ListIndentIncrease, { size: 15 }) }),
|
|
@@ -2472,7 +2473,7 @@ const Toolbar = () => {
|
|
|
2472
2473
|
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2473
2474
|
toolbarItems.map((ToolbarItem, idx) => /* @__PURE__ */ jsxRuntime.jsx(ToolbarItem, {}, idx))
|
|
2474
2475
|
] }),
|
|
2475
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
2476
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-toolbar-end", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2476
2477
|
ToolbarIconButton,
|
|
2477
2478
|
{
|
|
2478
2479
|
title: historySidebarOpen ? t.toolbar.closeHistory : t.toolbar.openHistory,
|
|
@@ -2483,7 +2484,7 @@ const Toolbar = () => {
|
|
|
2483
2484
|
}
|
|
2484
2485
|
) })
|
|
2485
2486
|
] }),
|
|
2486
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
2487
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-hf-row", children: [
|
|
2487
2488
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2488
2489
|
HeaderFooterToggle,
|
|
2489
2490
|
{
|
|
@@ -2526,15 +2527,12 @@ const ToolbarIconButton = ({
|
|
|
2526
2527
|
disabled,
|
|
2527
2528
|
onMouseDown: (e) => e.preventDefault(),
|
|
2528
2529
|
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
|
-
`,
|
|
2530
|
+
className: `lex4-toolbar-btn${active ? " active" : ""}`,
|
|
2533
2531
|
"data-testid": testId,
|
|
2534
2532
|
children
|
|
2535
2533
|
}
|
|
2536
2534
|
);
|
|
2537
|
-
const Divider = () => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
2535
|
+
const Divider = () => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-toolbar-separator" });
|
|
2538
2536
|
function computeBodyHeight(headerHeight, footerHeight) {
|
|
2539
2537
|
const verticalMargins = PAGE_MARGIN_PX * 2;
|
|
2540
2538
|
return A4_HEIGHT_PX - headerHeight - footerHeight - verticalMargins;
|
|
@@ -2841,33 +2839,33 @@ function usePagination(document2, dispatch) {
|
|
|
2841
2839
|
};
|
|
2842
2840
|
}
|
|
2843
2841
|
const lexicalTheme = {
|
|
2844
|
-
root: "lex4-root
|
|
2845
|
-
paragraph: "lex4-paragraph
|
|
2842
|
+
root: "lex4-root",
|
|
2843
|
+
paragraph: "lex4-paragraph",
|
|
2846
2844
|
heading: {
|
|
2847
|
-
h1: "
|
|
2848
|
-
h2: "
|
|
2849
|
-
h3: "
|
|
2850
|
-
h4: "
|
|
2851
|
-
h5: "
|
|
2845
|
+
h1: "lex4-heading lex4-heading-h1",
|
|
2846
|
+
h2: "lex4-heading lex4-heading-h2",
|
|
2847
|
+
h3: "lex4-heading lex4-heading-h3",
|
|
2848
|
+
h4: "lex4-heading lex4-heading-h4",
|
|
2849
|
+
h5: "lex4-heading lex4-heading-h5"
|
|
2852
2850
|
},
|
|
2853
2851
|
text: {
|
|
2854
|
-
bold: "
|
|
2855
|
-
italic: "italic",
|
|
2856
|
-
underline: "underline",
|
|
2857
|
-
strikethrough: "
|
|
2858
|
-
underlineStrikethrough: "underline
|
|
2852
|
+
bold: "lex4-text-bold",
|
|
2853
|
+
italic: "lex4-text-italic",
|
|
2854
|
+
underline: "lex4-text-underline",
|
|
2855
|
+
strikethrough: "lex4-text-strikethrough",
|
|
2856
|
+
underlineStrikethrough: "lex4-text-underline lex4-text-strikethrough"
|
|
2859
2857
|
},
|
|
2860
2858
|
list: {
|
|
2861
2859
|
nested: {
|
|
2862
|
-
listitem: "
|
|
2860
|
+
listitem: "lex4-listitem-nested"
|
|
2863
2861
|
},
|
|
2864
|
-
ol: "list
|
|
2865
|
-
ul: "list
|
|
2862
|
+
ol: "lex4-list lex4-list-ordered",
|
|
2863
|
+
ul: "lex4-list lex4-list-unordered",
|
|
2866
2864
|
listitem: "lex4-listitem",
|
|
2867
2865
|
listitemChecked: "lex4-listitem-checked",
|
|
2868
2866
|
listitemUnchecked: "lex4-listitem-unchecked"
|
|
2869
2867
|
},
|
|
2870
|
-
quote: "
|
|
2868
|
+
quote: "lex4-quote"
|
|
2871
2869
|
};
|
|
2872
2870
|
const DEFAULT_NODES = [richText.HeadingNode, richText.QuoteNode, list.ListNode, list.ListItemNode];
|
|
2873
2871
|
function createEditorConfig(mode, pageId, extraNodes = [], themeOverrides = {}) {
|
|
@@ -3758,8 +3756,7 @@ const PageBody = ({
|
|
|
3758
3756
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3759
3757
|
"div",
|
|
3760
3758
|
{
|
|
3761
|
-
className: "lex4-page-body
|
|
3762
|
-
style: { overflow: "hidden" },
|
|
3759
|
+
className: "lex4-page-body",
|
|
3763
3760
|
"data-testid": `page-body-${pageId}`,
|
|
3764
3761
|
onFocus,
|
|
3765
3762
|
children: /* @__PURE__ */ jsxRuntime.jsxs(LexicalComposer.LexicalComposer, { initialConfig: config, children: [
|
|
@@ -3769,11 +3766,10 @@ const PageBody = ({
|
|
|
3769
3766
|
contentEditable: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3770
3767
|
LexicalContentEditable.ContentEditable,
|
|
3771
3768
|
{
|
|
3772
|
-
className: "
|
|
3773
|
-
style: { overflow: "visible" }
|
|
3769
|
+
className: "lex4-page-body-editable"
|
|
3774
3770
|
}
|
|
3775
3771
|
),
|
|
3776
|
-
placeholder: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
3772
|
+
placeholder: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-page-placeholder", children: t.body.placeholder }),
|
|
3777
3773
|
ErrorBoundary: LexicalErrorBoundary.LexicalErrorBoundary
|
|
3778
3774
|
}
|
|
3779
3775
|
),
|
|
@@ -3901,7 +3897,7 @@ const PageHeader = ({
|
|
|
3901
3897
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3902
3898
|
"div",
|
|
3903
3899
|
{
|
|
3904
|
-
className: "lex4-page-header
|
|
3900
|
+
className: "lex4-page-header",
|
|
3905
3901
|
style: { maxHeight: MAX_HEADER_HEIGHT_PX, overflow: "clip" },
|
|
3906
3902
|
"data-testid": `page-header-${pageId}`,
|
|
3907
3903
|
children: [
|
|
@@ -3913,10 +3909,10 @@ const PageHeader = ({
|
|
|
3913
3909
|
LexicalContentEditable.ContentEditable,
|
|
3914
3910
|
{
|
|
3915
3911
|
ref: contentRef,
|
|
3916
|
-
className: `
|
|
3912
|
+
className: `lex4-page-hf-editable${hasPageCounter ? " lex4-page-hf-narrow" : ""}`
|
|
3917
3913
|
}
|
|
3918
3914
|
),
|
|
3919
|
-
placeholder: /* @__PURE__ */ jsxRuntime.jsx("div", { className: `
|
|
3915
|
+
placeholder: /* @__PURE__ */ jsxRuntime.jsx("div", { className: `lex4-page-hf-placeholder${hasPageCounter ? " lex4-page-hf-narrow" : ""}`, children: t.header.placeholder }),
|
|
3920
3916
|
ErrorBoundary: LexicalErrorBoundary.LexicalErrorBoundary
|
|
3921
3917
|
}
|
|
3922
3918
|
),
|
|
@@ -3928,7 +3924,7 @@ const PageHeader = ({
|
|
|
3928
3924
|
pageCounterLabel && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3929
3925
|
"div",
|
|
3930
3926
|
{
|
|
3931
|
-
className: "
|
|
3927
|
+
className: "lex4-page-counter",
|
|
3932
3928
|
"data-testid": `page-counter-header-${pageId}`,
|
|
3933
3929
|
children: pageCounterLabel
|
|
3934
3930
|
}
|
|
@@ -3981,7 +3977,7 @@ const PageFooter = ({
|
|
|
3981
3977
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3982
3978
|
"div",
|
|
3983
3979
|
{
|
|
3984
|
-
className: "lex4-page-footer
|
|
3980
|
+
className: "lex4-page-footer",
|
|
3985
3981
|
style: { maxHeight: MAX_FOOTER_HEIGHT_PX, overflow: "clip" },
|
|
3986
3982
|
"data-testid": `page-footer-${pageId}`,
|
|
3987
3983
|
children: [
|
|
@@ -3993,10 +3989,10 @@ const PageFooter = ({
|
|
|
3993
3989
|
LexicalContentEditable.ContentEditable,
|
|
3994
3990
|
{
|
|
3995
3991
|
ref: contentRef,
|
|
3996
|
-
className: `
|
|
3992
|
+
className: `lex4-page-hf-editable${hasPageCounter ? " lex4-page-hf-narrow" : ""}`
|
|
3997
3993
|
}
|
|
3998
3994
|
),
|
|
3999
|
-
placeholder: /* @__PURE__ */ jsxRuntime.jsx("div", { className: `
|
|
3995
|
+
placeholder: /* @__PURE__ */ jsxRuntime.jsx("div", { className: `lex4-page-hf-placeholder${hasPageCounter ? " lex4-page-hf-narrow" : ""}`, children: t.footer.placeholder }),
|
|
4000
3996
|
ErrorBoundary: LexicalErrorBoundary.LexicalErrorBoundary
|
|
4001
3997
|
}
|
|
4002
3998
|
),
|
|
@@ -4008,7 +4004,7 @@ const PageFooter = ({
|
|
|
4008
4004
|
pageCounterLabel && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4009
4005
|
"div",
|
|
4010
4006
|
{
|
|
4011
|
-
className: "
|
|
4007
|
+
className: "lex4-page-counter",
|
|
4012
4008
|
"data-testid": `page-counter-footer-${pageId}`,
|
|
4013
4009
|
children: pageCounterLabel
|
|
4014
4010
|
}
|
|
@@ -4066,7 +4062,7 @@ const PageView = React.memo(({
|
|
|
4066
4062
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4067
4063
|
"div",
|
|
4068
4064
|
{
|
|
4069
|
-
className: "lex4-page
|
|
4065
|
+
className: "lex4-page",
|
|
4070
4066
|
style: {
|
|
4071
4067
|
width: A4_WIDTH_PX,
|
|
4072
4068
|
height: A4_HEIGHT_PX,
|
|
@@ -4351,7 +4347,7 @@ const DocumentView = () => {
|
|
|
4351
4347
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4352
4348
|
"div",
|
|
4353
4349
|
{
|
|
4354
|
-
className: "lex4-document-view
|
|
4350
|
+
className: "lex4-document-view",
|
|
4355
4351
|
"data-testid": "document-view",
|
|
4356
4352
|
tabIndex: -1,
|
|
4357
4353
|
children: document2.pages.map((page, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -4370,6 +4366,247 @@ const DocumentView = () => {
|
|
|
4370
4366
|
}
|
|
4371
4367
|
);
|
|
4372
4368
|
};
|
|
4369
|
+
const AST_VERSION = "1.0.0";
|
|
4370
|
+
const IS_BOLD = 1;
|
|
4371
|
+
const IS_ITALIC = 2;
|
|
4372
|
+
const IS_STRIKETHROUGH = 4;
|
|
4373
|
+
const IS_UNDERLINE = 8;
|
|
4374
|
+
function decodeFormatBitmask(format) {
|
|
4375
|
+
const marks = {};
|
|
4376
|
+
if (format & IS_BOLD) marks.bold = true;
|
|
4377
|
+
if (format & IS_ITALIC) marks.italic = true;
|
|
4378
|
+
if (format & IS_UNDERLINE) marks.underline = true;
|
|
4379
|
+
if (format & IS_STRIKETHROUGH) marks.strikethrough = true;
|
|
4380
|
+
return marks;
|
|
4381
|
+
}
|
|
4382
|
+
function extractFontFamily(style) {
|
|
4383
|
+
const match = style.match(/font-family:\s*([^;]+)/);
|
|
4384
|
+
return match ? match[1].trim().replace(/['"]/g, "") : void 0;
|
|
4385
|
+
}
|
|
4386
|
+
function extractFontSizePt(style) {
|
|
4387
|
+
const match = style.match(/font-size:\s*(\d+(?:\.\d+)?)\s*pt/);
|
|
4388
|
+
return match ? parseFloat(match[1]) : void 0;
|
|
4389
|
+
}
|
|
4390
|
+
function buildTextMarks(format, style) {
|
|
4391
|
+
const formatMarks = decodeFormatBitmask(format);
|
|
4392
|
+
const fontFamily = style ? extractFontFamily(style) : void 0;
|
|
4393
|
+
const fontSize = style ? extractFontSizePt(style) : void 0;
|
|
4394
|
+
const marks = {
|
|
4395
|
+
...formatMarks,
|
|
4396
|
+
...fontFamily ? { fontFamily } : {},
|
|
4397
|
+
...fontSize ? { fontSize } : {}
|
|
4398
|
+
};
|
|
4399
|
+
return Object.keys(marks).length > 0 ? marks : void 0;
|
|
4400
|
+
}
|
|
4401
|
+
function mapInlineNode(node) {
|
|
4402
|
+
switch (node.type) {
|
|
4403
|
+
case "text":
|
|
4404
|
+
return mapTextNode(node);
|
|
4405
|
+
case "variable-node":
|
|
4406
|
+
return mapVariableNode(node);
|
|
4407
|
+
case "linebreak":
|
|
4408
|
+
return mapLineBreak();
|
|
4409
|
+
default:
|
|
4410
|
+
return { type: "text", text: "" };
|
|
4411
|
+
}
|
|
4412
|
+
}
|
|
4413
|
+
function mapTextNode(node) {
|
|
4414
|
+
const marks = buildTextMarks(node.format, node.style);
|
|
4415
|
+
return {
|
|
4416
|
+
type: "text",
|
|
4417
|
+
text: node.text,
|
|
4418
|
+
...marks ? { marks } : {}
|
|
4419
|
+
};
|
|
4420
|
+
}
|
|
4421
|
+
function mapVariableNode(node) {
|
|
4422
|
+
return {
|
|
4423
|
+
type: "variable",
|
|
4424
|
+
key: node.variableKey
|
|
4425
|
+
};
|
|
4426
|
+
}
|
|
4427
|
+
function mapLineBreak() {
|
|
4428
|
+
return { type: "linebreak" };
|
|
4429
|
+
}
|
|
4430
|
+
function mapInlineNodes(nodes) {
|
|
4431
|
+
return nodes.map(mapInlineNode);
|
|
4432
|
+
}
|
|
4433
|
+
const ALIGN_LEFT = 1;
|
|
4434
|
+
const ALIGN_CENTER = 2;
|
|
4435
|
+
const ALIGN_RIGHT = 3;
|
|
4436
|
+
const ALIGN_JUSTIFY = 4;
|
|
4437
|
+
function decodeAlignment(format) {
|
|
4438
|
+
if (typeof format === "string") {
|
|
4439
|
+
if (["left", "center", "right", "justify"].includes(format)) {
|
|
4440
|
+
return format;
|
|
4441
|
+
}
|
|
4442
|
+
return void 0;
|
|
4443
|
+
}
|
|
4444
|
+
if (typeof format !== "number" || format === 0) return void 0;
|
|
4445
|
+
switch (format) {
|
|
4446
|
+
case ALIGN_LEFT:
|
|
4447
|
+
return "left";
|
|
4448
|
+
case ALIGN_CENTER:
|
|
4449
|
+
return "center";
|
|
4450
|
+
case ALIGN_RIGHT:
|
|
4451
|
+
return "right";
|
|
4452
|
+
case ALIGN_JUSTIFY:
|
|
4453
|
+
return "justify";
|
|
4454
|
+
default:
|
|
4455
|
+
return void 0;
|
|
4456
|
+
}
|
|
4457
|
+
}
|
|
4458
|
+
function mapBlockNode(node) {
|
|
4459
|
+
switch (node.type) {
|
|
4460
|
+
case "paragraph":
|
|
4461
|
+
return mapParagraph(node);
|
|
4462
|
+
case "heading":
|
|
4463
|
+
return mapHeading(node);
|
|
4464
|
+
case "list":
|
|
4465
|
+
return mapList(node);
|
|
4466
|
+
case "quote":
|
|
4467
|
+
return mapBlockQuote(node);
|
|
4468
|
+
default:
|
|
4469
|
+
return {
|
|
4470
|
+
type: "paragraph",
|
|
4471
|
+
children: mapInlineChildren(node)
|
|
4472
|
+
};
|
|
4473
|
+
}
|
|
4474
|
+
}
|
|
4475
|
+
function mapParagraph(node) {
|
|
4476
|
+
const alignment = decodeAlignment(node.format);
|
|
4477
|
+
const indent = node.indent && node.indent > 0 ? node.indent : void 0;
|
|
4478
|
+
return {
|
|
4479
|
+
type: "paragraph",
|
|
4480
|
+
...alignment ? { alignment } : {},
|
|
4481
|
+
...indent ? { indent } : {},
|
|
4482
|
+
children: mapInlineChildren(node)
|
|
4483
|
+
};
|
|
4484
|
+
}
|
|
4485
|
+
function mapHeading(node) {
|
|
4486
|
+
var _a;
|
|
4487
|
+
const alignment = decodeAlignment(node.format);
|
|
4488
|
+
const tagMatch = (_a = node.tag) == null ? void 0 : _a.match(/^h(\d)$/);
|
|
4489
|
+
const level = tagMatch ? parseInt(tagMatch[1], 10) : 1;
|
|
4490
|
+
return {
|
|
4491
|
+
type: "heading",
|
|
4492
|
+
level,
|
|
4493
|
+
...alignment ? { alignment } : {},
|
|
4494
|
+
children: mapInlineChildren(node)
|
|
4495
|
+
};
|
|
4496
|
+
}
|
|
4497
|
+
function mapList(node) {
|
|
4498
|
+
const listType = node.listType === "number" ? "ordered" : "unordered";
|
|
4499
|
+
const items = (node.children ?? []).filter((c) => c.type === "listitem").map(mapListItem);
|
|
4500
|
+
return {
|
|
4501
|
+
type: "list",
|
|
4502
|
+
listType,
|
|
4503
|
+
items
|
|
4504
|
+
};
|
|
4505
|
+
}
|
|
4506
|
+
function mapListItem(node) {
|
|
4507
|
+
const inlineChildren = [];
|
|
4508
|
+
let nestedList;
|
|
4509
|
+
for (const child of node.children ?? []) {
|
|
4510
|
+
if (child.type === "list") {
|
|
4511
|
+
nestedList = mapList(child);
|
|
4512
|
+
} else {
|
|
4513
|
+
const mapped = mapInlineNodes([child]);
|
|
4514
|
+
inlineChildren.push(...mapped);
|
|
4515
|
+
}
|
|
4516
|
+
}
|
|
4517
|
+
return {
|
|
4518
|
+
type: "list-item",
|
|
4519
|
+
children: inlineChildren,
|
|
4520
|
+
...nestedList ? { nestedList } : {}
|
|
4521
|
+
};
|
|
4522
|
+
}
|
|
4523
|
+
function mapBlockQuote(node) {
|
|
4524
|
+
return {
|
|
4525
|
+
type: "blockquote",
|
|
4526
|
+
children: mapInlineChildren(node)
|
|
4527
|
+
};
|
|
4528
|
+
}
|
|
4529
|
+
function mapInlineChildren(node) {
|
|
4530
|
+
if (!node.children || node.children.length === 0) return [];
|
|
4531
|
+
return mapInlineNodes(node.children);
|
|
4532
|
+
}
|
|
4533
|
+
function mapBlockNodes(nodes) {
|
|
4534
|
+
return nodes.map(mapBlockNode);
|
|
4535
|
+
}
|
|
4536
|
+
function mapEditorStateToContent(state) {
|
|
4537
|
+
if (!state || !state.root || !state.root.children) {
|
|
4538
|
+
return null;
|
|
4539
|
+
}
|
|
4540
|
+
const blocks = mapBlockNodes(state.root.children);
|
|
4541
|
+
return { blocks };
|
|
4542
|
+
}
|
|
4543
|
+
function mapEditorStateToBlocks(state) {
|
|
4544
|
+
if (!state || !state.root || !state.root.children) {
|
|
4545
|
+
return [];
|
|
4546
|
+
}
|
|
4547
|
+
return mapBlockNodes(state.root.children);
|
|
4548
|
+
}
|
|
4549
|
+
const MARGIN_MM = Math.round(PAGE_MARGIN_PX / PX_PER_MM * 10) / 10;
|
|
4550
|
+
function serializeDocument(document2, variableDefinitions = []) {
|
|
4551
|
+
const pages = document2.pages.map(
|
|
4552
|
+
(page, index) => serializePage(page, index)
|
|
4553
|
+
);
|
|
4554
|
+
const metadata = buildMetadata(variableDefinitions);
|
|
4555
|
+
return {
|
|
4556
|
+
version: AST_VERSION,
|
|
4557
|
+
page: {
|
|
4558
|
+
format: "A4",
|
|
4559
|
+
widthMm: 210,
|
|
4560
|
+
heightMm: 297,
|
|
4561
|
+
margins: {
|
|
4562
|
+
topMm: MARGIN_MM,
|
|
4563
|
+
rightMm: MARGIN_MM,
|
|
4564
|
+
bottomMm: MARGIN_MM,
|
|
4565
|
+
leftMm: MARGIN_MM
|
|
4566
|
+
}
|
|
4567
|
+
},
|
|
4568
|
+
headerFooter: {
|
|
4569
|
+
enabled: document2.headerFooterEnabled,
|
|
4570
|
+
pageCounterMode: document2.pageCounterMode,
|
|
4571
|
+
defaultHeader: document2.pages.length > 0 ? mapEditorStateToContent(document2.pages[0].headerState) : null,
|
|
4572
|
+
defaultFooter: document2.pages.length > 0 ? mapEditorStateToContent(document2.pages[0].footerState) : null
|
|
4573
|
+
},
|
|
4574
|
+
pages,
|
|
4575
|
+
metadata
|
|
4576
|
+
};
|
|
4577
|
+
}
|
|
4578
|
+
function serializePage(page, pageIndex) {
|
|
4579
|
+
return {
|
|
4580
|
+
pageIndex,
|
|
4581
|
+
body: mapEditorStateToBlocks(page.bodyState),
|
|
4582
|
+
header: mapEditorStateToContent(page.headerState),
|
|
4583
|
+
footer: mapEditorStateToContent(page.footerState)
|
|
4584
|
+
};
|
|
4585
|
+
}
|
|
4586
|
+
function buildMetadata(variableDefinitions) {
|
|
4587
|
+
const variables = {};
|
|
4588
|
+
for (const def of variableDefinitions) {
|
|
4589
|
+
variables[def.key] = {
|
|
4590
|
+
key: def.key,
|
|
4591
|
+
label: def.label,
|
|
4592
|
+
...def.description ? { description: def.description } : {},
|
|
4593
|
+
...def.valueType ? { valueType: def.valueType } : {},
|
|
4594
|
+
...def.group ? { group: def.group } : {}
|
|
4595
|
+
};
|
|
4596
|
+
}
|
|
4597
|
+
return { variables };
|
|
4598
|
+
}
|
|
4599
|
+
function buildSavePayload(ast, options) {
|
|
4600
|
+
return {
|
|
4601
|
+
document: ast,
|
|
4602
|
+
...(options == null ? void 0 : options.exportTarget) ? { exportTarget: options.exportTarget } : {},
|
|
4603
|
+
...(options == null ? void 0 : options.documentId) ? { documentId: options.documentId } : {},
|
|
4604
|
+
...(options == null ? void 0 : options.metadata) ? { metadata: options.metadata } : {}
|
|
4605
|
+
};
|
|
4606
|
+
}
|
|
4607
|
+
function serializeDocumentJson(ast) {
|
|
4608
|
+
return JSON.stringify(ast, null, 2);
|
|
4609
|
+
}
|
|
4373
4610
|
function selectEntireDocument(rootElement, selectionBuffer) {
|
|
4374
4611
|
if (!rootElement || !selectionBuffer) {
|
|
4375
4612
|
return;
|
|
@@ -4393,6 +4630,7 @@ function isFormFieldTarget(target) {
|
|
|
4393
4630
|
}
|
|
4394
4631
|
const EditorChrome = ({
|
|
4395
4632
|
captureHistoryShortcutsOnWindow,
|
|
4633
|
+
onSave,
|
|
4396
4634
|
className
|
|
4397
4635
|
}) => {
|
|
4398
4636
|
const {
|
|
@@ -4403,7 +4641,7 @@ const EditorChrome = ({
|
|
|
4403
4641
|
undo,
|
|
4404
4642
|
redo
|
|
4405
4643
|
} = useDocument();
|
|
4406
|
-
const { sidePanels } = useExtensions();
|
|
4644
|
+
const { sidePanels, cssVariables, rootClassNames } = useExtensions();
|
|
4407
4645
|
const rootRef = React.useRef(null);
|
|
4408
4646
|
const selectionBufferRef = React.useRef(null);
|
|
4409
4647
|
const clearGlobalSelection = React.useCallback(() => {
|
|
@@ -4465,12 +4703,22 @@ const EditorChrome = ({
|
|
|
4465
4703
|
});
|
|
4466
4704
|
return;
|
|
4467
4705
|
}
|
|
4706
|
+
if (key === "s" && onSave) {
|
|
4707
|
+
event.preventDefault();
|
|
4708
|
+
event.stopPropagation();
|
|
4709
|
+
const ast = serializeDocument(document2);
|
|
4710
|
+
const json = serializeDocumentJson(ast);
|
|
4711
|
+
onSave({ document: document2, ast, json });
|
|
4712
|
+
return;
|
|
4713
|
+
}
|
|
4468
4714
|
if (handleHistoryShortcut(event)) {
|
|
4469
4715
|
return;
|
|
4470
4716
|
}
|
|
4471
4717
|
}, [
|
|
4718
|
+
document2,
|
|
4472
4719
|
dispatch,
|
|
4473
4720
|
handleHistoryShortcut,
|
|
4721
|
+
onSave,
|
|
4474
4722
|
setGlobalSelectionActive
|
|
4475
4723
|
]);
|
|
4476
4724
|
const handleMouseDownCapture = React.useCallback((event) => {
|
|
@@ -4488,9 +4736,13 @@ const EditorChrome = ({
|
|
|
4488
4736
|
const editableRoots = ((_a = rootRef.current) == null ? void 0 : _a.querySelectorAll(
|
|
4489
4737
|
'[data-testid^="page-body-"] [data-lexical-editor="true"]'
|
|
4490
4738
|
)) ?? [];
|
|
4739
|
+
const root = rootRef.current;
|
|
4740
|
+
const styles = root ? getComputedStyle(root) : null;
|
|
4741
|
+
const selBg = (styles == null ? void 0 : styles.getPropertyValue("--lex4-color-selection-bg").trim()) || GLOBAL_SELECTION_BACKGROUND;
|
|
4742
|
+
const selFg = (styles == null ? void 0 : styles.getPropertyValue("--lex4-color-selection-text").trim()) || GLOBAL_SELECTION_FOREGROUND;
|
|
4491
4743
|
editableRoots.forEach((editableRoot) => {
|
|
4492
|
-
editableRoot.style.backgroundColor = globalSelectionActive ?
|
|
4493
|
-
editableRoot.style.color = globalSelectionActive ?
|
|
4744
|
+
editableRoot.style.backgroundColor = globalSelectionActive ? selBg : "";
|
|
4745
|
+
editableRoot.style.color = globalSelectionActive ? selFg : "";
|
|
4494
4746
|
editableRoot.style.caretColor = globalSelectionActive ? "transparent" : "";
|
|
4495
4747
|
});
|
|
4496
4748
|
}, [globalSelectionActive, document2.pages.length]);
|
|
@@ -4523,11 +4775,14 @@ const EditorChrome = ({
|
|
|
4523
4775
|
window.removeEventListener("beforeinput", handleWindowBeforeInput, { capture: true });
|
|
4524
4776
|
};
|
|
4525
4777
|
}, [captureHistoryShortcutsOnWindow, clearGlobalSelection, handleHistoryShortcut, redo, undo]);
|
|
4778
|
+
const rootClassName = ["lex4-editor", ...rootClassNames, className].filter(Boolean).join(" ");
|
|
4779
|
+
const extensionStyle = Object.keys(cssVariables).length > 0 ? cssVariables : void 0;
|
|
4526
4780
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4527
4781
|
"div",
|
|
4528
4782
|
{
|
|
4529
4783
|
ref: rootRef,
|
|
4530
|
-
className:
|
|
4784
|
+
className: rootClassName,
|
|
4785
|
+
style: extensionStyle,
|
|
4531
4786
|
"data-testid": "lex4-editor",
|
|
4532
4787
|
"data-global-selection-active": globalSelectionActive ? "true" : "false",
|
|
4533
4788
|
onKeyDownCapture: handleKeyDownCapture,
|
|
@@ -4541,12 +4796,12 @@ const EditorChrome = ({
|
|
|
4541
4796
|
"data-testid": "global-selection-buffer",
|
|
4542
4797
|
readOnly: true,
|
|
4543
4798
|
tabIndex: -1,
|
|
4544
|
-
className: "
|
|
4799
|
+
className: "lex4-selection-buffer"
|
|
4545
4800
|
}
|
|
4546
4801
|
),
|
|
4547
4802
|
/* @__PURE__ */ jsxRuntime.jsx(Toolbar, {}),
|
|
4548
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
4549
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
4803
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-canvas", children: [
|
|
4804
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-canvas-scroll", children: /* @__PURE__ */ jsxRuntime.jsx(DocumentView, {}) }),
|
|
4550
4805
|
sidePanels.map((Panel, idx) => /* @__PURE__ */ jsxRuntime.jsx(Panel, {}, idx)),
|
|
4551
4806
|
/* @__PURE__ */ jsxRuntime.jsx(HistorySidebar, {})
|
|
4552
4807
|
] })
|
|
@@ -4554,7 +4809,7 @@ const EditorChrome = ({
|
|
|
4554
4809
|
}
|
|
4555
4810
|
);
|
|
4556
4811
|
};
|
|
4557
|
-
const EditorWithHandle = React.forwardRef(({ captureHistoryShortcutsOnWindow, className }, ref) => {
|
|
4812
|
+
const EditorWithHandle = React.forwardRef(({ captureHistoryShortcutsOnWindow, onSave, className }, ref) => {
|
|
4558
4813
|
const { document: doc, activeEditor } = useDocument();
|
|
4559
4814
|
const { handleFactories } = useExtensions();
|
|
4560
4815
|
const getDocument = React.useCallback(() => doc, [doc]);
|
|
@@ -4572,6 +4827,7 @@ const EditorWithHandle = React.forwardRef(({ captureHistoryShortcutsOnWindow, cl
|
|
|
4572
4827
|
EditorChrome,
|
|
4573
4828
|
{
|
|
4574
4829
|
captureHistoryShortcutsOnWindow,
|
|
4830
|
+
onSave,
|
|
4575
4831
|
className
|
|
4576
4832
|
}
|
|
4577
4833
|
);
|
|
@@ -4581,6 +4837,7 @@ const Lex4Editor = React.forwardRef(({
|
|
|
4581
4837
|
captureHistoryShortcutsOnWindow = true,
|
|
4582
4838
|
initialDocument,
|
|
4583
4839
|
onDocumentChange,
|
|
4840
|
+
onSave,
|
|
4584
4841
|
extensions,
|
|
4585
4842
|
translations,
|
|
4586
4843
|
className
|
|
@@ -4595,6 +4852,7 @@ const Lex4Editor = React.forwardRef(({
|
|
|
4595
4852
|
{
|
|
4596
4853
|
ref,
|
|
4597
4854
|
captureHistoryShortcutsOnWindow,
|
|
4855
|
+
onSave,
|
|
4598
4856
|
className
|
|
4599
4857
|
}
|
|
4600
4858
|
)
|
|
@@ -4667,247 +4925,6 @@ function useHeaderFooter(maxHeight, onHeightChange) {
|
|
|
4667
4925
|
}, []);
|
|
4668
4926
|
return { attachRef };
|
|
4669
4927
|
}
|
|
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
4928
|
function astExtension() {
|
|
4912
4929
|
return {
|
|
4913
4930
|
name: "ast",
|
|
@@ -5033,7 +5050,7 @@ function VariableChip({ variableKey }) {
|
|
|
5033
5050
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5034
5051
|
"span",
|
|
5035
5052
|
{
|
|
5036
|
-
className: "lex4-variable-chip
|
|
5053
|
+
className: "lex4-variable-chip",
|
|
5037
5054
|
"data-testid": `variable-chip-${variableKey}`,
|
|
5038
5055
|
title: variableKey,
|
|
5039
5056
|
children: label
|
|
@@ -5106,12 +5123,12 @@ const VariablePicker = ({ onInsert, disabled = false }) => {
|
|
|
5106
5123
|
document.addEventListener("mousedown", handler);
|
|
5107
5124
|
return () => document.removeEventListener("mousedown", handler);
|
|
5108
5125
|
}, [open]);
|
|
5109
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: "
|
|
5126
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: "lex4-variable-picker", children: [
|
|
5110
5127
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5111
5128
|
"button",
|
|
5112
5129
|
{
|
|
5113
5130
|
type: "button",
|
|
5114
|
-
className: "
|
|
5131
|
+
className: "lex4-variable-picker-btn",
|
|
5115
5132
|
"data-testid": "variable-picker-button",
|
|
5116
5133
|
disabled: disabled || definitions.length === 0,
|
|
5117
5134
|
onClick: () => setOpen(!open),
|
|
@@ -5122,14 +5139,13 @@ const VariablePicker = ({ onInsert, disabled = false }) => {
|
|
|
5122
5139
|
open && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5123
5140
|
"div",
|
|
5124
5141
|
{
|
|
5125
|
-
className: "
|
|
5142
|
+
className: "lex4-variable-picker-dropdown",
|
|
5126
5143
|
"data-testid": "variable-picker-dropdown",
|
|
5127
5144
|
children: [
|
|
5128
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
5145
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-variable-picker-search", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5129
5146
|
"input",
|
|
5130
5147
|
{
|
|
5131
5148
|
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
5149
|
placeholder: "Search variables...",
|
|
5134
5150
|
"data-testid": "variable-picker-search",
|
|
5135
5151
|
value: filter,
|
|
@@ -5137,20 +5153,20 @@ const VariablePicker = ({ onInsert, disabled = false }) => {
|
|
|
5137
5153
|
autoFocus: true
|
|
5138
5154
|
}
|
|
5139
5155
|
) }),
|
|
5140
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
5141
|
-
Object.keys(grouped).length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
5156
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-variable-picker-list", children: [
|
|
5157
|
+
Object.keys(grouped).length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-variable-picker-empty", children: "No variables found" }),
|
|
5142
5158
|
Object.entries(grouped).map(([group, defs]) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
5143
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
5159
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-variable-picker-group-label", children: group }),
|
|
5144
5160
|
defs.map((def) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5145
5161
|
"button",
|
|
5146
5162
|
{
|
|
5147
5163
|
type: "button",
|
|
5148
|
-
className: "
|
|
5164
|
+
className: "lex4-variable-picker-option",
|
|
5149
5165
|
"data-testid": `variable-option-${def.key}`,
|
|
5150
5166
|
onClick: () => handleInsert(def.key),
|
|
5151
5167
|
children: [
|
|
5152
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "
|
|
5153
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "
|
|
5168
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "lex4-variable-picker-key", children: `{{${def.key}}}` }),
|
|
5169
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "lex4-variable-picker-label", children: def.label })
|
|
5154
5170
|
]
|
|
5155
5171
|
},
|
|
5156
5172
|
def.key
|
|
@@ -5208,20 +5224,20 @@ const VariablePanel = ({ open, onClose }) => {
|
|
|
5208
5224
|
"button",
|
|
5209
5225
|
{
|
|
5210
5226
|
type: "button",
|
|
5211
|
-
className: "
|
|
5227
|
+
className: "lex4-sidebar-action-btn",
|
|
5212
5228
|
title: t.variables.refreshVariables,
|
|
5213
5229
|
"data-testid": "btn-refresh-variables",
|
|
5214
5230
|
children: /* @__PURE__ */ jsxRuntime.jsx(RefreshCw, { size: 12 })
|
|
5215
5231
|
}
|
|
5216
5232
|
),
|
|
5217
5233
|
children: [
|
|
5218
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
5219
|
-
/* @__PURE__ */ jsxRuntime.jsx(Search, { size: 14, className: "
|
|
5234
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-variable-search-container", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-variable-search-wrapper", children: [
|
|
5235
|
+
/* @__PURE__ */ jsxRuntime.jsx(Search, { size: 14, className: "lex4-variable-search-icon" }),
|
|
5220
5236
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5221
5237
|
"input",
|
|
5222
5238
|
{
|
|
5223
5239
|
type: "text",
|
|
5224
|
-
className: "
|
|
5240
|
+
className: "lex4-variable-search-input",
|
|
5225
5241
|
placeholder: t.variables.searchPlaceholder,
|
|
5226
5242
|
"data-testid": "variable-panel-search",
|
|
5227
5243
|
value: filter,
|
|
@@ -5229,25 +5245,19 @@ const VariablePanel = ({ open, onClose }) => {
|
|
|
5229
5245
|
}
|
|
5230
5246
|
)
|
|
5231
5247
|
] }) }),
|
|
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: "
|
|
5248
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lex4-variable-list", children: [
|
|
5249
|
+
Object.keys(grouped).length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lex4-variable-list-empty", children: t.variables.noVariablesFound }),
|
|
5250
|
+
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
5251
|
"button",
|
|
5236
5252
|
{
|
|
5237
5253
|
type: "button",
|
|
5238
|
-
className: "
|
|
5254
|
+
className: "lex4-variable-list-item",
|
|
5239
5255
|
"data-testid": `variable-panel-${def.key}`,
|
|
5240
5256
|
onClick: () => handleInsert(def.key),
|
|
5241
5257
|
disabled: !activeEditor,
|
|
5242
5258
|
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 })
|
|
5259
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "lex4-variable-badge", children: def.label }),
|
|
5260
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "lex4-variable-group-label", children: group })
|
|
5251
5261
|
]
|
|
5252
5262
|
},
|
|
5253
5263
|
def.key
|
|
@@ -5301,10 +5311,7 @@ const VariablePanelToggle = () => {
|
|
|
5301
5311
|
"aria-label": panelOpen ? t.variables.closePanel : t.variables.openPanel,
|
|
5302
5312
|
onMouseDown: (e) => e.preventDefault(),
|
|
5303
5313
|
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
|
-
`,
|
|
5314
|
+
className: `lex4-toolbar-btn${panelOpen ? " active" : ""}`,
|
|
5308
5315
|
"data-testid": "toggle-variable-panel",
|
|
5309
5316
|
children: /* @__PURE__ */ jsxRuntime.jsx(Braces, { size: 15 })
|
|
5310
5317
|
}
|