@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/dist/index.js CHANGED
@@ -40,10 +40,11 @@ __export(index_exports, {
40
40
  module.exports = __toCommonJS(index_exports);
41
41
 
42
42
  // src/components/LumirEditor.tsx
43
- var import_react23 = require("react");
44
- var import_react24 = require("@blocknote/react");
43
+ var import_react30 = require("react");
44
+ var import_react31 = require("@blocknote/react");
45
45
  var import_mantine = require("@blocknote/mantine");
46
- var import_core4 = require("@blocknote/core");
46
+ var import_core5 = require("@blocknote/core");
47
+ var import_locales = require("@blocknote/core/locales");
47
48
 
48
49
  // src/utils/cn.ts
49
50
  function cn(...inputs) {
@@ -1834,6 +1835,66 @@ var TextStyleButton = ({
1834
1835
 
1835
1836
  // src/components/FloatingMenu/components/AlignButton.tsx
1836
1837
  var import_react9 = require("react");
1838
+
1839
+ // src/utils/prosemirror-table-utils.ts
1840
+ function getSelectedCellPositions(editor) {
1841
+ const tiptap = editor._tiptapEditor;
1842
+ if (!tiptap) return [];
1843
+ const { state } = tiptap;
1844
+ const { selection } = state;
1845
+ if (typeof selection.forEachCell === "function") {
1846
+ const positions = [];
1847
+ selection.forEachCell((_node, pos) => {
1848
+ positions.push(pos);
1849
+ });
1850
+ return positions;
1851
+ }
1852
+ const $pos = selection.$from;
1853
+ for (let depth = $pos.depth; depth > 0; depth--) {
1854
+ const node = $pos.node(depth);
1855
+ if (node.type.name === "tableCell" || node.type.name === "tableHeader") {
1856
+ return [$pos.before(depth)];
1857
+ }
1858
+ }
1859
+ return [];
1860
+ }
1861
+ function setCellAttrAtPositions(editor, positions, attr, value) {
1862
+ const tiptap = editor?._tiptapEditor;
1863
+ if (!tiptap || positions.length === 0) return false;
1864
+ let tr = tiptap.state.tr;
1865
+ let changed = false;
1866
+ for (const pos of positions) {
1867
+ const node = tr.doc.nodeAt(pos);
1868
+ if (node && (node.type.name === "tableCell" || node.type.name === "tableHeader")) {
1869
+ tr = tr.setNodeMarkup(pos, void 0, { ...node.attrs, [attr]: value });
1870
+ changed = true;
1871
+ }
1872
+ }
1873
+ if (changed) {
1874
+ tiptap.view?.dispatch(tr);
1875
+ }
1876
+ return changed;
1877
+ }
1878
+ function setSelectedCellsAttr(editor, attr, value) {
1879
+ return setCellAttrAtPositions(
1880
+ editor,
1881
+ getSelectedCellPositions(editor),
1882
+ attr,
1883
+ value
1884
+ );
1885
+ }
1886
+ function isInTableCell(editor) {
1887
+ return getSelectedCellPositions(editor).length > 0;
1888
+ }
1889
+ function getFirstSelectedCellAttr(editor, attr) {
1890
+ const tiptap = editor?._tiptapEditor;
1891
+ const positions = getSelectedCellPositions(editor);
1892
+ if (!tiptap || positions.length === 0) return void 0;
1893
+ const node = tiptap.state.doc.nodeAt(positions[0]);
1894
+ return node?.attrs?.[attr];
1895
+ }
1896
+
1897
+ // src/components/FloatingMenu/components/AlignButton.tsx
1837
1898
  var import_jsx_runtime8 = require("react/jsx-runtime");
1838
1899
  var iconMap2 = {
1839
1900
  left: Icons.alignLeft,
@@ -1851,6 +1912,9 @@ var AlignButton = ({
1851
1912
  }) => {
1852
1913
  const getCurrentAlignment = () => {
1853
1914
  try {
1915
+ if (isInTableCell(editor)) {
1916
+ return getFirstSelectedCellAttr(editor, "textAlignment") || "left";
1917
+ }
1854
1918
  const block = editor?.getTextCursorPosition()?.block;
1855
1919
  return block?.props?.textAlignment || "left";
1856
1920
  } catch {
@@ -1860,6 +1924,9 @@ var AlignButton = ({
1860
1924
  const isActive = getCurrentAlignment() === alignment;
1861
1925
  const handleClick = (0, import_react9.useCallback)(() => {
1862
1926
  try {
1927
+ if (setSelectedCellsAttr(editor, "textAlignment", alignment)) {
1928
+ return;
1929
+ }
1863
1930
  const block = editor?.getTextCursorPosition()?.block;
1864
1931
  if (block && editor?.updateBlock) {
1865
1932
  editor.updateBlock(block, { props: { textAlignment: alignment } });
@@ -2025,6 +2092,10 @@ var ColorButton = ({ editor, type }) => {
2025
2092
  const colors = type === "text" ? TEXT_COLORS : BACKGROUND_COLORS;
2026
2093
  const getCurrentColor = (0, import_react12.useCallback)(() => {
2027
2094
  try {
2095
+ if (isInTableCell(editor)) {
2096
+ const attr = type === "text" ? "textColor" : "backgroundColor";
2097
+ return getFirstSelectedCellAttr(editor, attr) || "default";
2098
+ }
2028
2099
  const activeStyles = editor?.getActiveStyles?.() || {};
2029
2100
  if (type === "text" && activeStyles.textColor) {
2030
2101
  return activeStyles.textColor;
@@ -2054,13 +2125,15 @@ var ColorButton = ({ editor, type }) => {
2054
2125
  (color) => {
2055
2126
  try {
2056
2127
  if (!editor) return;
2057
- if (type === "text") {
2058
- editor.toggleStyles({ textColor: color });
2059
- } else {
2060
- editor.toggleStyles({ backgroundColor: color });
2128
+ const attr = type === "text" ? "textColor" : "backgroundColor";
2129
+ if (!setSelectedCellsAttr(editor, attr, color)) {
2130
+ editor.toggleStyles(
2131
+ type === "text" ? { textColor: color } : { backgroundColor: color }
2132
+ );
2061
2133
  }
2062
2134
  setCurrentColor(color);
2063
2135
  setIsOpen(false);
2136
+ setTimeout(() => editor.focus?.());
2064
2137
  } catch (err) {
2065
2138
  console.error(`Color apply failed:`, err);
2066
2139
  }
@@ -2864,37 +2937,12 @@ var VerticalAlignmentExtension = import_core2.Extension.create({
2864
2937
  });
2865
2938
 
2866
2939
  // src/components/CustomFormattingToolbar.tsx
2867
- var import_react22 = require("@blocknote/react");
2940
+ var import_react24 = require("@blocknote/react");
2868
2941
 
2869
2942
  // src/components/TextAlignButtonWithVA.tsx
2870
2943
  var import_core3 = require("@blocknote/core");
2871
2944
  var import_react18 = require("react");
2872
2945
  var import_react19 = require("@blocknote/react");
2873
-
2874
- // src/utils/prosemirror-table-utils.ts
2875
- function getSelectedCellPositions(editor) {
2876
- const tiptap = editor._tiptapEditor;
2877
- if (!tiptap) return [];
2878
- const { state } = tiptap;
2879
- const { selection } = state;
2880
- if (typeof selection.forEachCell === "function") {
2881
- const positions = [];
2882
- selection.forEachCell((_node, pos) => {
2883
- positions.push(pos);
2884
- });
2885
- return positions;
2886
- }
2887
- const $pos = selection.$from;
2888
- for (let depth = $pos.depth; depth > 0; depth--) {
2889
- const node = $pos.node(depth);
2890
- if (node.type.name === "tableCell" || node.type.name === "tableHeader") {
2891
- return [$pos.before(depth)];
2892
- }
2893
- }
2894
- return [];
2895
- }
2896
-
2897
- // src/components/TextAlignButtonWithVA.tsx
2898
2946
  var import_jsx_runtime17 = require("react/jsx-runtime");
2899
2947
  var icons = {
2900
2948
  left: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", width: "18", height: "18", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { d: "M15 15H3v2h12v-2zm0-8H3v2h12V7zM3 13h18v-2H3v2zm0 8h18v-2H3v2zM3 3v2h18V3H3z" }) }),
@@ -3071,77 +3119,759 @@ var VerticalAlignButton = (props) => {
3071
3119
  );
3072
3120
  };
3073
3121
 
3074
- // src/components/CustomFormattingToolbar.tsx
3122
+ // src/components/color/LumirColorControls.tsx
3123
+ var import_core4 = require("@blocknote/core");
3124
+ var import_react22 = require("@blocknote/react");
3125
+ var import_react23 = require("react");
3075
3126
  var import_jsx_runtime19 = require("react/jsx-runtime");
3076
- var CustomFormattingToolbar = () => {
3077
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_react22.FormattingToolbar, { children: [
3078
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react22.BlockTypeSelect, {}, "blockTypeSelect"),
3079
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react22.TableCellMergeButton, {}, "tableCellMergeButton"),
3080
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react22.FileCaptionButton, {}, "fileCaptionButton"),
3081
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react22.FileReplaceButton, {}, "replaceFileButton"),
3082
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react22.FileRenameButton, {}, "fileRenameButton"),
3083
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react22.FileDeleteButton, {}, "fileDeleteButton"),
3084
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react22.FileDownloadButton, {}, "fileDownloadButton"),
3085
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react22.FilePreviewButton, {}, "filePreviewButton"),
3086
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react22.BasicTextStyleButton, { basicTextStyle: "bold" }, "boldStyleButton"),
3127
+ var COLORS = [
3128
+ "default",
3129
+ "gray",
3130
+ "brown",
3131
+ "red",
3132
+ "orange",
3133
+ "yellow",
3134
+ "green",
3135
+ "blue",
3136
+ "purple",
3137
+ "pink"
3138
+ ];
3139
+ function ColorIcon(props) {
3140
+ const textColor = props.textColor || "default";
3141
+ const backgroundColor = props.backgroundColor || "default";
3142
+ const size = props.size || 16;
3143
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3144
+ "div",
3145
+ {
3146
+ className: "bn-color-icon",
3147
+ "data-background-color": backgroundColor,
3148
+ "data-text-color": textColor,
3149
+ style: {
3150
+ pointerEvents: "none",
3151
+ fontSize: `${size * 0.75}px`,
3152
+ height: `${size}px`,
3153
+ lineHeight: `${size}px`,
3154
+ textAlign: "center",
3155
+ width: `${size}px`
3156
+ },
3157
+ children: "A"
3158
+ }
3159
+ );
3160
+ }
3161
+ function CellFillIcon({ size = 18 }) {
3162
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3163
+ "svg",
3164
+ {
3165
+ width: size,
3166
+ height: size,
3167
+ viewBox: "0 0 24 24",
3168
+ fill: "currentColor",
3169
+ style: { pointerEvents: "none" },
3170
+ "aria-hidden": "true",
3171
+ children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("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" })
3172
+ }
3173
+ );
3174
+ }
3175
+ function LumirColorPicker(props) {
3176
+ const Components = (0, import_react22.useComponentsContext)();
3177
+ const dict = (0, import_react22.useDictionary)();
3178
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
3179
+ props.text ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
3180
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Components.Generic.Menu.Label, { children: props.textTitle ?? dict.color_picker.text_title }),
3181
+ COLORS.map((color) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3182
+ Components.Generic.Menu.Item,
3183
+ {
3184
+ onClick: () => {
3185
+ props.onClick?.();
3186
+ props.text.setColor(color);
3187
+ },
3188
+ "data-test": "text-color-" + color,
3189
+ icon: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ColorIcon, { textColor: color, size: props.iconSize }),
3190
+ checked: props.text.color === color,
3191
+ children: dict.color_picker.colors[color]
3192
+ },
3193
+ "text-color-" + color
3194
+ ))
3195
+ ] }) : null,
3196
+ props.background ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
3197
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Components.Generic.Menu.Label, { children: props.backgroundTitle ?? dict.color_picker.background_title }),
3198
+ COLORS.map((color) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3199
+ Components.Generic.Menu.Item,
3200
+ {
3201
+ onClick: () => {
3202
+ props.onClick?.();
3203
+ props.background.setColor(color);
3204
+ },
3205
+ "data-test": "background-color-" + color,
3206
+ icon: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ColorIcon, { backgroundColor: color, size: props.iconSize }),
3207
+ checked: props.background.color === color,
3208
+ children: dict.color_picker.colors[color]
3209
+ },
3210
+ "background-color-" + color
3211
+ ))
3212
+ ] }) : null
3213
+ ] });
3214
+ }
3215
+ function LumirColorStyleButton() {
3216
+ const Components = (0, import_react22.useComponentsContext)();
3217
+ const editor = (0, import_react22.useBlockNoteEditor)();
3218
+ const ed = editor;
3219
+ const styleSchema = editor.schema.styleSchema;
3220
+ const textColorInSchema = styleSchema.textColor?.type === "textColor" && styleSchema.textColor?.propSchema === "string";
3221
+ const backgroundColorInSchema = styleSchema.backgroundColor?.type === "backgroundColor" && styleSchema.backgroundColor?.propSchema === "string";
3222
+ const selectedBlocks = (0, import_react22.useSelectedBlocks)(editor);
3223
+ const [currentTextColor, setCurrentTextColor] = (0, import_react23.useState)(
3224
+ textColorInSchema ? ed.getActiveStyles().textColor || "default" : "default"
3225
+ );
3226
+ const [currentBackgroundColor, setCurrentBackgroundColor] = (0, import_react23.useState)(
3227
+ backgroundColorInSchema ? ed.getActiveStyles().backgroundColor || "default" : "default"
3228
+ );
3229
+ (0, import_react22.useEditorContentOrSelectionChange)(() => {
3230
+ const active = ed.getActiveStyles();
3231
+ if (textColorInSchema) {
3232
+ setCurrentTextColor(active.textColor || "default");
3233
+ }
3234
+ if (backgroundColorInSchema) {
3235
+ setCurrentBackgroundColor(active.backgroundColor || "default");
3236
+ }
3237
+ }, editor);
3238
+ const setTextColor = (0, import_react23.useCallback)(
3239
+ (color) => {
3240
+ color === "default" ? ed.removeStyles({ textColor: color }) : ed.addStyles({ textColor: color });
3241
+ setTimeout(() => editor.focus());
3242
+ },
3243
+ // eslint-disable-next-line react-hooks/exhaustive-deps
3244
+ [editor]
3245
+ );
3246
+ const setBackgroundColor = (0, import_react23.useCallback)(
3247
+ (color) => {
3248
+ color === "default" ? ed.removeStyles({ backgroundColor: color }) : ed.addStyles({ backgroundColor: color });
3249
+ setTimeout(() => editor.focus());
3250
+ },
3251
+ // eslint-disable-next-line react-hooks/exhaustive-deps
3252
+ [editor]
3253
+ );
3254
+ const show = (0, import_react23.useMemo)(() => {
3255
+ if (!textColorInSchema && !backgroundColorInSchema) {
3256
+ return false;
3257
+ }
3258
+ for (const block of selectedBlocks) {
3259
+ if (block.content !== void 0) {
3260
+ return true;
3261
+ }
3262
+ }
3263
+ return false;
3264
+ }, [backgroundColorInSchema, selectedBlocks, textColorInSchema]);
3265
+ if (!show || !editor.isEditable) {
3266
+ return null;
3267
+ }
3268
+ const tooltip = "\uD14D\uC2A4\uD2B8 \uC0C9\xB7\uBC30\uACBD";
3269
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(Components.Generic.Menu.Root, { children: [
3270
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Components.Generic.Menu.Trigger, { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3271
+ Components.FormattingToolbar.Button,
3272
+ {
3273
+ className: "bn-button",
3274
+ "data-test": "colors",
3275
+ label: tooltip,
3276
+ mainTooltip: tooltip,
3277
+ icon: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3278
+ ColorIcon,
3279
+ {
3280
+ textColor: currentTextColor,
3281
+ backgroundColor: currentBackgroundColor,
3282
+ size: 20
3283
+ }
3284
+ )
3285
+ }
3286
+ ) }),
3087
3287
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3088
- import_react22.BasicTextStyleButton,
3288
+ Components.Generic.Menu.Dropdown,
3289
+ {
3290
+ className: "bn-menu-dropdown bn-color-picker-dropdown",
3291
+ children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3292
+ LumirColorPicker,
3293
+ {
3294
+ textTitle: "\uD14D\uC2A4\uD2B8 \uC0C9",
3295
+ backgroundTitle: "\uD14D\uC2A4\uD2B8 \uBC30\uACBD",
3296
+ text: textColorInSchema ? { color: currentTextColor, setColor: setTextColor } : void 0,
3297
+ background: backgroundColorInSchema ? { color: currentBackgroundColor, setColor: setBackgroundColor } : void 0
3298
+ }
3299
+ )
3300
+ }
3301
+ )
3302
+ ] });
3303
+ }
3304
+ function LumirCellColorToolbarButton() {
3305
+ const Components = (0, import_react22.useComponentsContext)();
3306
+ const editor = (0, import_react22.useBlockNoteEditor)();
3307
+ const selectedBlocks = (0, import_react22.useSelectedBlocks)(editor);
3308
+ const isMultiCell = (0, import_react23.useMemo)(() => {
3309
+ if (selectedBlocks.length !== 1 || selectedBlocks[0].type !== "table") {
3310
+ return false;
3311
+ }
3312
+ const cs = editor.tableHandles?.getCellSelection();
3313
+ return !!cs && cs.cells.length > 1;
3314
+ }, [editor, selectedBlocks]);
3315
+ const stashRef = (0, import_react23.useRef)([]);
3316
+ const applyBackground = (0, import_react23.useCallback)(
3317
+ (color) => {
3318
+ const live = getSelectedCellPositions(editor);
3319
+ const positions = live.length > 0 ? live : stashRef.current;
3320
+ setCellAttrAtPositions(editor, positions, "backgroundColor", color);
3321
+ setTimeout(() => editor.focus());
3322
+ },
3323
+ [editor]
3324
+ );
3325
+ if (!editor.isEditable || !isMultiCell) {
3326
+ return null;
3327
+ }
3328
+ const tooltip = "\uC140 \uBC30\uACBD\uC0C9";
3329
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
3330
+ Components.Generic.Menu.Root,
3331
+ {
3332
+ onOpenChange: (open) => {
3333
+ if (open) {
3334
+ stashRef.current = getSelectedCellPositions(editor);
3335
+ }
3336
+ },
3337
+ children: [
3338
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Components.Generic.Menu.Trigger, { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3339
+ Components.FormattingToolbar.Button,
3340
+ {
3341
+ className: "bn-button",
3342
+ "data-test": "cell-colors",
3343
+ label: tooltip,
3344
+ mainTooltip: tooltip,
3345
+ icon: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(CellFillIcon, { size: 18 })
3346
+ }
3347
+ ) }),
3348
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3349
+ Components.Generic.Menu.Dropdown,
3350
+ {
3351
+ className: "bn-menu-dropdown bn-color-picker-dropdown",
3352
+ children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3353
+ LumirColorPicker,
3354
+ {
3355
+ backgroundTitle: "\uC140 \uBC30\uACBD",
3356
+ background: { color: "default", setColor: applyBackground }
3357
+ }
3358
+ )
3359
+ }
3360
+ )
3361
+ ]
3362
+ }
3363
+ );
3364
+ }
3365
+ function LumirCellColorPickerButton(props) {
3366
+ const Components = (0, import_react22.useComponentsContext)();
3367
+ const editor = (0, import_react22.useBlockNoteEditor)();
3368
+ const updateColor = (color, type) => {
3369
+ const newTable = props.block.content.rows.map((row) => ({
3370
+ ...row,
3371
+ cells: row.cells.map((cell) => (0, import_core4.mapTableCell)(cell))
3372
+ }));
3373
+ if (type === "text") {
3374
+ newTable[props.rowIndex].cells[props.colIndex].props.textColor = color;
3375
+ } else {
3376
+ newTable[props.rowIndex].cells[props.colIndex].props.backgroundColor = color;
3377
+ }
3378
+ editor.updateBlock(props.block, {
3379
+ type: "table",
3380
+ content: { ...props.block.content, rows: newTable }
3381
+ });
3382
+ editor.setTextCursorPosition(props.block);
3383
+ };
3384
+ const currentCell = props.block.content.rows[props.rowIndex]?.cells?.[props.colIndex];
3385
+ if (!currentCell || editor.settings.tables.cellTextColor === false && editor.settings.tables.cellBackgroundColor === false) {
3386
+ return null;
3387
+ }
3388
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(Components.Generic.Menu.Root, { position: "right", sub: true, children: [
3389
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Components.Generic.Menu.Trigger, { sub: true, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Components.Generic.Menu.Item, { className: "bn-menu-item", subTrigger: true, children: "\uC140 \uC0C9\xB7\uBC30\uACBD" }) }),
3390
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3391
+ Components.Generic.Menu.Dropdown,
3392
+ {
3393
+ sub: true,
3394
+ className: "bn-menu-dropdown bn-color-picker-dropdown",
3395
+ children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3396
+ LumirColorPicker,
3397
+ {
3398
+ iconSize: 18,
3399
+ textTitle: "\uC140 \uAE00\uC790\uC0C9",
3400
+ backgroundTitle: "\uC140 \uBC30\uACBD",
3401
+ text: editor.settings.tables.cellTextColor ? {
3402
+ color: (0, import_core4.isTableCell)(currentCell) ? currentCell.props.textColor : "default",
3403
+ setColor: (color) => updateColor(color, "text")
3404
+ } : void 0,
3405
+ background: editor.settings.tables.cellBackgroundColor ? {
3406
+ color: (0, import_core4.isTableCell)(currentCell) ? currentCell.props.backgroundColor : "default",
3407
+ setColor: (color) => updateColor(color, "background")
3408
+ } : void 0
3409
+ }
3410
+ )
3411
+ }
3412
+ )
3413
+ ] });
3414
+ }
3415
+ function LumirTableCellMenu(props) {
3416
+ const Components = (0, import_react22.useComponentsContext)();
3417
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3418
+ Components.Generic.Menu.Dropdown,
3419
+ {
3420
+ className: "bn-menu-dropdown bn-drag-handle-menu",
3421
+ children: props.children || /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
3422
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3423
+ import_react22.SplitButton,
3424
+ {
3425
+ block: props.block,
3426
+ rowIndex: props.rowIndex,
3427
+ colIndex: props.colIndex
3428
+ }
3429
+ ),
3430
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3431
+ LumirCellColorPickerButton,
3432
+ {
3433
+ block: props.block,
3434
+ rowIndex: props.rowIndex,
3435
+ colIndex: props.colIndex
3436
+ }
3437
+ )
3438
+ ] })
3439
+ }
3440
+ );
3441
+ }
3442
+
3443
+ // src/components/CustomFormattingToolbar.tsx
3444
+ var import_jsx_runtime20 = require("react/jsx-runtime");
3445
+ var CustomFormattingToolbar = () => {
3446
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_react24.FormattingToolbar, { children: [
3447
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react24.BlockTypeSelect, {}, "blockTypeSelect"),
3448
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react24.TableCellMergeButton, {}, "tableCellMergeButton"),
3449
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react24.FileCaptionButton, {}, "fileCaptionButton"),
3450
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react24.FileReplaceButton, {}, "replaceFileButton"),
3451
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react24.FileRenameButton, {}, "fileRenameButton"),
3452
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react24.FileDeleteButton, {}, "fileDeleteButton"),
3453
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react24.FileDownloadButton, {}, "fileDownloadButton"),
3454
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react24.FilePreviewButton, {}, "filePreviewButton"),
3455
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react24.BasicTextStyleButton, { basicTextStyle: "bold" }, "boldStyleButton"),
3456
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
3457
+ import_react24.BasicTextStyleButton,
3089
3458
  {
3090
3459
  basicTextStyle: "italic"
3091
3460
  },
3092
3461
  "italicStyleButton"
3093
3462
  ),
3094
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3095
- import_react22.BasicTextStyleButton,
3463
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
3464
+ import_react24.BasicTextStyleButton,
3096
3465
  {
3097
3466
  basicTextStyle: "underline"
3098
3467
  },
3099
3468
  "underlineStyleButton"
3100
3469
  ),
3101
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3102
- import_react22.BasicTextStyleButton,
3470
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
3471
+ import_react24.BasicTextStyleButton,
3103
3472
  {
3104
3473
  basicTextStyle: "strike"
3105
3474
  },
3106
3475
  "strikeStyleButton"
3107
3476
  ),
3108
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(TextAlignButtonWithVA, { textAlignment: "left" }, "textAlignLeftButton"),
3109
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3477
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TextAlignButtonWithVA, { textAlignment: "left" }, "textAlignLeftButton"),
3478
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
3110
3479
  TextAlignButtonWithVA,
3111
3480
  {
3112
3481
  textAlignment: "center"
3113
3482
  },
3114
3483
  "textAlignCenterButton"
3115
3484
  ),
3116
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(TextAlignButtonWithVA, { textAlignment: "right" }, "textAlignRightButton"),
3117
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3485
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TextAlignButtonWithVA, { textAlignment: "right" }, "textAlignRightButton"),
3486
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
3118
3487
  VerticalAlignButton,
3119
3488
  {
3120
3489
  verticalAlignment: "top"
3121
3490
  },
3122
3491
  "verticalAlignTop"
3123
3492
  ),
3124
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3493
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
3125
3494
  VerticalAlignButton,
3126
3495
  {
3127
3496
  verticalAlignment: "middle"
3128
3497
  },
3129
3498
  "verticalAlignMiddle"
3130
3499
  ),
3131
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3500
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
3132
3501
  VerticalAlignButton,
3133
3502
  {
3134
3503
  verticalAlignment: "bottom"
3135
3504
  },
3136
3505
  "verticalAlignBottom"
3137
3506
  ),
3138
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react22.ColorStyleButton, {}, "colorStyleButton"),
3139
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react22.NestBlockButton, {}, "nestBlockButton"),
3140
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react22.UnnestBlockButton, {}, "unnestBlockButton"),
3141
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react22.CreateLinkButton, {}, "createLinkButton")
3507
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(LumirColorStyleButton, {}, "colorStyleButton"),
3508
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(LumirCellColorToolbarButton, {}, "cellColorButton"),
3509
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react24.NestBlockButton, {}, "nestBlockButton"),
3510
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react24.UnnestBlockButton, {}, "unnestBlockButton"),
3511
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react24.CreateLinkButton, {}, "createLinkButton")
3142
3512
  ] });
3143
3513
  };
3144
3514
 
3515
+ // src/components/LumirTableHandlesController.tsx
3516
+ var import_react27 = require("@blocknote/react");
3517
+ var import_react28 = require("@floating-ui/react");
3518
+ var import_react29 = require("react");
3519
+
3520
+ // src/components/hooks/useFocusedCellHandlePositioning.ts
3521
+ var import_react25 = require("@floating-ui/react");
3522
+ var import_react26 = require("react");
3523
+ function useFocusedCellHandlePositioning(cellEl, tbodyEl, orientation, show) {
3524
+ const { refs, floatingStyles, context } = (0, import_react25.useFloating)({
3525
+ open: show,
3526
+ placement: orientation === "row" ? "left" : orientation === "col" ? "top" : "right",
3527
+ // col/row: 가장자리 선(zero-size)에, cell: 셀 우측 보더에 14px hit-area 중앙 정렬(-7).
3528
+ middleware: [(0, import_react25.offset)(-7)],
3529
+ whileElementsMounted: import_react25.autoUpdate
3530
+ });
3531
+ const { isMounted, styles } = (0, import_react25.useTransitionStyles)(context);
3532
+ (0, import_react26.useEffect)(() => {
3533
+ if (!cellEl) {
3534
+ refs.setReference(null);
3535
+ return;
3536
+ }
3537
+ refs.setReference({
3538
+ contextElement: cellEl,
3539
+ getBoundingClientRect: () => {
3540
+ const c = cellEl.getBoundingClientRect();
3541
+ const t = tbodyEl?.getBoundingClientRect() ?? c;
3542
+ if (orientation === "col") {
3543
+ return new DOMRect(c.left, t.top, c.width, 0);
3544
+ }
3545
+ if (orientation === "row") {
3546
+ return new DOMRect(t.left, c.top, 0, c.height);
3547
+ }
3548
+ return c;
3549
+ }
3550
+ });
3551
+ }, [cellEl, tbodyEl, orientation, refs]);
3552
+ return (0, import_react26.useMemo)(
3553
+ () => ({
3554
+ isMounted,
3555
+ ref: refs.setFloating,
3556
+ // display는 CSS 클래스에서 제어한다(absolute 자식 stacking).
3557
+ style: {
3558
+ ...styles,
3559
+ ...floatingStyles
3560
+ }
3561
+ }),
3562
+ [floatingStyles, isMounted, refs.setFloating, styles]
3563
+ );
3564
+ }
3565
+
3566
+ // src/components/LumirTableHandlesController.tsx
3567
+ var import_jsx_runtime21 = require("react/jsx-runtime");
3568
+ function syncCoreHoverToFocusedCell(cellEl) {
3569
+ const r = cellEl.getBoundingClientRect();
3570
+ cellEl.dispatchEvent(
3571
+ new MouseEvent("mousemove", {
3572
+ bubbles: true,
3573
+ cancelable: true,
3574
+ view: window,
3575
+ clientX: r.left + r.width / 2,
3576
+ clientY: r.top + r.height / 2
3577
+ })
3578
+ );
3579
+ }
3580
+ function LumirTableHandlesController() {
3581
+ const editor = (0, import_react27.useBlockNoteEditor)();
3582
+ const [focused, setFocused] = (0, import_react29.useState)(null);
3583
+ const [menuContainerRef, setMenuContainerRef] = (0, import_react29.useState)(null);
3584
+ const [overlayEl, setOverlayEl] = (0, import_react29.useState)(null);
3585
+ const [openMenu, setOpenMenu] = (0, import_react29.useState)(null);
3586
+ const frozenRef = (0, import_react29.useRef)(false);
3587
+ const menuOpenRef = (0, import_react29.useRef)(false);
3588
+ const draggingRef = (0, import_react29.useRef)(false);
3589
+ const recompute = (0, import_react29.useCallback)(() => {
3590
+ if (frozenRef.current) {
3591
+ return;
3592
+ }
3593
+ const th2 = editor.tableHandles;
3594
+ const view = editor.prosemirrorView;
3595
+ if (!th2 || !view) {
3596
+ setFocused(null);
3597
+ return;
3598
+ }
3599
+ let cellEl2 = null;
3600
+ try {
3601
+ const { node } = view.domAtPos(view.state.selection.from);
3602
+ const el = node.nodeType === Node.TEXT_NODE ? node.parentElement : node;
3603
+ cellEl2 = el?.closest?.("td, th") ?? null;
3604
+ } catch {
3605
+ cellEl2 = null;
3606
+ }
3607
+ if (!cellEl2 || !cellEl2.isConnected) {
3608
+ setFocused(null);
3609
+ return;
3610
+ }
3611
+ const blockId = cellEl2.closest("[data-id]")?.getAttribute("data-id");
3612
+ const block = blockId ? editor.getBlock(blockId) : void 0;
3613
+ if (!block || block.type !== "table") {
3614
+ setFocused(null);
3615
+ return;
3616
+ }
3617
+ const cellSel = th2.getCellSelection();
3618
+ if (!cellSel) {
3619
+ setFocused(null);
3620
+ return;
3621
+ }
3622
+ const widgetContainer = cellEl2.closest(".tableWrapper")?.querySelector(".table-widgets-container");
3623
+ const tbodyEl2 = cellEl2.closest("tbody");
3624
+ if (!widgetContainer || !tbodyEl2) {
3625
+ setFocused(null);
3626
+ return;
3627
+ }
3628
+ setFocused({
3629
+ block,
3630
+ rowIndex: cellSel.from.row,
3631
+ colIndex: cellSel.from.col,
3632
+ cellEl: cellEl2,
3633
+ tbodyEl: tbodyEl2,
3634
+ widgetContainer
3635
+ });
3636
+ }, [editor]);
3637
+ (0, import_react27.useEditorContentOrSelectionChange)(recompute, editor);
3638
+ (0, import_react29.useEffect)(() => {
3639
+ recompute();
3640
+ }, [recompute]);
3641
+ (0, import_react29.useEffect)(() => {
3642
+ const onUp = () => {
3643
+ requestAnimationFrame(() => {
3644
+ if (!menuOpenRef.current && !draggingRef.current && frozenRef.current) {
3645
+ frozenRef.current = false;
3646
+ recompute();
3647
+ }
3648
+ });
3649
+ };
3650
+ window.addEventListener("pointerup", onUp);
3651
+ return () => window.removeEventListener("pointerup", onUp);
3652
+ }, [recompute]);
3653
+ (0, import_react29.useEffect)(() => {
3654
+ const f = focused;
3655
+ if (!f || !overlayEl) {
3656
+ return;
3657
+ }
3658
+ const PAD = 1;
3659
+ const update = () => {
3660
+ const cr = f.cellEl.getBoundingClientRect();
3661
+ const tr = f.tbodyEl.getBoundingClientRect();
3662
+ const kr = f.widgetContainer.getBoundingClientRect();
3663
+ const x1 = openMenu === "row" ? tr.left : cr.left;
3664
+ const y1 = openMenu === "col" ? tr.top : cr.top;
3665
+ const x2 = openMenu === "row" ? tr.right : cr.right;
3666
+ const y2 = openMenu === "col" ? tr.bottom : cr.bottom;
3667
+ const dpr = window.devicePixelRatio || 1;
3668
+ const rd = (v) => Math.round(v * dpr) / dpr;
3669
+ const left = rd(x1 - kr.left) - PAD;
3670
+ const top = rd(y1 - kr.top) - PAD;
3671
+ const right = rd(x2 - kr.left) + PAD;
3672
+ const bottom = rd(y2 - kr.top) + PAD;
3673
+ overlayEl.style.transform = `translate(${left}px, ${top}px)`;
3674
+ overlayEl.style.width = `${right - left}px`;
3675
+ overlayEl.style.height = `${bottom - top}px`;
3676
+ };
3677
+ update();
3678
+ return (0, import_react28.autoUpdate)(f.cellEl, overlayEl, update);
3679
+ }, [focused, overlayEl, openMenu]);
3680
+ const cellEl = focused?.cellEl ?? null;
3681
+ const tbodyEl = focused?.tbodyEl ?? null;
3682
+ const show = focused !== null;
3683
+ const rowHandle = useFocusedCellHandlePositioning(cellEl, tbodyEl, "row", show);
3684
+ const colHandle = useFocusedCellHandlePositioning(cellEl, tbodyEl, "col", show);
3685
+ const cellHandle = useFocusedCellHandlePositioning(
3686
+ cellEl,
3687
+ tbodyEl,
3688
+ "cell",
3689
+ show
3690
+ );
3691
+ const th = editor.tableHandles;
3692
+ const coreState = (0, import_react27.useUIPluginState)(
3693
+ editor.tableHandles.onUpdate.bind(editor.tableHandles)
3694
+ );
3695
+ const { addOrRemoveColumnsButton, addOrRemoveRowsButton } = (0, import_react27.useExtendButtonsPositioning)(
3696
+ coreState?.showAddOrRemoveColumnsButton || false,
3697
+ coreState?.showAddOrRemoveRowsButton || false,
3698
+ coreState?.referencePosTable || null
3699
+ );
3700
+ const onStartExtend = (0, import_react29.useCallback)(() => {
3701
+ editor.tableHandles?.freezeHandles();
3702
+ }, [editor]);
3703
+ const onEndExtend = (0, import_react29.useCallback)(() => {
3704
+ editor.tableHandles?.unfreezeHandles();
3705
+ }, [editor]);
3706
+ const menuHandlers = (0, import_react29.useMemo)(() => {
3707
+ const mk = (kind) => ({
3708
+ freeze: () => {
3709
+ menuOpenRef.current = true;
3710
+ frozenRef.current = true;
3711
+ setOpenMenu(kind);
3712
+ editor.tableHandles?.freezeHandles();
3713
+ },
3714
+ unfreeze: () => {
3715
+ menuOpenRef.current = false;
3716
+ frozenRef.current = false;
3717
+ setOpenMenu(null);
3718
+ editor.tableHandles?.unfreezeHandles();
3719
+ recompute();
3720
+ }
3721
+ });
3722
+ return { col: mk("col"), row: mk("row"), cell: mk("cell") };
3723
+ }, [editor, recompute]);
3724
+ const onGutterPointerDown = (0, import_react29.useCallback)(() => {
3725
+ frozenRef.current = true;
3726
+ }, []);
3727
+ const onGutterPointerEnter = (0, import_react29.useCallback)(
3728
+ (e) => {
3729
+ if (e.buttons === 0 && focused) {
3730
+ syncCoreHoverToFocusedCell(focused.cellEl);
3731
+ }
3732
+ },
3733
+ [focused]
3734
+ );
3735
+ const makeDragStart = (0, import_react29.useCallback)(
3736
+ (dir) => (e) => {
3737
+ draggingRef.current = true;
3738
+ frozenRef.current = true;
3739
+ if (dir === "row") {
3740
+ editor.tableHandles?.rowDragStart(e);
3741
+ } else {
3742
+ editor.tableHandles?.colDragStart(e);
3743
+ }
3744
+ },
3745
+ [editor]
3746
+ );
3747
+ const onDragEnd = (0, import_react29.useCallback)(() => {
3748
+ editor.tableHandles?.dragEnd();
3749
+ draggingRef.current = false;
3750
+ frozenRef.current = false;
3751
+ recompute();
3752
+ }, [editor, recompute]);
3753
+ const noop = (0, import_react29.useCallback)(() => {
3754
+ }, []);
3755
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
3756
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { ref: setMenuContainerRef }),
3757
+ th && focused && menuContainerRef && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react28.FloatingPortal, { root: focused.widgetContainer, children: [
3758
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { ref: setOverlayEl, className: "lumir-tbl-cell-focus" }),
3759
+ colHandle.isMounted && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
3760
+ "div",
3761
+ {
3762
+ ref: colHandle.ref,
3763
+ style: colHandle.style,
3764
+ className: "lumir-tbl-gutter-wrap lumir-tbl-gutter-wrap--col" + (openMenu === "col" ? " lumir-tbl-gutter-wrap--active" : ""),
3765
+ onPointerEnter: onGutterPointerEnter,
3766
+ onPointerDown: onGutterPointerDown,
3767
+ children: [
3768
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "lumir-tbl-gutter" }),
3769
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "lumir-tbl-grip", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3770
+ import_react27.TableHandle,
3771
+ {
3772
+ editor,
3773
+ orientation: "column",
3774
+ index: focused.colIndex,
3775
+ block: focused.block,
3776
+ dragStart: makeDragStart("col"),
3777
+ dragEnd: onDragEnd,
3778
+ freezeHandles: menuHandlers.col.freeze,
3779
+ unfreezeHandles: menuHandlers.col.unfreeze,
3780
+ menuContainer: menuContainerRef,
3781
+ showOtherSide: noop,
3782
+ hideOtherSide: noop
3783
+ }
3784
+ ) })
3785
+ ]
3786
+ }
3787
+ ),
3788
+ rowHandle.isMounted && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
3789
+ "div",
3790
+ {
3791
+ ref: rowHandle.ref,
3792
+ style: rowHandle.style,
3793
+ className: "lumir-tbl-gutter-wrap lumir-tbl-gutter-wrap--row" + (openMenu === "row" ? " lumir-tbl-gutter-wrap--active" : ""),
3794
+ onPointerEnter: onGutterPointerEnter,
3795
+ onPointerDown: onGutterPointerDown,
3796
+ children: [
3797
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "lumir-tbl-gutter" }),
3798
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "lumir-tbl-grip", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3799
+ import_react27.TableHandle,
3800
+ {
3801
+ editor,
3802
+ orientation: "row",
3803
+ index: focused.rowIndex,
3804
+ block: focused.block,
3805
+ dragStart: makeDragStart("row"),
3806
+ dragEnd: onDragEnd,
3807
+ freezeHandles: menuHandlers.row.freeze,
3808
+ unfreezeHandles: menuHandlers.row.unfreeze,
3809
+ menuContainer: menuContainerRef,
3810
+ showOtherSide: noop,
3811
+ hideOtherSide: noop
3812
+ }
3813
+ ) })
3814
+ ]
3815
+ }
3816
+ ),
3817
+ cellHandle.isMounted && openMenu !== "col" && openMenu !== "row" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
3818
+ "div",
3819
+ {
3820
+ ref: cellHandle.ref,
3821
+ style: cellHandle.style,
3822
+ className: "lumir-tbl-gutter-wrap lumir-tbl-gutter-wrap--cell" + (openMenu === "cell" ? " lumir-tbl-gutter-wrap--active" : ""),
3823
+ onPointerDown: onGutterPointerDown,
3824
+ children: [
3825
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "lumir-tbl-gutter" }),
3826
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "lumir-tbl-grip", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3827
+ import_react27.TableCellButton,
3828
+ {
3829
+ editor,
3830
+ rowIndex: focused.rowIndex,
3831
+ colIndex: focused.colIndex,
3832
+ block: focused.block,
3833
+ tableCellMenu: LumirTableCellMenu,
3834
+ menuContainer: menuContainerRef,
3835
+ freezeHandles: menuHandlers.cell.freeze,
3836
+ unfreezeHandles: menuHandlers.cell.unfreeze
3837
+ }
3838
+ ) })
3839
+ ]
3840
+ }
3841
+ )
3842
+ ] }),
3843
+ th && coreState?.widgetContainer && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react28.FloatingPortal, { root: coreState.widgetContainer, children: [
3844
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { ref: addOrRemoveRowsButton.ref, style: addOrRemoveRowsButton.style, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3845
+ import_react27.ExtendButton,
3846
+ {
3847
+ editor,
3848
+ orientation: "addOrRemoveRows",
3849
+ block: coreState.block,
3850
+ onMouseDown: onStartExtend,
3851
+ onMouseUp: onEndExtend
3852
+ }
3853
+ ) }),
3854
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3855
+ "div",
3856
+ {
3857
+ ref: addOrRemoveColumnsButton.ref,
3858
+ style: addOrRemoveColumnsButton.style,
3859
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3860
+ import_react27.ExtendButton,
3861
+ {
3862
+ editor,
3863
+ orientation: "addOrRemoveColumns",
3864
+ block: coreState.block,
3865
+ onMouseDown: onStartExtend,
3866
+ onMouseUp: onEndExtend
3867
+ }
3868
+ )
3869
+ }
3870
+ )
3871
+ ] })
3872
+ ] });
3873
+ }
3874
+
3145
3875
  // src/utils/table-vertical-alignment.ts
3146
3876
  function injectVerticalAlignment(blocks, editor) {
3147
3877
  const tiptap = editor?._tiptapEditor;
@@ -3472,7 +4202,7 @@ var ALLOWED_VIDEO_EXTENSIONS = [
3472
4202
  ];
3473
4203
 
3474
4204
  // src/components/LumirEditor.tsx
3475
- var import_jsx_runtime20 = require("react/jsx-runtime");
4205
+ var import_jsx_runtime22 = require("react/jsx-runtime");
3476
4206
  var DEBUG_LOG = (loc, msg, data) => {
3477
4207
  const p = fetch("http://127.0.0.1:7686/ingest/1f8ee1c5-0cf0-4ae7-91ed-5ea7ed17130a", {
3478
4208
  method: "POST",
@@ -3697,9 +4427,9 @@ var findBlockWithLink = (blocks, targetUrl) => {
3697
4427
  return null;
3698
4428
  };
3699
4429
  var ConvertToPreviewButton = ({ url }) => {
3700
- const editor = (0, import_react24.useBlockNoteEditor)();
3701
- const Components = (0, import_react24.useComponentsContext)();
3702
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4430
+ const editor = (0, import_react31.useBlockNoteEditor)();
4431
+ const Components = (0, import_react31.useComponentsContext)();
4432
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3703
4433
  Components.LinkToolbar.Button,
3704
4434
  {
3705
4435
  className: "bn-button",
@@ -3718,29 +4448,29 @@ var ConvertToPreviewButton = ({ url }) => {
3718
4448
  console.error("Convert to link preview failed:", err);
3719
4449
  }
3720
4450
  },
3721
- icon: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
3722
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("rect", { x: "1", y: "3", width: "14", height: "10", rx: "2", stroke: "currentColor", strokeWidth: "1.5", fill: "none" }),
3723
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("line", { x1: "1", y1: "9", x2: "15", y2: "9", stroke: "currentColor", strokeWidth: "1.5" }),
3724
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("circle", { cx: "5", cy: "6.5", r: "1.5", stroke: "currentColor", strokeWidth: "1", fill: "none" })
4451
+ icon: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
4452
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("rect", { x: "1", y: "3", width: "14", height: "10", rx: "2", stroke: "currentColor", strokeWidth: "1.5", fill: "none" }),
4453
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("line", { x1: "1", y1: "9", x2: "15", y2: "9", stroke: "currentColor", strokeWidth: "1.5" }),
4454
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("circle", { cx: "5", cy: "6.5", r: "1.5", stroke: "currentColor", strokeWidth: "1", fill: "none" })
3725
4455
  ] })
3726
4456
  }
3727
4457
  );
3728
4458
  };
3729
4459
  var CustomLinkToolbar = (props) => {
3730
- const editor = (0, import_react24.useBlockNoteEditor)();
3731
- const Components = (0, import_react24.useComponentsContext)();
4460
+ const editor = (0, import_react31.useBlockNoteEditor)();
4461
+ const Components = (0, import_react31.useComponentsContext)();
3732
4462
  const hasLinkPreview = !!editor?._linkPreviewApiEndpoint;
3733
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
4463
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
3734
4464
  Components.LinkToolbar.Root,
3735
4465
  {
3736
4466
  className: "bn-toolbar bn-link-toolbar",
3737
4467
  onMouseEnter: props.stopHideTimer,
3738
4468
  onMouseLeave: props.startHideTimer,
3739
4469
  children: [
3740
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react24.EditLinkButton, { url: props.url, text: props.text, editLink: props.editLink }),
3741
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react24.OpenLinkButton, { url: props.url }),
3742
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react24.DeleteLinkButton, { deleteLink: props.deleteLink }),
3743
- hasLinkPreview && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ConvertToPreviewButton, { url: props.url })
4470
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react31.EditLinkButton, { url: props.url, text: props.text, editLink: props.editLink }),
4471
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react31.OpenLinkButton, { url: props.url }),
4472
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react31.DeleteLinkButton, { deleteLink: props.deleteLink }),
4473
+ hasLinkPreview && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ConvertToPreviewButton, { url: props.url })
3744
4474
  ]
3745
4475
  }
3746
4476
  );
@@ -3784,13 +4514,13 @@ function LumirEditor({
3784
4514
  onError,
3785
4515
  onImageDelete
3786
4516
  }) {
3787
- const [isUploading, setIsUploading] = (0, import_react23.useState)(false);
3788
- const [uploadProgress, setUploadProgress] = (0, import_react23.useState)(null);
3789
- const [errorMessage, setErrorMessage] = (0, import_react23.useState)(null);
3790
- const floatingMenuFileInputRef = (0, import_react23.useRef)(null);
3791
- const floatingMenuBlockRef = (0, import_react23.useRef)(null);
3792
- const floatingMenuUploadStartTimeRef = (0, import_react23.useRef)(0);
3793
- const handleError = (0, import_react23.useCallback)(
4517
+ const [isUploading, setIsUploading] = (0, import_react30.useState)(false);
4518
+ const [uploadProgress, setUploadProgress] = (0, import_react30.useState)(null);
4519
+ const [errorMessage, setErrorMessage] = (0, import_react30.useState)(null);
4520
+ const floatingMenuFileInputRef = (0, import_react30.useRef)(null);
4521
+ const floatingMenuBlockRef = (0, import_react30.useRef)(null);
4522
+ const floatingMenuUploadStartTimeRef = (0, import_react30.useRef)(0);
4523
+ const handleError = (0, import_react30.useCallback)(
3794
4524
  (error) => {
3795
4525
  onError?.(error);
3796
4526
  setErrorMessage(error.getUserMessage());
@@ -3798,10 +4528,10 @@ function LumirEditor({
3798
4528
  },
3799
4529
  [onError]
3800
4530
  );
3801
- const validatedContent = (0, import_react23.useMemo)(() => {
4531
+ const validatedContent = (0, import_react30.useMemo)(() => {
3802
4532
  return ContentUtils.validateContent(initialContent, initialEmptyBlocks);
3803
4533
  }, [initialContent, initialEmptyBlocks]);
3804
- const tableConfig = (0, import_react23.useMemo)(() => {
4534
+ const tableConfig = (0, import_react30.useMemo)(() => {
3805
4535
  return EditorConfig.getDefaultTableConfig(tables);
3806
4536
  }, [
3807
4537
  tables?.splitCells,
@@ -3809,10 +4539,10 @@ function LumirEditor({
3809
4539
  tables?.cellTextColor,
3810
4540
  tables?.headers
3811
4541
  ]);
3812
- const headingConfig = (0, import_react23.useMemo)(() => {
4542
+ const headingConfig = (0, import_react30.useMemo)(() => {
3813
4543
  return EditorConfig.getDefaultHeadingConfig(heading);
3814
4544
  }, [heading?.levels?.join(",") ?? ""]);
3815
- const disabledExtensions = (0, import_react23.useMemo)(() => {
4545
+ const disabledExtensions = (0, import_react30.useMemo)(() => {
3816
4546
  return EditorConfig.getDisabledExtensions(
3817
4547
  disableExtensions,
3818
4548
  allowVideoUpload,
@@ -3820,18 +4550,18 @@ function LumirEditor({
3820
4550
  allowFileUpload
3821
4551
  );
3822
4552
  }, [disableExtensions, allowVideoUpload, allowAudioUpload, allowFileUpload]);
3823
- (0, import_react23.useEffect)(() => {
4553
+ (0, import_react30.useEffect)(() => {
3824
4554
  DEBUG_LOG("LumirEditor:init:disabledExtensions", "snapshot", {
3825
4555
  allowVideoUpload,
3826
4556
  hasVideoInDisabled: disabledExtensions.includes("video"),
3827
4557
  disabledList: disabledExtensions.slice(0, 15)
3828
4558
  });
3829
4559
  }, [allowVideoUpload, disabledExtensions]);
3830
- const fileNameTransformRef = (0, import_react23.useRef)(s3Upload?.fileNameTransform);
3831
- (0, import_react23.useEffect)(() => {
4560
+ const fileNameTransformRef = (0, import_react30.useRef)(s3Upload?.fileNameTransform);
4561
+ (0, import_react30.useEffect)(() => {
3832
4562
  fileNameTransformRef.current = s3Upload?.fileNameTransform;
3833
4563
  }, [s3Upload?.fileNameTransform]);
3834
- const memoizedS3Upload = (0, import_react23.useMemo)(() => {
4564
+ const memoizedS3Upload = (0, import_react30.useMemo)(() => {
3835
4565
  if (!s3Upload) return void 0;
3836
4566
  return {
3837
4567
  apiEndpoint: s3Upload.apiEndpoint,
@@ -3860,10 +4590,19 @@ function LumirEditor({
3860
4590
  s3Upload?.maxRetries,
3861
4591
  s3Upload?.onProgress
3862
4592
  ]);
3863
- const editor = (0, import_react24.useCreateBlockNote)(
4593
+ const editor = (0, import_react31.useCreateBlockNote)(
3864
4594
  {
3865
4595
  // HTML 미리보기 블록이 포함된 커스텀 스키마 사용
3866
4596
  schema,
4597
+ // 모든 BlockNote UI 텍스트(테이블 드롭다운 등) 한글 적용 + "색깔"→"색"
4598
+ dictionary: {
4599
+ ...import_locales.ko,
4600
+ drag_handle: { ...import_locales.ko.drag_handle, colors_menuitem: "\uC0C9" },
4601
+ formatting_toolbar: {
4602
+ ...import_locales.ko.formatting_toolbar,
4603
+ colors: { ...import_locales.ko.formatting_toolbar.colors, tooltip: "\uC0C9" }
4604
+ }
4605
+ },
3867
4606
  initialContent: validatedContent,
3868
4607
  tables: tableConfig,
3869
4608
  heading: headingConfig,
@@ -4055,12 +4794,12 @@ function LumirEditor({
4055
4794
  if (editor && linkPreview?.apiEndpoint) {
4056
4795
  editor._linkPreviewApiEndpoint = linkPreview.apiEndpoint;
4057
4796
  }
4058
- (0, import_react23.useEffect)(() => {
4797
+ (0, import_react30.useEffect)(() => {
4059
4798
  if (editor) {
4060
4799
  editor.isEditable = editable;
4061
4800
  }
4062
4801
  }, [editor, editable]);
4063
- (0, import_react23.useEffect)(() => {
4802
+ (0, import_react30.useEffect)(() => {
4064
4803
  if (!editor || !onContentChange) return;
4065
4804
  const handleContentChange = () => {
4066
4805
  const blocks = editor.topLevelBlocks;
@@ -4069,13 +4808,13 @@ function LumirEditor({
4069
4808
  };
4070
4809
  return editor.onEditorContentChange(handleContentChange);
4071
4810
  }, [editor, onContentChange]);
4072
- const previousMediaUrlsRef = (0, import_react23.useRef)(/* @__PURE__ */ new Set());
4073
- (0, import_react23.useEffect)(() => {
4811
+ const previousMediaUrlsRef = (0, import_react30.useRef)(/* @__PURE__ */ new Set());
4812
+ (0, import_react30.useEffect)(() => {
4074
4813
  if (!editor) return;
4075
4814
  const initialBlocks = editor.topLevelBlocks;
4076
4815
  previousMediaUrlsRef.current = extractMediaUrls(initialBlocks);
4077
4816
  }, [editor]);
4078
- (0, import_react23.useEffect)(() => {
4817
+ (0, import_react30.useEffect)(() => {
4079
4818
  if (!editor || !onImageDelete) return;
4080
4819
  const handleMediaDeleteCheck = () => {
4081
4820
  const currentBlocks = editor.topLevelBlocks;
@@ -4089,7 +4828,7 @@ function LumirEditor({
4089
4828
  };
4090
4829
  return editor.onEditorContentChange(handleMediaDeleteCheck);
4091
4830
  }, [editor, onImageDelete]);
4092
- (0, import_react23.useEffect)(() => {
4831
+ (0, import_react30.useEffect)(() => {
4093
4832
  const el = editor?.domElement;
4094
4833
  if (!el) return;
4095
4834
  const handleDragOver = (e) => {
@@ -4220,20 +4959,20 @@ function LumirEditor({
4220
4959
  el.removeEventListener("drop", handleDrop, { capture: true });
4221
4960
  };
4222
4961
  }, [editor, allowVideoUpload]);
4223
- const computedSideMenu = (0, import_react23.useMemo)(() => {
4962
+ const computedSideMenu = (0, import_react30.useMemo)(() => {
4224
4963
  return sideMenuAddButton ? sideMenu : false;
4225
4964
  }, [sideMenuAddButton, sideMenu]);
4226
- const DragHandleOnlySideMenu = (0, import_react23.useMemo)(() => {
4227
- return (props) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react24.SideMenu, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react24.DragHandleButton, { ...props }) });
4965
+ const DragHandleOnlySideMenu = (0, import_react30.useMemo)(() => {
4966
+ return (props) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react31.SideMenu, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react31.DragHandleButton, { ...props }) });
4228
4967
  }, []);
4229
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
4968
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
4230
4969
  "div",
4231
4970
  {
4232
4971
  className: cn("lumirEditor", className),
4233
4972
  style: { position: "relative", display: "flex", flexDirection: "column" },
4234
4973
  children: [
4235
- floatingMenu && editor && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
4236
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4974
+ floatingMenu && editor && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
4975
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4237
4976
  "input",
4238
4977
  {
4239
4978
  ref: floatingMenuFileInputRef,
@@ -4304,7 +5043,7 @@ function LumirEditor({
4304
5043
  }
4305
5044
  }
4306
5045
  ),
4307
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5046
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4308
5047
  FloatingMenu,
4309
5048
  {
4310
5049
  editor,
@@ -4336,7 +5075,7 @@ function LumirEditor({
4336
5075
  }
4337
5076
  )
4338
5077
  ] }),
4339
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
5078
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
4340
5079
  import_mantine.BlockNoteView,
4341
5080
  {
4342
5081
  editor,
@@ -4348,23 +5087,24 @@ function LumirEditor({
4348
5087
  slashMenu: false,
4349
5088
  emojiPicker,
4350
5089
  filePanel,
4351
- tableHandles,
5090
+ tableHandles: false,
4352
5091
  onSelectionChange,
4353
5092
  children: [
4354
- formattingToolbar && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4355
- import_react24.FormattingToolbarController,
5093
+ tableHandles && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(LumirTableHandlesController, {}),
5094
+ formattingToolbar && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5095
+ import_react31.FormattingToolbarController,
4356
5096
  {
4357
5097
  formattingToolbar: CustomFormattingToolbar
4358
5098
  }
4359
5099
  ),
4360
- linkToolbar && (linkPreview?.apiEndpoint ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react24.LinkToolbarController, { linkToolbar: CustomLinkToolbar }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react24.LinkToolbarController, {})),
4361
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4362
- import_react24.SuggestionMenuController,
5100
+ linkToolbar && (linkPreview?.apiEndpoint ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react31.LinkToolbarController, { linkToolbar: CustomLinkToolbar }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react31.LinkToolbarController, {})),
5101
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5102
+ import_react31.SuggestionMenuController,
4363
5103
  {
4364
5104
  triggerCharacter: "/",
4365
- getItems: (0, import_react23.useCallback)(
5105
+ getItems: (0, import_react30.useCallback)(
4366
5106
  async (query) => {
4367
- const items = (0, import_react24.getDefaultReactSlashMenuItems)(editor);
5107
+ const items = (0, import_react31.getDefaultReactSlashMenuItems)(editor);
4368
5108
  const filtered = items.filter((item) => {
4369
5109
  const key = (item?.key || "").toString().toLowerCase();
4370
5110
  const title = (item?.title || "").toString().toLowerCase();
@@ -4406,7 +5146,7 @@ function LumirEditor({
4406
5146
  },
4407
5147
  aliases: ["html", "preview", "\uC6F9", "\uC6F9\uD398\uC774\uC9C0"],
4408
5148
  group: "Embeds",
4409
- icon: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
5149
+ icon: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
4410
5150
  "svg",
4411
5151
  {
4412
5152
  width: "18",
@@ -4418,8 +5158,8 @@ function LumirEditor({
4418
5158
  strokeLinecap: "round",
4419
5159
  strokeLinejoin: "round",
4420
5160
  children: [
4421
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("polyline", { points: "16 18 22 12 16 6" }),
4422
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("polyline", { points: "8 6 2 12 8 18" })
5161
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("polyline", { points: "16 18 22 12 16 6" }),
5162
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("polyline", { points: "8 6 2 12 8 18" })
4423
5163
  ]
4424
5164
  }
4425
5165
  ),
@@ -4430,7 +5170,7 @@ function LumirEditor({
4430
5170
  allItems.push({
4431
5171
  title: "Link Preview",
4432
5172
  onItemClick: () => {
4433
- (0, import_core4.insertOrUpdateBlock)(editor, {
5173
+ (0, import_core5.insertOrUpdateBlock)(editor, {
4434
5174
  type: "linkPreview",
4435
5175
  props: { url: "" }
4436
5176
  });
@@ -4444,7 +5184,7 @@ function LumirEditor({
4444
5184
  "\uD504\uB9AC\uBDF0"
4445
5185
  ],
4446
5186
  group: "Embeds",
4447
- icon: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
5187
+ icon: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
4448
5188
  "svg",
4449
5189
  {
4450
5190
  width: "18",
@@ -4456,14 +5196,31 @@ function LumirEditor({
4456
5196
  strokeLinecap: "round",
4457
5197
  strokeLinejoin: "round",
4458
5198
  children: [
4459
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
4460
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
5199
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
5200
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
4461
5201
  ]
4462
5202
  }
4463
5203
  ),
4464
5204
  subtext: "URL\uC758 \uBBF8\uB9AC\uBCF4\uAE30 \uCE74\uB4DC\uB97C \uC0BD\uC785"
4465
5205
  });
4466
5206
  }
5207
+ const enSlash = import_locales.en.slash_menu;
5208
+ for (const it of allItems) {
5209
+ const enEntry = it.key ? enSlash[it.key] : void 0;
5210
+ if (!enEntry) continue;
5211
+ const extra = [...enEntry.aliases ?? [], enEntry.title].filter((s) => Boolean(s)).map((s) => s.toLowerCase());
5212
+ it.aliases = Array.from(
5213
+ /* @__PURE__ */ new Set([...it.aliases ?? [], ...extra])
5214
+ );
5215
+ }
5216
+ const groupOrder = [];
5217
+ for (const it of allItems) {
5218
+ const g = it.group ?? "";
5219
+ if (!groupOrder.includes(g)) groupOrder.push(g);
5220
+ }
5221
+ allItems.sort(
5222
+ (a, b) => groupOrder.indexOf(a.group ?? "") - groupOrder.indexOf(b.group ?? "")
5223
+ );
4467
5224
  if (!query) return allItems;
4468
5225
  const q = query.toLowerCase();
4469
5226
  return allItems.filter(
@@ -4476,21 +5233,21 @@ function LumirEditor({
4476
5233
  )
4477
5234
  }
4478
5235
  ),
4479
- !sideMenuAddButton && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react24.SideMenuController, { sideMenu: DragHandleOnlySideMenu })
5236
+ !sideMenuAddButton && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react31.SideMenuController, { sideMenu: DragHandleOnlySideMenu })
4480
5237
  ]
4481
5238
  }
4482
5239
  ),
4483
- isUploading && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "lumirEditor-upload-overlay", children: [
4484
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "lumirEditor-spinner" }),
4485
- uploadProgress !== null && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "lumirEditor-upload-progress", children: [
5240
+ isUploading && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "lumirEditor-upload-overlay", children: [
5241
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "lumirEditor-spinner" }),
5242
+ uploadProgress !== null && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { className: "lumirEditor-upload-progress", children: [
4486
5243
  uploadProgress,
4487
5244
  "%"
4488
5245
  ] })
4489
5246
  ] }),
4490
- errorMessage && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "lumirEditor-error-toast", children: [
4491
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "lumirEditor-error-icon", children: "\u26A0\uFE0F" }),
4492
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "lumirEditor-error-message", children: errorMessage }),
4493
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5247
+ errorMessage && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "lumirEditor-error-toast", children: [
5248
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "lumirEditor-error-icon", children: "\u26A0\uFE0F" }),
5249
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "lumirEditor-error-message", children: errorMessage }),
5250
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4494
5251
  "button",
4495
5252
  {
4496
5253
  className: "lumirEditor-error-close",