@lumir-company/editor 0.4.13 → 0.4.15
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 +1588 -1511
- package/dist/api/link-preview.js.map +1 -1
- package/dist/api/link-preview.mjs.map +1 -1
- package/dist/index.js +1124 -128
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1138 -120
- package/dist/index.mjs.map +1 -1
- package/dist/style.css +1241 -1041
- package/package.json +96 -94
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// src/components/LumirEditor.tsx
|
|
4
|
-
import { useEffect as
|
|
4
|
+
import { useEffect as useEffect10, useMemo as useMemo6, useCallback as useCallback18, useState as useState10, useRef as useRef11 } from "react";
|
|
5
5
|
import {
|
|
6
6
|
useCreateBlockNote,
|
|
7
7
|
SideMenu as BlockSideMenu,
|
|
@@ -11,14 +11,15 @@ import {
|
|
|
11
11
|
getDefaultReactSlashMenuItems,
|
|
12
12
|
LinkToolbarController,
|
|
13
13
|
FormattingToolbarController,
|
|
14
|
-
useBlockNoteEditor as
|
|
15
|
-
useComponentsContext as
|
|
14
|
+
useBlockNoteEditor as useBlockNoteEditor5,
|
|
15
|
+
useComponentsContext as useComponentsContext4,
|
|
16
16
|
EditLinkButton,
|
|
17
17
|
OpenLinkButton,
|
|
18
18
|
DeleteLinkButton
|
|
19
19
|
} from "@blocknote/react";
|
|
20
20
|
import { BlockNoteView } from "@blocknote/mantine";
|
|
21
21
|
import { insertOrUpdateBlock } from "@blocknote/core";
|
|
22
|
+
import { ko, en } from "@blocknote/core/locales";
|
|
22
23
|
|
|
23
24
|
// src/utils/cn.ts
|
|
24
25
|
function cn(...inputs) {
|
|
@@ -1814,6 +1815,66 @@ var TextStyleButton = ({
|
|
|
1814
1815
|
|
|
1815
1816
|
// src/components/FloatingMenu/components/AlignButton.tsx
|
|
1816
1817
|
import { useCallback as useCallback6 } from "react";
|
|
1818
|
+
|
|
1819
|
+
// src/utils/prosemirror-table-utils.ts
|
|
1820
|
+
function getSelectedCellPositions(editor) {
|
|
1821
|
+
const tiptap = editor._tiptapEditor;
|
|
1822
|
+
if (!tiptap) return [];
|
|
1823
|
+
const { state } = tiptap;
|
|
1824
|
+
const { selection } = state;
|
|
1825
|
+
if (typeof selection.forEachCell === "function") {
|
|
1826
|
+
const positions = [];
|
|
1827
|
+
selection.forEachCell((_node, pos) => {
|
|
1828
|
+
positions.push(pos);
|
|
1829
|
+
});
|
|
1830
|
+
return positions;
|
|
1831
|
+
}
|
|
1832
|
+
const $pos = selection.$from;
|
|
1833
|
+
for (let depth = $pos.depth; depth > 0; depth--) {
|
|
1834
|
+
const node = $pos.node(depth);
|
|
1835
|
+
if (node.type.name === "tableCell" || node.type.name === "tableHeader") {
|
|
1836
|
+
return [$pos.before(depth)];
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
return [];
|
|
1840
|
+
}
|
|
1841
|
+
function setCellAttrAtPositions(editor, positions, attr, value) {
|
|
1842
|
+
const tiptap = editor?._tiptapEditor;
|
|
1843
|
+
if (!tiptap || positions.length === 0) return false;
|
|
1844
|
+
let tr = tiptap.state.tr;
|
|
1845
|
+
let changed = false;
|
|
1846
|
+
for (const pos of positions) {
|
|
1847
|
+
const node = tr.doc.nodeAt(pos);
|
|
1848
|
+
if (node && (node.type.name === "tableCell" || node.type.name === "tableHeader")) {
|
|
1849
|
+
tr = tr.setNodeMarkup(pos, void 0, { ...node.attrs, [attr]: value });
|
|
1850
|
+
changed = true;
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
if (changed) {
|
|
1854
|
+
tiptap.view?.dispatch(tr);
|
|
1855
|
+
}
|
|
1856
|
+
return changed;
|
|
1857
|
+
}
|
|
1858
|
+
function setSelectedCellsAttr(editor, attr, value) {
|
|
1859
|
+
return setCellAttrAtPositions(
|
|
1860
|
+
editor,
|
|
1861
|
+
getSelectedCellPositions(editor),
|
|
1862
|
+
attr,
|
|
1863
|
+
value
|
|
1864
|
+
);
|
|
1865
|
+
}
|
|
1866
|
+
function isInTableCell(editor) {
|
|
1867
|
+
return getSelectedCellPositions(editor).length > 0;
|
|
1868
|
+
}
|
|
1869
|
+
function getFirstSelectedCellAttr(editor, attr) {
|
|
1870
|
+
const tiptap = editor?._tiptapEditor;
|
|
1871
|
+
const positions = getSelectedCellPositions(editor);
|
|
1872
|
+
if (!tiptap || positions.length === 0) return void 0;
|
|
1873
|
+
const node = tiptap.state.doc.nodeAt(positions[0]);
|
|
1874
|
+
return node?.attrs?.[attr];
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
// src/components/FloatingMenu/components/AlignButton.tsx
|
|
1817
1878
|
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
1818
1879
|
var iconMap2 = {
|
|
1819
1880
|
left: Icons.alignLeft,
|
|
@@ -1831,6 +1892,9 @@ var AlignButton = ({
|
|
|
1831
1892
|
}) => {
|
|
1832
1893
|
const getCurrentAlignment = () => {
|
|
1833
1894
|
try {
|
|
1895
|
+
if (isInTableCell(editor)) {
|
|
1896
|
+
return getFirstSelectedCellAttr(editor, "textAlignment") || "left";
|
|
1897
|
+
}
|
|
1834
1898
|
const block = editor?.getTextCursorPosition()?.block;
|
|
1835
1899
|
return block?.props?.textAlignment || "left";
|
|
1836
1900
|
} catch {
|
|
@@ -1840,6 +1904,9 @@ var AlignButton = ({
|
|
|
1840
1904
|
const isActive = getCurrentAlignment() === alignment;
|
|
1841
1905
|
const handleClick = useCallback6(() => {
|
|
1842
1906
|
try {
|
|
1907
|
+
if (setSelectedCellsAttr(editor, "textAlignment", alignment)) {
|
|
1908
|
+
return;
|
|
1909
|
+
}
|
|
1843
1910
|
const block = editor?.getTextCursorPosition()?.block;
|
|
1844
1911
|
if (block && editor?.updateBlock) {
|
|
1845
1912
|
editor.updateBlock(block, { props: { textAlignment: alignment } });
|
|
@@ -2005,6 +2072,10 @@ var ColorButton = ({ editor, type }) => {
|
|
|
2005
2072
|
const colors = type === "text" ? TEXT_COLORS : BACKGROUND_COLORS;
|
|
2006
2073
|
const getCurrentColor = useCallback9(() => {
|
|
2007
2074
|
try {
|
|
2075
|
+
if (isInTableCell(editor)) {
|
|
2076
|
+
const attr = type === "text" ? "textColor" : "backgroundColor";
|
|
2077
|
+
return getFirstSelectedCellAttr(editor, attr) || "default";
|
|
2078
|
+
}
|
|
2008
2079
|
const activeStyles = editor?.getActiveStyles?.() || {};
|
|
2009
2080
|
if (type === "text" && activeStyles.textColor) {
|
|
2010
2081
|
return activeStyles.textColor;
|
|
@@ -2034,13 +2105,15 @@ var ColorButton = ({ editor, type }) => {
|
|
|
2034
2105
|
(color) => {
|
|
2035
2106
|
try {
|
|
2036
2107
|
if (!editor) return;
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2108
|
+
const attr = type === "text" ? "textColor" : "backgroundColor";
|
|
2109
|
+
if (!setSelectedCellsAttr(editor, attr, color)) {
|
|
2110
|
+
editor.toggleStyles(
|
|
2111
|
+
type === "text" ? { textColor: color } : { backgroundColor: color }
|
|
2112
|
+
);
|
|
2041
2113
|
}
|
|
2042
2114
|
setCurrentColor(color);
|
|
2043
2115
|
setIsOpen(false);
|
|
2116
|
+
setTimeout(() => editor.focus?.());
|
|
2044
2117
|
} catch (err) {
|
|
2045
2118
|
console.error(`Color apply failed:`, err);
|
|
2046
2119
|
}
|
|
@@ -2847,7 +2920,6 @@ var VerticalAlignmentExtension = Extension.create({
|
|
|
2847
2920
|
import {
|
|
2848
2921
|
BasicTextStyleButton,
|
|
2849
2922
|
BlockTypeSelect as BlockTypeSelect2,
|
|
2850
|
-
ColorStyleButton,
|
|
2851
2923
|
CreateLinkButton,
|
|
2852
2924
|
FileCaptionButton,
|
|
2853
2925
|
FileDeleteButton,
|
|
@@ -2873,31 +2945,6 @@ import {
|
|
|
2873
2945
|
useBlockNoteEditor,
|
|
2874
2946
|
useSelectedBlocks
|
|
2875
2947
|
} from "@blocknote/react";
|
|
2876
|
-
|
|
2877
|
-
// src/utils/prosemirror-table-utils.ts
|
|
2878
|
-
function getSelectedCellPositions(editor) {
|
|
2879
|
-
const tiptap = editor._tiptapEditor;
|
|
2880
|
-
if (!tiptap) return [];
|
|
2881
|
-
const { state } = tiptap;
|
|
2882
|
-
const { selection } = state;
|
|
2883
|
-
if (typeof selection.forEachCell === "function") {
|
|
2884
|
-
const positions = [];
|
|
2885
|
-
selection.forEachCell((_node, pos) => {
|
|
2886
|
-
positions.push(pos);
|
|
2887
|
-
});
|
|
2888
|
-
return positions;
|
|
2889
|
-
}
|
|
2890
|
-
const $pos = selection.$from;
|
|
2891
|
-
for (let depth = $pos.depth; depth > 0; depth--) {
|
|
2892
|
-
const node = $pos.node(depth);
|
|
2893
|
-
if (node.type.name === "tableCell" || node.type.name === "tableHeader") {
|
|
2894
|
-
return [$pos.before(depth)];
|
|
2895
|
-
}
|
|
2896
|
-
}
|
|
2897
|
-
return [];
|
|
2898
|
-
}
|
|
2899
|
-
|
|
2900
|
-
// src/components/TextAlignButtonWithVA.tsx
|
|
2901
2948
|
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
2902
2949
|
var icons = {
|
|
2903
2950
|
left: /* @__PURE__ */ jsx17("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", width: "18", height: "18", children: /* @__PURE__ */ jsx17("path", { d: "M15 15H3v2h12v-2zm0-8H3v2h12V7zM3 13h18v-2H3v2zm0 8h18v-2H3v2zM3 3v2h18V3H3z" }) }),
|
|
@@ -3078,77 +3125,782 @@ var VerticalAlignButton = (props) => {
|
|
|
3078
3125
|
);
|
|
3079
3126
|
};
|
|
3080
3127
|
|
|
3128
|
+
// src/components/color/LumirColorControls.tsx
|
|
3129
|
+
import {
|
|
3130
|
+
isTableCell,
|
|
3131
|
+
mapTableCell as mapTableCell2
|
|
3132
|
+
} from "@blocknote/core";
|
|
3133
|
+
import {
|
|
3134
|
+
SplitButton,
|
|
3135
|
+
useBlockNoteEditor as useBlockNoteEditor3,
|
|
3136
|
+
useComponentsContext as useComponentsContext3,
|
|
3137
|
+
useDictionary,
|
|
3138
|
+
useEditorContentOrSelectionChange,
|
|
3139
|
+
useSelectedBlocks as useSelectedBlocks3
|
|
3140
|
+
} from "@blocknote/react";
|
|
3141
|
+
import { useCallback as useCallback16, useMemo as useMemo3, useRef as useRef9, useState as useState8 } from "react";
|
|
3142
|
+
import { Fragment as Fragment5, jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3143
|
+
var COLORS = [
|
|
3144
|
+
"default",
|
|
3145
|
+
"gray",
|
|
3146
|
+
"brown",
|
|
3147
|
+
"red",
|
|
3148
|
+
"orange",
|
|
3149
|
+
"yellow",
|
|
3150
|
+
"green",
|
|
3151
|
+
"blue",
|
|
3152
|
+
"purple",
|
|
3153
|
+
"pink"
|
|
3154
|
+
];
|
|
3155
|
+
function ColorIcon(props) {
|
|
3156
|
+
const textColor = props.textColor || "default";
|
|
3157
|
+
const backgroundColor = props.backgroundColor || "default";
|
|
3158
|
+
const size = props.size || 16;
|
|
3159
|
+
return /* @__PURE__ */ jsx19(
|
|
3160
|
+
"div",
|
|
3161
|
+
{
|
|
3162
|
+
className: "bn-color-icon",
|
|
3163
|
+
"data-background-color": backgroundColor,
|
|
3164
|
+
"data-text-color": textColor,
|
|
3165
|
+
style: {
|
|
3166
|
+
pointerEvents: "none",
|
|
3167
|
+
fontSize: `${size * 0.75}px`,
|
|
3168
|
+
height: `${size}px`,
|
|
3169
|
+
lineHeight: `${size}px`,
|
|
3170
|
+
textAlign: "center",
|
|
3171
|
+
width: `${size}px`
|
|
3172
|
+
},
|
|
3173
|
+
children: "A"
|
|
3174
|
+
}
|
|
3175
|
+
);
|
|
3176
|
+
}
|
|
3177
|
+
function CellFillIcon({ size = 18 }) {
|
|
3178
|
+
return /* @__PURE__ */ jsx19(
|
|
3179
|
+
"svg",
|
|
3180
|
+
{
|
|
3181
|
+
width: size,
|
|
3182
|
+
height: size,
|
|
3183
|
+
viewBox: "0 0 24 24",
|
|
3184
|
+
fill: "currentColor",
|
|
3185
|
+
style: { pointerEvents: "none" },
|
|
3186
|
+
"aria-hidden": "true",
|
|
3187
|
+
children: /* @__PURE__ */ jsx19("path", { d: "M16.56 8.94 7.62 0 6.21 1.41l2.38 2.38-5.15 5.15c-.59.59-.59 1.54 0 2.12l5.5 5.5c.29.29.68.44 1.06.44s.77-.15 1.06-.44l5.5-5.5c.59-.58.59-1.53 0-2.12zM5.21 10 10 5.21 14.79 10H5.21zM19 11.5s-2 2.17-2 3.5c0 1.1.9 2 2 2s2-.9 2-2c0-1.33-2-3.5-2-3.5z" })
|
|
3188
|
+
}
|
|
3189
|
+
);
|
|
3190
|
+
}
|
|
3191
|
+
function LumirColorPicker(props) {
|
|
3192
|
+
const Components = useComponentsContext3();
|
|
3193
|
+
const dict = useDictionary();
|
|
3194
|
+
return /* @__PURE__ */ jsxs12(Fragment5, { children: [
|
|
3195
|
+
props.text ? /* @__PURE__ */ jsxs12(Fragment5, { children: [
|
|
3196
|
+
/* @__PURE__ */ jsx19(Components.Generic.Menu.Label, { children: props.textTitle ?? dict.color_picker.text_title }),
|
|
3197
|
+
COLORS.map((color) => /* @__PURE__ */ jsx19(
|
|
3198
|
+
Components.Generic.Menu.Item,
|
|
3199
|
+
{
|
|
3200
|
+
onClick: () => {
|
|
3201
|
+
props.onClick?.();
|
|
3202
|
+
props.text.setColor(color);
|
|
3203
|
+
},
|
|
3204
|
+
"data-test": "text-color-" + color,
|
|
3205
|
+
icon: /* @__PURE__ */ jsx19(ColorIcon, { textColor: color, size: props.iconSize }),
|
|
3206
|
+
checked: props.text.color === color,
|
|
3207
|
+
children: dict.color_picker.colors[color]
|
|
3208
|
+
},
|
|
3209
|
+
"text-color-" + color
|
|
3210
|
+
))
|
|
3211
|
+
] }) : null,
|
|
3212
|
+
props.background ? /* @__PURE__ */ jsxs12(Fragment5, { children: [
|
|
3213
|
+
/* @__PURE__ */ jsx19(Components.Generic.Menu.Label, { children: props.backgroundTitle ?? dict.color_picker.background_title }),
|
|
3214
|
+
COLORS.map((color) => /* @__PURE__ */ jsx19(
|
|
3215
|
+
Components.Generic.Menu.Item,
|
|
3216
|
+
{
|
|
3217
|
+
onClick: () => {
|
|
3218
|
+
props.onClick?.();
|
|
3219
|
+
props.background.setColor(color);
|
|
3220
|
+
},
|
|
3221
|
+
"data-test": "background-color-" + color,
|
|
3222
|
+
icon: /* @__PURE__ */ jsx19(ColorIcon, { backgroundColor: color, size: props.iconSize }),
|
|
3223
|
+
checked: props.background.color === color,
|
|
3224
|
+
children: dict.color_picker.colors[color]
|
|
3225
|
+
},
|
|
3226
|
+
"background-color-" + color
|
|
3227
|
+
))
|
|
3228
|
+
] }) : null
|
|
3229
|
+
] });
|
|
3230
|
+
}
|
|
3231
|
+
function LumirColorStyleButton() {
|
|
3232
|
+
const Components = useComponentsContext3();
|
|
3233
|
+
const editor = useBlockNoteEditor3();
|
|
3234
|
+
const ed = editor;
|
|
3235
|
+
const styleSchema = editor.schema.styleSchema;
|
|
3236
|
+
const textColorInSchema = styleSchema.textColor?.type === "textColor" && styleSchema.textColor?.propSchema === "string";
|
|
3237
|
+
const backgroundColorInSchema = styleSchema.backgroundColor?.type === "backgroundColor" && styleSchema.backgroundColor?.propSchema === "string";
|
|
3238
|
+
const selectedBlocks = useSelectedBlocks3(editor);
|
|
3239
|
+
const [currentTextColor, setCurrentTextColor] = useState8(
|
|
3240
|
+
textColorInSchema ? ed.getActiveStyles().textColor || "default" : "default"
|
|
3241
|
+
);
|
|
3242
|
+
const [currentBackgroundColor, setCurrentBackgroundColor] = useState8(
|
|
3243
|
+
backgroundColorInSchema ? ed.getActiveStyles().backgroundColor || "default" : "default"
|
|
3244
|
+
);
|
|
3245
|
+
useEditorContentOrSelectionChange(() => {
|
|
3246
|
+
const active = ed.getActiveStyles();
|
|
3247
|
+
if (textColorInSchema) {
|
|
3248
|
+
setCurrentTextColor(active.textColor || "default");
|
|
3249
|
+
}
|
|
3250
|
+
if (backgroundColorInSchema) {
|
|
3251
|
+
setCurrentBackgroundColor(active.backgroundColor || "default");
|
|
3252
|
+
}
|
|
3253
|
+
}, editor);
|
|
3254
|
+
const setTextColor = useCallback16(
|
|
3255
|
+
(color) => {
|
|
3256
|
+
color === "default" ? ed.removeStyles({ textColor: color }) : ed.addStyles({ textColor: color });
|
|
3257
|
+
setTimeout(() => editor.focus());
|
|
3258
|
+
},
|
|
3259
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3260
|
+
[editor]
|
|
3261
|
+
);
|
|
3262
|
+
const setBackgroundColor = useCallback16(
|
|
3263
|
+
(color) => {
|
|
3264
|
+
color === "default" ? ed.removeStyles({ backgroundColor: color }) : ed.addStyles({ backgroundColor: color });
|
|
3265
|
+
setTimeout(() => editor.focus());
|
|
3266
|
+
},
|
|
3267
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3268
|
+
[editor]
|
|
3269
|
+
);
|
|
3270
|
+
const show = useMemo3(() => {
|
|
3271
|
+
if (!textColorInSchema && !backgroundColorInSchema) {
|
|
3272
|
+
return false;
|
|
3273
|
+
}
|
|
3274
|
+
for (const block of selectedBlocks) {
|
|
3275
|
+
if (block.content !== void 0) {
|
|
3276
|
+
return true;
|
|
3277
|
+
}
|
|
3278
|
+
}
|
|
3279
|
+
return false;
|
|
3280
|
+
}, [backgroundColorInSchema, selectedBlocks, textColorInSchema]);
|
|
3281
|
+
if (!show || !editor.isEditable) {
|
|
3282
|
+
return null;
|
|
3283
|
+
}
|
|
3284
|
+
const tooltip = "\uD14D\uC2A4\uD2B8 \uC0C9\xB7\uBC30\uACBD";
|
|
3285
|
+
return /* @__PURE__ */ jsxs12(Components.Generic.Menu.Root, { children: [
|
|
3286
|
+
/* @__PURE__ */ jsx19(Components.Generic.Menu.Trigger, { children: /* @__PURE__ */ jsx19(
|
|
3287
|
+
Components.FormattingToolbar.Button,
|
|
3288
|
+
{
|
|
3289
|
+
className: "bn-button",
|
|
3290
|
+
"data-test": "colors",
|
|
3291
|
+
label: tooltip,
|
|
3292
|
+
mainTooltip: tooltip,
|
|
3293
|
+
icon: /* @__PURE__ */ jsx19(
|
|
3294
|
+
ColorIcon,
|
|
3295
|
+
{
|
|
3296
|
+
textColor: currentTextColor,
|
|
3297
|
+
backgroundColor: currentBackgroundColor,
|
|
3298
|
+
size: 20
|
|
3299
|
+
}
|
|
3300
|
+
)
|
|
3301
|
+
}
|
|
3302
|
+
) }),
|
|
3303
|
+
/* @__PURE__ */ jsx19(
|
|
3304
|
+
Components.Generic.Menu.Dropdown,
|
|
3305
|
+
{
|
|
3306
|
+
className: "bn-menu-dropdown bn-color-picker-dropdown",
|
|
3307
|
+
children: /* @__PURE__ */ jsx19(
|
|
3308
|
+
LumirColorPicker,
|
|
3309
|
+
{
|
|
3310
|
+
textTitle: "\uD14D\uC2A4\uD2B8 \uC0C9",
|
|
3311
|
+
backgroundTitle: "\uD14D\uC2A4\uD2B8 \uBC30\uACBD",
|
|
3312
|
+
text: textColorInSchema ? { color: currentTextColor, setColor: setTextColor } : void 0,
|
|
3313
|
+
background: backgroundColorInSchema ? { color: currentBackgroundColor, setColor: setBackgroundColor } : void 0
|
|
3314
|
+
}
|
|
3315
|
+
)
|
|
3316
|
+
}
|
|
3317
|
+
)
|
|
3318
|
+
] });
|
|
3319
|
+
}
|
|
3320
|
+
function LumirCellColorToolbarButton() {
|
|
3321
|
+
const Components = useComponentsContext3();
|
|
3322
|
+
const editor = useBlockNoteEditor3();
|
|
3323
|
+
const selectedBlocks = useSelectedBlocks3(editor);
|
|
3324
|
+
const isMultiCell = useMemo3(() => {
|
|
3325
|
+
if (selectedBlocks.length !== 1 || selectedBlocks[0].type !== "table") {
|
|
3326
|
+
return false;
|
|
3327
|
+
}
|
|
3328
|
+
const cs = editor.tableHandles?.getCellSelection();
|
|
3329
|
+
return !!cs && cs.cells.length > 1;
|
|
3330
|
+
}, [editor, selectedBlocks]);
|
|
3331
|
+
const stashRef = useRef9([]);
|
|
3332
|
+
const applyBackground = useCallback16(
|
|
3333
|
+
(color) => {
|
|
3334
|
+
const live = getSelectedCellPositions(editor);
|
|
3335
|
+
const positions = live.length > 0 ? live : stashRef.current;
|
|
3336
|
+
setCellAttrAtPositions(editor, positions, "backgroundColor", color);
|
|
3337
|
+
setTimeout(() => editor.focus());
|
|
3338
|
+
},
|
|
3339
|
+
[editor]
|
|
3340
|
+
);
|
|
3341
|
+
if (!editor.isEditable || !isMultiCell) {
|
|
3342
|
+
return null;
|
|
3343
|
+
}
|
|
3344
|
+
const tooltip = "\uC140 \uBC30\uACBD\uC0C9";
|
|
3345
|
+
return /* @__PURE__ */ jsxs12(
|
|
3346
|
+
Components.Generic.Menu.Root,
|
|
3347
|
+
{
|
|
3348
|
+
onOpenChange: (open) => {
|
|
3349
|
+
if (open) {
|
|
3350
|
+
stashRef.current = getSelectedCellPositions(editor);
|
|
3351
|
+
}
|
|
3352
|
+
},
|
|
3353
|
+
children: [
|
|
3354
|
+
/* @__PURE__ */ jsx19(Components.Generic.Menu.Trigger, { children: /* @__PURE__ */ jsx19(
|
|
3355
|
+
Components.FormattingToolbar.Button,
|
|
3356
|
+
{
|
|
3357
|
+
className: "bn-button",
|
|
3358
|
+
"data-test": "cell-colors",
|
|
3359
|
+
label: tooltip,
|
|
3360
|
+
mainTooltip: tooltip,
|
|
3361
|
+
icon: /* @__PURE__ */ jsx19(CellFillIcon, { size: 18 })
|
|
3362
|
+
}
|
|
3363
|
+
) }),
|
|
3364
|
+
/* @__PURE__ */ jsx19(
|
|
3365
|
+
Components.Generic.Menu.Dropdown,
|
|
3366
|
+
{
|
|
3367
|
+
className: "bn-menu-dropdown bn-color-picker-dropdown",
|
|
3368
|
+
children: /* @__PURE__ */ jsx19(
|
|
3369
|
+
LumirColorPicker,
|
|
3370
|
+
{
|
|
3371
|
+
backgroundTitle: "\uC140 \uBC30\uACBD",
|
|
3372
|
+
background: { color: "default", setColor: applyBackground }
|
|
3373
|
+
}
|
|
3374
|
+
)
|
|
3375
|
+
}
|
|
3376
|
+
)
|
|
3377
|
+
]
|
|
3378
|
+
}
|
|
3379
|
+
);
|
|
3380
|
+
}
|
|
3381
|
+
function LumirCellColorPickerButton(props) {
|
|
3382
|
+
const Components = useComponentsContext3();
|
|
3383
|
+
const editor = useBlockNoteEditor3();
|
|
3384
|
+
const updateColor = (color, type) => {
|
|
3385
|
+
const newTable = props.block.content.rows.map((row) => ({
|
|
3386
|
+
...row,
|
|
3387
|
+
cells: row.cells.map((cell) => mapTableCell2(cell))
|
|
3388
|
+
}));
|
|
3389
|
+
if (type === "text") {
|
|
3390
|
+
newTable[props.rowIndex].cells[props.colIndex].props.textColor = color;
|
|
3391
|
+
} else {
|
|
3392
|
+
newTable[props.rowIndex].cells[props.colIndex].props.backgroundColor = color;
|
|
3393
|
+
}
|
|
3394
|
+
editor.updateBlock(props.block, {
|
|
3395
|
+
type: "table",
|
|
3396
|
+
content: { ...props.block.content, rows: newTable }
|
|
3397
|
+
});
|
|
3398
|
+
editor.setTextCursorPosition(props.block);
|
|
3399
|
+
};
|
|
3400
|
+
const currentCell = props.block.content.rows[props.rowIndex]?.cells?.[props.colIndex];
|
|
3401
|
+
if (!currentCell || editor.settings.tables.cellTextColor === false && editor.settings.tables.cellBackgroundColor === false) {
|
|
3402
|
+
return null;
|
|
3403
|
+
}
|
|
3404
|
+
return /* @__PURE__ */ jsxs12(Components.Generic.Menu.Root, { position: "right", sub: true, children: [
|
|
3405
|
+
/* @__PURE__ */ jsx19(Components.Generic.Menu.Trigger, { sub: true, children: /* @__PURE__ */ jsx19(Components.Generic.Menu.Item, { className: "bn-menu-item", subTrigger: true, children: "\uC140 \uC0C9\xB7\uBC30\uACBD" }) }),
|
|
3406
|
+
/* @__PURE__ */ jsx19(
|
|
3407
|
+
Components.Generic.Menu.Dropdown,
|
|
3408
|
+
{
|
|
3409
|
+
sub: true,
|
|
3410
|
+
className: "bn-menu-dropdown bn-color-picker-dropdown",
|
|
3411
|
+
children: /* @__PURE__ */ jsx19(
|
|
3412
|
+
LumirColorPicker,
|
|
3413
|
+
{
|
|
3414
|
+
iconSize: 18,
|
|
3415
|
+
textTitle: "\uC140 \uAE00\uC790\uC0C9",
|
|
3416
|
+
backgroundTitle: "\uC140 \uBC30\uACBD",
|
|
3417
|
+
text: editor.settings.tables.cellTextColor ? {
|
|
3418
|
+
color: isTableCell(currentCell) ? currentCell.props.textColor : "default",
|
|
3419
|
+
setColor: (color) => updateColor(color, "text")
|
|
3420
|
+
} : void 0,
|
|
3421
|
+
background: editor.settings.tables.cellBackgroundColor ? {
|
|
3422
|
+
color: isTableCell(currentCell) ? currentCell.props.backgroundColor : "default",
|
|
3423
|
+
setColor: (color) => updateColor(color, "background")
|
|
3424
|
+
} : void 0
|
|
3425
|
+
}
|
|
3426
|
+
)
|
|
3427
|
+
}
|
|
3428
|
+
)
|
|
3429
|
+
] });
|
|
3430
|
+
}
|
|
3431
|
+
function LumirTableCellMenu(props) {
|
|
3432
|
+
const Components = useComponentsContext3();
|
|
3433
|
+
return /* @__PURE__ */ jsx19(
|
|
3434
|
+
Components.Generic.Menu.Dropdown,
|
|
3435
|
+
{
|
|
3436
|
+
className: "bn-menu-dropdown bn-drag-handle-menu",
|
|
3437
|
+
children: props.children || /* @__PURE__ */ jsxs12(Fragment5, { children: [
|
|
3438
|
+
/* @__PURE__ */ jsx19(
|
|
3439
|
+
SplitButton,
|
|
3440
|
+
{
|
|
3441
|
+
block: props.block,
|
|
3442
|
+
rowIndex: props.rowIndex,
|
|
3443
|
+
colIndex: props.colIndex
|
|
3444
|
+
}
|
|
3445
|
+
),
|
|
3446
|
+
/* @__PURE__ */ jsx19(
|
|
3447
|
+
LumirCellColorPickerButton,
|
|
3448
|
+
{
|
|
3449
|
+
block: props.block,
|
|
3450
|
+
rowIndex: props.rowIndex,
|
|
3451
|
+
colIndex: props.colIndex
|
|
3452
|
+
}
|
|
3453
|
+
)
|
|
3454
|
+
] })
|
|
3455
|
+
}
|
|
3456
|
+
);
|
|
3457
|
+
}
|
|
3458
|
+
|
|
3081
3459
|
// src/components/CustomFormattingToolbar.tsx
|
|
3082
|
-
import { jsx as
|
|
3460
|
+
import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
3083
3461
|
var CustomFormattingToolbar = () => {
|
|
3084
|
-
return /* @__PURE__ */
|
|
3085
|
-
/* @__PURE__ */
|
|
3086
|
-
/* @__PURE__ */
|
|
3087
|
-
/* @__PURE__ */
|
|
3088
|
-
/* @__PURE__ */
|
|
3089
|
-
/* @__PURE__ */
|
|
3090
|
-
/* @__PURE__ */
|
|
3091
|
-
/* @__PURE__ */
|
|
3092
|
-
/* @__PURE__ */
|
|
3093
|
-
/* @__PURE__ */
|
|
3094
|
-
/* @__PURE__ */
|
|
3462
|
+
return /* @__PURE__ */ jsxs13(FormattingToolbar, { children: [
|
|
3463
|
+
/* @__PURE__ */ jsx20(BlockTypeSelect2, {}, "blockTypeSelect"),
|
|
3464
|
+
/* @__PURE__ */ jsx20(TableCellMergeButton, {}, "tableCellMergeButton"),
|
|
3465
|
+
/* @__PURE__ */ jsx20(FileCaptionButton, {}, "fileCaptionButton"),
|
|
3466
|
+
/* @__PURE__ */ jsx20(FileReplaceButton, {}, "replaceFileButton"),
|
|
3467
|
+
/* @__PURE__ */ jsx20(FileRenameButton, {}, "fileRenameButton"),
|
|
3468
|
+
/* @__PURE__ */ jsx20(FileDeleteButton, {}, "fileDeleteButton"),
|
|
3469
|
+
/* @__PURE__ */ jsx20(FileDownloadButton, {}, "fileDownloadButton"),
|
|
3470
|
+
/* @__PURE__ */ jsx20(FilePreviewButton, {}, "filePreviewButton"),
|
|
3471
|
+
/* @__PURE__ */ jsx20(BasicTextStyleButton, { basicTextStyle: "bold" }, "boldStyleButton"),
|
|
3472
|
+
/* @__PURE__ */ jsx20(
|
|
3095
3473
|
BasicTextStyleButton,
|
|
3096
3474
|
{
|
|
3097
3475
|
basicTextStyle: "italic"
|
|
3098
3476
|
},
|
|
3099
3477
|
"italicStyleButton"
|
|
3100
3478
|
),
|
|
3101
|
-
/* @__PURE__ */
|
|
3479
|
+
/* @__PURE__ */ jsx20(
|
|
3102
3480
|
BasicTextStyleButton,
|
|
3103
3481
|
{
|
|
3104
3482
|
basicTextStyle: "underline"
|
|
3105
3483
|
},
|
|
3106
3484
|
"underlineStyleButton"
|
|
3107
3485
|
),
|
|
3108
|
-
/* @__PURE__ */
|
|
3486
|
+
/* @__PURE__ */ jsx20(
|
|
3109
3487
|
BasicTextStyleButton,
|
|
3110
3488
|
{
|
|
3111
3489
|
basicTextStyle: "strike"
|
|
3112
3490
|
},
|
|
3113
3491
|
"strikeStyleButton"
|
|
3114
3492
|
),
|
|
3115
|
-
/* @__PURE__ */
|
|
3116
|
-
/* @__PURE__ */
|
|
3493
|
+
/* @__PURE__ */ jsx20(TextAlignButtonWithVA, { textAlignment: "left" }, "textAlignLeftButton"),
|
|
3494
|
+
/* @__PURE__ */ jsx20(
|
|
3117
3495
|
TextAlignButtonWithVA,
|
|
3118
3496
|
{
|
|
3119
3497
|
textAlignment: "center"
|
|
3120
3498
|
},
|
|
3121
3499
|
"textAlignCenterButton"
|
|
3122
3500
|
),
|
|
3123
|
-
/* @__PURE__ */
|
|
3124
|
-
/* @__PURE__ */
|
|
3501
|
+
/* @__PURE__ */ jsx20(TextAlignButtonWithVA, { textAlignment: "right" }, "textAlignRightButton"),
|
|
3502
|
+
/* @__PURE__ */ jsx20(
|
|
3125
3503
|
VerticalAlignButton,
|
|
3126
3504
|
{
|
|
3127
3505
|
verticalAlignment: "top"
|
|
3128
3506
|
},
|
|
3129
3507
|
"verticalAlignTop"
|
|
3130
3508
|
),
|
|
3131
|
-
/* @__PURE__ */
|
|
3509
|
+
/* @__PURE__ */ jsx20(
|
|
3132
3510
|
VerticalAlignButton,
|
|
3133
3511
|
{
|
|
3134
3512
|
verticalAlignment: "middle"
|
|
3135
3513
|
},
|
|
3136
3514
|
"verticalAlignMiddle"
|
|
3137
3515
|
),
|
|
3138
|
-
/* @__PURE__ */
|
|
3516
|
+
/* @__PURE__ */ jsx20(
|
|
3139
3517
|
VerticalAlignButton,
|
|
3140
3518
|
{
|
|
3141
3519
|
verticalAlignment: "bottom"
|
|
3142
3520
|
},
|
|
3143
3521
|
"verticalAlignBottom"
|
|
3144
3522
|
),
|
|
3145
|
-
/* @__PURE__ */
|
|
3146
|
-
/* @__PURE__ */
|
|
3147
|
-
/* @__PURE__ */
|
|
3148
|
-
/* @__PURE__ */
|
|
3523
|
+
/* @__PURE__ */ jsx20(LumirColorStyleButton, {}, "colorStyleButton"),
|
|
3524
|
+
/* @__PURE__ */ jsx20(LumirCellColorToolbarButton, {}, "cellColorButton"),
|
|
3525
|
+
/* @__PURE__ */ jsx20(NestBlockButton, {}, "nestBlockButton"),
|
|
3526
|
+
/* @__PURE__ */ jsx20(UnnestBlockButton, {}, "unnestBlockButton"),
|
|
3527
|
+
/* @__PURE__ */ jsx20(CreateLinkButton, {}, "createLinkButton")
|
|
3149
3528
|
] });
|
|
3150
3529
|
};
|
|
3151
3530
|
|
|
3531
|
+
// src/components/LumirTableHandlesController.tsx
|
|
3532
|
+
import {
|
|
3533
|
+
ExtendButton,
|
|
3534
|
+
TableCellButton,
|
|
3535
|
+
TableHandle,
|
|
3536
|
+
useBlockNoteEditor as useBlockNoteEditor4,
|
|
3537
|
+
useEditorContentOrSelectionChange as useEditorContentOrSelectionChange2,
|
|
3538
|
+
useExtendButtonsPositioning,
|
|
3539
|
+
useUIPluginState
|
|
3540
|
+
} from "@blocknote/react";
|
|
3541
|
+
import { autoUpdate as autoUpdate2, FloatingPortal } from "@floating-ui/react";
|
|
3542
|
+
import { useCallback as useCallback17, useEffect as useEffect9, useMemo as useMemo5, useRef as useRef10, useState as useState9 } from "react";
|
|
3543
|
+
|
|
3544
|
+
// src/components/hooks/useFocusedCellHandlePositioning.ts
|
|
3545
|
+
import {
|
|
3546
|
+
autoUpdate,
|
|
3547
|
+
offset,
|
|
3548
|
+
useFloating,
|
|
3549
|
+
useTransitionStyles
|
|
3550
|
+
} from "@floating-ui/react";
|
|
3551
|
+
import { useEffect as useEffect8, useMemo as useMemo4 } from "react";
|
|
3552
|
+
function useFocusedCellHandlePositioning(cellEl, tbodyEl, orientation, show) {
|
|
3553
|
+
const { refs, floatingStyles, context } = useFloating({
|
|
3554
|
+
open: show,
|
|
3555
|
+
placement: orientation === "row" ? "left" : orientation === "col" ? "top" : "right",
|
|
3556
|
+
// col/row: 가장자리 선(zero-size)에, cell: 셀 우측 보더에 14px hit-area 중앙 정렬(-7).
|
|
3557
|
+
middleware: [offset(-7)],
|
|
3558
|
+
whileElementsMounted: autoUpdate
|
|
3559
|
+
});
|
|
3560
|
+
const { isMounted, styles } = useTransitionStyles(context);
|
|
3561
|
+
useEffect8(() => {
|
|
3562
|
+
if (!cellEl) {
|
|
3563
|
+
refs.setReference(null);
|
|
3564
|
+
return;
|
|
3565
|
+
}
|
|
3566
|
+
refs.setReference({
|
|
3567
|
+
contextElement: cellEl,
|
|
3568
|
+
getBoundingClientRect: () => {
|
|
3569
|
+
const c = cellEl.getBoundingClientRect();
|
|
3570
|
+
const t = tbodyEl?.getBoundingClientRect() ?? c;
|
|
3571
|
+
if (orientation === "col") {
|
|
3572
|
+
return new DOMRect(c.left, t.top, c.width, 0);
|
|
3573
|
+
}
|
|
3574
|
+
if (orientation === "row") {
|
|
3575
|
+
return new DOMRect(t.left, c.top, 0, c.height);
|
|
3576
|
+
}
|
|
3577
|
+
return c;
|
|
3578
|
+
}
|
|
3579
|
+
});
|
|
3580
|
+
}, [cellEl, tbodyEl, orientation, refs]);
|
|
3581
|
+
return useMemo4(
|
|
3582
|
+
() => ({
|
|
3583
|
+
isMounted,
|
|
3584
|
+
ref: refs.setFloating,
|
|
3585
|
+
// display는 CSS 클래스에서 제어한다(absolute 자식 stacking).
|
|
3586
|
+
style: {
|
|
3587
|
+
...styles,
|
|
3588
|
+
...floatingStyles
|
|
3589
|
+
}
|
|
3590
|
+
}),
|
|
3591
|
+
[floatingStyles, isMounted, refs.setFloating, styles]
|
|
3592
|
+
);
|
|
3593
|
+
}
|
|
3594
|
+
|
|
3595
|
+
// src/components/LumirTableHandlesController.tsx
|
|
3596
|
+
import { Fragment as Fragment6, jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
3597
|
+
function syncCoreHoverToFocusedCell(cellEl) {
|
|
3598
|
+
const r = cellEl.getBoundingClientRect();
|
|
3599
|
+
cellEl.dispatchEvent(
|
|
3600
|
+
new MouseEvent("mousemove", {
|
|
3601
|
+
bubbles: true,
|
|
3602
|
+
cancelable: true,
|
|
3603
|
+
view: window,
|
|
3604
|
+
clientX: r.left + r.width / 2,
|
|
3605
|
+
clientY: r.top + r.height / 2
|
|
3606
|
+
})
|
|
3607
|
+
);
|
|
3608
|
+
}
|
|
3609
|
+
function LumirTableHandlesController() {
|
|
3610
|
+
const editor = useBlockNoteEditor4();
|
|
3611
|
+
const [focused, setFocused] = useState9(null);
|
|
3612
|
+
const [menuContainerRef, setMenuContainerRef] = useState9(null);
|
|
3613
|
+
const [overlayEl, setOverlayEl] = useState9(null);
|
|
3614
|
+
const [openMenu, setOpenMenu] = useState9(null);
|
|
3615
|
+
const frozenRef = useRef10(false);
|
|
3616
|
+
const menuOpenRef = useRef10(false);
|
|
3617
|
+
const draggingRef = useRef10(false);
|
|
3618
|
+
const recompute = useCallback17(() => {
|
|
3619
|
+
if (frozenRef.current) {
|
|
3620
|
+
return;
|
|
3621
|
+
}
|
|
3622
|
+
const th2 = editor.tableHandles;
|
|
3623
|
+
const view = editor.prosemirrorView;
|
|
3624
|
+
if (!th2 || !view) {
|
|
3625
|
+
setFocused(null);
|
|
3626
|
+
return;
|
|
3627
|
+
}
|
|
3628
|
+
let cellEl2 = null;
|
|
3629
|
+
try {
|
|
3630
|
+
const { node } = view.domAtPos(view.state.selection.from);
|
|
3631
|
+
const el = node.nodeType === Node.TEXT_NODE ? node.parentElement : node;
|
|
3632
|
+
cellEl2 = el?.closest?.("td, th") ?? null;
|
|
3633
|
+
} catch {
|
|
3634
|
+
cellEl2 = null;
|
|
3635
|
+
}
|
|
3636
|
+
if (!cellEl2 || !cellEl2.isConnected) {
|
|
3637
|
+
setFocused(null);
|
|
3638
|
+
return;
|
|
3639
|
+
}
|
|
3640
|
+
const blockId = cellEl2.closest("[data-id]")?.getAttribute("data-id");
|
|
3641
|
+
const block = blockId ? editor.getBlock(blockId) : void 0;
|
|
3642
|
+
if (!block || block.type !== "table") {
|
|
3643
|
+
setFocused(null);
|
|
3644
|
+
return;
|
|
3645
|
+
}
|
|
3646
|
+
const cellSel = th2.getCellSelection();
|
|
3647
|
+
if (!cellSel) {
|
|
3648
|
+
setFocused(null);
|
|
3649
|
+
return;
|
|
3650
|
+
}
|
|
3651
|
+
const widgetContainer = cellEl2.closest(".tableWrapper")?.querySelector(".table-widgets-container");
|
|
3652
|
+
const tbodyEl2 = cellEl2.closest("tbody");
|
|
3653
|
+
if (!widgetContainer || !tbodyEl2) {
|
|
3654
|
+
setFocused(null);
|
|
3655
|
+
return;
|
|
3656
|
+
}
|
|
3657
|
+
setFocused({
|
|
3658
|
+
block,
|
|
3659
|
+
rowIndex: cellSel.from.row,
|
|
3660
|
+
colIndex: cellSel.from.col,
|
|
3661
|
+
cellEl: cellEl2,
|
|
3662
|
+
tbodyEl: tbodyEl2,
|
|
3663
|
+
widgetContainer
|
|
3664
|
+
});
|
|
3665
|
+
}, [editor]);
|
|
3666
|
+
useEditorContentOrSelectionChange2(recompute, editor);
|
|
3667
|
+
useEffect9(() => {
|
|
3668
|
+
recompute();
|
|
3669
|
+
}, [recompute]);
|
|
3670
|
+
useEffect9(() => {
|
|
3671
|
+
const onUp = () => {
|
|
3672
|
+
requestAnimationFrame(() => {
|
|
3673
|
+
if (!menuOpenRef.current && !draggingRef.current && frozenRef.current) {
|
|
3674
|
+
frozenRef.current = false;
|
|
3675
|
+
recompute();
|
|
3676
|
+
}
|
|
3677
|
+
});
|
|
3678
|
+
};
|
|
3679
|
+
window.addEventListener("pointerup", onUp);
|
|
3680
|
+
return () => window.removeEventListener("pointerup", onUp);
|
|
3681
|
+
}, [recompute]);
|
|
3682
|
+
useEffect9(() => {
|
|
3683
|
+
const f = focused;
|
|
3684
|
+
if (!f || !overlayEl) {
|
|
3685
|
+
return;
|
|
3686
|
+
}
|
|
3687
|
+
const PAD = 1;
|
|
3688
|
+
const update = () => {
|
|
3689
|
+
const cr = f.cellEl.getBoundingClientRect();
|
|
3690
|
+
const tr = f.tbodyEl.getBoundingClientRect();
|
|
3691
|
+
const kr = f.widgetContainer.getBoundingClientRect();
|
|
3692
|
+
const x1 = openMenu === "row" ? tr.left : cr.left;
|
|
3693
|
+
const y1 = openMenu === "col" ? tr.top : cr.top;
|
|
3694
|
+
const x2 = openMenu === "row" ? tr.right : cr.right;
|
|
3695
|
+
const y2 = openMenu === "col" ? tr.bottom : cr.bottom;
|
|
3696
|
+
const dpr = window.devicePixelRatio || 1;
|
|
3697
|
+
const rd = (v) => Math.round(v * dpr) / dpr;
|
|
3698
|
+
const left = rd(x1 - kr.left) - PAD;
|
|
3699
|
+
const top = rd(y1 - kr.top) - PAD;
|
|
3700
|
+
const right = rd(x2 - kr.left) + PAD;
|
|
3701
|
+
const bottom = rd(y2 - kr.top) + PAD;
|
|
3702
|
+
overlayEl.style.transform = `translate(${left}px, ${top}px)`;
|
|
3703
|
+
overlayEl.style.width = `${right - left}px`;
|
|
3704
|
+
overlayEl.style.height = `${bottom - top}px`;
|
|
3705
|
+
};
|
|
3706
|
+
update();
|
|
3707
|
+
return autoUpdate2(f.cellEl, overlayEl, update);
|
|
3708
|
+
}, [focused, overlayEl, openMenu]);
|
|
3709
|
+
const cellEl = focused?.cellEl ?? null;
|
|
3710
|
+
const tbodyEl = focused?.tbodyEl ?? null;
|
|
3711
|
+
const show = focused !== null;
|
|
3712
|
+
const rowHandle = useFocusedCellHandlePositioning(cellEl, tbodyEl, "row", show);
|
|
3713
|
+
const colHandle = useFocusedCellHandlePositioning(cellEl, tbodyEl, "col", show);
|
|
3714
|
+
const cellHandle = useFocusedCellHandlePositioning(
|
|
3715
|
+
cellEl,
|
|
3716
|
+
tbodyEl,
|
|
3717
|
+
"cell",
|
|
3718
|
+
show
|
|
3719
|
+
);
|
|
3720
|
+
const th = editor.tableHandles;
|
|
3721
|
+
const coreState = useUIPluginState(
|
|
3722
|
+
editor.tableHandles.onUpdate.bind(editor.tableHandles)
|
|
3723
|
+
);
|
|
3724
|
+
const { addOrRemoveColumnsButton, addOrRemoveRowsButton } = useExtendButtonsPositioning(
|
|
3725
|
+
coreState?.showAddOrRemoveColumnsButton || false,
|
|
3726
|
+
coreState?.showAddOrRemoveRowsButton || false,
|
|
3727
|
+
coreState?.referencePosTable || null
|
|
3728
|
+
);
|
|
3729
|
+
const onStartExtend = useCallback17(() => {
|
|
3730
|
+
editor.tableHandles?.freezeHandles();
|
|
3731
|
+
}, [editor]);
|
|
3732
|
+
const onEndExtend = useCallback17(() => {
|
|
3733
|
+
editor.tableHandles?.unfreezeHandles();
|
|
3734
|
+
}, [editor]);
|
|
3735
|
+
const menuHandlers = useMemo5(() => {
|
|
3736
|
+
const mk = (kind) => ({
|
|
3737
|
+
freeze: () => {
|
|
3738
|
+
menuOpenRef.current = true;
|
|
3739
|
+
frozenRef.current = true;
|
|
3740
|
+
setOpenMenu(kind);
|
|
3741
|
+
editor.tableHandles?.freezeHandles();
|
|
3742
|
+
},
|
|
3743
|
+
unfreeze: () => {
|
|
3744
|
+
menuOpenRef.current = false;
|
|
3745
|
+
frozenRef.current = false;
|
|
3746
|
+
setOpenMenu(null);
|
|
3747
|
+
editor.tableHandles?.unfreezeHandles();
|
|
3748
|
+
recompute();
|
|
3749
|
+
}
|
|
3750
|
+
});
|
|
3751
|
+
return { col: mk("col"), row: mk("row"), cell: mk("cell") };
|
|
3752
|
+
}, [editor, recompute]);
|
|
3753
|
+
const onGutterPointerDown = useCallback17(() => {
|
|
3754
|
+
frozenRef.current = true;
|
|
3755
|
+
}, []);
|
|
3756
|
+
const onGutterPointerEnter = useCallback17(
|
|
3757
|
+
(e) => {
|
|
3758
|
+
if (e.buttons === 0 && focused) {
|
|
3759
|
+
syncCoreHoverToFocusedCell(focused.cellEl);
|
|
3760
|
+
}
|
|
3761
|
+
},
|
|
3762
|
+
[focused]
|
|
3763
|
+
);
|
|
3764
|
+
const makeDragStart = useCallback17(
|
|
3765
|
+
(dir) => (e) => {
|
|
3766
|
+
draggingRef.current = true;
|
|
3767
|
+
frozenRef.current = true;
|
|
3768
|
+
if (dir === "row") {
|
|
3769
|
+
editor.tableHandles?.rowDragStart(e);
|
|
3770
|
+
} else {
|
|
3771
|
+
editor.tableHandles?.colDragStart(e);
|
|
3772
|
+
}
|
|
3773
|
+
},
|
|
3774
|
+
[editor]
|
|
3775
|
+
);
|
|
3776
|
+
const onDragEnd = useCallback17(() => {
|
|
3777
|
+
editor.tableHandles?.dragEnd();
|
|
3778
|
+
draggingRef.current = false;
|
|
3779
|
+
frozenRef.current = false;
|
|
3780
|
+
recompute();
|
|
3781
|
+
}, [editor, recompute]);
|
|
3782
|
+
const noop = useCallback17(() => {
|
|
3783
|
+
}, []);
|
|
3784
|
+
return /* @__PURE__ */ jsxs14(Fragment6, { children: [
|
|
3785
|
+
/* @__PURE__ */ jsx21("div", { ref: setMenuContainerRef }),
|
|
3786
|
+
th && focused && menuContainerRef && /* @__PURE__ */ jsxs14(FloatingPortal, { root: focused.widgetContainer, children: [
|
|
3787
|
+
/* @__PURE__ */ jsx21("div", { ref: setOverlayEl, className: "lumir-tbl-cell-focus" }),
|
|
3788
|
+
colHandle.isMounted && /* @__PURE__ */ jsxs14(
|
|
3789
|
+
"div",
|
|
3790
|
+
{
|
|
3791
|
+
ref: colHandle.ref,
|
|
3792
|
+
style: colHandle.style,
|
|
3793
|
+
className: "lumir-tbl-gutter-wrap lumir-tbl-gutter-wrap--col" + (openMenu === "col" ? " lumir-tbl-gutter-wrap--active" : ""),
|
|
3794
|
+
onPointerEnter: onGutterPointerEnter,
|
|
3795
|
+
onPointerDown: onGutterPointerDown,
|
|
3796
|
+
children: [
|
|
3797
|
+
/* @__PURE__ */ jsx21("span", { className: "lumir-tbl-gutter" }),
|
|
3798
|
+
/* @__PURE__ */ jsx21("div", { className: "lumir-tbl-grip", children: /* @__PURE__ */ jsx21(
|
|
3799
|
+
TableHandle,
|
|
3800
|
+
{
|
|
3801
|
+
editor,
|
|
3802
|
+
orientation: "column",
|
|
3803
|
+
index: focused.colIndex,
|
|
3804
|
+
block: focused.block,
|
|
3805
|
+
dragStart: makeDragStart("col"),
|
|
3806
|
+
dragEnd: onDragEnd,
|
|
3807
|
+
freezeHandles: menuHandlers.col.freeze,
|
|
3808
|
+
unfreezeHandles: menuHandlers.col.unfreeze,
|
|
3809
|
+
menuContainer: menuContainerRef,
|
|
3810
|
+
showOtherSide: noop,
|
|
3811
|
+
hideOtherSide: noop
|
|
3812
|
+
}
|
|
3813
|
+
) })
|
|
3814
|
+
]
|
|
3815
|
+
}
|
|
3816
|
+
),
|
|
3817
|
+
rowHandle.isMounted && /* @__PURE__ */ jsxs14(
|
|
3818
|
+
"div",
|
|
3819
|
+
{
|
|
3820
|
+
ref: rowHandle.ref,
|
|
3821
|
+
style: rowHandle.style,
|
|
3822
|
+
className: "lumir-tbl-gutter-wrap lumir-tbl-gutter-wrap--row" + (openMenu === "row" ? " lumir-tbl-gutter-wrap--active" : ""),
|
|
3823
|
+
onPointerEnter: onGutterPointerEnter,
|
|
3824
|
+
onPointerDown: onGutterPointerDown,
|
|
3825
|
+
children: [
|
|
3826
|
+
/* @__PURE__ */ jsx21("span", { className: "lumir-tbl-gutter" }),
|
|
3827
|
+
/* @__PURE__ */ jsx21("div", { className: "lumir-tbl-grip", children: /* @__PURE__ */ jsx21(
|
|
3828
|
+
TableHandle,
|
|
3829
|
+
{
|
|
3830
|
+
editor,
|
|
3831
|
+
orientation: "row",
|
|
3832
|
+
index: focused.rowIndex,
|
|
3833
|
+
block: focused.block,
|
|
3834
|
+
dragStart: makeDragStart("row"),
|
|
3835
|
+
dragEnd: onDragEnd,
|
|
3836
|
+
freezeHandles: menuHandlers.row.freeze,
|
|
3837
|
+
unfreezeHandles: menuHandlers.row.unfreeze,
|
|
3838
|
+
menuContainer: menuContainerRef,
|
|
3839
|
+
showOtherSide: noop,
|
|
3840
|
+
hideOtherSide: noop
|
|
3841
|
+
}
|
|
3842
|
+
) })
|
|
3843
|
+
]
|
|
3844
|
+
}
|
|
3845
|
+
),
|
|
3846
|
+
cellHandle.isMounted && openMenu !== "col" && openMenu !== "row" && /* @__PURE__ */ jsxs14(
|
|
3847
|
+
"div",
|
|
3848
|
+
{
|
|
3849
|
+
ref: cellHandle.ref,
|
|
3850
|
+
style: cellHandle.style,
|
|
3851
|
+
className: "lumir-tbl-gutter-wrap lumir-tbl-gutter-wrap--cell" + (openMenu === "cell" ? " lumir-tbl-gutter-wrap--active" : ""),
|
|
3852
|
+
onPointerDown: onGutterPointerDown,
|
|
3853
|
+
children: [
|
|
3854
|
+
/* @__PURE__ */ jsx21("span", { className: "lumir-tbl-gutter" }),
|
|
3855
|
+
/* @__PURE__ */ jsx21("div", { className: "lumir-tbl-grip", children: /* @__PURE__ */ jsx21(
|
|
3856
|
+
TableCellButton,
|
|
3857
|
+
{
|
|
3858
|
+
editor,
|
|
3859
|
+
rowIndex: focused.rowIndex,
|
|
3860
|
+
colIndex: focused.colIndex,
|
|
3861
|
+
block: focused.block,
|
|
3862
|
+
tableCellMenu: LumirTableCellMenu,
|
|
3863
|
+
menuContainer: menuContainerRef,
|
|
3864
|
+
freezeHandles: menuHandlers.cell.freeze,
|
|
3865
|
+
unfreezeHandles: menuHandlers.cell.unfreeze
|
|
3866
|
+
}
|
|
3867
|
+
) })
|
|
3868
|
+
]
|
|
3869
|
+
}
|
|
3870
|
+
)
|
|
3871
|
+
] }),
|
|
3872
|
+
th && coreState?.widgetContainer && /* @__PURE__ */ jsxs14(FloatingPortal, { root: coreState.widgetContainer, children: [
|
|
3873
|
+
/* @__PURE__ */ jsx21("div", { ref: addOrRemoveRowsButton.ref, style: addOrRemoveRowsButton.style, children: /* @__PURE__ */ jsx21(
|
|
3874
|
+
ExtendButton,
|
|
3875
|
+
{
|
|
3876
|
+
editor,
|
|
3877
|
+
orientation: "addOrRemoveRows",
|
|
3878
|
+
block: coreState.block,
|
|
3879
|
+
onMouseDown: onStartExtend,
|
|
3880
|
+
onMouseUp: onEndExtend
|
|
3881
|
+
}
|
|
3882
|
+
) }),
|
|
3883
|
+
/* @__PURE__ */ jsx21(
|
|
3884
|
+
"div",
|
|
3885
|
+
{
|
|
3886
|
+
ref: addOrRemoveColumnsButton.ref,
|
|
3887
|
+
style: addOrRemoveColumnsButton.style,
|
|
3888
|
+
children: /* @__PURE__ */ jsx21(
|
|
3889
|
+
ExtendButton,
|
|
3890
|
+
{
|
|
3891
|
+
editor,
|
|
3892
|
+
orientation: "addOrRemoveColumns",
|
|
3893
|
+
block: coreState.block,
|
|
3894
|
+
onMouseDown: onStartExtend,
|
|
3895
|
+
onMouseUp: onEndExtend
|
|
3896
|
+
}
|
|
3897
|
+
)
|
|
3898
|
+
}
|
|
3899
|
+
)
|
|
3900
|
+
] })
|
|
3901
|
+
] });
|
|
3902
|
+
}
|
|
3903
|
+
|
|
3152
3904
|
// src/utils/table-vertical-alignment.ts
|
|
3153
3905
|
function injectVerticalAlignment(blocks, editor) {
|
|
3154
3906
|
const tiptap = editor?._tiptapEditor;
|
|
@@ -3231,6 +3983,235 @@ function patchBlocks(blocks, tableVAMap) {
|
|
|
3231
3983
|
});
|
|
3232
3984
|
}
|
|
3233
3985
|
|
|
3986
|
+
// src/utils/excel-paste.ts
|
|
3987
|
+
var NAMED_COLORS = {
|
|
3988
|
+
black: "#000000",
|
|
3989
|
+
white: "#ffffff",
|
|
3990
|
+
red: "#ff0000",
|
|
3991
|
+
green: "#008000",
|
|
3992
|
+
blue: "#0000ff",
|
|
3993
|
+
yellow: "#ffff00",
|
|
3994
|
+
orange: "#ffa500",
|
|
3995
|
+
purple: "#800080",
|
|
3996
|
+
gray: "#808080",
|
|
3997
|
+
grey: "#808080"
|
|
3998
|
+
};
|
|
3999
|
+
function parseCssColorToRgb(input) {
|
|
4000
|
+
if (!input) return null;
|
|
4001
|
+
const s = input.trim().toLowerCase();
|
|
4002
|
+
if (!s || s === "transparent" || s === "none" || s === "inherit") return null;
|
|
4003
|
+
let m = s.match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/);
|
|
4004
|
+
if (m) {
|
|
4005
|
+
let h = m[1];
|
|
4006
|
+
if (h.length === 3)
|
|
4007
|
+
h = h.split("").map((c) => c + c).join("");
|
|
4008
|
+
return [
|
|
4009
|
+
parseInt(h.slice(0, 2), 16),
|
|
4010
|
+
parseInt(h.slice(2, 4), 16),
|
|
4011
|
+
parseInt(h.slice(4, 6), 16)
|
|
4012
|
+
];
|
|
4013
|
+
}
|
|
4014
|
+
m = s.match(/^rgba?\(([^)]+)\)$/);
|
|
4015
|
+
if (m) {
|
|
4016
|
+
const parts = m[1].split(",").map((x) => parseFloat(x.trim()));
|
|
4017
|
+
if (parts.length >= 3 && parts.slice(0, 3).every((n) => !isNaN(n))) {
|
|
4018
|
+
return [parts[0], parts[1], parts[2]];
|
|
4019
|
+
}
|
|
4020
|
+
return null;
|
|
4021
|
+
}
|
|
4022
|
+
if (NAMED_COLORS[s]) return parseCssColorToRgb(NAMED_COLORS[s]);
|
|
4023
|
+
return null;
|
|
4024
|
+
}
|
|
4025
|
+
function rgbToHsl([r, g, b]) {
|
|
4026
|
+
r /= 255;
|
|
4027
|
+
g /= 255;
|
|
4028
|
+
b /= 255;
|
|
4029
|
+
const max = Math.max(r, g, b);
|
|
4030
|
+
const min = Math.min(r, g, b);
|
|
4031
|
+
const l = (max + min) / 2;
|
|
4032
|
+
let h = 0;
|
|
4033
|
+
let s = 0;
|
|
4034
|
+
const d = max - min;
|
|
4035
|
+
if (d !== 0) {
|
|
4036
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
4037
|
+
switch (max) {
|
|
4038
|
+
case r:
|
|
4039
|
+
h = ((g - b) / d + (g < b ? 6 : 0)) * 60;
|
|
4040
|
+
break;
|
|
4041
|
+
case g:
|
|
4042
|
+
h = ((b - r) / d + 2) * 60;
|
|
4043
|
+
break;
|
|
4044
|
+
default:
|
|
4045
|
+
h = ((r - g) / d + 4) * 60;
|
|
4046
|
+
break;
|
|
4047
|
+
}
|
|
4048
|
+
}
|
|
4049
|
+
return [h, s, l];
|
|
4050
|
+
}
|
|
4051
|
+
var HUE_REFERENCE = [
|
|
4052
|
+
{ value: "red", hue: 0 },
|
|
4053
|
+
{ value: "brown", hue: 17 },
|
|
4054
|
+
{ value: "orange", hue: 30 },
|
|
4055
|
+
{ value: "yellow", hue: 46 },
|
|
4056
|
+
{ value: "green", hue: 150 },
|
|
4057
|
+
{ value: "blue", hue: 197 },
|
|
4058
|
+
{ value: "purple", hue: 262 },
|
|
4059
|
+
{ value: "pink", hue: 324 }
|
|
4060
|
+
];
|
|
4061
|
+
function hueDist(a, b) {
|
|
4062
|
+
const d = Math.abs(a - b) % 360;
|
|
4063
|
+
return d > 180 ? 360 - d : d;
|
|
4064
|
+
}
|
|
4065
|
+
function paletteValueFromRgb(rgb) {
|
|
4066
|
+
const [h, s, l] = rgbToHsl(rgb);
|
|
4067
|
+
if (s < 0.15) {
|
|
4068
|
+
if (l < 0.35) return "default";
|
|
4069
|
+
if (l > 0.85) return "default";
|
|
4070
|
+
return "gray";
|
|
4071
|
+
}
|
|
4072
|
+
let best = "gray";
|
|
4073
|
+
let bestDist = Infinity;
|
|
4074
|
+
for (const ref of HUE_REFERENCE) {
|
|
4075
|
+
const d = hueDist(h, ref.hue);
|
|
4076
|
+
if (d < bestDist) {
|
|
4077
|
+
bestDist = d;
|
|
4078
|
+
best = ref.value;
|
|
4079
|
+
}
|
|
4080
|
+
}
|
|
4081
|
+
return best;
|
|
4082
|
+
}
|
|
4083
|
+
function nearestTextColorValue(rgb) {
|
|
4084
|
+
return paletteValueFromRgb(rgb);
|
|
4085
|
+
}
|
|
4086
|
+
function nearestBackgroundColorValue(rgb) {
|
|
4087
|
+
const [, s, l] = rgbToHsl(rgb);
|
|
4088
|
+
if (s < 0.12 && l > 0.85) return "default";
|
|
4089
|
+
return paletteValueFromRgb(rgb);
|
|
4090
|
+
}
|
|
4091
|
+
function parseStyle(style) {
|
|
4092
|
+
const out = {};
|
|
4093
|
+
style.split(";").forEach((decl) => {
|
|
4094
|
+
const idx = decl.indexOf(":");
|
|
4095
|
+
if (idx === -1) return;
|
|
4096
|
+
const k = decl.slice(0, idx).trim().toLowerCase();
|
|
4097
|
+
const v = decl.slice(idx + 1).trim();
|
|
4098
|
+
if (k) out[k] = v;
|
|
4099
|
+
});
|
|
4100
|
+
return out;
|
|
4101
|
+
}
|
|
4102
|
+
function colorFromBackgroundShorthand(value) {
|
|
4103
|
+
if (!value) return null;
|
|
4104
|
+
const direct = parseCssColorToRgb(value);
|
|
4105
|
+
if (direct) return direct;
|
|
4106
|
+
for (const token of value.split(/\s+/)) {
|
|
4107
|
+
const rgb = parseCssColorToRgb(token);
|
|
4108
|
+
if (rgb) return rgb;
|
|
4109
|
+
}
|
|
4110
|
+
return null;
|
|
4111
|
+
}
|
|
4112
|
+
function isTransparentColor(css) {
|
|
4113
|
+
if (!css) return true;
|
|
4114
|
+
const s = css.trim().toLowerCase();
|
|
4115
|
+
if (s === "transparent" || s === "none") return true;
|
|
4116
|
+
const m = s.match(/^rgba?\(([^)]+)\)$/);
|
|
4117
|
+
if (m) {
|
|
4118
|
+
const p = m[1].split(",").map((x) => parseFloat(x.trim()));
|
|
4119
|
+
if (p.length >= 4 && p[3] === 0) return true;
|
|
4120
|
+
}
|
|
4121
|
+
return false;
|
|
4122
|
+
}
|
|
4123
|
+
function normalizeAlign(ta) {
|
|
4124
|
+
const v = (ta || "").trim().toLowerCase();
|
|
4125
|
+
if (v === "right" || v === "end") return "right";
|
|
4126
|
+
if (v === "center") return "center";
|
|
4127
|
+
if (v === "justify") return "justify";
|
|
4128
|
+
return "";
|
|
4129
|
+
}
|
|
4130
|
+
function applyCellFormatting(el, fmt) {
|
|
4131
|
+
if (fmt.bgRgb && !fmt.bgTransparent) {
|
|
4132
|
+
const v = nearestBackgroundColorValue(fmt.bgRgb);
|
|
4133
|
+
if (v !== "default") el.setAttribute("data-background-color", v);
|
|
4134
|
+
}
|
|
4135
|
+
if (fmt.colorRgb) {
|
|
4136
|
+
const v = nearestTextColorValue(fmt.colorRgb);
|
|
4137
|
+
if (v !== "default") el.setAttribute("data-text-color", v);
|
|
4138
|
+
}
|
|
4139
|
+
if (["right", "center", "justify"].includes(fmt.align)) {
|
|
4140
|
+
el.setAttribute("data-text-alignment", fmt.align);
|
|
4141
|
+
}
|
|
4142
|
+
if ((fmt.bold || fmt.italic || fmt.underline) && el.innerHTML.trim()) {
|
|
4143
|
+
let inner = el.innerHTML;
|
|
4144
|
+
if (fmt.underline) inner = `<u>${inner}</u>`;
|
|
4145
|
+
if (fmt.italic) inner = `<em>${inner}</em>`;
|
|
4146
|
+
if (fmt.bold) inner = `<strong>${inner}</strong>`;
|
|
4147
|
+
el.innerHTML = inner;
|
|
4148
|
+
}
|
|
4149
|
+
}
|
|
4150
|
+
function readComputedFormat(el) {
|
|
4151
|
+
const cs = getComputedStyle(el);
|
|
4152
|
+
const fw = cs.fontWeight;
|
|
4153
|
+
const fwNum = parseInt(fw, 10);
|
|
4154
|
+
const decoration = cs.textDecorationLine || cs.textDecoration || "";
|
|
4155
|
+
return {
|
|
4156
|
+
bgRgb: parseCssColorToRgb(cs.backgroundColor),
|
|
4157
|
+
bgTransparent: isTransparentColor(cs.backgroundColor),
|
|
4158
|
+
colorRgb: parseCssColorToRgb(cs.color),
|
|
4159
|
+
align: normalizeAlign(cs.textAlign),
|
|
4160
|
+
bold: fw === "bold" || fw === "bolder" || !isNaN(fwNum) && fwNum >= 600,
|
|
4161
|
+
italic: (cs.fontStyle || "").toLowerCase().includes("italic"),
|
|
4162
|
+
underline: decoration.toLowerCase().includes("underline")
|
|
4163
|
+
};
|
|
4164
|
+
}
|
|
4165
|
+
function readInlineFormat(el) {
|
|
4166
|
+
const sm = parseStyle(el.getAttribute("style") || "");
|
|
4167
|
+
const bgRaw = sm["background-color"] || sm["background"] || "";
|
|
4168
|
+
const bgRgb = colorFromBackgroundShorthand(bgRaw) || parseCssColorToRgb(el.getAttribute("bgcolor"));
|
|
4169
|
+
const fw = (sm["font-weight"] || "").toLowerCase();
|
|
4170
|
+
const decoration = sm["text-decoration"] || sm["text-decoration-line"] || "";
|
|
4171
|
+
return {
|
|
4172
|
+
bgRgb,
|
|
4173
|
+
bgTransparent: !bgRaw && !el.getAttribute("bgcolor"),
|
|
4174
|
+
colorRgb: parseCssColorToRgb(sm["color"]),
|
|
4175
|
+
align: normalizeAlign(sm["text-align"] || el.getAttribute("align")),
|
|
4176
|
+
bold: fw === "bold" || fw === "bolder" || parseInt(fw, 10) >= 600,
|
|
4177
|
+
italic: (sm["font-style"] || "").toLowerCase().includes("italic"),
|
|
4178
|
+
underline: decoration.toLowerCase().includes("underline")
|
|
4179
|
+
};
|
|
4180
|
+
}
|
|
4181
|
+
function normalizeExcelTableHtml(html) {
|
|
4182
|
+
if (!html || typeof DOMParser === "undefined") return html;
|
|
4183
|
+
try {
|
|
4184
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
4185
|
+
doc.querySelectorAll("script").forEach((s) => s.remove());
|
|
4186
|
+
if (!doc.querySelector("table")) return html;
|
|
4187
|
+
if (typeof document !== "undefined" && document.body && typeof HTMLElement !== "undefined" && typeof HTMLElement.prototype.attachShadow === "function") {
|
|
4188
|
+
let host = null;
|
|
4189
|
+
try {
|
|
4190
|
+
host = document.createElement("div");
|
|
4191
|
+
host.setAttribute("aria-hidden", "true");
|
|
4192
|
+
host.style.cssText = "position:absolute;left:-99999px;top:0;width:0;height:0;overflow:hidden;opacity:0;pointer-events:none";
|
|
4193
|
+
const shadow = host.attachShadow({ mode: "open" });
|
|
4194
|
+
const styles = Array.from(doc.querySelectorAll("style")).map((s) => s.outerHTML).join("");
|
|
4195
|
+
shadow.innerHTML = styles + doc.body.innerHTML;
|
|
4196
|
+
document.body.appendChild(host);
|
|
4197
|
+
shadow.querySelectorAll("td, th").forEach((node) => {
|
|
4198
|
+
applyCellFormatting(node, readComputedFormat(node));
|
|
4199
|
+
});
|
|
4200
|
+
const out = Array.from(shadow.querySelectorAll("table")).map((t) => t.outerHTML).join("");
|
|
4201
|
+
return out || html;
|
|
4202
|
+
} finally {
|
|
4203
|
+
if (host && host.parentNode) host.parentNode.removeChild(host);
|
|
4204
|
+
}
|
|
4205
|
+
}
|
|
4206
|
+
doc.querySelectorAll("td, th").forEach((node) => {
|
|
4207
|
+
applyCellFormatting(node, readInlineFormat(node));
|
|
4208
|
+
});
|
|
4209
|
+
return Array.from(doc.querySelectorAll("table")).map((t) => t.outerHTML).join("") || html;
|
|
4210
|
+
} catch {
|
|
4211
|
+
return html;
|
|
4212
|
+
}
|
|
4213
|
+
}
|
|
4214
|
+
|
|
3234
4215
|
// src/constants/limits.ts
|
|
3235
4216
|
var MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
3236
4217
|
var MAX_VIDEO_FILE_SIZE = 100 * 1024 * 1024;
|
|
@@ -3250,7 +4231,7 @@ var ALLOWED_VIDEO_EXTENSIONS = [
|
|
|
3250
4231
|
];
|
|
3251
4232
|
|
|
3252
4233
|
// src/components/LumirEditor.tsx
|
|
3253
|
-
import { Fragment as
|
|
4234
|
+
import { Fragment as Fragment7, jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
3254
4235
|
var DEBUG_LOG = (loc, msg, data) => {
|
|
3255
4236
|
const p = fetch("http://127.0.0.1:7686/ingest/1f8ee1c5-0cf0-4ae7-91ed-5ea7ed17130a", {
|
|
3256
4237
|
method: "POST",
|
|
@@ -3475,9 +4456,9 @@ var findBlockWithLink = (blocks, targetUrl) => {
|
|
|
3475
4456
|
return null;
|
|
3476
4457
|
};
|
|
3477
4458
|
var ConvertToPreviewButton = ({ url }) => {
|
|
3478
|
-
const editor =
|
|
3479
|
-
const Components =
|
|
3480
|
-
return /* @__PURE__ */
|
|
4459
|
+
const editor = useBlockNoteEditor5();
|
|
4460
|
+
const Components = useComponentsContext4();
|
|
4461
|
+
return /* @__PURE__ */ jsx22(
|
|
3481
4462
|
Components.LinkToolbar.Button,
|
|
3482
4463
|
{
|
|
3483
4464
|
className: "bn-button",
|
|
@@ -3496,29 +4477,29 @@ var ConvertToPreviewButton = ({ url }) => {
|
|
|
3496
4477
|
console.error("Convert to link preview failed:", err);
|
|
3497
4478
|
}
|
|
3498
4479
|
},
|
|
3499
|
-
icon: /* @__PURE__ */
|
|
3500
|
-
/* @__PURE__ */
|
|
3501
|
-
/* @__PURE__ */
|
|
3502
|
-
/* @__PURE__ */
|
|
4480
|
+
icon: /* @__PURE__ */ jsxs15("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
4481
|
+
/* @__PURE__ */ jsx22("rect", { x: "1", y: "3", width: "14", height: "10", rx: "2", stroke: "currentColor", strokeWidth: "1.5", fill: "none" }),
|
|
4482
|
+
/* @__PURE__ */ jsx22("line", { x1: "1", y1: "9", x2: "15", y2: "9", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
4483
|
+
/* @__PURE__ */ jsx22("circle", { cx: "5", cy: "6.5", r: "1.5", stroke: "currentColor", strokeWidth: "1", fill: "none" })
|
|
3503
4484
|
] })
|
|
3504
4485
|
}
|
|
3505
4486
|
);
|
|
3506
4487
|
};
|
|
3507
4488
|
var CustomLinkToolbar = (props) => {
|
|
3508
|
-
const editor =
|
|
3509
|
-
const Components =
|
|
4489
|
+
const editor = useBlockNoteEditor5();
|
|
4490
|
+
const Components = useComponentsContext4();
|
|
3510
4491
|
const hasLinkPreview = !!editor?._linkPreviewApiEndpoint;
|
|
3511
|
-
return /* @__PURE__ */
|
|
4492
|
+
return /* @__PURE__ */ jsxs15(
|
|
3512
4493
|
Components.LinkToolbar.Root,
|
|
3513
4494
|
{
|
|
3514
4495
|
className: "bn-toolbar bn-link-toolbar",
|
|
3515
4496
|
onMouseEnter: props.stopHideTimer,
|
|
3516
4497
|
onMouseLeave: props.startHideTimer,
|
|
3517
4498
|
children: [
|
|
3518
|
-
/* @__PURE__ */
|
|
3519
|
-
/* @__PURE__ */
|
|
3520
|
-
/* @__PURE__ */
|
|
3521
|
-
hasLinkPreview && /* @__PURE__ */
|
|
4499
|
+
/* @__PURE__ */ jsx22(EditLinkButton, { url: props.url, text: props.text, editLink: props.editLink }),
|
|
4500
|
+
/* @__PURE__ */ jsx22(OpenLinkButton, { url: props.url }),
|
|
4501
|
+
/* @__PURE__ */ jsx22(DeleteLinkButton, { deleteLink: props.deleteLink }),
|
|
4502
|
+
hasLinkPreview && /* @__PURE__ */ jsx22(ConvertToPreviewButton, { url: props.url })
|
|
3522
4503
|
]
|
|
3523
4504
|
}
|
|
3524
4505
|
);
|
|
@@ -3562,13 +4543,13 @@ function LumirEditor({
|
|
|
3562
4543
|
onError,
|
|
3563
4544
|
onImageDelete
|
|
3564
4545
|
}) {
|
|
3565
|
-
const [isUploading, setIsUploading] =
|
|
3566
|
-
const [uploadProgress, setUploadProgress] =
|
|
3567
|
-
const [errorMessage, setErrorMessage] =
|
|
3568
|
-
const floatingMenuFileInputRef =
|
|
3569
|
-
const floatingMenuBlockRef =
|
|
3570
|
-
const floatingMenuUploadStartTimeRef =
|
|
3571
|
-
const handleError =
|
|
4546
|
+
const [isUploading, setIsUploading] = useState10(false);
|
|
4547
|
+
const [uploadProgress, setUploadProgress] = useState10(null);
|
|
4548
|
+
const [errorMessage, setErrorMessage] = useState10(null);
|
|
4549
|
+
const floatingMenuFileInputRef = useRef11(null);
|
|
4550
|
+
const floatingMenuBlockRef = useRef11(null);
|
|
4551
|
+
const floatingMenuUploadStartTimeRef = useRef11(0);
|
|
4552
|
+
const handleError = useCallback18(
|
|
3572
4553
|
(error) => {
|
|
3573
4554
|
onError?.(error);
|
|
3574
4555
|
setErrorMessage(error.getUserMessage());
|
|
@@ -3576,10 +4557,10 @@ function LumirEditor({
|
|
|
3576
4557
|
},
|
|
3577
4558
|
[onError]
|
|
3578
4559
|
);
|
|
3579
|
-
const validatedContent =
|
|
4560
|
+
const validatedContent = useMemo6(() => {
|
|
3580
4561
|
return ContentUtils.validateContent(initialContent, initialEmptyBlocks);
|
|
3581
4562
|
}, [initialContent, initialEmptyBlocks]);
|
|
3582
|
-
const tableConfig =
|
|
4563
|
+
const tableConfig = useMemo6(() => {
|
|
3583
4564
|
return EditorConfig.getDefaultTableConfig(tables);
|
|
3584
4565
|
}, [
|
|
3585
4566
|
tables?.splitCells,
|
|
@@ -3587,10 +4568,10 @@ function LumirEditor({
|
|
|
3587
4568
|
tables?.cellTextColor,
|
|
3588
4569
|
tables?.headers
|
|
3589
4570
|
]);
|
|
3590
|
-
const headingConfig =
|
|
4571
|
+
const headingConfig = useMemo6(() => {
|
|
3591
4572
|
return EditorConfig.getDefaultHeadingConfig(heading);
|
|
3592
4573
|
}, [heading?.levels?.join(",") ?? ""]);
|
|
3593
|
-
const disabledExtensions =
|
|
4574
|
+
const disabledExtensions = useMemo6(() => {
|
|
3594
4575
|
return EditorConfig.getDisabledExtensions(
|
|
3595
4576
|
disableExtensions,
|
|
3596
4577
|
allowVideoUpload,
|
|
@@ -3598,18 +4579,18 @@ function LumirEditor({
|
|
|
3598
4579
|
allowFileUpload
|
|
3599
4580
|
);
|
|
3600
4581
|
}, [disableExtensions, allowVideoUpload, allowAudioUpload, allowFileUpload]);
|
|
3601
|
-
|
|
4582
|
+
useEffect10(() => {
|
|
3602
4583
|
DEBUG_LOG("LumirEditor:init:disabledExtensions", "snapshot", {
|
|
3603
4584
|
allowVideoUpload,
|
|
3604
4585
|
hasVideoInDisabled: disabledExtensions.includes("video"),
|
|
3605
4586
|
disabledList: disabledExtensions.slice(0, 15)
|
|
3606
4587
|
});
|
|
3607
4588
|
}, [allowVideoUpload, disabledExtensions]);
|
|
3608
|
-
const fileNameTransformRef =
|
|
3609
|
-
|
|
4589
|
+
const fileNameTransformRef = useRef11(s3Upload?.fileNameTransform);
|
|
4590
|
+
useEffect10(() => {
|
|
3610
4591
|
fileNameTransformRef.current = s3Upload?.fileNameTransform;
|
|
3611
4592
|
}, [s3Upload?.fileNameTransform]);
|
|
3612
|
-
const memoizedS3Upload =
|
|
4593
|
+
const memoizedS3Upload = useMemo6(() => {
|
|
3613
4594
|
if (!s3Upload) return void 0;
|
|
3614
4595
|
return {
|
|
3615
4596
|
apiEndpoint: s3Upload.apiEndpoint,
|
|
@@ -3642,6 +4623,15 @@ function LumirEditor({
|
|
|
3642
4623
|
{
|
|
3643
4624
|
// HTML 미리보기 블록이 포함된 커스텀 스키마 사용
|
|
3644
4625
|
schema,
|
|
4626
|
+
// 모든 BlockNote UI 텍스트(테이블 드롭다운 등) 한글 적용 + "색깔"→"색"
|
|
4627
|
+
dictionary: {
|
|
4628
|
+
...ko,
|
|
4629
|
+
drag_handle: { ...ko.drag_handle, colors_menuitem: "\uC0C9" },
|
|
4630
|
+
formatting_toolbar: {
|
|
4631
|
+
...ko.formatting_toolbar,
|
|
4632
|
+
colors: { ...ko.formatting_toolbar.colors, tooltip: "\uC0C9" }
|
|
4633
|
+
}
|
|
4634
|
+
},
|
|
3645
4635
|
initialContent: validatedContent,
|
|
3646
4636
|
tables: tableConfig,
|
|
3647
4637
|
heading: headingConfig,
|
|
@@ -3749,6 +4739,16 @@ function LumirEditor({
|
|
|
3749
4739
|
return true;
|
|
3750
4740
|
}
|
|
3751
4741
|
}
|
|
4742
|
+
const pastedHtml = event?.clipboardData?.getData?.("text/html") || "";
|
|
4743
|
+
if (/<table[\s>]/i.test(pastedHtml)) {
|
|
4744
|
+
DEBUG_LOG("paste:step0:table", "table HTML detected, using pasteHTML", {
|
|
4745
|
+
htmlLen: pastedHtml.length,
|
|
4746
|
+
hasFiles: !!event?.clipboardData?.files?.length
|
|
4747
|
+
});
|
|
4748
|
+
event.preventDefault();
|
|
4749
|
+
editor2.pasteHTML(normalizeExcelTableHtml(pastedHtml));
|
|
4750
|
+
return true;
|
|
4751
|
+
}
|
|
3752
4752
|
const fileList = event?.clipboardData?.files ?? null;
|
|
3753
4753
|
const files = fileList ? Array.from(fileList) : [];
|
|
3754
4754
|
const acceptedFiles = files.filter(
|
|
@@ -3823,12 +4823,12 @@ function LumirEditor({
|
|
|
3823
4823
|
if (editor && linkPreview?.apiEndpoint) {
|
|
3824
4824
|
editor._linkPreviewApiEndpoint = linkPreview.apiEndpoint;
|
|
3825
4825
|
}
|
|
3826
|
-
|
|
4826
|
+
useEffect10(() => {
|
|
3827
4827
|
if (editor) {
|
|
3828
4828
|
editor.isEditable = editable;
|
|
3829
4829
|
}
|
|
3830
4830
|
}, [editor, editable]);
|
|
3831
|
-
|
|
4831
|
+
useEffect10(() => {
|
|
3832
4832
|
if (!editor || !onContentChange) return;
|
|
3833
4833
|
const handleContentChange = () => {
|
|
3834
4834
|
const blocks = editor.topLevelBlocks;
|
|
@@ -3837,13 +4837,13 @@ function LumirEditor({
|
|
|
3837
4837
|
};
|
|
3838
4838
|
return editor.onEditorContentChange(handleContentChange);
|
|
3839
4839
|
}, [editor, onContentChange]);
|
|
3840
|
-
const previousMediaUrlsRef =
|
|
3841
|
-
|
|
4840
|
+
const previousMediaUrlsRef = useRef11(/* @__PURE__ */ new Set());
|
|
4841
|
+
useEffect10(() => {
|
|
3842
4842
|
if (!editor) return;
|
|
3843
4843
|
const initialBlocks = editor.topLevelBlocks;
|
|
3844
4844
|
previousMediaUrlsRef.current = extractMediaUrls(initialBlocks);
|
|
3845
4845
|
}, [editor]);
|
|
3846
|
-
|
|
4846
|
+
useEffect10(() => {
|
|
3847
4847
|
if (!editor || !onImageDelete) return;
|
|
3848
4848
|
const handleMediaDeleteCheck = () => {
|
|
3849
4849
|
const currentBlocks = editor.topLevelBlocks;
|
|
@@ -3857,7 +4857,7 @@ function LumirEditor({
|
|
|
3857
4857
|
};
|
|
3858
4858
|
return editor.onEditorContentChange(handleMediaDeleteCheck);
|
|
3859
4859
|
}, [editor, onImageDelete]);
|
|
3860
|
-
|
|
4860
|
+
useEffect10(() => {
|
|
3861
4861
|
const el = editor?.domElement;
|
|
3862
4862
|
if (!el) return;
|
|
3863
4863
|
const handleDragOver = (e) => {
|
|
@@ -3988,20 +4988,20 @@ function LumirEditor({
|
|
|
3988
4988
|
el.removeEventListener("drop", handleDrop, { capture: true });
|
|
3989
4989
|
};
|
|
3990
4990
|
}, [editor, allowVideoUpload]);
|
|
3991
|
-
const computedSideMenu =
|
|
4991
|
+
const computedSideMenu = useMemo6(() => {
|
|
3992
4992
|
return sideMenuAddButton ? sideMenu : false;
|
|
3993
4993
|
}, [sideMenuAddButton, sideMenu]);
|
|
3994
|
-
const DragHandleOnlySideMenu =
|
|
3995
|
-
return (props) => /* @__PURE__ */
|
|
4994
|
+
const DragHandleOnlySideMenu = useMemo6(() => {
|
|
4995
|
+
return (props) => /* @__PURE__ */ jsx22(BlockSideMenu, { ...props, children: /* @__PURE__ */ jsx22(DragHandleButton, { ...props }) });
|
|
3996
4996
|
}, []);
|
|
3997
|
-
return /* @__PURE__ */
|
|
4997
|
+
return /* @__PURE__ */ jsxs15(
|
|
3998
4998
|
"div",
|
|
3999
4999
|
{
|
|
4000
5000
|
className: cn("lumirEditor", className),
|
|
4001
5001
|
style: { position: "relative", display: "flex", flexDirection: "column" },
|
|
4002
5002
|
children: [
|
|
4003
|
-
floatingMenu && editor && /* @__PURE__ */
|
|
4004
|
-
/* @__PURE__ */
|
|
5003
|
+
floatingMenu && editor && /* @__PURE__ */ jsxs15(Fragment7, { children: [
|
|
5004
|
+
/* @__PURE__ */ jsx22(
|
|
4005
5005
|
"input",
|
|
4006
5006
|
{
|
|
4007
5007
|
ref: floatingMenuFileInputRef,
|
|
@@ -4072,7 +5072,7 @@ function LumirEditor({
|
|
|
4072
5072
|
}
|
|
4073
5073
|
}
|
|
4074
5074
|
),
|
|
4075
|
-
/* @__PURE__ */
|
|
5075
|
+
/* @__PURE__ */ jsx22(
|
|
4076
5076
|
FloatingMenu,
|
|
4077
5077
|
{
|
|
4078
5078
|
editor,
|
|
@@ -4104,7 +5104,7 @@ function LumirEditor({
|
|
|
4104
5104
|
}
|
|
4105
5105
|
)
|
|
4106
5106
|
] }),
|
|
4107
|
-
/* @__PURE__ */
|
|
5107
|
+
/* @__PURE__ */ jsxs15(
|
|
4108
5108
|
BlockNoteView,
|
|
4109
5109
|
{
|
|
4110
5110
|
editor,
|
|
@@ -4116,21 +5116,22 @@ function LumirEditor({
|
|
|
4116
5116
|
slashMenu: false,
|
|
4117
5117
|
emojiPicker,
|
|
4118
5118
|
filePanel,
|
|
4119
|
-
tableHandles,
|
|
5119
|
+
tableHandles: false,
|
|
4120
5120
|
onSelectionChange,
|
|
4121
5121
|
children: [
|
|
4122
|
-
|
|
5122
|
+
tableHandles && /* @__PURE__ */ jsx22(LumirTableHandlesController, {}),
|
|
5123
|
+
formattingToolbar && /* @__PURE__ */ jsx22(
|
|
4123
5124
|
FormattingToolbarController,
|
|
4124
5125
|
{
|
|
4125
5126
|
formattingToolbar: CustomFormattingToolbar
|
|
4126
5127
|
}
|
|
4127
5128
|
),
|
|
4128
|
-
linkToolbar && (linkPreview?.apiEndpoint ? /* @__PURE__ */
|
|
4129
|
-
/* @__PURE__ */
|
|
5129
|
+
linkToolbar && (linkPreview?.apiEndpoint ? /* @__PURE__ */ jsx22(LinkToolbarController, { linkToolbar: CustomLinkToolbar }) : /* @__PURE__ */ jsx22(LinkToolbarController, {})),
|
|
5130
|
+
/* @__PURE__ */ jsx22(
|
|
4130
5131
|
SuggestionMenuController,
|
|
4131
5132
|
{
|
|
4132
5133
|
triggerCharacter: "/",
|
|
4133
|
-
getItems:
|
|
5134
|
+
getItems: useCallback18(
|
|
4134
5135
|
async (query) => {
|
|
4135
5136
|
const items = getDefaultReactSlashMenuItems(editor);
|
|
4136
5137
|
const filtered = items.filter((item) => {
|
|
@@ -4174,7 +5175,7 @@ function LumirEditor({
|
|
|
4174
5175
|
},
|
|
4175
5176
|
aliases: ["html", "preview", "\uC6F9", "\uC6F9\uD398\uC774\uC9C0"],
|
|
4176
5177
|
group: "Embeds",
|
|
4177
|
-
icon: /* @__PURE__ */
|
|
5178
|
+
icon: /* @__PURE__ */ jsxs15(
|
|
4178
5179
|
"svg",
|
|
4179
5180
|
{
|
|
4180
5181
|
width: "18",
|
|
@@ -4186,8 +5187,8 @@ function LumirEditor({
|
|
|
4186
5187
|
strokeLinecap: "round",
|
|
4187
5188
|
strokeLinejoin: "round",
|
|
4188
5189
|
children: [
|
|
4189
|
-
/* @__PURE__ */
|
|
4190
|
-
/* @__PURE__ */
|
|
5190
|
+
/* @__PURE__ */ jsx22("polyline", { points: "16 18 22 12 16 6" }),
|
|
5191
|
+
/* @__PURE__ */ jsx22("polyline", { points: "8 6 2 12 8 18" })
|
|
4191
5192
|
]
|
|
4192
5193
|
}
|
|
4193
5194
|
),
|
|
@@ -4212,7 +5213,7 @@ function LumirEditor({
|
|
|
4212
5213
|
"\uD504\uB9AC\uBDF0"
|
|
4213
5214
|
],
|
|
4214
5215
|
group: "Embeds",
|
|
4215
|
-
icon: /* @__PURE__ */
|
|
5216
|
+
icon: /* @__PURE__ */ jsxs15(
|
|
4216
5217
|
"svg",
|
|
4217
5218
|
{
|
|
4218
5219
|
width: "18",
|
|
@@ -4224,14 +5225,31 @@ function LumirEditor({
|
|
|
4224
5225
|
strokeLinecap: "round",
|
|
4225
5226
|
strokeLinejoin: "round",
|
|
4226
5227
|
children: [
|
|
4227
|
-
/* @__PURE__ */
|
|
4228
|
-
/* @__PURE__ */
|
|
5228
|
+
/* @__PURE__ */ jsx22("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
|
|
5229
|
+
/* @__PURE__ */ jsx22("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
|
|
4229
5230
|
]
|
|
4230
5231
|
}
|
|
4231
5232
|
),
|
|
4232
5233
|
subtext: "URL\uC758 \uBBF8\uB9AC\uBCF4\uAE30 \uCE74\uB4DC\uB97C \uC0BD\uC785"
|
|
4233
5234
|
});
|
|
4234
5235
|
}
|
|
5236
|
+
const enSlash = en.slash_menu;
|
|
5237
|
+
for (const it of allItems) {
|
|
5238
|
+
const enEntry = it.key ? enSlash[it.key] : void 0;
|
|
5239
|
+
if (!enEntry) continue;
|
|
5240
|
+
const extra = [...enEntry.aliases ?? [], enEntry.title].filter((s) => Boolean(s)).map((s) => s.toLowerCase());
|
|
5241
|
+
it.aliases = Array.from(
|
|
5242
|
+
/* @__PURE__ */ new Set([...it.aliases ?? [], ...extra])
|
|
5243
|
+
);
|
|
5244
|
+
}
|
|
5245
|
+
const groupOrder = [];
|
|
5246
|
+
for (const it of allItems) {
|
|
5247
|
+
const g = it.group ?? "";
|
|
5248
|
+
if (!groupOrder.includes(g)) groupOrder.push(g);
|
|
5249
|
+
}
|
|
5250
|
+
allItems.sort(
|
|
5251
|
+
(a, b) => groupOrder.indexOf(a.group ?? "") - groupOrder.indexOf(b.group ?? "")
|
|
5252
|
+
);
|
|
4235
5253
|
if (!query) return allItems;
|
|
4236
5254
|
const q = query.toLowerCase();
|
|
4237
5255
|
return allItems.filter(
|
|
@@ -4244,21 +5262,21 @@ function LumirEditor({
|
|
|
4244
5262
|
)
|
|
4245
5263
|
}
|
|
4246
5264
|
),
|
|
4247
|
-
!sideMenuAddButton && /* @__PURE__ */
|
|
5265
|
+
!sideMenuAddButton && /* @__PURE__ */ jsx22(SideMenuController, { sideMenu: DragHandleOnlySideMenu })
|
|
4248
5266
|
]
|
|
4249
5267
|
}
|
|
4250
5268
|
),
|
|
4251
|
-
isUploading && /* @__PURE__ */
|
|
4252
|
-
/* @__PURE__ */
|
|
4253
|
-
uploadProgress !== null && /* @__PURE__ */
|
|
5269
|
+
isUploading && /* @__PURE__ */ jsxs15("div", { className: "lumirEditor-upload-overlay", children: [
|
|
5270
|
+
/* @__PURE__ */ jsx22("div", { className: "lumirEditor-spinner" }),
|
|
5271
|
+
uploadProgress !== null && /* @__PURE__ */ jsxs15("span", { className: "lumirEditor-upload-progress", children: [
|
|
4254
5272
|
uploadProgress,
|
|
4255
5273
|
"%"
|
|
4256
5274
|
] })
|
|
4257
5275
|
] }),
|
|
4258
|
-
errorMessage && /* @__PURE__ */
|
|
4259
|
-
/* @__PURE__ */
|
|
4260
|
-
/* @__PURE__ */
|
|
4261
|
-
/* @__PURE__ */
|
|
5276
|
+
errorMessage && /* @__PURE__ */ jsxs15("div", { className: "lumirEditor-error-toast", children: [
|
|
5277
|
+
/* @__PURE__ */ jsx22("span", { className: "lumirEditor-error-icon", children: "\u26A0\uFE0F" }),
|
|
5278
|
+
/* @__PURE__ */ jsx22("span", { className: "lumirEditor-error-message", children: errorMessage }),
|
|
5279
|
+
/* @__PURE__ */ jsx22(
|
|
4262
5280
|
"button",
|
|
4263
5281
|
{
|
|
4264
5282
|
className: "lumirEditor-error-close",
|