@lumir-company/editor 0.4.14 → 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 +85 -8
- package/dist/index.js +885 -128
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +899 -120
- package/dist/index.mjs.map +1 -1
- package/dist/style.css +241 -41
- package/package.json +4 -2
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;
|
|
@@ -3479,7 +4231,7 @@ var ALLOWED_VIDEO_EXTENSIONS = [
|
|
|
3479
4231
|
];
|
|
3480
4232
|
|
|
3481
4233
|
// src/components/LumirEditor.tsx
|
|
3482
|
-
import { Fragment as
|
|
4234
|
+
import { Fragment as Fragment7, jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
3483
4235
|
var DEBUG_LOG = (loc, msg, data) => {
|
|
3484
4236
|
const p = fetch("http://127.0.0.1:7686/ingest/1f8ee1c5-0cf0-4ae7-91ed-5ea7ed17130a", {
|
|
3485
4237
|
method: "POST",
|
|
@@ -3704,9 +4456,9 @@ var findBlockWithLink = (blocks, targetUrl) => {
|
|
|
3704
4456
|
return null;
|
|
3705
4457
|
};
|
|
3706
4458
|
var ConvertToPreviewButton = ({ url }) => {
|
|
3707
|
-
const editor =
|
|
3708
|
-
const Components =
|
|
3709
|
-
return /* @__PURE__ */
|
|
4459
|
+
const editor = useBlockNoteEditor5();
|
|
4460
|
+
const Components = useComponentsContext4();
|
|
4461
|
+
return /* @__PURE__ */ jsx22(
|
|
3710
4462
|
Components.LinkToolbar.Button,
|
|
3711
4463
|
{
|
|
3712
4464
|
className: "bn-button",
|
|
@@ -3725,29 +4477,29 @@ var ConvertToPreviewButton = ({ url }) => {
|
|
|
3725
4477
|
console.error("Convert to link preview failed:", err);
|
|
3726
4478
|
}
|
|
3727
4479
|
},
|
|
3728
|
-
icon: /* @__PURE__ */
|
|
3729
|
-
/* @__PURE__ */
|
|
3730
|
-
/* @__PURE__ */
|
|
3731
|
-
/* @__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" })
|
|
3732
4484
|
] })
|
|
3733
4485
|
}
|
|
3734
4486
|
);
|
|
3735
4487
|
};
|
|
3736
4488
|
var CustomLinkToolbar = (props) => {
|
|
3737
|
-
const editor =
|
|
3738
|
-
const Components =
|
|
4489
|
+
const editor = useBlockNoteEditor5();
|
|
4490
|
+
const Components = useComponentsContext4();
|
|
3739
4491
|
const hasLinkPreview = !!editor?._linkPreviewApiEndpoint;
|
|
3740
|
-
return /* @__PURE__ */
|
|
4492
|
+
return /* @__PURE__ */ jsxs15(
|
|
3741
4493
|
Components.LinkToolbar.Root,
|
|
3742
4494
|
{
|
|
3743
4495
|
className: "bn-toolbar bn-link-toolbar",
|
|
3744
4496
|
onMouseEnter: props.stopHideTimer,
|
|
3745
4497
|
onMouseLeave: props.startHideTimer,
|
|
3746
4498
|
children: [
|
|
3747
|
-
/* @__PURE__ */
|
|
3748
|
-
/* @__PURE__ */
|
|
3749
|
-
/* @__PURE__ */
|
|
3750
|
-
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 })
|
|
3751
4503
|
]
|
|
3752
4504
|
}
|
|
3753
4505
|
);
|
|
@@ -3791,13 +4543,13 @@ function LumirEditor({
|
|
|
3791
4543
|
onError,
|
|
3792
4544
|
onImageDelete
|
|
3793
4545
|
}) {
|
|
3794
|
-
const [isUploading, setIsUploading] =
|
|
3795
|
-
const [uploadProgress, setUploadProgress] =
|
|
3796
|
-
const [errorMessage, setErrorMessage] =
|
|
3797
|
-
const floatingMenuFileInputRef =
|
|
3798
|
-
const floatingMenuBlockRef =
|
|
3799
|
-
const floatingMenuUploadStartTimeRef =
|
|
3800
|
-
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(
|
|
3801
4553
|
(error) => {
|
|
3802
4554
|
onError?.(error);
|
|
3803
4555
|
setErrorMessage(error.getUserMessage());
|
|
@@ -3805,10 +4557,10 @@ function LumirEditor({
|
|
|
3805
4557
|
},
|
|
3806
4558
|
[onError]
|
|
3807
4559
|
);
|
|
3808
|
-
const validatedContent =
|
|
4560
|
+
const validatedContent = useMemo6(() => {
|
|
3809
4561
|
return ContentUtils.validateContent(initialContent, initialEmptyBlocks);
|
|
3810
4562
|
}, [initialContent, initialEmptyBlocks]);
|
|
3811
|
-
const tableConfig =
|
|
4563
|
+
const tableConfig = useMemo6(() => {
|
|
3812
4564
|
return EditorConfig.getDefaultTableConfig(tables);
|
|
3813
4565
|
}, [
|
|
3814
4566
|
tables?.splitCells,
|
|
@@ -3816,10 +4568,10 @@ function LumirEditor({
|
|
|
3816
4568
|
tables?.cellTextColor,
|
|
3817
4569
|
tables?.headers
|
|
3818
4570
|
]);
|
|
3819
|
-
const headingConfig =
|
|
4571
|
+
const headingConfig = useMemo6(() => {
|
|
3820
4572
|
return EditorConfig.getDefaultHeadingConfig(heading);
|
|
3821
4573
|
}, [heading?.levels?.join(",") ?? ""]);
|
|
3822
|
-
const disabledExtensions =
|
|
4574
|
+
const disabledExtensions = useMemo6(() => {
|
|
3823
4575
|
return EditorConfig.getDisabledExtensions(
|
|
3824
4576
|
disableExtensions,
|
|
3825
4577
|
allowVideoUpload,
|
|
@@ -3827,18 +4579,18 @@ function LumirEditor({
|
|
|
3827
4579
|
allowFileUpload
|
|
3828
4580
|
);
|
|
3829
4581
|
}, [disableExtensions, allowVideoUpload, allowAudioUpload, allowFileUpload]);
|
|
3830
|
-
|
|
4582
|
+
useEffect10(() => {
|
|
3831
4583
|
DEBUG_LOG("LumirEditor:init:disabledExtensions", "snapshot", {
|
|
3832
4584
|
allowVideoUpload,
|
|
3833
4585
|
hasVideoInDisabled: disabledExtensions.includes("video"),
|
|
3834
4586
|
disabledList: disabledExtensions.slice(0, 15)
|
|
3835
4587
|
});
|
|
3836
4588
|
}, [allowVideoUpload, disabledExtensions]);
|
|
3837
|
-
const fileNameTransformRef =
|
|
3838
|
-
|
|
4589
|
+
const fileNameTransformRef = useRef11(s3Upload?.fileNameTransform);
|
|
4590
|
+
useEffect10(() => {
|
|
3839
4591
|
fileNameTransformRef.current = s3Upload?.fileNameTransform;
|
|
3840
4592
|
}, [s3Upload?.fileNameTransform]);
|
|
3841
|
-
const memoizedS3Upload =
|
|
4593
|
+
const memoizedS3Upload = useMemo6(() => {
|
|
3842
4594
|
if (!s3Upload) return void 0;
|
|
3843
4595
|
return {
|
|
3844
4596
|
apiEndpoint: s3Upload.apiEndpoint,
|
|
@@ -3871,6 +4623,15 @@ function LumirEditor({
|
|
|
3871
4623
|
{
|
|
3872
4624
|
// HTML 미리보기 블록이 포함된 커스텀 스키마 사용
|
|
3873
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
|
+
},
|
|
3874
4635
|
initialContent: validatedContent,
|
|
3875
4636
|
tables: tableConfig,
|
|
3876
4637
|
heading: headingConfig,
|
|
@@ -4062,12 +4823,12 @@ function LumirEditor({
|
|
|
4062
4823
|
if (editor && linkPreview?.apiEndpoint) {
|
|
4063
4824
|
editor._linkPreviewApiEndpoint = linkPreview.apiEndpoint;
|
|
4064
4825
|
}
|
|
4065
|
-
|
|
4826
|
+
useEffect10(() => {
|
|
4066
4827
|
if (editor) {
|
|
4067
4828
|
editor.isEditable = editable;
|
|
4068
4829
|
}
|
|
4069
4830
|
}, [editor, editable]);
|
|
4070
|
-
|
|
4831
|
+
useEffect10(() => {
|
|
4071
4832
|
if (!editor || !onContentChange) return;
|
|
4072
4833
|
const handleContentChange = () => {
|
|
4073
4834
|
const blocks = editor.topLevelBlocks;
|
|
@@ -4076,13 +4837,13 @@ function LumirEditor({
|
|
|
4076
4837
|
};
|
|
4077
4838
|
return editor.onEditorContentChange(handleContentChange);
|
|
4078
4839
|
}, [editor, onContentChange]);
|
|
4079
|
-
const previousMediaUrlsRef =
|
|
4080
|
-
|
|
4840
|
+
const previousMediaUrlsRef = useRef11(/* @__PURE__ */ new Set());
|
|
4841
|
+
useEffect10(() => {
|
|
4081
4842
|
if (!editor) return;
|
|
4082
4843
|
const initialBlocks = editor.topLevelBlocks;
|
|
4083
4844
|
previousMediaUrlsRef.current = extractMediaUrls(initialBlocks);
|
|
4084
4845
|
}, [editor]);
|
|
4085
|
-
|
|
4846
|
+
useEffect10(() => {
|
|
4086
4847
|
if (!editor || !onImageDelete) return;
|
|
4087
4848
|
const handleMediaDeleteCheck = () => {
|
|
4088
4849
|
const currentBlocks = editor.topLevelBlocks;
|
|
@@ -4096,7 +4857,7 @@ function LumirEditor({
|
|
|
4096
4857
|
};
|
|
4097
4858
|
return editor.onEditorContentChange(handleMediaDeleteCheck);
|
|
4098
4859
|
}, [editor, onImageDelete]);
|
|
4099
|
-
|
|
4860
|
+
useEffect10(() => {
|
|
4100
4861
|
const el = editor?.domElement;
|
|
4101
4862
|
if (!el) return;
|
|
4102
4863
|
const handleDragOver = (e) => {
|
|
@@ -4227,20 +4988,20 @@ function LumirEditor({
|
|
|
4227
4988
|
el.removeEventListener("drop", handleDrop, { capture: true });
|
|
4228
4989
|
};
|
|
4229
4990
|
}, [editor, allowVideoUpload]);
|
|
4230
|
-
const computedSideMenu =
|
|
4991
|
+
const computedSideMenu = useMemo6(() => {
|
|
4231
4992
|
return sideMenuAddButton ? sideMenu : false;
|
|
4232
4993
|
}, [sideMenuAddButton, sideMenu]);
|
|
4233
|
-
const DragHandleOnlySideMenu =
|
|
4234
|
-
return (props) => /* @__PURE__ */
|
|
4994
|
+
const DragHandleOnlySideMenu = useMemo6(() => {
|
|
4995
|
+
return (props) => /* @__PURE__ */ jsx22(BlockSideMenu, { ...props, children: /* @__PURE__ */ jsx22(DragHandleButton, { ...props }) });
|
|
4235
4996
|
}, []);
|
|
4236
|
-
return /* @__PURE__ */
|
|
4997
|
+
return /* @__PURE__ */ jsxs15(
|
|
4237
4998
|
"div",
|
|
4238
4999
|
{
|
|
4239
5000
|
className: cn("lumirEditor", className),
|
|
4240
5001
|
style: { position: "relative", display: "flex", flexDirection: "column" },
|
|
4241
5002
|
children: [
|
|
4242
|
-
floatingMenu && editor && /* @__PURE__ */
|
|
4243
|
-
/* @__PURE__ */
|
|
5003
|
+
floatingMenu && editor && /* @__PURE__ */ jsxs15(Fragment7, { children: [
|
|
5004
|
+
/* @__PURE__ */ jsx22(
|
|
4244
5005
|
"input",
|
|
4245
5006
|
{
|
|
4246
5007
|
ref: floatingMenuFileInputRef,
|
|
@@ -4311,7 +5072,7 @@ function LumirEditor({
|
|
|
4311
5072
|
}
|
|
4312
5073
|
}
|
|
4313
5074
|
),
|
|
4314
|
-
/* @__PURE__ */
|
|
5075
|
+
/* @__PURE__ */ jsx22(
|
|
4315
5076
|
FloatingMenu,
|
|
4316
5077
|
{
|
|
4317
5078
|
editor,
|
|
@@ -4343,7 +5104,7 @@ function LumirEditor({
|
|
|
4343
5104
|
}
|
|
4344
5105
|
)
|
|
4345
5106
|
] }),
|
|
4346
|
-
/* @__PURE__ */
|
|
5107
|
+
/* @__PURE__ */ jsxs15(
|
|
4347
5108
|
BlockNoteView,
|
|
4348
5109
|
{
|
|
4349
5110
|
editor,
|
|
@@ -4355,21 +5116,22 @@ function LumirEditor({
|
|
|
4355
5116
|
slashMenu: false,
|
|
4356
5117
|
emojiPicker,
|
|
4357
5118
|
filePanel,
|
|
4358
|
-
tableHandles,
|
|
5119
|
+
tableHandles: false,
|
|
4359
5120
|
onSelectionChange,
|
|
4360
5121
|
children: [
|
|
4361
|
-
|
|
5122
|
+
tableHandles && /* @__PURE__ */ jsx22(LumirTableHandlesController, {}),
|
|
5123
|
+
formattingToolbar && /* @__PURE__ */ jsx22(
|
|
4362
5124
|
FormattingToolbarController,
|
|
4363
5125
|
{
|
|
4364
5126
|
formattingToolbar: CustomFormattingToolbar
|
|
4365
5127
|
}
|
|
4366
5128
|
),
|
|
4367
|
-
linkToolbar && (linkPreview?.apiEndpoint ? /* @__PURE__ */
|
|
4368
|
-
/* @__PURE__ */
|
|
5129
|
+
linkToolbar && (linkPreview?.apiEndpoint ? /* @__PURE__ */ jsx22(LinkToolbarController, { linkToolbar: CustomLinkToolbar }) : /* @__PURE__ */ jsx22(LinkToolbarController, {})),
|
|
5130
|
+
/* @__PURE__ */ jsx22(
|
|
4369
5131
|
SuggestionMenuController,
|
|
4370
5132
|
{
|
|
4371
5133
|
triggerCharacter: "/",
|
|
4372
|
-
getItems:
|
|
5134
|
+
getItems: useCallback18(
|
|
4373
5135
|
async (query) => {
|
|
4374
5136
|
const items = getDefaultReactSlashMenuItems(editor);
|
|
4375
5137
|
const filtered = items.filter((item) => {
|
|
@@ -4413,7 +5175,7 @@ function LumirEditor({
|
|
|
4413
5175
|
},
|
|
4414
5176
|
aliases: ["html", "preview", "\uC6F9", "\uC6F9\uD398\uC774\uC9C0"],
|
|
4415
5177
|
group: "Embeds",
|
|
4416
|
-
icon: /* @__PURE__ */
|
|
5178
|
+
icon: /* @__PURE__ */ jsxs15(
|
|
4417
5179
|
"svg",
|
|
4418
5180
|
{
|
|
4419
5181
|
width: "18",
|
|
@@ -4425,8 +5187,8 @@ function LumirEditor({
|
|
|
4425
5187
|
strokeLinecap: "round",
|
|
4426
5188
|
strokeLinejoin: "round",
|
|
4427
5189
|
children: [
|
|
4428
|
-
/* @__PURE__ */
|
|
4429
|
-
/* @__PURE__ */
|
|
5190
|
+
/* @__PURE__ */ jsx22("polyline", { points: "16 18 22 12 16 6" }),
|
|
5191
|
+
/* @__PURE__ */ jsx22("polyline", { points: "8 6 2 12 8 18" })
|
|
4430
5192
|
]
|
|
4431
5193
|
}
|
|
4432
5194
|
),
|
|
@@ -4451,7 +5213,7 @@ function LumirEditor({
|
|
|
4451
5213
|
"\uD504\uB9AC\uBDF0"
|
|
4452
5214
|
],
|
|
4453
5215
|
group: "Embeds",
|
|
4454
|
-
icon: /* @__PURE__ */
|
|
5216
|
+
icon: /* @__PURE__ */ jsxs15(
|
|
4455
5217
|
"svg",
|
|
4456
5218
|
{
|
|
4457
5219
|
width: "18",
|
|
@@ -4463,14 +5225,31 @@ function LumirEditor({
|
|
|
4463
5225
|
strokeLinecap: "round",
|
|
4464
5226
|
strokeLinejoin: "round",
|
|
4465
5227
|
children: [
|
|
4466
|
-
/* @__PURE__ */
|
|
4467
|
-
/* @__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" })
|
|
4468
5230
|
]
|
|
4469
5231
|
}
|
|
4470
5232
|
),
|
|
4471
5233
|
subtext: "URL\uC758 \uBBF8\uB9AC\uBCF4\uAE30 \uCE74\uB4DC\uB97C \uC0BD\uC785"
|
|
4472
5234
|
});
|
|
4473
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
|
+
);
|
|
4474
5253
|
if (!query) return allItems;
|
|
4475
5254
|
const q = query.toLowerCase();
|
|
4476
5255
|
return allItems.filter(
|
|
@@ -4483,21 +5262,21 @@ function LumirEditor({
|
|
|
4483
5262
|
)
|
|
4484
5263
|
}
|
|
4485
5264
|
),
|
|
4486
|
-
!sideMenuAddButton && /* @__PURE__ */
|
|
5265
|
+
!sideMenuAddButton && /* @__PURE__ */ jsx22(SideMenuController, { sideMenu: DragHandleOnlySideMenu })
|
|
4487
5266
|
]
|
|
4488
5267
|
}
|
|
4489
5268
|
),
|
|
4490
|
-
isUploading && /* @__PURE__ */
|
|
4491
|
-
/* @__PURE__ */
|
|
4492
|
-
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: [
|
|
4493
5272
|
uploadProgress,
|
|
4494
5273
|
"%"
|
|
4495
5274
|
] })
|
|
4496
5275
|
] }),
|
|
4497
|
-
errorMessage && /* @__PURE__ */
|
|
4498
|
-
/* @__PURE__ */
|
|
4499
|
-
/* @__PURE__ */
|
|
4500
|
-
/* @__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(
|
|
4501
5280
|
"button",
|
|
4502
5281
|
{
|
|
4503
5282
|
className: "lumirEditor-error-close",
|