@underverse-ui/underverse 1.0.75 → 1.0.76

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
@@ -704,6 +704,17 @@ var en_default = {
704
704
  undo: "Undo (Ctrl+Z)",
705
705
  redo: "Redo (Ctrl+Y)",
706
706
  textStyle: "Text Style",
707
+ fontFamily: "Font Family",
708
+ fontSize: "Font Size",
709
+ lineHeight: "Line Height",
710
+ fontDefault: "Default Font",
711
+ sizeDefault: "Default Size",
712
+ lineHeightDefault: "Default Leading",
713
+ letterSpacing: "Letter Spacing",
714
+ letterSpacingDefault: "Default Tracking",
715
+ fontSans: "Sans",
716
+ fontSerif: "Serif",
717
+ fontMono: "Mono",
707
718
  normal: "Normal text",
708
719
  heading1: "Heading 1",
709
720
  heading2: "Heading 2",
@@ -777,6 +788,8 @@ var en_default = {
777
788
  },
778
789
  tableMenu: {
779
790
  insert3x3: "Insert 3\xD73 Table",
791
+ insertTable: "Insert Table",
792
+ gridPreview: "Insert {rows}\xD7{cols} Table",
780
793
  addColumnBefore: "Add Column Before",
781
794
  addColumnAfter: "Add Column After",
782
795
  addRowBefore: "Add Row Before",
@@ -795,7 +808,10 @@ var en_default = {
795
808
  quickAddRowAfter: "Quick Add Row After",
796
809
  expandTable: "Expand Table",
797
810
  dragRow: "Drag Row",
798
- dragColumn: "Drag Column"
811
+ dragColumn: "Drag Column",
812
+ alignLeft: "Align Table Left",
813
+ alignCenter: "Align Table Center",
814
+ alignRight: "Align Table Right"
799
815
  }
800
816
  }
801
817
  };
@@ -953,6 +969,17 @@ var vi_default = {
953
969
  undo: "Ho\xE0n t\xE1c (Ctrl+Z)",
954
970
  redo: "L\xE0m l\u1EA1i (Ctrl+Y)",
955
971
  textStyle: "Ki\u1EC3u ch\u1EEF",
972
+ fontFamily: "Ph\xF4ng ch\u1EEF",
973
+ fontSize: "C\u1EE1 ch\u1EEF",
974
+ lineHeight: "Gi\xE3n d\xF2ng",
975
+ fontDefault: "Ph\xF4ng m\u1EB7c \u0111\u1ECBnh",
976
+ sizeDefault: "C\u1EE1 m\u1EB7c \u0111\u1ECBnh",
977
+ lineHeightDefault: "Gi\xE3n d\xF2ng m\u1EB7c \u0111\u1ECBnh",
978
+ letterSpacing: "Gi\xE3n ch\u1EEF",
979
+ letterSpacingDefault: "Gi\xE3n ch\u1EEF m\u1EB7c \u0111\u1ECBnh",
980
+ fontSans: "Sans",
981
+ fontSerif: "Serif",
982
+ fontMono: "Mono",
956
983
  normal: "V\u0103n b\u1EA3n th\u01B0\u1EDDng",
957
984
  heading1: "Ti\xEAu \u0111\u1EC1 1",
958
985
  heading2: "Ti\xEAu \u0111\u1EC1 2",
@@ -1026,6 +1053,8 @@ var vi_default = {
1026
1053
  },
1027
1054
  tableMenu: {
1028
1055
  insert3x3: "Ch\xE8n b\u1EA3ng 3\xD73",
1056
+ insertTable: "Ch\xE8n b\u1EA3ng",
1057
+ gridPreview: "Ch\xE8n b\u1EA3ng {rows}\xD7{cols}",
1029
1058
  addColumnBefore: "Th\xEAm c\u1ED9t tr\u01B0\u1EDBc",
1030
1059
  addColumnAfter: "Th\xEAm c\u1ED9t sau",
1031
1060
  addRowBefore: "Th\xEAm h\xE0ng tr\u01B0\u1EDBc",
@@ -1044,7 +1073,10 @@ var vi_default = {
1044
1073
  quickAddRowAfter: "Th\xEAm nhanh h\xE0ng sau",
1045
1074
  expandTable: "M\u1EDF r\u1ED9ng b\u1EA3ng",
1046
1075
  dragRow: "K\xE9o h\xE0ng",
1047
- dragColumn: "K\xE9o c\u1ED9t"
1076
+ dragColumn: "K\xE9o c\u1ED9t",
1077
+ alignLeft: "C\u0103n b\u1EA3ng tr\xE1i",
1078
+ alignCenter: "C\u0103n b\u1EA3ng gi\u1EEFa",
1079
+ alignRight: "C\u0103n b\u1EA3ng ph\u1EA3i"
1048
1080
  }
1049
1081
  }
1050
1082
  };
@@ -1202,6 +1234,17 @@ var ko_default = {
1202
1234
  undo: "\uC2E4\uD589 \uCDE8\uC18C",
1203
1235
  redo: "\uB2E4\uC2DC \uC2E4\uD589",
1204
1236
  textStyle: "\uD14D\uC2A4\uD2B8 \uC2A4\uD0C0\uC77C",
1237
+ fontFamily: "\uAE00\uAF34",
1238
+ fontSize: "\uAE00\uC790 \uD06C\uAE30",
1239
+ lineHeight: "\uC904 \uAC04\uACA9",
1240
+ fontDefault: "\uAE30\uBCF8 \uAE00\uAF34",
1241
+ sizeDefault: "\uAE30\uBCF8 \uD06C\uAE30",
1242
+ lineHeightDefault: "\uAE30\uBCF8 \uC904 \uAC04\uACA9",
1243
+ letterSpacing: "\uC790\uAC04",
1244
+ letterSpacingDefault: "\uAE30\uBCF8 \uC790\uAC04",
1245
+ fontSans: "Sans",
1246
+ fontSerif: "Serif",
1247
+ fontMono: "Mono",
1205
1248
  normal: "\uC77C\uBC18 \uD14D\uC2A4\uD2B8",
1206
1249
  heading1: "\uC81C\uBAA9 1",
1207
1250
  heading2: "\uC81C\uBAA9 2",
@@ -1274,6 +1317,8 @@ var ko_default = {
1274
1317
  },
1275
1318
  tableMenu: {
1276
1319
  insert3x3: "3x3 \uD45C \uC0BD\uC785",
1320
+ insertTable: "\uD45C \uC0BD\uC785",
1321
+ gridPreview: "{rows}\xD7{cols} \uD45C \uC0BD\uC785",
1277
1322
  addColumnBefore: "\uC55E\uC5D0 \uC5F4 \uCD94\uAC00",
1278
1323
  addColumnAfter: "\uB4A4\uC5D0 \uC5F4 \uCD94\uAC00",
1279
1324
  addRowBefore: "\uC704\uC5D0 \uD589 \uCD94\uAC00",
@@ -1292,7 +1337,10 @@ var ko_default = {
1292
1337
  quickAddRowAfter: "\uC544\uB798 \uD589 \uBE60\uB974\uAC8C \uCD94\uAC00",
1293
1338
  expandTable: "\uD45C \uD655\uC7A5",
1294
1339
  dragRow: "\uD589 \uB4DC\uB798\uADF8",
1295
- dragColumn: "\uC5F4 \uB4DC\uB798\uADF8"
1340
+ dragColumn: "\uC5F4 \uB4DC\uB798\uADF8",
1341
+ alignLeft: "\uD45C \uC67C\uCABD \uC815\uB82C",
1342
+ alignCenter: "\uD45C \uAC00\uC6B4\uB370 \uC815\uB82C",
1343
+ alignRight: "\uD45C \uC624\uB978\uCABD \uC815\uB82C"
1296
1344
  }
1297
1345
  }
1298
1346
  };
@@ -1450,6 +1498,17 @@ var ja_default = {
1450
1498
  undo: "\u5143\u306B\u623B\u3059",
1451
1499
  redo: "\u3084\u308A\u76F4\u3057",
1452
1500
  textStyle: "\u30C6\u30AD\u30B9\u30C8\u30B9\u30BF\u30A4\u30EB",
1501
+ fontFamily: "\u30D5\u30A9\u30F3\u30C8",
1502
+ fontSize: "\u6587\u5B57\u30B5\u30A4\u30BA",
1503
+ lineHeight: "\u884C\u9593",
1504
+ fontDefault: "\u6A19\u6E96\u30D5\u30A9\u30F3\u30C8",
1505
+ sizeDefault: "\u6A19\u6E96\u30B5\u30A4\u30BA",
1506
+ lineHeightDefault: "\u6A19\u6E96\u306E\u884C\u9593",
1507
+ letterSpacing: "\u6587\u5B57\u9593\u9694",
1508
+ letterSpacingDefault: "\u6A19\u6E96\u306E\u5B57\u9593",
1509
+ fontSans: "Sans",
1510
+ fontSerif: "Serif",
1511
+ fontMono: "Mono",
1453
1512
  normal: "\u6A19\u6E96\u30C6\u30AD\u30B9\u30C8",
1454
1513
  heading1: "\u898B\u51FA\u3057 1",
1455
1514
  heading2: "\u898B\u51FA\u3057 2",
@@ -1522,6 +1581,8 @@ var ja_default = {
1522
1581
  },
1523
1582
  tableMenu: {
1524
1583
  insert3x3: "3x3 \u8868\u3092\u633F\u5165",
1584
+ insertTable: "\u8868\u3092\u633F\u5165",
1585
+ gridPreview: "{rows}\xD7{cols} \u306E\u8868\u3092\u633F\u5165",
1525
1586
  addColumnBefore: "\u524D\u306B\u5217\u3092\u8FFD\u52A0",
1526
1587
  addColumnAfter: "\u5F8C\u306B\u5217\u3092\u8FFD\u52A0",
1527
1588
  addRowBefore: "\u524D\u306B\u884C\u3092\u8FFD\u52A0",
@@ -1540,7 +1601,10 @@ var ja_default = {
1540
1601
  quickAddRowAfter: "\u4E0B\u306B\u884C\u3092\u3059\u3070\u3084\u304F\u8FFD\u52A0",
1541
1602
  expandTable: "\u8868\u3092\u62E1\u5F35",
1542
1603
  dragRow: "\u884C\u3092\u30C9\u30E9\u30C3\u30B0",
1543
- dragColumn: "\u5217\u3092\u30C9\u30E9\u30C3\u30B0"
1604
+ dragColumn: "\u5217\u3092\u30C9\u30E9\u30C3\u30B0",
1605
+ alignLeft: "\u8868\u3092\u5DE6\u5BC4\u305B",
1606
+ alignCenter: "\u8868\u3092\u4E2D\u592E\u63C3\u3048",
1607
+ alignRight: "\u8868\u3092\u53F3\u5BC4\u305B"
1544
1608
  }
1545
1609
  }
1546
1610
  };
@@ -22021,7 +22085,6 @@ import { TextStyle } from "@tiptap/extension-text-style";
22021
22085
  import Color from "@tiptap/extension-color";
22022
22086
  import Highlight from "@tiptap/extension-highlight";
22023
22087
  import TextAlign from "@tiptap/extension-text-align";
22024
- import { Table as Table3 } from "@tiptap/extension-table";
22025
22088
  import TableCell2 from "@tiptap/extension-table-cell";
22026
22089
  import TableHeader2 from "@tiptap/extension-table-header";
22027
22090
  import CharacterCount from "@tiptap/extension-character-count";
@@ -23001,6 +23064,283 @@ var UEditorTableRow = TableRow2.extend({
23001
23064
  });
23002
23065
  var table_row_default = UEditorTableRow;
23003
23066
 
23067
+ // src/components/UEditor/font-family.ts
23068
+ import { Extension as Extension5 } from "@tiptap/core";
23069
+ var FontFamily = Extension5.create({
23070
+ name: "fontFamily",
23071
+ addOptions() {
23072
+ return {
23073
+ types: ["textStyle"]
23074
+ };
23075
+ },
23076
+ addGlobalAttributes() {
23077
+ return [
23078
+ {
23079
+ types: this.options.types,
23080
+ attributes: {
23081
+ fontFamily: {
23082
+ default: null,
23083
+ parseHTML: (element) => element.style.fontFamily || null,
23084
+ renderHTML: (attributes) => {
23085
+ const fontFamily = typeof attributes.fontFamily === "string" ? attributes.fontFamily.trim() : "";
23086
+ if (!fontFamily) return {};
23087
+ return { style: `font-family: ${fontFamily}` };
23088
+ }
23089
+ }
23090
+ }
23091
+ }
23092
+ ];
23093
+ },
23094
+ addCommands() {
23095
+ return {
23096
+ setFontFamily: (fontFamily) => ({ chain }) => chain().setMark("textStyle", { fontFamily }).run(),
23097
+ unsetFontFamily: () => ({ chain }) => chain().setMark("textStyle", { fontFamily: null }).removeEmptyTextStyle().run()
23098
+ };
23099
+ }
23100
+ });
23101
+ var font_family_default = FontFamily;
23102
+
23103
+ // src/components/UEditor/font-size.ts
23104
+ import { Extension as Extension6 } from "@tiptap/core";
23105
+ var FontSize = Extension6.create({
23106
+ name: "fontSize",
23107
+ addOptions() {
23108
+ return {
23109
+ types: ["textStyle"]
23110
+ };
23111
+ },
23112
+ addGlobalAttributes() {
23113
+ return [
23114
+ {
23115
+ types: this.options.types,
23116
+ attributes: {
23117
+ fontSize: {
23118
+ default: null,
23119
+ parseHTML: (element) => element.style.fontSize || null,
23120
+ renderHTML: (attributes) => {
23121
+ const fontSize = typeof attributes.fontSize === "string" ? attributes.fontSize.trim() : "";
23122
+ if (!fontSize) return {};
23123
+ return { style: `font-size: ${fontSize}` };
23124
+ }
23125
+ }
23126
+ }
23127
+ }
23128
+ ];
23129
+ },
23130
+ addCommands() {
23131
+ return {
23132
+ setFontSize: (fontSize) => ({ chain }) => chain().setMark("textStyle", { fontSize }).run(),
23133
+ unsetFontSize: () => ({ chain }) => chain().setMark("textStyle", { fontSize: null }).removeEmptyTextStyle().run()
23134
+ };
23135
+ }
23136
+ });
23137
+ var font_size_default = FontSize;
23138
+
23139
+ // src/components/UEditor/line-height.ts
23140
+ import { Extension as Extension7 } from "@tiptap/core";
23141
+ var LineHeight = Extension7.create({
23142
+ name: "lineHeight",
23143
+ addOptions() {
23144
+ return {
23145
+ types: ["textStyle"]
23146
+ };
23147
+ },
23148
+ addGlobalAttributes() {
23149
+ return [
23150
+ {
23151
+ types: this.options.types,
23152
+ attributes: {
23153
+ lineHeight: {
23154
+ default: null,
23155
+ parseHTML: (element) => element.style.lineHeight || null,
23156
+ renderHTML: (attributes) => {
23157
+ const lineHeight = typeof attributes.lineHeight === "string" ? attributes.lineHeight.trim() : "";
23158
+ if (!lineHeight) return {};
23159
+ return { style: `line-height: ${lineHeight}` };
23160
+ }
23161
+ }
23162
+ }
23163
+ }
23164
+ ];
23165
+ },
23166
+ addCommands() {
23167
+ return {
23168
+ setLineHeight: (lineHeight) => ({ chain }) => chain().setMark("textStyle", { lineHeight }).run(),
23169
+ unsetLineHeight: () => ({ chain }) => chain().setMark("textStyle", { lineHeight: null }).removeEmptyTextStyle().run()
23170
+ };
23171
+ }
23172
+ });
23173
+ var line_height_default = LineHeight;
23174
+
23175
+ // src/components/UEditor/letter-spacing.ts
23176
+ import { Extension as Extension8 } from "@tiptap/core";
23177
+ var LetterSpacing = Extension8.create({
23178
+ name: "letterSpacing",
23179
+ addOptions() {
23180
+ return {
23181
+ types: ["textStyle"]
23182
+ };
23183
+ },
23184
+ addGlobalAttributes() {
23185
+ return [
23186
+ {
23187
+ types: this.options.types,
23188
+ attributes: {
23189
+ letterSpacing: {
23190
+ default: null,
23191
+ parseHTML: (element) => element.style.letterSpacing || null,
23192
+ renderHTML: (attributes) => {
23193
+ const letterSpacing = typeof attributes.letterSpacing === "string" ? attributes.letterSpacing.trim() : "";
23194
+ if (!letterSpacing) return {};
23195
+ return { style: `letter-spacing: ${letterSpacing}` };
23196
+ }
23197
+ }
23198
+ }
23199
+ }
23200
+ ];
23201
+ },
23202
+ addCommands() {
23203
+ return {
23204
+ setLetterSpacing: (letterSpacing) => ({ chain }) => chain().setMark("textStyle", { letterSpacing }).run(),
23205
+ unsetLetterSpacing: () => ({ chain }) => chain().setMark("textStyle", { letterSpacing: null }).removeEmptyTextStyle().run()
23206
+ };
23207
+ }
23208
+ });
23209
+ var letter_spacing_default = LetterSpacing;
23210
+
23211
+ // src/components/UEditor/table-align.ts
23212
+ import { Table as Table3 } from "@tiptap/extension-table";
23213
+
23214
+ // src/components/UEditor/table-align-utils.ts
23215
+ function findTableNodeInfoAtResolvedPos($pos) {
23216
+ for (let depth = $pos.depth; depth > 0; depth -= 1) {
23217
+ const node = $pos.node(depth);
23218
+ if (node.type.name === "table") {
23219
+ return {
23220
+ depth,
23221
+ pos: $pos.before(depth),
23222
+ node
23223
+ };
23224
+ }
23225
+ }
23226
+ return null;
23227
+ }
23228
+ function findTableNodeInfoFromState(state, anchorPos) {
23229
+ if (typeof anchorPos === "number" && Number.isFinite(anchorPos)) {
23230
+ const safePos = Math.max(0, Math.min(anchorPos, state.doc.content.size));
23231
+ return findTableNodeInfoAtResolvedPos(state.doc.resolve(safePos));
23232
+ }
23233
+ return findTableNodeInfoAtResolvedPos(state.selection.$from);
23234
+ }
23235
+ function applyTableAlignment(editor, tableAlign, anchorPos) {
23236
+ const tableInfo = findTableNodeInfoFromState(editor.state, anchorPos);
23237
+ if (!tableInfo) return false;
23238
+ editor.view.dispatch(
23239
+ editor.state.tr.setNodeMarkup(tableInfo.pos, tableInfo.node.type, {
23240
+ ...tableInfo.node.attrs,
23241
+ tableAlign
23242
+ })
23243
+ );
23244
+ const tableDom = editor.view.nodeDOM(tableInfo.pos);
23245
+ const tableElement = tableDom instanceof HTMLTableElement ? tableDom : tableDom instanceof HTMLElement ? tableDom.querySelector("table") : null;
23246
+ if (tableElement instanceof HTMLTableElement) {
23247
+ if (tableAlign) {
23248
+ tableElement.setAttribute("data-table-align", tableAlign);
23249
+ tableElement.style.width = "max-content";
23250
+ tableElement.style.maxWidth = "100%";
23251
+ tableElement.style.marginLeft = tableAlign === "center" || tableAlign === "right" ? "auto" : "0";
23252
+ tableElement.style.marginRight = tableAlign === "center" ? "auto" : tableAlign === "right" ? "0" : "auto";
23253
+ } else {
23254
+ tableElement.removeAttribute("data-table-align");
23255
+ tableElement.style.removeProperty("width");
23256
+ tableElement.style.removeProperty("max-width");
23257
+ tableElement.style.removeProperty("margin-left");
23258
+ tableElement.style.removeProperty("margin-right");
23259
+ }
23260
+ }
23261
+ return true;
23262
+ }
23263
+
23264
+ // src/components/UEditor/table-align.ts
23265
+ function normalizeTableAlign(value) {
23266
+ if (value === "left" || value === "center" || value === "right") {
23267
+ return value;
23268
+ }
23269
+ return null;
23270
+ }
23271
+ function parseTableAlign(element) {
23272
+ const dataAlign = normalizeTableAlign(element.getAttribute("data-table-align"));
23273
+ if (dataAlign) return dataAlign;
23274
+ const marginLeft = element.style.marginLeft?.trim();
23275
+ const marginRight = element.style.marginRight?.trim();
23276
+ if (marginLeft === "auto" && marginRight === "auto") return "center";
23277
+ if (marginLeft === "auto" && (marginRight === "0px" || marginRight === "0")) return "right";
23278
+ if ((marginLeft === "0px" || marginLeft === "0") && marginRight === "auto") return "left";
23279
+ return null;
23280
+ }
23281
+ function renderTableAlignStyle(tableAlign) {
23282
+ switch (tableAlign) {
23283
+ case "center":
23284
+ return "width: max-content; max-width: 100%; margin-left: auto; margin-right: auto;";
23285
+ case "right":
23286
+ return "width: max-content; max-width: 100%; margin-left: auto; margin-right: 0;";
23287
+ case "left":
23288
+ return "width: max-content; max-width: 100%; margin-left: 0; margin-right: auto;";
23289
+ default:
23290
+ return "";
23291
+ }
23292
+ }
23293
+ var UEditorTable = Table3.extend({
23294
+ addAttributes() {
23295
+ return {
23296
+ ...this.parent?.(),
23297
+ tableAlign: {
23298
+ default: null,
23299
+ parseHTML: (element) => {
23300
+ if (!(element instanceof HTMLElement)) return null;
23301
+ return parseTableAlign(element);
23302
+ },
23303
+ renderHTML: (attributes) => {
23304
+ const tableAlign = normalizeTableAlign(attributes.tableAlign);
23305
+ if (!tableAlign) return {};
23306
+ return {
23307
+ "data-table-align": tableAlign,
23308
+ style: renderTableAlignStyle(tableAlign)
23309
+ };
23310
+ }
23311
+ }
23312
+ };
23313
+ },
23314
+ addCommands() {
23315
+ return {
23316
+ ...this.parent?.(),
23317
+ setTableAlign: (tableAlign) => ({ state, dispatch }) => {
23318
+ const tableInfo = findTableNodeInfoFromState(state);
23319
+ if (!tableInfo) return false;
23320
+ dispatch?.(
23321
+ state.tr.setNodeMarkup(tableInfo.pos, tableInfo.node.type, {
23322
+ ...tableInfo.node.attrs,
23323
+ tableAlign
23324
+ })
23325
+ );
23326
+ return true;
23327
+ },
23328
+ unsetTableAlign: () => ({ state, dispatch }) => {
23329
+ const tableInfo = findTableNodeInfoFromState(state);
23330
+ if (!tableInfo) return false;
23331
+ dispatch?.(
23332
+ state.tr.setNodeMarkup(tableInfo.pos, tableInfo.node.type, {
23333
+ ...tableInfo.node.attrs,
23334
+ tableAlign: null
23335
+ })
23336
+ );
23337
+ return true;
23338
+ }
23339
+ };
23340
+ }
23341
+ });
23342
+ var table_align_default = UEditorTable;
23343
+
23004
23344
  // src/components/UEditor/extensions.ts
23005
23345
  var lowlight = createLowlight(common);
23006
23346
  function buildUEditorExtensions({
@@ -23056,7 +23396,7 @@ function buildUEditorExtensions({
23056
23396
  CodeBlockLowlight.configure({
23057
23397
  lowlight,
23058
23398
  HTMLAttributes: {
23059
- class: "rounded-lg bg-[#1e1e1e] p-4 font-mono text-sm overflow-x-auto"
23399
+ class: "rounded-lg border border-border/60 bg-muted/40 text-foreground p-4 font-mono text-sm overflow-x-auto"
23060
23400
  }
23061
23401
  }),
23062
23402
  HorizontalRule,
@@ -23069,6 +23409,10 @@ function buildUEditorExtensions({
23069
23409
  resizable_image_default,
23070
23410
  ClipboardImages.configure({ upload: uploadImage, insertMode: imageInsertMode }),
23071
23411
  TextStyle,
23412
+ font_family_default,
23413
+ font_size_default,
23414
+ line_height_default,
23415
+ letter_spacing_default,
23072
23416
  Color,
23073
23417
  Highlight.configure({
23074
23418
  multicolor: true
@@ -23076,7 +23420,7 @@ function buildUEditorExtensions({
23076
23420
  TextAlign.configure({
23077
23421
  types: ["heading", "paragraph", "image"]
23078
23422
  }),
23079
- Table3.configure({
23423
+ table_align_default.configure({
23080
23424
  resizable: true,
23081
23425
  handleWidth: 10,
23082
23426
  allowTableNodeSelection: true,
@@ -23421,6 +23765,48 @@ var EmojiPicker2 = ({ onSelect }) => {
23421
23765
  return /* @__PURE__ */ jsx79(EmojiPicker, { onEmojiSelect: onSelect });
23422
23766
  };
23423
23767
 
23768
+ // src/components/UEditor/typography-options.ts
23769
+ function normalizeStyleValue(value) {
23770
+ return typeof value === "string" ? value.trim().replace(/^['"]|['"]$/g, "") : "";
23771
+ }
23772
+ function getDefaultFontFamilies(t) {
23773
+ return [
23774
+ { label: "Inter", value: "Inter, ui-sans-serif, system-ui, sans-serif" },
23775
+ { label: "System UI", value: "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" },
23776
+ { label: "Georgia", value: "Georgia, 'Times New Roman', serif" },
23777
+ { label: "Palatino", value: "'Palatino Linotype', Palatino, Georgia, serif" },
23778
+ { label: "Times", value: "'Times New Roman', Times, serif" },
23779
+ { label: "JetBrains Mono", value: "'JetBrains Mono', 'Fira Code', 'SFMono-Regular', Consolas, monospace" }
23780
+ ];
23781
+ }
23782
+ function getDefaultFontSizes() {
23783
+ return [
23784
+ { label: "12", value: "12px" },
23785
+ { label: "14", value: "14px" },
23786
+ { label: "16", value: "16px" },
23787
+ { label: "18", value: "18px" },
23788
+ { label: "24", value: "24px" },
23789
+ { label: "32", value: "32px" }
23790
+ ];
23791
+ }
23792
+ function getDefaultLineHeights() {
23793
+ return [
23794
+ { label: "1.2", value: "1.2" },
23795
+ { label: "1.5", value: "1.5" },
23796
+ { label: "1.75", value: "1.75" },
23797
+ { label: "2", value: "2" }
23798
+ ];
23799
+ }
23800
+ function getDefaultLetterSpacings() {
23801
+ return [
23802
+ { label: "-0.02em", value: "-0.02em" },
23803
+ { label: "0", value: "0" },
23804
+ { label: "0.02em", value: "0.02em" },
23805
+ { label: "0.05em", value: "0.05em" },
23806
+ { label: "0.08em", value: "0.08em" }
23807
+ ];
23808
+ }
23809
+
23424
23810
  // src/components/UEditor/toolbar.tsx
23425
23811
  import { Fragment as Fragment25, jsx as jsx80, jsxs as jsxs67 } from "react/jsx-runtime";
23426
23812
  function fileToDataUrl2(file) {
@@ -23431,12 +23817,16 @@ function fileToDataUrl2(file) {
23431
23817
  reader.readAsDataURL(file);
23432
23818
  });
23433
23819
  }
23820
+ function formatTableInsertLabel(template, rows, cols) {
23821
+ return template.replace("{rows}", String(rows)).replace("{cols}", String(cols));
23822
+ }
23434
23823
  var ToolbarButton = React71.forwardRef(({ onClick, onMouseDown, active, disabled, children, title, className }, ref) => {
23435
23824
  const button = /* @__PURE__ */ jsx80(
23436
23825
  "button",
23437
23826
  {
23438
23827
  ref,
23439
23828
  type: "button",
23829
+ "aria-label": title,
23440
23830
  onMouseDown: (e) => {
23441
23831
  onMouseDown?.(e);
23442
23832
  e.preventDefault();
@@ -23461,22 +23851,115 @@ var ToolbarButton = React71.forwardRef(({ onClick, onMouseDown, active, disabled
23461
23851
  });
23462
23852
  ToolbarButton.displayName = "ToolbarButton";
23463
23853
  var ToolbarDivider = () => /* @__PURE__ */ jsx80("div", { className: "w-px h-6 bg-border/50 mx-1" });
23854
+ var TableInsertGrid = ({
23855
+ insertLabel,
23856
+ previewTemplate,
23857
+ onInsert
23858
+ }) => {
23859
+ const [selection, setSelection] = React71.useState({ rows: 3, cols: 3 });
23860
+ const maxRows = 8;
23861
+ const maxCols = 8;
23862
+ return /* @__PURE__ */ jsxs67("div", { className: "mb-2 rounded-xl border border-border/60 bg-muted/20 p-2", children: [
23863
+ /* @__PURE__ */ jsx80("div", { className: "mb-2 text-sm font-medium text-foreground", children: formatTableInsertLabel(previewTemplate, selection.rows, selection.cols) }),
23864
+ /* @__PURE__ */ jsx80(
23865
+ "div",
23866
+ {
23867
+ className: "grid grid-cols-8 gap-1",
23868
+ onMouseLeave: () => setSelection((prev) => prev),
23869
+ children: Array.from({ length: maxRows }).map(
23870
+ (_, rowIndex) => Array.from({ length: maxCols }).map((__, colIndex) => {
23871
+ const rows = rowIndex + 1;
23872
+ const cols = colIndex + 1;
23873
+ const active = rows <= selection.rows && cols <= selection.cols;
23874
+ return /* @__PURE__ */ jsx80(
23875
+ "button",
23876
+ {
23877
+ type: "button",
23878
+ "aria-label": formatTableInsertLabel(previewTemplate, rows, cols),
23879
+ onMouseDown: (e) => e.preventDefault(),
23880
+ onMouseEnter: () => setSelection({ rows, cols }),
23881
+ onFocus: () => setSelection({ rows, cols }),
23882
+ onClick: () => onInsert(rows, cols),
23883
+ className: cn(
23884
+ "h-5 w-5 rounded-[4px] border transition-colors",
23885
+ active ? "border-primary bg-primary/20" : "border-border/70 bg-background hover:border-primary/60 hover:bg-primary/10"
23886
+ )
23887
+ },
23888
+ `${rows}-${cols}`
23889
+ );
23890
+ })
23891
+ )
23892
+ }
23893
+ ),
23894
+ /* @__PURE__ */ jsx80("div", { className: "mt-2 text-xs text-muted-foreground", children: insertLabel })
23895
+ ] });
23896
+ };
23464
23897
  var EditorToolbar = ({
23465
23898
  editor,
23466
23899
  variant,
23467
23900
  uploadImage,
23468
- imageInsertMode = "base64"
23901
+ imageInsertMode = "base64",
23902
+ fontFamilies,
23903
+ fontSizes,
23904
+ lineHeights,
23905
+ letterSpacings
23469
23906
  }) => {
23470
23907
  const t = useSmartTranslations("UEditor");
23471
23908
  const { textColors, highlightColors } = useEditorColors();
23472
23909
  const [showImageInput, setShowImageInput] = useState43(false);
23910
+ const [isTableMenuOpen, setIsTableMenuOpen] = useState43(false);
23911
+ const tableCommandAnchorPosRef = useRef29(null);
23473
23912
  const fileInputRef = useRef29(null);
23474
23913
  const [isUploadingImage, setIsUploadingImage] = useState43(false);
23475
23914
  const [imageUploadError, setImageUploadError] = useState43(null);
23915
+ const [fontSizeDraft, setFontSizeDraft] = useState43("");
23476
23916
  const isImageSelected = editor.isActive("image");
23477
23917
  const imageAttrs = editor.getAttributes("image");
23918
+ const tableAttrs = editor.getAttributes("table");
23919
+ const textStyleAttrs = editor.getAttributes("textStyle");
23478
23920
  const imageLayout = imageAttrs.imageLayout === "left" || imageAttrs.imageLayout === "right" ? imageAttrs.imageLayout : "block";
23479
23921
  const imageWidthPreset = imageAttrs.imageWidthPreset === "sm" || imageAttrs.imageWidthPreset === "md" || imageAttrs.imageWidthPreset === "lg" ? imageAttrs.imageWidthPreset : null;
23922
+ const currentTableAlign = tableAttrs.tableAlign === "center" || tableAttrs.tableAlign === "right" ? tableAttrs.tableAlign : "left";
23923
+ const isTableSelected = editor.isActive("table");
23924
+ const hasTableContext = isTableSelected || tableCommandAnchorPosRef.current !== null;
23925
+ const currentFontFamily = normalizeStyleValue(textStyleAttrs.fontFamily);
23926
+ const currentFontSize = normalizeStyleValue(textStyleAttrs.fontSize);
23927
+ const currentLineHeight = normalizeStyleValue(textStyleAttrs.lineHeight);
23928
+ const currentLetterSpacing = normalizeStyleValue(textStyleAttrs.letterSpacing);
23929
+ const availableFontFamilies = React71.useMemo(
23930
+ () => fontFamilies ?? getDefaultFontFamilies(t),
23931
+ [fontFamilies, t]
23932
+ );
23933
+ const availableFontSizes = React71.useMemo(
23934
+ () => fontSizes ?? getDefaultFontSizes(),
23935
+ [fontSizes]
23936
+ );
23937
+ const availableLineHeights = React71.useMemo(
23938
+ () => lineHeights ?? getDefaultLineHeights(),
23939
+ [lineHeights]
23940
+ );
23941
+ const availableLetterSpacings = React71.useMemo(
23942
+ () => letterSpacings ?? getDefaultLetterSpacings(),
23943
+ [letterSpacings]
23944
+ );
23945
+ const currentFontFamilyLabel = availableFontFamilies.find((option) => normalizeStyleValue(option.value) === currentFontFamily)?.label ?? t("toolbar.fontDefault");
23946
+ const currentFontSizeLabel = availableFontSizes.find((option) => normalizeStyleValue(option.value) === currentFontSize)?.label ?? t("toolbar.sizeDefault");
23947
+ const currentLineHeightLabel = availableLineHeights.find((option) => normalizeStyleValue(option.value) === currentLineHeight)?.label ?? t("toolbar.lineHeightDefault");
23948
+ const currentLetterSpacingLabel = availableLetterSpacings.find((option) => normalizeStyleValue(option.value) === currentLetterSpacing)?.label ?? t("toolbar.letterSpacingDefault");
23949
+ React71.useEffect(() => {
23950
+ setFontSizeDraft(currentFontSize.replace(/px$/i, ""));
23951
+ }, [currentFontSize]);
23952
+ const applyFontSizeDraft = () => {
23953
+ const normalized = fontSizeDraft.trim();
23954
+ if (!normalized) {
23955
+ editor.chain().focus().unsetFontSize().run();
23956
+ return;
23957
+ }
23958
+ const parsed = Number.parseFloat(normalized);
23959
+ if (!Number.isFinite(parsed) || parsed <= 0) return;
23960
+ const clamped = Math.min(96, Math.max(8, parsed));
23961
+ editor.chain().focus().setFontSize(`${clamped}px`).run();
23962
+ };
23480
23963
  const insertImageFiles = async (files) => {
23481
23964
  if (files.length === 0) return;
23482
23965
  setIsUploadingImage(true);
@@ -23513,6 +23996,7 @@ var EditorToolbar = ({
23513
23996
  /* @__PURE__ */ jsxs67(
23514
23997
  DropdownMenu,
23515
23998
  {
23999
+ contentClassName: "p-2",
23516
24000
  trigger: /* @__PURE__ */ jsxs67(ToolbarButton, { onClick: () => {
23517
24001
  }, title: t("toolbar.textStyle"), className: "px-2 w-auto gap-1", children: [
23518
24002
  /* @__PURE__ */ jsx80(Type2, { className: "w-4 h-4" }),
@@ -23561,6 +24045,183 @@ var EditorToolbar = ({
23561
24045
  ]
23562
24046
  }
23563
24047
  ),
24048
+ /* @__PURE__ */ jsxs67(
24049
+ DropdownMenu,
24050
+ {
24051
+ trigger: /* @__PURE__ */ jsx80(
24052
+ ToolbarButton,
24053
+ {
24054
+ onClick: () => {
24055
+ },
24056
+ title: t("toolbar.fontFamily"),
24057
+ className: "relative",
24058
+ children: /* @__PURE__ */ jsx80(Type2, { className: "w-4 h-4" })
24059
+ }
24060
+ ),
24061
+ contentClassName: "max-h-80 overflow-y-auto min-w-56 p-2",
24062
+ children: [
24063
+ /* @__PURE__ */ jsx80(
24064
+ DropdownMenuItem,
24065
+ {
24066
+ icon: Type2,
24067
+ label: t("toolbar.fontDefault"),
24068
+ onClick: () => editor.chain().focus().unsetFontFamily().run(),
24069
+ active: !currentFontFamily
24070
+ }
24071
+ ),
24072
+ availableFontFamilies.map((option) => /* @__PURE__ */ jsx80(
24073
+ DropdownMenuItem,
24074
+ {
24075
+ label: option.label,
24076
+ onClick: () => editor.chain().focus().setFontFamily(option.value).run(),
24077
+ active: normalizeStyleValue(option.value) === currentFontFamily,
24078
+ className: "font-medium"
24079
+ },
24080
+ option.value
24081
+ ))
24082
+ ]
24083
+ }
24084
+ ),
24085
+ /* @__PURE__ */ jsxs67(
24086
+ DropdownMenu,
24087
+ {
24088
+ closeOnSelect: false,
24089
+ trigger: /* @__PURE__ */ jsx80(
24090
+ ToolbarButton,
24091
+ {
24092
+ onClick: () => {
24093
+ },
24094
+ title: t("toolbar.fontSize"),
24095
+ className: "px-2 w-auto min-w-9",
24096
+ children: /* @__PURE__ */ jsx80("span", { className: "text-[10px] font-semibold leading-none", children: currentFontSize.replace(/px$/i, "") || "T" })
24097
+ }
24098
+ ),
24099
+ contentClassName: "max-h-80 overflow-y-auto min-w-44 p-2",
24100
+ children: [
24101
+ /* @__PURE__ */ jsx80("div", { className: "mb-2 rounded-lg border border-border/60 bg-muted/30 p-2", children: /* @__PURE__ */ jsxs67("label", { className: "flex items-center gap-2", children: [
24102
+ /* @__PURE__ */ jsx80(
24103
+ "input",
24104
+ {
24105
+ type: "number",
24106
+ min: 8,
24107
+ max: 96,
24108
+ step: 1,
24109
+ value: fontSizeDraft,
24110
+ onChange: (e) => setFontSizeDraft(e.target.value),
24111
+ onMouseDown: (e) => e.stopPropagation(),
24112
+ onClick: (e) => e.stopPropagation(),
24113
+ onKeyDown: (e) => {
24114
+ e.stopPropagation();
24115
+ if (e.key === "Enter") {
24116
+ e.preventDefault();
24117
+ applyFontSizeDraft();
24118
+ }
24119
+ },
24120
+ "aria-label": t("toolbar.fontSize"),
24121
+ className: "h-8 w-full rounded-md border border-border bg-background px-2 text-sm outline-none focus:ring-2 focus:ring-primary/20"
24122
+ }
24123
+ ),
24124
+ /* @__PURE__ */ jsx80("span", { className: "text-xs text-muted-foreground", children: "px" })
24125
+ ] }) }),
24126
+ /* @__PURE__ */ jsx80(
24127
+ DropdownMenuItem,
24128
+ {
24129
+ icon: Type2,
24130
+ label: t("toolbar.sizeDefault"),
24131
+ onClick: () => editor.chain().focus().unsetFontSize().run(),
24132
+ active: !currentFontSize
24133
+ }
24134
+ ),
24135
+ availableFontSizes.map((option) => /* @__PURE__ */ jsx80(
24136
+ DropdownMenuItem,
24137
+ {
24138
+ label: option.label,
24139
+ onClick: () => editor.chain().focus().setFontSize(option.value).run(),
24140
+ active: normalizeStyleValue(option.value) === currentFontSize
24141
+ },
24142
+ option.value
24143
+ ))
24144
+ ]
24145
+ }
24146
+ ),
24147
+ /* @__PURE__ */ jsxs67(
24148
+ DropdownMenu,
24149
+ {
24150
+ trigger: /* @__PURE__ */ jsxs67(
24151
+ ToolbarButton,
24152
+ {
24153
+ onClick: () => {
24154
+ },
24155
+ title: t("toolbar.lineHeight"),
24156
+ className: "gap-0.5",
24157
+ children: [
24158
+ /* @__PURE__ */ jsx80(ArrowUp, { className: "w-3 h-3" }),
24159
+ /* @__PURE__ */ jsx80(ArrowDown, { className: "w-3 h-3" })
24160
+ ]
24161
+ }
24162
+ ),
24163
+ contentClassName: "max-h-72 overflow-y-auto p-2",
24164
+ children: [
24165
+ /* @__PURE__ */ jsx80(
24166
+ DropdownMenuItem,
24167
+ {
24168
+ icon: Type2,
24169
+ label: t("toolbar.lineHeightDefault"),
24170
+ onClick: () => editor.chain().focus().unsetLineHeight().run(),
24171
+ active: !currentLineHeight
24172
+ }
24173
+ ),
24174
+ availableLineHeights.map((option) => /* @__PURE__ */ jsx80(
24175
+ DropdownMenuItem,
24176
+ {
24177
+ label: option.label,
24178
+ onClick: () => editor.chain().focus().setLineHeight(option.value).run(),
24179
+ active: normalizeStyleValue(option.value) === currentLineHeight
24180
+ },
24181
+ option.value
24182
+ ))
24183
+ ]
24184
+ }
24185
+ ),
24186
+ /* @__PURE__ */ jsxs67(
24187
+ DropdownMenu,
24188
+ {
24189
+ trigger: /* @__PURE__ */ jsxs67(
24190
+ ToolbarButton,
24191
+ {
24192
+ onClick: () => {
24193
+ },
24194
+ title: t("toolbar.letterSpacing"),
24195
+ className: "gap-0.5",
24196
+ children: [
24197
+ /* @__PURE__ */ jsx80(ArrowLeft, { className: "w-3 h-3" }),
24198
+ /* @__PURE__ */ jsx80(ArrowRight, { className: "w-3 h-3" })
24199
+ ]
24200
+ }
24201
+ ),
24202
+ contentClassName: "max-h-72 overflow-y-auto p-2",
24203
+ children: [
24204
+ /* @__PURE__ */ jsx80(
24205
+ DropdownMenuItem,
24206
+ {
24207
+ icon: Type2,
24208
+ label: t("toolbar.letterSpacingDefault"),
24209
+ onClick: () => editor.chain().focus().unsetLetterSpacing().run(),
24210
+ active: !currentLetterSpacing
24211
+ }
24212
+ ),
24213
+ availableLetterSpacings.map((option) => /* @__PURE__ */ jsx80(
24214
+ DropdownMenuItem,
24215
+ {
24216
+ label: option.label,
24217
+ onClick: () => editor.chain().focus().setLetterSpacing(option.value).run(),
24218
+ active: normalizeStyleValue(option.value) === currentLetterSpacing
24219
+ },
24220
+ option.value
24221
+ ))
24222
+ ]
24223
+ }
24224
+ ),
23564
24225
  /* @__PURE__ */ jsx80(ToolbarDivider, {}),
23565
24226
  /* @__PURE__ */ jsx80(ToolbarButton, { onClick: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold"), title: t("toolbar.bold"), children: /* @__PURE__ */ jsx80(BoldIcon, { className: "w-4 h-4" }) }),
23566
24227
  /* @__PURE__ */ jsx80(ToolbarButton, { onClick: () => editor.chain().focus().toggleItalic().run(), active: editor.isActive("italic"), title: t("toolbar.italic"), children: /* @__PURE__ */ jsx80(ItalicIcon, { className: "w-4 h-4" }) }),
@@ -23895,18 +24556,58 @@ var EditorToolbar = ({
23895
24556
  /* @__PURE__ */ jsxs67(
23896
24557
  DropdownMenu,
23897
24558
  {
24559
+ isOpen: isTableMenuOpen,
24560
+ onOpenChange: (open) => {
24561
+ setIsTableMenuOpen(open);
24562
+ tableCommandAnchorPosRef.current = open && editor.isActive("table") ? editor.state.selection.$from.pos : null;
24563
+ },
23898
24564
  trigger: /* @__PURE__ */ jsxs67(ToolbarButton, { onClick: () => {
23899
24565
  }, title: t("toolbar.table"), children: [
23900
24566
  /* @__PURE__ */ jsx80(TableIcon, { className: "w-4 h-4" }),
23901
24567
  /* @__PURE__ */ jsx80(ChevronDown7, { className: "w-3 h-3" })
23902
24568
  ] }),
24569
+ contentClassName: "p-2 min-w-56",
23903
24570
  children: [
24571
+ /* @__PURE__ */ jsx80(
24572
+ TableInsertGrid,
24573
+ {
24574
+ insertLabel: t("tableMenu.insertTable"),
24575
+ previewTemplate: t("tableMenu.gridPreview"),
24576
+ onInsert: (rows, cols) => {
24577
+ editor.chain().focus().insertTable({ rows, cols, withHeaderRow: true }).run();
24578
+ setIsTableMenuOpen(false);
24579
+ }
24580
+ }
24581
+ ),
24582
+ /* @__PURE__ */ jsx80("div", { className: "my-1 border-t" }),
23904
24583
  /* @__PURE__ */ jsx80(
23905
24584
  DropdownMenuItem,
23906
24585
  {
23907
- icon: TableIcon,
23908
- label: t("tableMenu.insert3x3"),
23909
- onClick: () => editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()
24586
+ icon: AlignLeft,
24587
+ label: t("tableMenu.alignLeft"),
24588
+ onClick: () => applyTableAlignment(editor, "left", tableCommandAnchorPosRef.current ?? void 0),
24589
+ active: hasTableContext && currentTableAlign === "left",
24590
+ disabled: !hasTableContext
24591
+ }
24592
+ ),
24593
+ /* @__PURE__ */ jsx80(
24594
+ DropdownMenuItem,
24595
+ {
24596
+ icon: AlignCenter,
24597
+ label: t("tableMenu.alignCenter"),
24598
+ onClick: () => applyTableAlignment(editor, "center", tableCommandAnchorPosRef.current ?? void 0),
24599
+ active: hasTableContext && currentTableAlign === "center",
24600
+ disabled: !hasTableContext
24601
+ }
24602
+ ),
24603
+ /* @__PURE__ */ jsx80(
24604
+ DropdownMenuItem,
24605
+ {
24606
+ icon: AlignRight,
24607
+ label: t("tableMenu.alignRight"),
24608
+ onClick: () => applyTableAlignment(editor, "right", tableCommandAnchorPosRef.current ?? void 0),
24609
+ active: hasTableContext && currentTableAlign === "right",
24610
+ disabled: !hasTableContext
23910
24611
  }
23911
24612
  ),
23912
24613
  /* @__PURE__ */ jsx80("div", { className: "my-1 border-t" }),
@@ -23916,7 +24617,7 @@ var EditorToolbar = ({
23916
24617
  icon: ArrowLeft,
23917
24618
  label: t("tableMenu.addColumnBefore"),
23918
24619
  onClick: () => editor.chain().focus().addColumnBefore().run(),
23919
- disabled: !editor.can().addColumnBefore()
24620
+ disabled: !hasTableContext || !editor.can().addColumnBefore()
23920
24621
  }
23921
24622
  ),
23922
24623
  /* @__PURE__ */ jsx80(
@@ -23925,7 +24626,7 @@ var EditorToolbar = ({
23925
24626
  icon: ArrowDown,
23926
24627
  label: t("tableMenu.addColumnAfter"),
23927
24628
  onClick: () => editor.chain().focus().addColumnAfter().run(),
23928
- disabled: !editor.can().addColumnAfter()
24629
+ disabled: !hasTableContext || !editor.can().addColumnAfter()
23929
24630
  }
23930
24631
  ),
23931
24632
  /* @__PURE__ */ jsx80(
@@ -23934,7 +24635,7 @@ var EditorToolbar = ({
23934
24635
  icon: ArrowUp,
23935
24636
  label: t("tableMenu.addRowBefore"),
23936
24637
  onClick: () => editor.chain().focus().addRowBefore().run(),
23937
- disabled: !editor.can().addRowBefore()
24638
+ disabled: !hasTableContext || !editor.can().addRowBefore()
23938
24639
  }
23939
24640
  ),
23940
24641
  /* @__PURE__ */ jsx80(
@@ -23943,7 +24644,7 @@ var EditorToolbar = ({
23943
24644
  icon: ArrowRight,
23944
24645
  label: t("tableMenu.addRowAfter"),
23945
24646
  onClick: () => editor.chain().focus().addRowAfter().run(),
23946
- disabled: !editor.can().addRowAfter()
24647
+ disabled: !hasTableContext || !editor.can().addRowAfter()
23947
24648
  }
23948
24649
  ),
23949
24650
  /* @__PURE__ */ jsx80("div", { className: "my-1 border-t" }),
@@ -23953,7 +24654,7 @@ var EditorToolbar = ({
23953
24654
  icon: TableIcon,
23954
24655
  label: t("tableMenu.toggleHeaderRow"),
23955
24656
  onClick: () => editor.chain().focus().toggleHeaderRow().run(),
23956
- disabled: !editor.can().toggleHeaderRow()
24657
+ disabled: !hasTableContext || !editor.can().toggleHeaderRow()
23957
24658
  }
23958
24659
  ),
23959
24660
  /* @__PURE__ */ jsx80(
@@ -23962,7 +24663,7 @@ var EditorToolbar = ({
23962
24663
  icon: TableIcon,
23963
24664
  label: t("tableMenu.toggleHeaderColumn"),
23964
24665
  onClick: () => editor.chain().focus().toggleHeaderColumn().run(),
23965
- disabled: !editor.can().toggleHeaderColumn()
24666
+ disabled: !hasTableContext || !editor.can().toggleHeaderColumn()
23966
24667
  }
23967
24668
  ),
23968
24669
  /* @__PURE__ */ jsx80("div", { className: "my-1 border-t" }),
@@ -23972,7 +24673,7 @@ var EditorToolbar = ({
23972
24673
  icon: Trash22,
23973
24674
  label: t("tableMenu.deleteColumn"),
23974
24675
  onClick: () => editor.chain().focus().deleteColumn().run(),
23975
- disabled: !editor.can().deleteColumn()
24676
+ disabled: !hasTableContext || !editor.can().deleteColumn()
23976
24677
  }
23977
24678
  ),
23978
24679
  /* @__PURE__ */ jsx80(
@@ -23981,7 +24682,7 @@ var EditorToolbar = ({
23981
24682
  icon: Trash22,
23982
24683
  label: t("tableMenu.deleteRow"),
23983
24684
  onClick: () => editor.chain().focus().deleteRow().run(),
23984
- disabled: !editor.can().deleteRow()
24685
+ disabled: !hasTableContext || !editor.can().deleteRow()
23985
24686
  }
23986
24687
  ),
23987
24688
  /* @__PURE__ */ jsx80(
@@ -23990,7 +24691,7 @@ var EditorToolbar = ({
23990
24691
  icon: Trash22,
23991
24692
  label: t("tableMenu.deleteTable"),
23992
24693
  onClick: () => editor.chain().focus().deleteTable().run(),
23993
- disabled: !editor.can().deleteTable()
24694
+ disabled: !hasTableContext || !editor.can().deleteTable()
23994
24695
  }
23995
24696
  )
23996
24697
  ]
@@ -24096,7 +24797,9 @@ var FloatingMenuContent = ({ editor }) => {
24096
24797
  };
24097
24798
  var BubbleMenuContent = ({
24098
24799
  editor,
24099
- onKeepOpenChange
24800
+ onKeepOpenChange,
24801
+ fontSizes,
24802
+ lineHeights
24100
24803
  }) => {
24101
24804
  const t = useSmartTranslations("UEditor");
24102
24805
  const { textColors, highlightColors } = useEditorColors();
@@ -24106,6 +24809,17 @@ var BubbleMenuContent = ({
24106
24809
  const imageAttrs = editor.getAttributes("image");
24107
24810
  const imageLayout = imageAttrs.imageLayout === "left" || imageAttrs.imageLayout === "right" ? imageAttrs.imageLayout : "block";
24108
24811
  const imageWidthPreset = imageAttrs.imageWidthPreset === "sm" || imageAttrs.imageWidthPreset === "md" || imageAttrs.imageWidthPreset === "lg" ? imageAttrs.imageWidthPreset : null;
24812
+ const textStyleAttrs = editor.getAttributes("textStyle");
24813
+ const currentFontSize = normalizeStyleValue(textStyleAttrs.fontSize);
24814
+ const currentLineHeight = normalizeStyleValue(textStyleAttrs.lineHeight);
24815
+ const quickFontSizes = useMemo23(
24816
+ () => (fontSizes ?? getDefaultFontSizes()).filter((option) => ["14px", "16px", "24px"].includes(option.value)),
24817
+ [fontSizes]
24818
+ );
24819
+ const quickLineHeights = useMemo23(
24820
+ () => (lineHeights ?? getDefaultLineHeights()).filter((option) => ["1.2", "1.5", "1.75"].includes(option.value)),
24821
+ [lineHeights]
24822
+ );
24109
24823
  useEffect33(() => {
24110
24824
  onKeepOpenChange?.(showLinkInput);
24111
24825
  }, [onKeepOpenChange, showLinkInput]);
@@ -24225,6 +24939,50 @@ var BubbleMenuContent = ({
24225
24939
  ),
24226
24940
  /* @__PURE__ */ jsx81(ToolbarButton, { onClick: () => setShowEditorColorPalette(true), title: t("colors.textColor"), children: /* @__PURE__ */ jsx81(Palette3, { className: "w-4 h-4" }) }),
24227
24941
  /* @__PURE__ */ jsx81("div", { className: "w-px h-6 bg-border/50 mx-1" }),
24942
+ /* @__PURE__ */ jsx81(
24943
+ ToolbarButton,
24944
+ {
24945
+ onClick: () => editor.chain().focus().unsetFontSize().run(),
24946
+ active: !currentFontSize,
24947
+ title: t("toolbar.sizeDefault"),
24948
+ className: "px-2 w-auto",
24949
+ children: /* @__PURE__ */ jsx81("span", { className: "text-[10px] font-semibold", children: "A" })
24950
+ }
24951
+ ),
24952
+ quickFontSizes.map((option) => /* @__PURE__ */ jsx81(
24953
+ ToolbarButton,
24954
+ {
24955
+ onClick: () => editor.chain().focus().setFontSize(option.value).run(),
24956
+ active: normalizeStyleValue(option.value) === currentFontSize,
24957
+ title: `${t("toolbar.fontSize")} ${option.label}`,
24958
+ className: "px-2 w-auto",
24959
+ children: /* @__PURE__ */ jsx81("span", { className: "text-[10px] font-semibold", children: option.label })
24960
+ },
24961
+ option.value
24962
+ )),
24963
+ /* @__PURE__ */ jsx81("div", { className: "w-px h-6 bg-border/50 mx-1" }),
24964
+ /* @__PURE__ */ jsx81(
24965
+ ToolbarButton,
24966
+ {
24967
+ onClick: () => editor.chain().focus().unsetLineHeight().run(),
24968
+ active: !currentLineHeight,
24969
+ title: t("toolbar.lineHeightDefault"),
24970
+ className: "px-2 w-auto",
24971
+ children: /* @__PURE__ */ jsx81("span", { className: "text-[10px] font-semibold leading-none", children: "LH" })
24972
+ }
24973
+ ),
24974
+ quickLineHeights.map((option) => /* @__PURE__ */ jsx81(
24975
+ ToolbarButton,
24976
+ {
24977
+ onClick: () => editor.chain().focus().setLineHeight(option.value).run(),
24978
+ active: normalizeStyleValue(option.value) === currentLineHeight,
24979
+ title: `${t("toolbar.lineHeight")} ${option.label}`,
24980
+ className: "px-2 w-auto",
24981
+ children: /* @__PURE__ */ jsx81("span", { className: "text-[10px] font-semibold", children: option.label })
24982
+ },
24983
+ option.value
24984
+ )),
24985
+ /* @__PURE__ */ jsx81("div", { className: "w-px h-6 bg-border/50 mx-1" }),
24228
24986
  /* @__PURE__ */ jsx81(
24229
24987
  ToolbarButton,
24230
24988
  {
@@ -24245,8 +25003,13 @@ var BubbleMenuContent = ({
24245
25003
  )
24246
25004
  ] });
24247
25005
  };
24248
- var CustomBubbleMenu = ({ editor }) => {
25006
+ var CustomBubbleMenu = ({
25007
+ editor,
25008
+ fontSizes,
25009
+ lineHeights
25010
+ }) => {
24249
25011
  const SHOW_DELAY_MS = 180;
25012
+ const BUBBLE_MENU_OFFSET = 16;
24250
25013
  const [isVisible, setIsVisible] = useState44(false);
24251
25014
  const [position, setPosition] = useState44({ top: 0, left: 0 });
24252
25015
  const menuRef = useRef30(null);
@@ -24274,7 +25037,7 @@ var CustomBubbleMenu = ({ editor }) => {
24274
25037
  const start = view.coordsAtPos(from);
24275
25038
  const end = view.coordsAtPos(to);
24276
25039
  const left = (start.left + end.left) / 2;
24277
- const top = start.top - 10;
25040
+ const top = start.top - BUBBLE_MENU_OFFSET;
24278
25041
  setPosition({ top, left });
24279
25042
  if (keepOpenRef.current) {
24280
25043
  clearShowTimeout();
@@ -24320,7 +25083,9 @@ var CustomBubbleMenu = ({ editor }) => {
24320
25083
  BubbleMenuContent,
24321
25084
  {
24322
25085
  editor,
24323
- onKeepOpenChange: setKeepOpen
25086
+ onKeepOpenChange: setKeepOpen,
25087
+ fontSizes,
25088
+ lineHeights
24324
25089
  }
24325
25090
  )
24326
25091
  }
@@ -24329,6 +25094,7 @@ var CustomBubbleMenu = ({ editor }) => {
24329
25094
  );
24330
25095
  };
24331
25096
  var CustomFloatingMenu = ({ editor }) => {
25097
+ const FLOATING_MENU_OFFSET = 16;
24332
25098
  const [isVisible, setIsVisible] = useState44(false);
24333
25099
  const [position, setPosition] = useState44({ top: 0, left: 0 });
24334
25100
  useEffect33(() => {
@@ -24341,7 +25107,7 @@ var CustomFloatingMenu = ({ editor }) => {
24341
25107
  return;
24342
25108
  }
24343
25109
  const coords = view.coordsAtPos($from.pos);
24344
- setPosition({ top: coords.top - 10, left: coords.left });
25110
+ setPosition({ top: coords.top - FLOATING_MENU_OFFSET, left: coords.left });
24345
25111
  setIsVisible(true);
24346
25112
  };
24347
25113
  const handleBlur = () => setIsVisible(false);
@@ -28811,6 +29577,9 @@ var columnResizingPluginKey = new PluginKey3("tableColumnResizing");
28811
29577
 
28812
29578
  // src/components/UEditor/table-controls.tsx
28813
29579
  import {
29580
+ AlignCenter as AlignCenter3,
29581
+ AlignLeft as AlignLeft3,
29582
+ AlignRight as AlignRight3,
28814
29583
  ArrowDown as ArrowDown2,
28815
29584
  ArrowLeft as ArrowLeft2,
28816
29585
  ArrowRight as ArrowRight2,
@@ -28828,9 +29597,16 @@ var FALLBACK_TABLE_COLUMN_WIDTH = 160;
28828
29597
  var MENU_HOVER_PADDING = 18;
28829
29598
  var ROW_HANDLE_HOVER_WIDTH = 28;
28830
29599
  var COLUMN_HANDLE_HOVER_HEIGHT = 28;
29600
+ var ROW_HANDLE_GUTTER = 20;
29601
+ var TABLE_MENU_TOP_OFFSET = 10;
29602
+ var COLUMN_HANDLE_TOP_OFFSET = 8;
29603
+ var ADD_COLUMN_RAIL_GAP = 4;
29604
+ var ADD_ROW_RAIL_GAP = 4;
28831
29605
  var ADD_COLUMN_HOVER_WIDTH = 24;
28832
29606
  var ADD_ROW_HOVER_HEIGHT = 24;
28833
29607
  var HANDLE_HOVER_RADIUS = 14;
29608
+ var IDLE_HANDLE_OPACITY = "0.4";
29609
+ var IDLE_HANDLE_SCALE = "0.78";
28834
29610
  var DEFAULT_HOVER_STATE = {
28835
29611
  menuVisible: false,
28836
29612
  addColumnVisible: false,
@@ -29072,8 +29848,8 @@ function TableControls({ editor, containerRef }) {
29072
29848
  const rowHandleIndex = Number.isFinite(directRowHandleIndex) ? directRowHandleIndex : activeLayout.rowHandles.find((rowHandle) => relativeX >= activeLayout.tableLeft - ROW_HANDLE_HOVER_WIDTH && relativeX <= activeLayout.tableLeft && Math.abs(relativeY - rowHandle.center) <= HANDLE_HOVER_RADIUS)?.index ?? null;
29073
29849
  const columnHandleIndex = Number.isFinite(directColumnHandleIndex) ? directColumnHandleIndex : activeLayout.columnHandles.find((columnHandle) => relativeY >= activeLayout.tableTop - COLUMN_HANDLE_HOVER_HEIGHT && relativeY <= activeLayout.tableTop && Math.abs(relativeX - columnHandle.center) <= HANDLE_HOVER_RADIUS)?.index ?? null;
29074
29850
  const menuVisible = Boolean(directTableMenu) || relativeX >= activeLayout.tableLeft - MENU_HOVER_PADDING && relativeX <= activeLayout.tableLeft + 42 && relativeY >= activeLayout.tableTop - COLUMN_HANDLE_HOVER_HEIGHT && relativeY <= activeLayout.tableTop + MENU_HOVER_PADDING;
29075
- const addColumnVisible = Boolean(directAddColumn) || relativeX >= activeLayout.wrapperLeft + visibleTableWidth2 && relativeX <= activeLayout.wrapperLeft + visibleTableWidth2 + ADD_COLUMN_HOVER_WIDTH && relativeY >= activeLayout.wrapperTop && relativeY <= activeLayout.wrapperTop + visibleTableHeight2;
29076
- const addRowVisible = Boolean(directAddRow) || relativeY >= activeLayout.wrapperTop + activeLayout.wrapperHeight && relativeY <= activeLayout.wrapperTop + activeLayout.wrapperHeight + ADD_ROW_HOVER_HEIGHT && relativeX >= activeLayout.wrapperLeft && relativeX <= activeLayout.wrapperLeft + visibleTableWidth2;
29851
+ const addColumnVisible = Boolean(directAddColumn) || relativeX >= activeLayout.tableLeft + visibleTableWidth2 && relativeX <= activeLayout.tableLeft + visibleTableWidth2 + ADD_COLUMN_HOVER_WIDTH && relativeY >= activeLayout.tableTop && relativeY <= activeLayout.tableTop + visibleTableHeight2;
29852
+ const addRowVisible = Boolean(directAddRow) || relativeY >= activeLayout.tableTop + visibleTableHeight2 && relativeY <= activeLayout.tableTop + visibleTableHeight2 + ADD_ROW_HOVER_HEIGHT && relativeX >= activeLayout.tableLeft && relativeX <= activeLayout.tableLeft + visibleTableWidth2;
29077
29853
  setHoverState((prev) => {
29078
29854
  if (prev.menuVisible === menuVisible && prev.addColumnVisible === addColumnVisible && prev.addRowVisible === addRowVisible && prev.rowHandleIndex === rowHandleIndex && prev.columnHandleIndex === columnHandleIndex) {
29079
29855
  return prev;
@@ -29313,6 +30089,21 @@ function TableControls({ editor, containerRef }) {
29313
30089
  const menuItems = React73.useMemo(() => {
29314
30090
  if (!layout) return [];
29315
30091
  return [
30092
+ {
30093
+ label: t("tableMenu.alignLeft"),
30094
+ icon: AlignLeft3,
30095
+ onClick: () => applyTableAlignment(editor, "left", layout.cellPos)
30096
+ },
30097
+ {
30098
+ label: t("tableMenu.alignCenter"),
30099
+ icon: AlignCenter3,
30100
+ onClick: () => applyTableAlignment(editor, "center", layout.cellPos)
30101
+ },
30102
+ {
30103
+ label: t("tableMenu.alignRight"),
30104
+ icon: AlignRight3,
30105
+ onClick: () => applyTableAlignment(editor, "right", layout.cellPos)
30106
+ },
29316
30107
  {
29317
30108
  label: t("tableMenu.addColumnBefore"),
29318
30109
  icon: ArrowLeft2,
@@ -29422,16 +30213,16 @@ function TableControls({ editor, containerRef }) {
29422
30213
  if (!layout) {
29423
30214
  return null;
29424
30215
  }
29425
- const menuTop = Math.max(8, layout.tableTop - 16);
30216
+ const menuTop = Math.max(8, layout.tableTop - TABLE_MENU_TOP_OFFSET);
29426
30217
  const menuLeft = Math.max(8, layout.tableLeft);
29427
- const rowHandleLeft = Math.max(8, layout.tableLeft - 66);
29428
- const columnHandleTop = Math.max(8, layout.tableTop - 14);
30218
+ const rowHandleLeft = Math.max(8, layout.tableLeft - ROW_HANDLE_GUTTER);
30219
+ const columnHandleTop = Math.max(8, layout.tableTop - COLUMN_HANDLE_TOP_OFFSET);
29429
30220
  const visibleTableWidth = Math.min(layout.tableWidth, layout.viewportWidth);
29430
30221
  const visibleTableHeight = Math.min(layout.tableHeight, layout.viewportHeight);
29431
- const columnRailTop = layout.wrapperTop;
29432
- const columnRailLeft = layout.wrapperLeft + visibleTableWidth + 8;
29433
- const rowRailTop = layout.wrapperTop + layout.wrapperHeight + 8;
29434
- const rowRailLeft = layout.wrapperLeft;
30222
+ const columnRailTop = layout.tableTop;
30223
+ const columnRailLeft = layout.tableLeft + visibleTableWidth + ADD_COLUMN_RAIL_GAP;
30224
+ const rowRailTop = layout.tableTop + visibleTableHeight + ADD_ROW_RAIL_GAP;
30225
+ const rowRailLeft = layout.tableLeft;
29435
30226
  const expandPreviewWidth = dragPreview?.kind === "add-column" ? layout.tableWidth + dragPreview.previewCols * layout.avgColumnWidth : layout.tableWidth;
29436
30227
  const expandPreviewHeight = dragPreview?.kind === "add-row" ? layout.tableHeight + dragPreview.previewRows * layout.avgRowHeight : layout.tableHeight;
29437
30228
  const dragStatusText = dragPreview?.kind === "row" ? `${t("tableMenu.dragRow")} ${dragPreview.originIndex + 1} -> ${dragPreview.targetIndex + 1}` : dragPreview?.kind === "column" ? `${t("tableMenu.dragColumn")} ${dragPreview.originIndex + 1} -> ${dragPreview.targetIndex + 1}` : dragPreview?.kind === "add-row" ? `+${dragPreview.previewRows}R` : dragPreview?.kind === "add-column" ? `+${dragPreview.previewCols}C` : null;
@@ -29439,7 +30230,6 @@ function TableControls({ editor, containerRef }) {
29439
30230
  layout.rowHandles.map((rowHandle) => {
29440
30231
  const menuKey = getRowMenuKey(rowHandle.index);
29441
30232
  const visible = controlsVisible || hoverState.rowHandleIndex === rowHandle.index || openMenuKey === menuKey;
29442
- if (!visible) return null;
29443
30233
  return /* @__PURE__ */ jsx82(
29444
30234
  "div",
29445
30235
  {
@@ -29453,6 +30243,7 @@ function TableControls({ editor, containerRef }) {
29453
30243
  Tooltip,
29454
30244
  {
29455
30245
  placement: "right",
30246
+ disabled: openMenuKey === menuKey,
29456
30247
  content: /* @__PURE__ */ jsx82("span", { className: "text-xs font-medium", children: `${t("tableMenu.dragRow")} ${rowHandle.index + 1}` }),
29457
30248
  children: /* @__PURE__ */ jsx82("span", { className: "inline-flex", children: /* @__PURE__ */ jsx82(
29458
30249
  DropdownMenu,
@@ -29462,6 +30253,7 @@ function TableControls({ editor, containerRef }) {
29462
30253
  onOpenChange: (open) => {
29463
30254
  setOpenMenuKey((prev) => open ? menuKey : prev === menuKey ? null : prev);
29464
30255
  },
30256
+ contentClassName: "p-2",
29465
30257
  items: getRowHandleMenuItems(rowHandle),
29466
30258
  trigger: /* @__PURE__ */ jsx82(
29467
30259
  "button",
@@ -29490,8 +30282,13 @@ function TableControls({ editor, containerRef }) {
29490
30282
  className: cn(
29491
30283
  "inline-flex h-6 w-6 items-center justify-center rounded-full",
29492
30284
  "border border-border/70 bg-background/95 text-muted-foreground shadow-sm backdrop-blur",
30285
+ "cursor-grab active:cursor-grabbing",
29493
30286
  "transition-[opacity,transform,colors] duration-150 hover:bg-accent hover:text-foreground"
29494
30287
  ),
30288
+ style: {
30289
+ opacity: visible ? 1 : Number(IDLE_HANDLE_OPACITY),
30290
+ transform: visible ? "scale(1)" : `scale(${IDLE_HANDLE_SCALE})`
30291
+ },
29495
30292
  children: /* @__PURE__ */ jsx82(GripVertical3, { className: "h-3.5 w-3.5" })
29496
30293
  }
29497
30294
  )
@@ -29506,7 +30303,6 @@ function TableControls({ editor, containerRef }) {
29506
30303
  layout.columnHandles.map((columnHandle) => {
29507
30304
  const menuKey = getColumnMenuKey(columnHandle.index);
29508
30305
  const visible = controlsVisible || hoverState.columnHandleIndex === columnHandle.index || openMenuKey === menuKey;
29509
- if (!visible) return null;
29510
30306
  return /* @__PURE__ */ jsx82(
29511
30307
  "div",
29512
30308
  {
@@ -29520,6 +30316,7 @@ function TableControls({ editor, containerRef }) {
29520
30316
  Tooltip,
29521
30317
  {
29522
30318
  placement: "top",
30319
+ disabled: openMenuKey === menuKey,
29523
30320
  content: /* @__PURE__ */ jsx82("span", { className: "text-xs font-medium", children: `${t("tableMenu.dragColumn")} ${columnHandle.index + 1}` }),
29524
30321
  children: /* @__PURE__ */ jsx82("span", { className: "inline-flex", children: /* @__PURE__ */ jsx82(
29525
30322
  DropdownMenu,
@@ -29529,6 +30326,7 @@ function TableControls({ editor, containerRef }) {
29529
30326
  onOpenChange: (open) => {
29530
30327
  setOpenMenuKey((prev) => open ? menuKey : prev === menuKey ? null : prev);
29531
30328
  },
30329
+ contentClassName: "p-2",
29532
30330
  items: getColumnHandleMenuItems(columnHandle),
29533
30331
  trigger: /* @__PURE__ */ jsx82(
29534
30332
  "button",
@@ -29557,8 +30355,13 @@ function TableControls({ editor, containerRef }) {
29557
30355
  className: cn(
29558
30356
  "inline-flex h-6 w-6 items-center justify-center rounded-full",
29559
30357
  "border border-border/70 bg-background/95 text-muted-foreground shadow-sm backdrop-blur",
30358
+ "cursor-grab active:cursor-grabbing",
29560
30359
  "transition-[opacity,transform,colors] duration-150 hover:bg-accent hover:text-foreground"
29561
30360
  ),
30361
+ style: {
30362
+ opacity: visible ? 1 : Number(IDLE_HANDLE_OPACITY),
30363
+ transform: visible ? "scale(1)" : `scale(${IDLE_HANDLE_SCALE})`
30364
+ },
29562
30365
  children: /* @__PURE__ */ jsx82(GripHorizontal, { className: "h-3.5 w-3.5" })
29563
30366
  }
29564
30367
  )
@@ -29570,7 +30373,7 @@ function TableControls({ editor, containerRef }) {
29570
30373
  `column-handle-${columnHandle.index}`
29571
30374
  );
29572
30375
  }),
29573
- (controlsVisible || hoverState.menuVisible || tableMenuOpen) && /* @__PURE__ */ jsx82(
30376
+ /* @__PURE__ */ jsx82(
29574
30377
  "div",
29575
30378
  {
29576
30379
  className: "absolute z-30",
@@ -29583,6 +30386,7 @@ function TableControls({ editor, containerRef }) {
29583
30386
  Tooltip,
29584
30387
  {
29585
30388
  placement: "top",
30389
+ disabled: tableMenuOpen,
29586
30390
  content: /* @__PURE__ */ jsx82("span", { className: "text-xs font-medium", children: t("tableMenu.openControls") }),
29587
30391
  children: /* @__PURE__ */ jsx82("span", { className: "inline-flex", children: /* @__PURE__ */ jsx82(
29588
30392
  DropdownMenu,
@@ -29592,6 +30396,7 @@ function TableControls({ editor, containerRef }) {
29592
30396
  onOpenChange: (open) => {
29593
30397
  setOpenMenuKey((prev) => open ? "table" : prev === "table" ? null : prev);
29594
30398
  },
30399
+ contentClassName: "p-2",
29595
30400
  items: menuItems,
29596
30401
  trigger: /* @__PURE__ */ jsx82(
29597
30402
  "button",
@@ -29604,6 +30409,10 @@ function TableControls({ editor, containerRef }) {
29604
30409
  "border border-border/70 bg-background/95 text-muted-foreground shadow-sm backdrop-blur",
29605
30410
  "transition-[opacity,transform,colors] duration-150 hover:bg-accent hover:text-foreground"
29606
30411
  ),
30412
+ style: {
30413
+ opacity: controlsVisible || hoverState.menuVisible || tableMenuOpen ? 1 : 0.5,
30414
+ transform: controlsVisible || hoverState.menuVisible || tableMenuOpen ? "scale(1)" : "scale(0.82)"
30415
+ },
29607
30416
  children: /* @__PURE__ */ jsx82(MoreHorizontal2, { className: "h-4 w-4" })
29608
30417
  }
29609
30418
  )
@@ -29613,7 +30422,7 @@ function TableControls({ editor, containerRef }) {
29613
30422
  )
29614
30423
  }
29615
30424
  ),
29616
- (controlsVisible || hoverState.addColumnVisible) && /* @__PURE__ */ jsx82(
30425
+ /* @__PURE__ */ jsx82(
29617
30426
  Tooltip,
29618
30427
  {
29619
30428
  placement: "right",
@@ -29640,17 +30449,19 @@ function TableControls({ editor, containerRef }) {
29640
30449
  "transition-[opacity,transform,colors] duration-150 hover:bg-accent hover:text-foreground disabled:opacity-50 disabled:cursor-not-allowed"
29641
30450
  ),
29642
30451
  style: {
29643
- top: columnRailTop,
30452
+ top: controlsVisible || hoverState.addColumnVisible ? columnRailTop : columnRailTop + Math.max(0, visibleTableHeight / 2 - 24),
29644
30453
  left: columnRailLeft,
29645
- width: 18,
29646
- height: visibleTableHeight
30454
+ width: controlsVisible || hoverState.addColumnVisible ? 18 : 12,
30455
+ height: controlsVisible || hoverState.addColumnVisible ? visibleTableHeight : 48,
30456
+ opacity: controlsVisible || hoverState.addColumnVisible ? 1 : 0.45,
30457
+ transform: controlsVisible || hoverState.addColumnVisible ? "scale(1)" : "scale(0.92)"
29647
30458
  },
29648
30459
  children: /* @__PURE__ */ jsx82("span", { className: "text-sm font-medium leading-none", children: "+" })
29649
30460
  }
29650
30461
  )
29651
30462
  }
29652
30463
  ),
29653
- (controlsVisible || hoverState.addRowVisible) && /* @__PURE__ */ jsx82(
30464
+ /* @__PURE__ */ jsx82(
29654
30465
  Tooltip,
29655
30466
  {
29656
30467
  placement: "bottom",
@@ -29678,9 +30489,11 @@ function TableControls({ editor, containerRef }) {
29678
30489
  ),
29679
30490
  style: {
29680
30491
  top: rowRailTop,
29681
- left: rowRailLeft,
29682
- width: visibleTableWidth,
29683
- height: 16
30492
+ left: controlsVisible || hoverState.addRowVisible ? rowRailLeft : rowRailLeft + Math.max(0, visibleTableWidth / 2 - 24),
30493
+ width: controlsVisible || hoverState.addRowVisible ? visibleTableWidth : 48,
30494
+ height: controlsVisible || hoverState.addRowVisible ? 16 : 12,
30495
+ opacity: controlsVisible || hoverState.addRowVisible ? 1 : 0.45,
30496
+ transform: controlsVisible || hoverState.addRowVisible ? "scale(1)" : "scale(0.92)"
29684
30497
  },
29685
30498
  children: /* @__PURE__ */ jsx82("span", { className: "text-sm font-medium leading-none", children: "+" })
29686
30499
  }
@@ -29867,6 +30680,32 @@ function getRelativeCellMetrics(surface, cell) {
29867
30680
  height: cellRect.height
29868
30681
  };
29869
30682
  }
30683
+ function getRelativeSelectedCellsMetrics(surface) {
30684
+ const selectedCells = Array.from(
30685
+ surface.querySelectorAll("td.selectedCell, th.selectedCell")
30686
+ );
30687
+ if (selectedCells.length === 0) {
30688
+ return null;
30689
+ }
30690
+ const surfaceRect = surface.getBoundingClientRect();
30691
+ let left = Number.POSITIVE_INFINITY;
30692
+ let top = Number.POSITIVE_INFINITY;
30693
+ let right = Number.NEGATIVE_INFINITY;
30694
+ let bottom = Number.NEGATIVE_INFINITY;
30695
+ selectedCells.forEach((cell) => {
30696
+ const rect = cell.getBoundingClientRect();
30697
+ left = Math.min(left, rect.left);
30698
+ top = Math.min(top, rect.top);
30699
+ right = Math.max(right, rect.right);
30700
+ bottom = Math.max(bottom, rect.bottom);
30701
+ });
30702
+ return {
30703
+ left: left - surfaceRect.left + surface.scrollLeft,
30704
+ top: top - surfaceRect.top + surface.scrollTop,
30705
+ width: right - left,
30706
+ height: bottom - top
30707
+ };
30708
+ }
29870
30709
  var UEditor = React74.forwardRef(({
29871
30710
  content = "",
29872
30711
  onChange,
@@ -29886,7 +30725,11 @@ var UEditor = React74.forwardRef(({
29886
30725
  maxCharacters,
29887
30726
  minHeight = "200px",
29888
30727
  maxHeight = "auto",
29889
- variant = "default"
30728
+ variant = "default",
30729
+ fontFamilies,
30730
+ fontSizes,
30731
+ lineHeights,
30732
+ letterSpacings
29890
30733
  }, ref) => {
29891
30734
  const t = useSmartTranslations("UEditor");
29892
30735
  const effectivePlaceholder = placeholder ?? t("placeholder");
@@ -29931,7 +30774,7 @@ var UEditor = React74.forwardRef(({
29931
30774
  highlight.style.display = "none";
29932
30775
  return;
29933
30776
  }
29934
- const metrics = getRelativeCellMetrics(surface, cell);
30777
+ const metrics = getRelativeSelectedCellsMetrics(surface) ?? getRelativeCellMetrics(surface, cell);
29935
30778
  highlight.style.display = "block";
29936
30779
  highlight.style.left = `${metrics.left}px`;
29937
30780
  highlight.style.top = `${metrics.top}px`;
@@ -30034,8 +30877,10 @@ var UEditor = React74.forwardRef(({
30034
30877
  "[&_ul[data-type='taskList']_li>label>input]:border-2",
30035
30878
  "[&_ul[data-type='taskList']_li>label>input]:border-primary/50",
30036
30879
  "[&_ul[data-type='taskList']_li>label>input]:accent-primary",
30037
- "[&_pre]:bg-[#1e1e1e]!",
30038
- "[&_pre]:text-[#d4d4d4]!",
30880
+ "[&_pre]:bg-muted/40!",
30881
+ "[&_pre]:text-foreground!",
30882
+ "[&_pre]:border!",
30883
+ "[&_pre]:border-border/60!",
30039
30884
  "[&_pre_code]:bg-transparent!",
30040
30885
  "[&_.tableWrapper]:overflow-x-auto",
30041
30886
  "[&_.tableWrapper]:pb-1.5",
@@ -30055,6 +30900,11 @@ var UEditor = React74.forwardRef(({
30055
30900
  "[&_table]:table-fixed",
30056
30901
  "[&_table]:overflow-hidden",
30057
30902
  "[&_table]:select-text",
30903
+ "[&_table[data-table-align]]:w-max",
30904
+ "[&_table[data-table-align]]:max-w-full",
30905
+ "[&_table[data-table-align='center']]:mx-auto",
30906
+ "[&_table[data-table-align='right']]:ml-auto",
30907
+ "[&_table[data-table-align='right']]:mr-0",
30058
30908
  "[&_td]:relative",
30059
30909
  "[&_td]:align-top",
30060
30910
  "[&_td]:box-border",
@@ -30417,8 +31267,27 @@ var UEditor = React74.forwardRef(({
30417
31267
  className
30418
31268
  ),
30419
31269
  children: [
30420
- editable && showToolbar && /* @__PURE__ */ jsx83(EditorToolbar, { editor, variant, uploadImage, imageInsertMode }),
30421
- editable && showBubbleMenu && /* @__PURE__ */ jsx83(CustomBubbleMenu, { editor }),
31270
+ editable && showToolbar && /* @__PURE__ */ jsx83(
31271
+ EditorToolbar,
31272
+ {
31273
+ editor,
31274
+ variant,
31275
+ uploadImage,
31276
+ imageInsertMode,
31277
+ fontFamilies,
31278
+ fontSizes,
31279
+ lineHeights,
31280
+ letterSpacings
31281
+ }
31282
+ ),
31283
+ editable && showBubbleMenu && /* @__PURE__ */ jsx83(
31284
+ CustomBubbleMenu,
31285
+ {
31286
+ editor,
31287
+ fontSizes,
31288
+ lineHeights
31289
+ }
31290
+ ),
30422
31291
  editable && showFloatingMenu && /* @__PURE__ */ jsx83(CustomFloatingMenu, { editor }),
30423
31292
  /* @__PURE__ */ jsxs71(
30424
31293
  "div",
@@ -30451,7 +31320,7 @@ var UEditor = React74.forwardRef(({
30451
31320
  {
30452
31321
  ref: activeTableCellHighlightRef,
30453
31322
  "aria-hidden": "true",
30454
- className: "pointer-events-none hidden absolute z-20 rounded-[2px] border-2 border-[#2383e2] bg-[#2383e2]/[0.06] transition-[left,top,width,height] duration-100"
31323
+ className: "pointer-events-none hidden absolute z-20 rounded-[2px] border-2 border-primary bg-primary/10 transition-[left,top,width,height] duration-100"
30455
31324
  }
30456
31325
  ),
30457
31326
  editable && /* @__PURE__ */ jsx83(TableControls, { editor, containerRef: editorContentRef }),