@underverse-ui/underverse 1.0.70 → 1.0.72

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.cjs CHANGED
@@ -20281,10 +20281,65 @@ var TableCaption = import_react28.default.forwardRef(({ className, ...props }, r
20281
20281
  TableCaption.displayName = "TableCaption";
20282
20282
 
20283
20283
  // src/components/DataTable/DataTable.tsx
20284
- var import_react37 = __toESM(require("react"), 1);
20284
+ var import_react38 = __toESM(require("react"), 1);
20285
20285
 
20286
20286
  // src/components/DataTable/components/DataTableBody.tsx
20287
+ var import_react29 = __toESM(require("react"), 1);
20287
20288
  var import_jsx_runtime62 = require("react/jsx-runtime");
20289
+ function DataTableOverflowText({
20290
+ text,
20291
+ align
20292
+ }) {
20293
+ const triggerId = import_react29.default.useId();
20294
+ const [isOverflowing, setIsOverflowing] = import_react29.default.useState(false);
20295
+ const alignClass = align === "right" ? "text-right" : align === "center" ? "text-center" : "text-left";
20296
+ const measureOverflow = import_react29.default.useCallback(() => {
20297
+ if (typeof document === "undefined") return;
20298
+ const element = document.querySelector(`[data-underverse-datatable-cell="${triggerId}"]`);
20299
+ if (!element) return;
20300
+ setIsOverflowing(
20301
+ element.scrollWidth - element.clientWidth > 1 || element.scrollHeight - element.clientHeight > 1
20302
+ );
20303
+ }, [triggerId]);
20304
+ import_react29.default.useLayoutEffect(() => {
20305
+ measureOverflow();
20306
+ }, [measureOverflow, text]);
20307
+ import_react29.default.useEffect(() => {
20308
+ if (typeof document === "undefined") return;
20309
+ const element = document.querySelector(`[data-underverse-datatable-cell="${triggerId}"]`);
20310
+ if (!element) return;
20311
+ if (typeof ResizeObserver === "undefined") return;
20312
+ const observer = new ResizeObserver(() => {
20313
+ measureOverflow();
20314
+ });
20315
+ observer.observe(element);
20316
+ return () => observer.disconnect();
20317
+ }, [measureOverflow, triggerId]);
20318
+ const trigger = /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
20319
+ "button",
20320
+ {
20321
+ type: "button",
20322
+ "data-underverse-datatable-cell": triggerId,
20323
+ onMouseEnter: measureOverflow,
20324
+ onFocus: measureOverflow,
20325
+ className: cn(
20326
+ "block w-full truncate bg-transparent p-0 font-inherit text-inherit select-text",
20327
+ "cursor-text",
20328
+ alignClass
20329
+ ),
20330
+ children: text
20331
+ }
20332
+ );
20333
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
20334
+ Tooltip,
20335
+ {
20336
+ disabled: !isOverflowing,
20337
+ placement: "top",
20338
+ content: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: cn("max-w-[min(40rem,calc(100vw-2rem))] whitespace-pre-wrap break-all select-text", alignClass), children: text }),
20339
+ children: trigger
20340
+ }
20341
+ );
20342
+ }
20288
20343
  function DataTableBodyRows({
20289
20344
  leafColumns,
20290
20345
  displayedData,
@@ -20333,6 +20388,7 @@ function DataTableBodyRows({
20333
20388
  return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
20334
20389
  TableCell,
20335
20390
  {
20391
+ "data-underverse-column-key": col.key,
20336
20392
  style: getStickyColumnStyle(col),
20337
20393
  className: cn(
20338
20394
  cellPadding,
@@ -20341,7 +20397,7 @@ function DataTableBodyRows({
20341
20397
  showBorderLeft && "border-l border-border/60",
20342
20398
  getStickyCellClass(col, isStripedRow)
20343
20399
  ),
20344
- children: col.render ? col.render(value, row, idx) : String(value ?? "")
20400
+ children: col.render ? col.render(value, row, idx) : /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(DataTableOverflowText, { text: String(value ?? ""), align: col.align })
20345
20401
  },
20346
20402
  col.key
20347
20403
  );
@@ -20353,7 +20409,7 @@ function DataTableBodyRows({
20353
20409
  }
20354
20410
 
20355
20411
  // src/components/DataTable/components/DataTableHeader.tsx
20356
- var import_react29 = __toESM(require("react"), 1);
20412
+ var import_react30 = __toESM(require("react"), 1);
20357
20413
  var import_lucide_react35 = require("lucide-react");
20358
20414
  var import_jsx_runtime63 = require("react/jsx-runtime");
20359
20415
  function DataTableHeader({
@@ -20369,11 +20425,13 @@ function DataTableHeader({
20369
20425
  setCurPage,
20370
20426
  setFilters,
20371
20427
  setSort,
20428
+ onAutoFitColumn,
20429
+ enableHeaderAutoFit,
20372
20430
  getStickyHeaderClass,
20373
20431
  getStickyHeaderCellStyle,
20374
20432
  t
20375
20433
  }) {
20376
- const renderFilterControl = import_react29.default.useCallback(
20434
+ const renderFilterControl = import_react30.default.useCallback(
20377
20435
  (col) => {
20378
20436
  if (!col.filter) return null;
20379
20437
  const key = col.key;
@@ -20426,7 +20484,7 @@ function DataTableHeader({
20426
20484
  },
20427
20485
  [filters, setCurPage, setFilters, size]
20428
20486
  );
20429
- const renderHeaderContent = import_react29.default.useCallback(
20487
+ const renderHeaderContent = import_react30.default.useCallback(
20430
20488
  (col, isLeaf) => {
20431
20489
  if (!isLeaf) {
20432
20490
  return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
@@ -20566,22 +20624,55 @@ function DataTableHeader({
20566
20624
  const prevCol = prevCell?.column;
20567
20625
  const isAfterFixedLeft = prevCol?.fixed === "left";
20568
20626
  const showBorderLeft = columnDividers && cellIndex > 0 && !isAfterFixedLeft && !col.fixed;
20569
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
20627
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
20570
20628
  TableHead,
20571
20629
  {
20572
20630
  colSpan,
20573
20631
  rowSpan,
20632
+ "data-underverse-column-key": isLeaf ? col.key : void 0,
20574
20633
  style: {
20575
20634
  width: col.width,
20576
20635
  ...getStickyHeaderCellStyle(headerCell)
20577
20636
  },
20578
20637
  className: cn(
20638
+ "relative",
20579
20639
  (col.align === "right" || !col.align && headerAlign === "right") && "text-right",
20580
20640
  (col.align === "center" || !col.align && headerAlign === "center") && "text-center",
20581
20641
  showBorderLeft && "border-l border-border/60",
20582
20642
  getStickyHeaderClass(col)
20583
20643
  ),
20584
- children: renderHeaderContent(col, isLeaf)
20644
+ children: [
20645
+ renderHeaderContent(col, isLeaf),
20646
+ isLeaf && enableHeaderAutoFit && /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
20647
+ Tooltip,
20648
+ {
20649
+ placement: "top",
20650
+ content: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "text-xs font-medium", children: "Double click to auto-fit" }),
20651
+ children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
20652
+ "button",
20653
+ {
20654
+ type: "button",
20655
+ "aria-label": `Auto fit ${String(col.title)}`,
20656
+ onClick: (event) => {
20657
+ event.preventDefault();
20658
+ event.stopPropagation();
20659
+ },
20660
+ onDoubleClick: (event) => {
20661
+ event.preventDefault();
20662
+ event.stopPropagation();
20663
+ onAutoFitColumn?.(col.key);
20664
+ },
20665
+ className: cn(
20666
+ "absolute inset-y-0 right-0 z-10 w-3 -mr-1",
20667
+ "cursor-col-resize select-none bg-transparent",
20668
+ "after:absolute after:inset-y-2 after:right-[3px] after:w-px after:bg-border/0 after:transition-colors",
20669
+ "hover:after:bg-primary/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary"
20670
+ )
20671
+ }
20672
+ )
20673
+ }
20674
+ )
20675
+ ]
20585
20676
  },
20586
20677
  col.key
20587
20678
  );
@@ -20589,7 +20680,7 @@ function DataTableHeader({
20589
20680
  }
20590
20681
 
20591
20682
  // src/components/DataTable/components/Pagination.tsx
20592
- var import_react30 = __toESM(require("react"), 1);
20683
+ var import_react31 = __toESM(require("react"), 1);
20593
20684
  var import_jsx_runtime64 = require("react/jsx-runtime");
20594
20685
  function DataTablePagination({
20595
20686
  totalItems,
@@ -20601,7 +20692,7 @@ function DataTablePagination({
20601
20692
  size
20602
20693
  }) {
20603
20694
  const totalPages = Math.ceil(totalItems / curPageSize);
20604
- const pages = import_react30.default.useMemo(() => {
20695
+ const pages = import_react31.default.useMemo(() => {
20605
20696
  const result = [];
20606
20697
  if (totalPages <= 5) {
20607
20698
  for (let i = 1; i <= totalPages; i++) result.push(i);
@@ -20683,7 +20774,7 @@ function DataTablePagination({
20683
20774
  }
20684
20775
 
20685
20776
  // src/components/DataTable/components/Toolbar.tsx
20686
- var import_react31 = __toESM(require("react"), 1);
20777
+ var import_react32 = __toESM(require("react"), 1);
20687
20778
 
20688
20779
  // src/components/DataTable/utils/headers.ts
20689
20780
  function isLeafColumn(col) {
@@ -20804,7 +20895,7 @@ function DataTableToolbar({
20804
20895
  const controlButtonClass = size === "sm" ? "h-7 px-2 text-xs" : size === "lg" ? "h-9 px-3 text-sm" : "h-8 px-2";
20805
20896
  const iconClass = size === "sm" ? "w-3.5 h-3.5 mr-1" : "w-4 h-4 mr-1";
20806
20897
  const captionClass = size === "sm" ? "text-xs" : size === "lg" ? "text-sm" : "text-sm";
20807
- const leafCols = import_react31.default.useMemo(() => getLeafColumns(columns), [columns]);
20898
+ const leafCols = import_react32.default.useMemo(() => getLeafColumns(columns), [columns]);
20808
20899
  return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "flex items-center justify-between gap-4 mb-1", children: [
20809
20900
  /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { className: captionClass + " text-muted-foreground", children: caption }),
20810
20901
  /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "flex items-center gap-2", children: [
@@ -20872,10 +20963,10 @@ function DataTableToolbar({
20872
20963
  }
20873
20964
 
20874
20965
  // src/components/DataTable/hooks/useDebounced.ts
20875
- var import_react32 = __toESM(require("react"), 1);
20966
+ var import_react33 = __toESM(require("react"), 1);
20876
20967
  function useDebounced(value, delay = 300) {
20877
- const [debounced, setDebounced] = import_react32.default.useState(value);
20878
- import_react32.default.useEffect(() => {
20968
+ const [debounced, setDebounced] = import_react33.default.useState(value);
20969
+ import_react33.default.useEffect(() => {
20879
20970
  const id = setTimeout(() => setDebounced(value), delay);
20880
20971
  return () => clearTimeout(id);
20881
20972
  }, [value, delay]);
@@ -20883,7 +20974,7 @@ function useDebounced(value, delay = 300) {
20883
20974
  }
20884
20975
 
20885
20976
  // src/components/DataTable/hooks/useDataTableModel.ts
20886
- var import_react33 = __toESM(require("react"), 1);
20977
+ var import_react34 = __toESM(require("react"), 1);
20887
20978
 
20888
20979
  // src/components/DataTable/utils/columns.ts
20889
20980
  function getColumnWidth(col, fallback = 150) {
@@ -20911,22 +21002,22 @@ function useDataTableModel({
20911
21002
  isServerMode,
20912
21003
  total
20913
21004
  }) {
20914
- const visibleColsSet = import_react33.default.useMemo(() => new Set(visibleCols), [visibleCols]);
20915
- const allLeafColumns = import_react33.default.useMemo(() => getLeafColumns(columns), [columns]);
20916
- const columnMap = import_react33.default.useMemo(() => {
21005
+ const visibleColsSet = import_react34.default.useMemo(() => new Set(visibleCols), [visibleCols]);
21006
+ const allLeafColumns = import_react34.default.useMemo(() => getLeafColumns(columns), [columns]);
21007
+ const columnMap = import_react34.default.useMemo(() => {
20917
21008
  return new Map(allLeafColumns.map((column) => [column.key, column]));
20918
21009
  }, [allLeafColumns]);
20919
- const visibleColumns = import_react33.default.useMemo(() => {
21010
+ const visibleColumns = import_react34.default.useMemo(() => {
20920
21011
  return filterVisibleColumns(columns, visibleColsSet);
20921
21012
  }, [columns, visibleColsSet]);
20922
- const leafColumns = import_react33.default.useMemo(() => {
21013
+ const leafColumns = import_react34.default.useMemo(() => {
20923
21014
  return getLeafColumnsWithFixedInheritance(visibleColumns);
20924
21015
  }, [visibleColumns]);
20925
- const headerRows = import_react33.default.useMemo(() => buildHeaderRows(visibleColumns), [visibleColumns]);
20926
- const totalColumnsWidth = import_react33.default.useMemo(() => {
21016
+ const headerRows = import_react34.default.useMemo(() => buildHeaderRows(visibleColumns), [visibleColumns]);
21017
+ const totalColumnsWidth = import_react34.default.useMemo(() => {
20927
21018
  return leafColumns.reduce((sum, column) => sum + getColumnWidth(column), 0);
20928
21019
  }, [leafColumns]);
20929
- const processedData = import_react33.default.useMemo(() => {
21020
+ const processedData = import_react34.default.useMemo(() => {
20930
21021
  if (isServerMode) return data;
20931
21022
  let result = [...data];
20932
21023
  if (Object.keys(filters).length > 0) {
@@ -20958,7 +21049,7 @@ function useDataTableModel({
20958
21049
  return result;
20959
21050
  }, [columnMap, data, filters, isServerMode, sort]);
20960
21051
  const totalItems = isServerMode ? total : processedData.length;
20961
- const displayedData = import_react33.default.useMemo(() => {
21052
+ const displayedData = import_react34.default.useMemo(() => {
20962
21053
  if (isServerMode) return data;
20963
21054
  const start = (curPage - 1) * curPageSize;
20964
21055
  return processedData.slice(start, start + curPageSize);
@@ -20974,10 +21065,10 @@ function useDataTableModel({
20974
21065
  }
20975
21066
 
20976
21067
  // src/components/DataTable/hooks/useDataTableState.ts
20977
- var import_react35 = __toESM(require("react"), 1);
21068
+ var import_react36 = __toESM(require("react"), 1);
20978
21069
 
20979
21070
  // src/components/DataTable/hooks/usePageSizeStorage.ts
20980
- var import_react34 = __toESM(require("react"), 1);
21071
+ var import_react35 = __toESM(require("react"), 1);
20981
21072
  function readStoredPageSize(storageKey) {
20982
21073
  if (typeof window === "undefined" || !storageKey) return null;
20983
21074
  try {
@@ -20990,8 +21081,8 @@ function readStoredPageSize(storageKey) {
20990
21081
  }
20991
21082
  }
20992
21083
  function usePageSizeStorage({ pageSize, storageKey }) {
20993
- const storedPageSize = import_react34.default.useMemo(() => readStoredPageSize(storageKey), [storageKey]);
20994
- const [overrideState, setOverrideState] = import_react34.default.useState({
21084
+ const storedPageSize = import_react35.default.useMemo(() => readStoredPageSize(storageKey), [storageKey]);
21085
+ const [overrideState, setOverrideState] = import_react35.default.useState({
20995
21086
  storageKey,
20996
21087
  pageSize: null
20997
21088
  });
@@ -20999,7 +21090,7 @@ function usePageSizeStorage({ pageSize, storageKey }) {
20999
21090
  const persistedPageSize = storageKey ? overridePageSize ?? storedPageSize : null;
21000
21091
  const loadedFromStorage = persistedPageSize != null;
21001
21092
  const curPageSize = storageKey ? persistedPageSize ?? pageSize : overridePageSize ?? pageSize;
21002
- const setCurPageSize = import_react34.default.useCallback(
21093
+ const setCurPageSize = import_react35.default.useCallback(
21003
21094
  (nextPageSize) => {
21004
21095
  const baseValue = storageKey ? persistedPageSize ?? pageSize : overridePageSize ?? pageSize;
21005
21096
  const resolved = typeof nextPageSize === "function" ? nextPageSize(baseValue) : nextPageSize;
@@ -21028,17 +21119,17 @@ function useDataTableState({
21028
21119
  size,
21029
21120
  storageKey
21030
21121
  }) {
21031
- const allLeafColumns = import_react35.default.useMemo(() => getLeafColumns(columns), [columns]);
21032
- const defaultVisibleLeafKeys = import_react35.default.useMemo(() => allLeafColumns.filter((column) => column.visible !== false).map((column) => column.key), [allLeafColumns]);
21033
- const knownLeafKeysRef = import_react35.default.useRef(new Set(defaultVisibleLeafKeys));
21034
- const [headerAlign, setHeaderAlign] = import_react35.default.useState("left");
21035
- const [visibleCols, setVisibleCols] = import_react35.default.useState(defaultVisibleLeafKeys);
21036
- const [filters, setFilters] = import_react35.default.useState({});
21037
- const [sort, setSort] = import_react35.default.useState(null);
21038
- const [density, setDensity] = import_react35.default.useState(() => SIZE_TO_DENSITY[size]);
21039
- const [curPage, setCurPage] = import_react35.default.useState(page);
21122
+ const allLeafColumns = import_react36.default.useMemo(() => getLeafColumns(columns), [columns]);
21123
+ const defaultVisibleLeafKeys = import_react36.default.useMemo(() => allLeafColumns.filter((column) => column.visible !== false).map((column) => column.key), [allLeafColumns]);
21124
+ const knownLeafKeysRef = import_react36.default.useRef(new Set(defaultVisibleLeafKeys));
21125
+ const [headerAlign, setHeaderAlign] = import_react36.default.useState("left");
21126
+ const [visibleCols, setVisibleCols] = import_react36.default.useState(defaultVisibleLeafKeys);
21127
+ const [filters, setFilters] = import_react36.default.useState({});
21128
+ const [sort, setSort] = import_react36.default.useState(null);
21129
+ const [density, setDensity] = import_react36.default.useState(() => SIZE_TO_DENSITY[size]);
21130
+ const [curPage, setCurPage] = import_react36.default.useState(page);
21040
21131
  const { curPageSize, setCurPageSize } = usePageSizeStorage({ pageSize, storageKey });
21041
- import_react35.default.useEffect(() => {
21132
+ import_react36.default.useEffect(() => {
21042
21133
  const knownLeafKeys = knownLeafKeysRef.current;
21043
21134
  setVisibleCols((prev) => {
21044
21135
  const prevSet = new Set(prev);
@@ -21046,10 +21137,10 @@ function useDataTableState({
21046
21137
  });
21047
21138
  knownLeafKeysRef.current = new Set(allLeafColumns.map((column) => column.key));
21048
21139
  }, [allLeafColumns]);
21049
- import_react35.default.useEffect(() => {
21140
+ import_react36.default.useEffect(() => {
21050
21141
  setCurPage(page);
21051
21142
  }, [page]);
21052
- import_react35.default.useEffect(() => {
21143
+ import_react36.default.useEffect(() => {
21053
21144
  setDensity(SIZE_TO_DENSITY[size]);
21054
21145
  }, [size]);
21055
21146
  return {
@@ -21071,7 +21162,7 @@ function useDataTableState({
21071
21162
  }
21072
21163
 
21073
21164
  // src/components/DataTable/hooks/useStickyColumns.ts
21074
- var import_react36 = __toESM(require("react"), 1);
21165
+ var import_react37 = __toESM(require("react"), 1);
21075
21166
 
21076
21167
  // src/components/DataTable/utils/sticky.ts
21077
21168
  function buildStickyLayout(visibleColumns) {
@@ -21118,8 +21209,8 @@ function resolveGroupStickyPosition(column, positions) {
21118
21209
 
21119
21210
  // src/components/DataTable/hooks/useStickyColumns.ts
21120
21211
  function useStickyColumns(visibleColumns) {
21121
- const { positions, leftBoundaryKey, rightBoundaryKey } = import_react36.default.useMemo(() => buildStickyLayout(visibleColumns), [visibleColumns]);
21122
- const getStickyColumnStyle = import_react36.default.useCallback(
21212
+ const { positions, leftBoundaryKey, rightBoundaryKey } = import_react37.default.useMemo(() => buildStickyLayout(visibleColumns), [visibleColumns]);
21213
+ const getStickyColumnStyle = import_react37.default.useCallback(
21123
21214
  (col) => {
21124
21215
  const pos = resolveStickyPosition(col, positions);
21125
21216
  if (!pos) return {};
@@ -21130,7 +21221,7 @@ function useStickyColumns(visibleColumns) {
21130
21221
  },
21131
21222
  [positions]
21132
21223
  );
21133
- const getBoundaryShadowClass = import_react36.default.useCallback(
21224
+ const getBoundaryShadowClass = import_react37.default.useCallback(
21134
21225
  (col) => {
21135
21226
  if (col.fixed === "left" && col.key === leftBoundaryKey) {
21136
21227
  return "border-r border-border/80 shadow-[10px_0_16px_-10px_rgba(0,0,0,0.55)]";
@@ -21142,14 +21233,14 @@ function useStickyColumns(visibleColumns) {
21142
21233
  },
21143
21234
  [leftBoundaryKey, rightBoundaryKey]
21144
21235
  );
21145
- const getStickyHeaderClass = import_react36.default.useCallback(
21236
+ const getStickyHeaderClass = import_react37.default.useCallback(
21146
21237
  (col) => {
21147
21238
  if (!col.fixed) return "";
21148
21239
  return cn("sticky", col.fixed === "left" && "left-0", col.fixed === "right" && "right-0", getBoundaryShadowClass(col), "z-50 !bg-muted");
21149
21240
  },
21150
21241
  [getBoundaryShadowClass]
21151
21242
  );
21152
- const getStickyCellClass = import_react36.default.useCallback(
21243
+ const getStickyCellClass = import_react37.default.useCallback(
21153
21244
  (col, isStripedRow) => {
21154
21245
  if (!col.fixed) return "";
21155
21246
  return cn(
@@ -21162,7 +21253,7 @@ function useStickyColumns(visibleColumns) {
21162
21253
  },
21163
21254
  [getBoundaryShadowClass]
21164
21255
  );
21165
- const getStickyHeaderCellStyle = import_react36.default.useCallback(
21256
+ const getStickyHeaderCellStyle = import_react37.default.useCallback(
21166
21257
  (headerCell) => {
21167
21258
  const col = headerCell.column;
21168
21259
  if (headerCell.isLeaf) {
@@ -21261,6 +21352,66 @@ function validateColumns(columns) {
21261
21352
 
21262
21353
  // src/components/DataTable/DataTable.tsx
21263
21354
  var import_jsx_runtime66 = require("react/jsx-runtime");
21355
+ function applyColumnWidthOverrides(columns, widthOverrides) {
21356
+ return columns.map((column) => {
21357
+ if (column.children?.length) {
21358
+ return {
21359
+ ...column,
21360
+ children: applyColumnWidthOverrides(column.children, widthOverrides)
21361
+ };
21362
+ }
21363
+ const nextWidth = widthOverrides[column.key];
21364
+ if (nextWidth == null) {
21365
+ return column;
21366
+ }
21367
+ return {
21368
+ ...column,
21369
+ width: nextWidth
21370
+ };
21371
+ });
21372
+ }
21373
+ function measureNaturalContentWidth(node) {
21374
+ if (typeof document === "undefined") return 0;
21375
+ const measurementRoot = document.createElement("div");
21376
+ measurementRoot.style.position = "absolute";
21377
+ measurementRoot.style.left = "-99999px";
21378
+ measurementRoot.style.top = "0";
21379
+ measurementRoot.style.visibility = "hidden";
21380
+ measurementRoot.style.pointerEvents = "none";
21381
+ measurementRoot.style.whiteSpace = "nowrap";
21382
+ measurementRoot.style.width = "max-content";
21383
+ measurementRoot.style.maxWidth = "none";
21384
+ measurementRoot.style.minWidth = "0";
21385
+ measurementRoot.style.overflow = "visible";
21386
+ const clone = (node.firstElementChild instanceof HTMLElement ? node.firstElementChild : node).cloneNode(true);
21387
+ if (!(clone instanceof HTMLElement)) {
21388
+ return 0;
21389
+ }
21390
+ const sourceStyle = window.getComputedStyle(node);
21391
+ const cloneStyle = window.getComputedStyle(clone);
21392
+ clone.style.width = "max-content";
21393
+ clone.style.maxWidth = "none";
21394
+ clone.style.minWidth = "0";
21395
+ clone.style.overflow = "visible";
21396
+ clone.style.textOverflow = "clip";
21397
+ clone.style.whiteSpace = cloneStyle.whiteSpace === "normal" ? "pre-wrap" : "nowrap";
21398
+ measurementRoot.appendChild(clone);
21399
+ document.body.appendChild(measurementRoot);
21400
+ const horizontalPadding = parseFloat(sourceStyle.paddingLeft || "0") + parseFloat(sourceStyle.paddingRight || "0");
21401
+ const horizontalBorder = parseFloat(sourceStyle.borderLeftWidth || "0") + parseFloat(sourceStyle.borderRightWidth || "0");
21402
+ const cloneRectWidth = clone.getBoundingClientRect().width;
21403
+ const cloneScrollWidth = clone.scrollWidth;
21404
+ const sourceScrollWidth = node.scrollWidth;
21405
+ const measuredContentWidth = Math.max(cloneRectWidth, cloneScrollWidth) || sourceScrollWidth;
21406
+ const measured = Math.ceil(measuredContentWidth + horizontalPadding + horizontalBorder);
21407
+ document.body.removeChild(measurementRoot);
21408
+ return measured;
21409
+ }
21410
+ function isNodeOverflowing(node) {
21411
+ const contentNode = node.firstElementChild instanceof HTMLElement ? node.firstElementChild : node;
21412
+ return node.scrollWidth > node.clientWidth + 1 || contentNode.scrollWidth > contentNode.clientWidth + 1;
21413
+ }
21414
+ var AUTO_FIT_BUFFER_PX = 8;
21264
21415
  function DataTable({
21265
21416
  columns,
21266
21417
  data,
@@ -21284,9 +21435,15 @@ function DataTable({
21284
21435
  stickyHeader = true,
21285
21436
  maxHeight = 500,
21286
21437
  useOverlayScrollbar = false,
21438
+ enableHeaderAutoFit = true,
21287
21439
  labels
21288
21440
  }) {
21289
21441
  const t = useSmartTranslations("Common");
21442
+ const [columnWidthOverrides, setColumnWidthOverrides] = import_react38.default.useState({});
21443
+ const columnsWithWidthOverrides = import_react38.default.useMemo(
21444
+ () => applyColumnWidthOverrides(columns, columnWidthOverrides),
21445
+ [columnWidthOverrides, columns]
21446
+ );
21290
21447
  const {
21291
21448
  headerAlign,
21292
21449
  setHeaderAlign,
@@ -21303,22 +21460,22 @@ function DataTable({
21303
21460
  curPageSize,
21304
21461
  setCurPageSize
21305
21462
  } = useDataTableState({
21306
- columns,
21463
+ columns: columnsWithWidthOverrides,
21307
21464
  page,
21308
21465
  pageSize,
21309
21466
  size,
21310
21467
  storageKey
21311
21468
  });
21312
- import_react37.default.useEffect(() => {
21469
+ import_react38.default.useEffect(() => {
21313
21470
  if (process.env.NODE_ENV === "development") {
21314
- const warnings = validateColumns(columns);
21471
+ const warnings = validateColumns(columnsWithWidthOverrides);
21315
21472
  warnings.forEach((w) => console.warn(`[DataTable] ${w}`));
21316
21473
  }
21317
- }, [columns]);
21474
+ }, [columnsWithWidthOverrides]);
21318
21475
  const debouncedFilters = useDebounced(filters, 350);
21319
21476
  const isServerMode = Boolean(onQueryChange);
21320
- const hasEmittedQuery = import_react37.default.useRef(false);
21321
- import_react37.default.useEffect(() => {
21477
+ const hasEmittedQuery = import_react38.default.useRef(false);
21478
+ import_react38.default.useEffect(() => {
21322
21479
  if (!onQueryChange) return;
21323
21480
  if (!hasEmittedQuery.current) {
21324
21481
  hasEmittedQuery.current = true;
@@ -21326,7 +21483,7 @@ function DataTable({
21326
21483
  }
21327
21484
  onQueryChange({ filters: debouncedFilters, sort, page: curPage, pageSize: curPageSize });
21328
21485
  }, [debouncedFilters, sort, curPage, curPageSize, onQueryChange]);
21329
- import_react37.default.useEffect(() => {
21486
+ import_react38.default.useEffect(() => {
21330
21487
  if (process.env.NODE_ENV !== "development" || rowKey) return;
21331
21488
  const hasQueryFeatures = columns.some((column) => column.sortable || column.filter) || Boolean(pageSizeOptions?.length) || isServerMode;
21332
21489
  if (!hasQueryFeatures) return;
@@ -21338,7 +21495,7 @@ function DataTable({
21338
21495
  const headerMinHeightClass = size === "sm" ? "min-h-9" : size === "lg" ? "min-h-11" : "min-h-10";
21339
21496
  const sortIconClass = size === "sm" ? "w-3.5 h-3.5" : size === "lg" ? "w-4 h-4" : "w-3.5 h-3.5";
21340
21497
  const { visibleColumns, leafColumns, headerRows, totalColumnsWidth, totalItems, displayedData } = useDataTableModel({
21341
- columns,
21498
+ columns: columnsWithWidthOverrides,
21342
21499
  data,
21343
21500
  visibleCols,
21344
21501
  filters,
@@ -21354,15 +21511,45 @@ function DataTable({
21354
21511
  if (typeof rowKey === "function") return String(rowKey(row));
21355
21512
  return String(row[rowKey]);
21356
21513
  };
21357
- const viewportRef = import_react37.default.useRef(null);
21514
+ const viewportRef = import_react38.default.useRef(null);
21515
+ const tableRef = import_react38.default.useRef(null);
21358
21516
  useOverlayScrollbarTarget(viewportRef, { enabled: useOverlayScrollbar });
21517
+ const autoFitColumn = import_react38.default.useCallback((columnKey) => {
21518
+ const tableElement = tableRef.current;
21519
+ if (!tableElement) return;
21520
+ const nodes = Array.from(
21521
+ tableElement.querySelectorAll(`[data-underverse-column-key="${columnKey}"]`)
21522
+ );
21523
+ if (nodes.length === 0) return;
21524
+ const hasOverflow = nodes.some((node) => isNodeOverflowing(node));
21525
+ if (!hasOverflow) return;
21526
+ const measuredWidth = nodes.reduce((maxWidth, node) => {
21527
+ const nextWidth2 = measureNaturalContentWidth(node);
21528
+ return Math.max(maxWidth, nextWidth2);
21529
+ }, 0);
21530
+ const currentRenderedWidth = nodes.reduce((maxWidth, node) => {
21531
+ const nextWidth2 = Math.max(
21532
+ Math.ceil(node.getBoundingClientRect().width || 0),
21533
+ node.offsetWidth || 0,
21534
+ node.clientWidth || 0
21535
+ );
21536
+ return Math.max(maxWidth, nextWidth2);
21537
+ }, 0);
21538
+ if (measuredWidth <= 0) return;
21539
+ if (currentRenderedWidth > 0 && measuredWidth <= currentRenderedWidth + AUTO_FIT_BUFFER_PX) return;
21540
+ const nextWidth = Math.max(80, measuredWidth + AUTO_FIT_BUFFER_PX);
21541
+ setColumnWidthOverrides((prev) => {
21542
+ if (prev[columnKey] === nextWidth) return prev;
21543
+ return { ...prev, [columnKey]: nextWidth };
21544
+ });
21545
+ }, []);
21359
21546
  return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: cn("space-y-2", className), children: [
21360
21547
  /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
21361
21548
  DataTableToolbar,
21362
21549
  {
21363
21550
  caption,
21364
21551
  toolbar,
21365
- columns,
21552
+ columns: columnsWithWidthOverrides,
21366
21553
  visibleCols,
21367
21554
  setVisibleCols,
21368
21555
  enableDensityToggle,
@@ -21392,6 +21579,7 @@ function DataTable({
21392
21579
  children: /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
21393
21580
  Table,
21394
21581
  {
21582
+ ref: tableRef,
21395
21583
  disableContainer: true,
21396
21584
  className: cn(
21397
21585
  "table-fixed",
@@ -21414,6 +21602,8 @@ function DataTable({
21414
21602
  setCurPage,
21415
21603
  setFilters,
21416
21604
  setSort,
21605
+ onAutoFitColumn: autoFitColumn,
21606
+ enableHeaderAutoFit,
21417
21607
  getStickyHeaderClass,
21418
21608
  getStickyHeaderCellStyle,
21419
21609
  t
@@ -21460,10 +21650,10 @@ function DataTable({
21460
21650
  var DataTable_default = DataTable;
21461
21651
 
21462
21652
  // src/components/Form.tsx
21463
- var React62 = __toESM(require("react"), 1);
21653
+ var React63 = __toESM(require("react"), 1);
21464
21654
  var import_react_hook_form = require("react-hook-form");
21465
21655
  var import_jsx_runtime67 = require("react/jsx-runtime");
21466
- var FormConfigContext = React62.createContext({ size: "md" });
21656
+ var FormConfigContext = React63.createContext({ size: "md" });
21467
21657
  var FormWrapper = ({
21468
21658
  children,
21469
21659
  onSubmit,
@@ -21476,7 +21666,7 @@ var FormWrapper = ({
21476
21666
  const methods = (0, import_react_hook_form.useForm)({
21477
21667
  defaultValues: initialValues
21478
21668
  });
21479
- React62.useEffect(() => {
21669
+ React63.useEffect(() => {
21480
21670
  if (initialValues) {
21481
21671
  methods.reset(initialValues);
21482
21672
  }
@@ -21485,15 +21675,15 @@ var FormWrapper = ({
21485
21675
  return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(import_react_hook_form.FormProvider, { ...methods, children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(FormConfigContext.Provider, { value: { size }, children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("form", { onSubmit: methods.handleSubmit(onSubmit), className, ...formProps, children }) }) });
21486
21676
  };
21487
21677
  var Form = FormWrapper;
21488
- var FormFieldContext = React62.createContext({});
21678
+ var FormFieldContext = React63.createContext({});
21489
21679
  var FormField = ({
21490
21680
  ...props
21491
21681
  }) => {
21492
21682
  return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(FormFieldContext.Provider, { value: { name: props.name }, children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(import_react_hook_form.Controller, { ...props }) });
21493
21683
  };
21494
21684
  var useFormField = () => {
21495
- const fieldContext = React62.useContext(FormFieldContext);
21496
- const itemContext = React62.useContext(FormItemContext);
21685
+ const fieldContext = React63.useContext(FormFieldContext);
21686
+ const itemContext = React63.useContext(FormItemContext);
21497
21687
  const { getFieldState, formState } = (0, import_react_hook_form.useFormContext)();
21498
21688
  if (!fieldContext) {
21499
21689
  throw new Error("useFormField must be used within FormField");
@@ -21509,16 +21699,16 @@ var useFormField = () => {
21509
21699
  ...fieldState
21510
21700
  };
21511
21701
  };
21512
- var FormItemContext = React62.createContext({});
21513
- var FormItem = React62.forwardRef(({ className, ...props }, ref) => {
21514
- const id = React62.useId();
21702
+ var FormItemContext = React63.createContext({});
21703
+ var FormItem = React63.forwardRef(({ className, ...props }, ref) => {
21704
+ const id = React63.useId();
21515
21705
  return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(FormItemContext.Provider, { value: { id }, children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { ref, className: cn("space-y-2", className), ...props }) });
21516
21706
  });
21517
21707
  FormItem.displayName = "FormItem";
21518
- var FormLabel = React62.forwardRef(
21708
+ var FormLabel = React63.forwardRef(
21519
21709
  ({ className, children, required, ...props }, ref) => {
21520
21710
  const { error, formItemId } = useFormField();
21521
- const config = React62.useContext(FormConfigContext);
21711
+ const config = React63.useContext(FormConfigContext);
21522
21712
  const sizeClass = config.size === "sm" ? "text-xs" : config.size === "lg" ? "text-base" : "text-sm";
21523
21713
  return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(Label, { ref, className: cn(sizeClass, error && "text-destructive", className), htmlFor: formItemId, ...props, children: [
21524
21714
  children,
@@ -21527,7 +21717,7 @@ var FormLabel = React62.forwardRef(
21527
21717
  }
21528
21718
  );
21529
21719
  FormLabel.displayName = "FormLabel";
21530
- var FormControl = React62.forwardRef(({ ...props }, ref) => {
21720
+ var FormControl = React63.forwardRef(({ ...props }, ref) => {
21531
21721
  const { error, formItemId, formDescriptionId, formMessageId } = useFormField();
21532
21722
  return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
21533
21723
  "div",
@@ -21541,12 +21731,12 @@ var FormControl = React62.forwardRef(({ ...props }, ref) => {
21541
21731
  );
21542
21732
  });
21543
21733
  FormControl.displayName = "FormControl";
21544
- var FormDescription = React62.forwardRef(({ className, ...props }, ref) => {
21734
+ var FormDescription = React63.forwardRef(({ className, ...props }, ref) => {
21545
21735
  const { formDescriptionId } = useFormField();
21546
21736
  return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("p", { ref, id: formDescriptionId, className: cn("text-sm text-muted-foreground", className), ...props });
21547
21737
  });
21548
21738
  FormDescription.displayName = "FormDescription";
21549
- var FormMessage = React62.forwardRef(({ className, children, ...props }, ref) => {
21739
+ var FormMessage = React63.forwardRef(({ className, children, ...props }, ref) => {
21550
21740
  const { error, formMessageId } = useFormField();
21551
21741
  const body = error ? String(error?.message) : children;
21552
21742
  if (!body) {
@@ -21555,7 +21745,7 @@ var FormMessage = React62.forwardRef(({ className, children, ...props }, ref) =>
21555
21745
  return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("p", { ref, id: formMessageId, className: cn("text-sm font-medium text-destructive", className), ...props, children: body });
21556
21746
  });
21557
21747
  FormMessage.displayName = "FormMessage";
21558
- var FormInput = React62.forwardRef(({ name, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
21748
+ var FormInput = React63.forwardRef(({ name, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
21559
21749
  FormField,
21560
21750
  {
21561
21751
  name,
@@ -21566,7 +21756,7 @@ var FormInput = React62.forwardRef(({ name, ...props }, ref) => /* @__PURE__ */
21566
21756
  }
21567
21757
  ) }));
21568
21758
  FormInput.displayName = "FormInput";
21569
- var FormCheckbox = React62.forwardRef(({ name, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
21759
+ var FormCheckbox = React63.forwardRef(({ name, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
21570
21760
  FormField,
21571
21761
  {
21572
21762
  name,
@@ -21590,9 +21780,9 @@ var FormCheckbox = React62.forwardRef(({ name, ...props }, ref) => /* @__PURE__
21590
21780
  }
21591
21781
  ) }));
21592
21782
  FormCheckbox.displayName = "FormCheckbox";
21593
- var FormActions = React62.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { ref, className: cn("flex gap-2 justify-end", className), ...props }));
21783
+ var FormActions = React63.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { ref, className: cn("flex gap-2 justify-end", className), ...props }));
21594
21784
  FormActions.displayName = "FormActions";
21595
- var FormSubmitButton = React62.forwardRef(
21785
+ var FormSubmitButton = React63.forwardRef(
21596
21786
  ({ children, loading: loading2, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(FormConfigContext.Consumer, { children: ({ size }) => /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(Button_default, { ref, type: "submit", size: props.size ?? size, disabled: loading2, ...props, children }) })
21597
21787
  );
21598
21788
  FormSubmitButton.displayName = "FormSubmitButton";
@@ -21674,7 +21864,7 @@ function AccessDenied({
21674
21864
 
21675
21865
  // src/components/ThemeToggleHeadless.tsx
21676
21866
  var import_lucide_react38 = require("lucide-react");
21677
- var import_react38 = require("react");
21867
+ var import_react39 = require("react");
21678
21868
  var import_react_dom6 = require("react-dom");
21679
21869
  var import_jsx_runtime70 = require("react/jsx-runtime");
21680
21870
  function ThemeToggleHeadless({
@@ -21683,10 +21873,10 @@ function ThemeToggleHeadless({
21683
21873
  labels,
21684
21874
  className
21685
21875
  }) {
21686
- const [isOpen, setIsOpen] = (0, import_react38.useState)(false);
21876
+ const [isOpen, setIsOpen] = (0, import_react39.useState)(false);
21687
21877
  const isHydrated = useHydrated();
21688
- const triggerRef = (0, import_react38.useRef)(null);
21689
- const [dropdownPosition, setDropdownPosition] = (0, import_react38.useState)(null);
21878
+ const triggerRef = (0, import_react39.useRef)(null);
21879
+ const [dropdownPosition, setDropdownPosition] = (0, import_react39.useState)(null);
21690
21880
  const themes = [
21691
21881
  { value: "light", label: labels?.light ?? "Light", icon: import_lucide_react38.Sun },
21692
21882
  { value: "dark", label: labels?.dark ?? "Dark", icon: import_lucide_react38.Moon },
@@ -21775,7 +21965,7 @@ function ThemeToggleHeadless({
21775
21965
  }
21776
21966
 
21777
21967
  // src/components/LanguageSwitcherHeadless.tsx
21778
- var import_react39 = require("react");
21968
+ var import_react40 = require("react");
21779
21969
  var import_react_dom7 = require("react-dom");
21780
21970
  var import_lucide_react39 = require("lucide-react");
21781
21971
  var import_jsx_runtime71 = require("react/jsx-runtime");
@@ -21786,9 +21976,9 @@ function LanguageSwitcherHeadless({
21786
21976
  labels,
21787
21977
  className
21788
21978
  }) {
21789
- const [isOpen, setIsOpen] = (0, import_react39.useState)(false);
21790
- const [dropdownPosition, setDropdownPosition] = (0, import_react39.useState)(null);
21791
- const triggerButtonRef = (0, import_react39.useRef)(null);
21979
+ const [isOpen, setIsOpen] = (0, import_react40.useState)(false);
21980
+ const [dropdownPosition, setDropdownPosition] = (0, import_react40.useState)(null);
21981
+ const triggerButtonRef = (0, import_react40.useRef)(null);
21792
21982
  const currentLanguage = locales.find((l) => l.code === currentLocale) || locales[0];
21793
21983
  const calculatePosition = () => {
21794
21984
  const rect = triggerButtonRef.current?.getBoundingClientRect();
@@ -21882,7 +22072,7 @@ var VARIANT_STYLES_ALERT = {
21882
22072
  };
21883
22073
 
21884
22074
  // ../../lib/i18n/translation-adapter.tsx
21885
- var React64 = __toESM(require("react"), 1);
22075
+ var React65 = __toESM(require("react"), 1);
21886
22076
  var import_jsx_runtime72 = require("react/jsx-runtime");
21887
22077
  function isUnresolvedTranslation2(value, namespace, key) {
21888
22078
  return value === key || value === `${namespace}.${key}`;
@@ -21907,7 +22097,7 @@ function useTranslations(namespace) {
21907
22097
  const nextIntlBridge = useNextIntlBridge();
21908
22098
  const internalLocale = useUnderverseLocale();
21909
22099
  const internalT = useUnderverseTranslations(namespace);
21910
- return React64.useCallback((key, params) => {
22100
+ return React65.useCallback((key, params) => {
21911
22101
  if (nextIntlBridge) {
21912
22102
  const nextIntlResult = nextIntlBridge.translate(namespace, key, params);
21913
22103
  if (nextIntlResult.translated && !isUnresolvedTranslation2(nextIntlResult.translated, namespace, key)) {
@@ -21932,8 +22122,8 @@ function useLocale2() {
21932
22122
  }
21933
22123
 
21934
22124
  // src/components/UEditor/UEditor.tsx
21935
- var import_react52 = __toESM(require("react"), 1);
21936
- var import_react53 = require("@tiptap/react");
22125
+ var import_react53 = __toESM(require("react"), 1);
22126
+ var import_react54 = require("@tiptap/react");
21937
22127
 
21938
22128
  // src/components/UEditor/extensions.ts
21939
22129
  var import_extension_document = __toESM(require("@tiptap/extension-document"), 1);
@@ -21971,8 +22161,8 @@ var import_lowlight = require("lowlight");
21971
22161
  // src/components/UEditor/slash-command.tsx
21972
22162
  var import_core = require("@tiptap/core");
21973
22163
  var import_suggestion = __toESM(require("@tiptap/suggestion"), 1);
21974
- var import_react40 = require("@tiptap/react");
21975
- var import_react41 = __toESM(require("react"), 1);
22164
+ var import_react41 = require("@tiptap/react");
22165
+ var import_react42 = __toESM(require("react"), 1);
21976
22166
  var import_lucide_react40 = require("lucide-react");
21977
22167
  var import_tippy = __toESM(require("tippy.js"), 1);
21978
22168
  var import_jsx_runtime73 = require("react/jsx-runtime");
@@ -22003,9 +22193,9 @@ var DEFAULT_MESSAGES = {
22003
22193
  tableDesc: "Insert a table"
22004
22194
  };
22005
22195
  function useResettingIndex2(resetToken) {
22006
- const [state, setState] = import_react41.default.useState({ resetToken, index: 0 });
22196
+ const [state, setState] = import_react42.default.useState({ resetToken, index: 0 });
22007
22197
  const selectedIndex = Object.is(state.resetToken, resetToken) ? state.index : 0;
22008
- const setSelectedIndex = import_react41.default.useCallback((nextIndex) => {
22198
+ const setSelectedIndex = import_react42.default.useCallback((nextIndex) => {
22009
22199
  setState((prev) => {
22010
22200
  const prevIndex = Object.is(prev.resetToken, resetToken) ? prev.index : 0;
22011
22201
  return {
@@ -22144,14 +22334,14 @@ function buildSlashCommandItems({
22144
22334
  }
22145
22335
  ].filter((item) => item.title.toLowerCase().includes(query.toLowerCase()));
22146
22336
  }
22147
- var SlashCommandList = (0, import_react41.forwardRef)((props, ref) => {
22337
+ var SlashCommandList = (0, import_react42.forwardRef)((props, ref) => {
22148
22338
  const [selectedIndex, setSelectedIndex] = useResettingIndex2(props.items);
22149
- const listRef = (0, import_react41.useRef)(null);
22150
- (0, import_react41.useEffect)(() => {
22339
+ const listRef = (0, import_react42.useRef)(null);
22340
+ (0, import_react42.useEffect)(() => {
22151
22341
  const selectedElement = listRef.current?.querySelector(`[data-index="${selectedIndex}"]`);
22152
22342
  selectedElement?.scrollIntoView({ block: "nearest" });
22153
22343
  }, [selectedIndex, props.items]);
22154
- (0, import_react41.useImperativeHandle)(ref, () => ({
22344
+ (0, import_react42.useImperativeHandle)(ref, () => ({
22155
22345
  onKeyDown: ({ event }) => {
22156
22346
  if (props.items.length === 0) {
22157
22347
  return false;
@@ -22234,7 +22424,7 @@ var SlashCommand = import_core.Extension.create({
22234
22424
  let popup;
22235
22425
  return {
22236
22426
  onStart: (props) => {
22237
- component = new import_react40.ReactRenderer(SlashCommandList, {
22427
+ component = new import_react41.ReactRenderer(SlashCommandList, {
22238
22428
  props: {
22239
22429
  ...props,
22240
22430
  messages
@@ -22382,16 +22572,16 @@ var ClipboardImages = import_core2.Extension.create({
22382
22572
  // src/components/UEditor/emoji-suggestion.tsx
22383
22573
  var import_core3 = require("@tiptap/core");
22384
22574
  var import_suggestion2 = __toESM(require("@tiptap/suggestion"), 1);
22385
- var import_react42 = require("@tiptap/react");
22575
+ var import_react43 = require("@tiptap/react");
22386
22576
  var import_state2 = require("@tiptap/pm/state");
22387
- var import_react43 = __toESM(require("react"), 1);
22577
+ var import_react44 = __toESM(require("react"), 1);
22388
22578
  var import_lucide_react41 = require("lucide-react");
22389
22579
  var import_tippy2 = __toESM(require("tippy.js"), 1);
22390
22580
  var import_jsx_runtime74 = require("react/jsx-runtime");
22391
22581
  function useResettingIndex3(resetToken) {
22392
- const [state, setState] = import_react43.default.useState({ resetToken, index: 0 });
22582
+ const [state, setState] = import_react44.default.useState({ resetToken, index: 0 });
22393
22583
  const selectedIndex = Object.is(state.resetToken, resetToken) ? state.index : 0;
22394
- const setSelectedIndex = import_react43.default.useCallback((nextIndex) => {
22584
+ const setSelectedIndex = import_react44.default.useCallback((nextIndex) => {
22395
22585
  setState((prev) => {
22396
22586
  const prevIndex = Object.is(prev.resetToken, resetToken) ? prev.index : 0;
22397
22587
  return {
@@ -22402,9 +22592,9 @@ function useResettingIndex3(resetToken) {
22402
22592
  }, [resetToken]);
22403
22593
  return [selectedIndex, setSelectedIndex];
22404
22594
  }
22405
- var EmojiList = (0, import_react43.forwardRef)((props, ref) => {
22595
+ var EmojiList = (0, import_react44.forwardRef)((props, ref) => {
22406
22596
  const [selectedIndex, setSelectedIndex] = useResettingIndex3(props.items);
22407
- (0, import_react43.useImperativeHandle)(ref, () => ({
22597
+ (0, import_react44.useImperativeHandle)(ref, () => ({
22408
22598
  onKeyDown: ({ event }) => {
22409
22599
  if (event.key === "ArrowUp") {
22410
22600
  setSelectedIndex((prev) => (prev + props.items.length - 1) % props.items.length);
@@ -22491,7 +22681,7 @@ var EmojiSuggestion = import_core3.Extension.create({
22491
22681
  let popup;
22492
22682
  return {
22493
22683
  onStart: (props) => {
22494
- component = new import_react42.ReactRenderer(EmojiList, {
22684
+ component = new import_react43.ReactRenderer(EmojiList, {
22495
22685
  props,
22496
22686
  editor: props.editor
22497
22687
  });
@@ -22609,10 +22799,10 @@ var UEditorPlaceholder = import_core4.Extension.create({
22609
22799
  });
22610
22800
 
22611
22801
  // src/components/UEditor/resizable-image.tsx
22612
- var import_react44 = require("react");
22802
+ var import_react45 = require("react");
22613
22803
  var import_extension_image = __toESM(require("@tiptap/extension-image"), 1);
22614
22804
  var import_core5 = require("@tiptap/core");
22615
- var import_react45 = require("@tiptap/react");
22805
+ var import_react46 = require("@tiptap/react");
22616
22806
  var import_jsx_runtime75 = require("react/jsx-runtime");
22617
22807
  var MIN_IMAGE_SIZE_PX = 40;
22618
22808
  var AXIS_LOCK_THRESHOLD_PX = 4;
@@ -22658,17 +22848,17 @@ function getImageLayoutStyles(layout) {
22658
22848
  }
22659
22849
  function ResizableImageNodeView(props) {
22660
22850
  const { node, selected, updateAttributes, editor, getPos } = props;
22661
- const wrapperRef = (0, import_react44.useRef)(null);
22662
- const imgRef = (0, import_react44.useRef)(null);
22663
- const [isHovered, setIsHovered] = (0, import_react44.useState)(false);
22664
- const [isResizing, setIsResizing] = (0, import_react44.useState)(false);
22851
+ const wrapperRef = (0, import_react45.useRef)(null);
22852
+ const imgRef = (0, import_react45.useRef)(null);
22853
+ const [isHovered, setIsHovered] = (0, import_react45.useState)(false);
22854
+ const [isResizing, setIsResizing] = (0, import_react45.useState)(false);
22665
22855
  const widthAttr = toNullableNumber(node.attrs["width"]);
22666
22856
  const heightAttr = toNullableNumber(node.attrs["height"]);
22667
22857
  const textAlign = String(node.attrs["textAlign"] ?? "");
22668
22858
  const imageLayout = parseImageLayout(node.attrs["imageLayout"]);
22669
22859
  const preserveAspectByDefault = imageLayout === "left" || imageLayout === "right";
22670
- const dragStateRef = (0, import_react44.useRef)(null);
22671
- (0, import_react44.useEffect)(() => {
22860
+ const dragStateRef = (0, import_react45.useRef)(null);
22861
+ (0, import_react45.useEffect)(() => {
22672
22862
  const img = imgRef.current;
22673
22863
  if (!img) return;
22674
22864
  img.style.width = widthAttr ? `${widthAttr}px` : "";
@@ -22765,7 +22955,7 @@ function ResizableImageNodeView(props) {
22765
22955
  const wrapperAlignClass = imageLayout === "block" ? textAlign === "center" ? "mx-auto" : textAlign === "right" ? "ml-auto" : textAlign === "justify" ? "mx-auto" : "" : "";
22766
22956
  const wrapperLayoutClass = imageLayout === "left" ? "float-left mr-4 mb-3 mt-1 clear-none max-w-[min(45%,20rem)]" : imageLayout === "right" ? "float-right ml-4 mb-3 mt-1 clear-none max-w-[min(45%,20rem)]" : "w-fit";
22767
22957
  return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)(
22768
- import_react45.NodeViewWrapper,
22958
+ import_react46.NodeViewWrapper,
22769
22959
  {
22770
22960
  as: "div",
22771
22961
  ref: wrapperRef,
@@ -22866,7 +23056,7 @@ var ResizableImage = import_extension_image.default.extend({
22866
23056
  return ["img", (0, import_core5.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes)];
22867
23057
  },
22868
23058
  addNodeView() {
22869
- return (0, import_react45.ReactNodeViewRenderer)(ResizableImageNodeView);
23059
+ return (0, import_react46.ReactNodeViewRenderer)(ResizableImageNodeView);
22870
23060
  }
22871
23061
  }).configure({
22872
23062
  allowBase64: true,
@@ -23032,16 +23222,16 @@ function buildUEditorExtensions({
23032
23222
  }
23033
23223
 
23034
23224
  // src/components/UEditor/toolbar.tsx
23035
- var import_react49 = __toESM(require("react"), 1);
23225
+ var import_react50 = __toESM(require("react"), 1);
23036
23226
  var import_lucide_react45 = require("lucide-react");
23037
23227
 
23038
23228
  // src/components/UEditor/colors.tsx
23039
- var import_react46 = require("react");
23229
+ var import_react47 = require("react");
23040
23230
  var import_lucide_react42 = require("lucide-react");
23041
23231
  var import_jsx_runtime76 = require("react/jsx-runtime");
23042
23232
  var useEditorColors = () => {
23043
23233
  const t = useSmartTranslations("UEditor");
23044
- const textColors = (0, import_react46.useMemo)(
23234
+ const textColors = (0, import_react47.useMemo)(
23045
23235
  () => [
23046
23236
  { name: t("colors.default"), color: "inherit", cssClass: "text-foreground" },
23047
23237
  { name: t("colors.muted"), color: "var(--muted-foreground)", cssClass: "text-muted-foreground" },
@@ -23054,7 +23244,7 @@ var useEditorColors = () => {
23054
23244
  ],
23055
23245
  [t]
23056
23246
  );
23057
- const highlightColors = (0, import_react46.useMemo)(
23247
+ const highlightColors = (0, import_react47.useMemo)(
23058
23248
  () => [
23059
23249
  { name: t("colors.default"), color: "", cssClass: "" },
23060
23250
  { name: t("colors.muted"), color: "var(--muted)", cssClass: "bg-muted" },
@@ -23189,7 +23379,7 @@ function deleteSelectedImage(editor) {
23189
23379
  }
23190
23380
 
23191
23381
  // src/components/UEditor/inputs.tsx
23192
- var import_react47 = require("react");
23382
+ var import_react48 = require("react");
23193
23383
  var import_lucide_react43 = require("lucide-react");
23194
23384
  var import_jsx_runtime77 = require("react/jsx-runtime");
23195
23385
  function normalizeUrl(raw) {
@@ -23205,9 +23395,9 @@ var LinkInput = ({
23205
23395
  initialUrl = ""
23206
23396
  }) => {
23207
23397
  const t = useSmartTranslations("UEditor");
23208
- const [url, setUrl] = (0, import_react47.useState)(initialUrl);
23209
- const inputRef = (0, import_react47.useRef)(null);
23210
- (0, import_react47.useEffect)(() => {
23398
+ const [url, setUrl] = (0, import_react48.useState)(initialUrl);
23399
+ const inputRef = (0, import_react48.useRef)(null);
23400
+ (0, import_react48.useEffect)(() => {
23211
23401
  inputRef.current?.focus();
23212
23402
  inputRef.current?.select();
23213
23403
  }, []);
@@ -23234,10 +23424,10 @@ var LinkInput = ({
23234
23424
  };
23235
23425
  var ImageInput = ({ onSubmit, onCancel }) => {
23236
23426
  const t = useSmartTranslations("UEditor");
23237
- const [url, setUrl] = (0, import_react47.useState)("");
23238
- const [alt, setAlt] = (0, import_react47.useState)("");
23239
- const inputRef = (0, import_react47.useRef)(null);
23240
- (0, import_react47.useEffect)(() => {
23427
+ const [url, setUrl] = (0, import_react48.useState)("");
23428
+ const [alt, setAlt] = (0, import_react48.useState)("");
23429
+ const inputRef = (0, import_react48.useRef)(null);
23430
+ (0, import_react48.useEffect)(() => {
23241
23431
  inputRef.current?.focus();
23242
23432
  }, []);
23243
23433
  const handleSubmit = (e) => {
@@ -23290,7 +23480,7 @@ var ImageInput = ({ onSubmit, onCancel }) => {
23290
23480
  };
23291
23481
 
23292
23482
  // src/components/UEditor/emoji-picker.tsx
23293
- var import_react48 = require("react");
23483
+ var import_react49 = require("react");
23294
23484
  var import_lucide_react44 = require("lucide-react");
23295
23485
  var import_jsx_runtime78 = require("react/jsx-runtime");
23296
23486
  var CATEGORY_ICONS2 = {
@@ -23304,12 +23494,12 @@ var CATEGORY_ICONS2 = {
23304
23494
  };
23305
23495
  var EmojiPicker2 = ({ onSelect, onClose }) => {
23306
23496
  const t = useSmartTranslations("UEditor");
23307
- const [search, setSearch] = (0, import_react48.useState)("");
23308
- const [activeCategory, setActiveCategory] = (0, import_react48.useState)(EMOJI_LIST[0]?.id || "");
23309
- const scrollContainerRef = (0, import_react48.useRef)(null);
23310
- const categoryRefs = (0, import_react48.useRef)({});
23311
- const isUserScrolling = (0, import_react48.useRef)(false);
23312
- const filteredCategories = (0, import_react48.useMemo)(() => {
23497
+ const [search, setSearch] = (0, import_react49.useState)("");
23498
+ const [activeCategory, setActiveCategory] = (0, import_react49.useState)(EMOJI_LIST[0]?.id || "");
23499
+ const scrollContainerRef = (0, import_react49.useRef)(null);
23500
+ const categoryRefs = (0, import_react49.useRef)({});
23501
+ const isUserScrolling = (0, import_react49.useRef)(false);
23502
+ const filteredCategories = (0, import_react49.useMemo)(() => {
23313
23503
  if (!search.trim()) return EMOJI_LIST;
23314
23504
  const query = search.toLowerCase();
23315
23505
  return EMOJI_LIST.map((category) => ({
@@ -23323,7 +23513,7 @@ var EmojiPicker2 = ({ onSelect, onClose }) => {
23323
23513
  onSelect(emoji);
23324
23514
  setSearch("");
23325
23515
  };
23326
- (0, import_react48.useEffect)(() => {
23516
+ (0, import_react49.useEffect)(() => {
23327
23517
  if (search) return;
23328
23518
  const container = scrollContainerRef.current;
23329
23519
  if (!container) return;
@@ -23363,7 +23553,7 @@ var EmojiPicker2 = ({ onSelect, onClose }) => {
23363
23553
  isUserScrolling.current = true;
23364
23554
  }, 500);
23365
23555
  };
23366
- (0, import_react48.useEffect)(() => {
23556
+ (0, import_react49.useEffect)(() => {
23367
23557
  isUserScrolling.current = true;
23368
23558
  }, []);
23369
23559
  return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "w-96 bg-card border border-border/50 rounded-2xl shadow-xl overflow-hidden flex flex-col max-h-128", children: [
@@ -23482,7 +23672,7 @@ function fileToDataUrl2(file) {
23482
23672
  reader.readAsDataURL(file);
23483
23673
  });
23484
23674
  }
23485
- var ToolbarButton = import_react49.default.forwardRef(({ onClick, onMouseDown, active, disabled, children, title, className }, ref) => {
23675
+ var ToolbarButton = import_react50.default.forwardRef(({ onClick, onMouseDown, active, disabled, children, title, className }, ref) => {
23486
23676
  const button = /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
23487
23677
  "button",
23488
23678
  {
@@ -23520,10 +23710,10 @@ var EditorToolbar = ({
23520
23710
  }) => {
23521
23711
  const t = useSmartTranslations("UEditor");
23522
23712
  const { textColors, highlightColors } = useEditorColors();
23523
- const [showImageInput, setShowImageInput] = (0, import_react49.useState)(false);
23524
- const fileInputRef = (0, import_react49.useRef)(null);
23525
- const [isUploadingImage, setIsUploadingImage] = (0, import_react49.useState)(false);
23526
- const [imageUploadError, setImageUploadError] = (0, import_react49.useState)(null);
23713
+ const [showImageInput, setShowImageInput] = (0, import_react50.useState)(false);
23714
+ const fileInputRef = (0, import_react50.useRef)(null);
23715
+ const [isUploadingImage, setIsUploadingImage] = (0, import_react50.useState)(false);
23716
+ const [imageUploadError, setImageUploadError] = (0, import_react50.useState)(null);
23527
23717
  const isImageSelected = editor.isActive("image");
23528
23718
  const imageAttrs = editor.getAttributes("image");
23529
23719
  const imageLayout = imageAttrs.imageLayout === "left" || imageAttrs.imageLayout === "right" ? imageAttrs.imageLayout : "block";
@@ -24073,16 +24263,16 @@ var EditorToolbar = ({
24073
24263
  };
24074
24264
 
24075
24265
  // src/components/UEditor/menus.tsx
24076
- var import_react50 = require("react");
24266
+ var import_react51 = require("react");
24077
24267
  var import_react_dom8 = require("react-dom");
24078
24268
  var import_lucide_react46 = require("lucide-react");
24079
24269
  var import_jsx_runtime80 = require("react/jsx-runtime");
24080
24270
  var FloatingSlashCommandMenu = ({ editor, onClose }) => {
24081
24271
  const t = useSmartTranslations("UEditor");
24082
- const messages = (0, import_react50.useMemo)(() => buildSlashCommandMessages(t), [t]);
24083
- const items = (0, import_react50.useMemo)(() => buildSlashCommandItems({ query: "", messages }), [messages]);
24084
- const listRef = (0, import_react50.useRef)(null);
24085
- (0, import_react50.useEffect)(() => {
24272
+ const messages = (0, import_react51.useMemo)(() => buildSlashCommandMessages(t), [t]);
24273
+ const items = (0, import_react51.useMemo)(() => buildSlashCommandItems({ query: "", messages }), [messages]);
24274
+ const listRef = (0, import_react51.useRef)(null);
24275
+ (0, import_react51.useEffect)(() => {
24086
24276
  const handleKeyDown2 = (event) => {
24087
24277
  if (event.key === "Escape") {
24088
24278
  event.preventDefault();
@@ -24112,7 +24302,7 @@ var FloatingSlashCommandMenu = ({ editor, onClose }) => {
24112
24302
  };
24113
24303
  var FloatingMenuContent = ({ editor }) => {
24114
24304
  const t = useSmartTranslations("UEditor");
24115
- const [showCommands, setShowCommands] = (0, import_react50.useState)(false);
24305
+ const [showCommands, setShowCommands] = (0, import_react51.useState)(false);
24116
24306
  if (showCommands) {
24117
24307
  return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(FloatingSlashCommandMenu, { editor, onClose: () => setShowCommands(false) });
24118
24308
  }
@@ -24135,16 +24325,16 @@ var BubbleMenuContent = ({
24135
24325
  }) => {
24136
24326
  const t = useSmartTranslations("UEditor");
24137
24327
  const { textColors, highlightColors } = useEditorColors();
24138
- const [showLinkInput, setShowLinkInput] = (0, import_react50.useState)(false);
24139
- const [showEditorColorPalette, setShowEditorColorPalette] = (0, import_react50.useState)(false);
24328
+ const [showLinkInput, setShowLinkInput] = (0, import_react51.useState)(false);
24329
+ const [showEditorColorPalette, setShowEditorColorPalette] = (0, import_react51.useState)(false);
24140
24330
  const isImageSelected = editor.isActive("image");
24141
24331
  const imageAttrs = editor.getAttributes("image");
24142
24332
  const imageLayout = imageAttrs.imageLayout === "left" || imageAttrs.imageLayout === "right" ? imageAttrs.imageLayout : "block";
24143
24333
  const imageWidthPreset = imageAttrs.imageWidthPreset === "sm" || imageAttrs.imageWidthPreset === "md" || imageAttrs.imageWidthPreset === "lg" ? imageAttrs.imageWidthPreset : null;
24144
- (0, import_react50.useEffect)(() => {
24334
+ (0, import_react51.useEffect)(() => {
24145
24335
  onKeepOpenChange?.(showLinkInput);
24146
24336
  }, [onKeepOpenChange, showLinkInput]);
24147
- (0, import_react50.useEffect)(() => {
24337
+ (0, import_react51.useEffect)(() => {
24148
24338
  if (!showLinkInput) return;
24149
24339
  const close2 = () => setShowLinkInput(false);
24150
24340
  editor.on("selectionUpdate", close2);
@@ -24282,16 +24472,16 @@ var BubbleMenuContent = ({
24282
24472
  };
24283
24473
  var CustomBubbleMenu = ({ editor }) => {
24284
24474
  const SHOW_DELAY_MS = 180;
24285
- const [isVisible, setIsVisible] = (0, import_react50.useState)(false);
24286
- const [position, setPosition] = (0, import_react50.useState)({ top: 0, left: 0 });
24287
- const menuRef = (0, import_react50.useRef)(null);
24288
- const keepOpenRef = (0, import_react50.useRef)(false);
24289
- const showTimeoutRef = (0, import_react50.useRef)(null);
24290
- const setKeepOpen = (0, import_react50.useCallback)((next) => {
24475
+ const [isVisible, setIsVisible] = (0, import_react51.useState)(false);
24476
+ const [position, setPosition] = (0, import_react51.useState)({ top: 0, left: 0 });
24477
+ const menuRef = (0, import_react51.useRef)(null);
24478
+ const keepOpenRef = (0, import_react51.useRef)(false);
24479
+ const showTimeoutRef = (0, import_react51.useRef)(null);
24480
+ const setKeepOpen = (0, import_react51.useCallback)((next) => {
24291
24481
  keepOpenRef.current = next;
24292
24482
  if (next) setIsVisible(true);
24293
24483
  }, []);
24294
- (0, import_react50.useEffect)(() => {
24484
+ (0, import_react51.useEffect)(() => {
24295
24485
  const clearShowTimeout = () => {
24296
24486
  if (showTimeoutRef.current) {
24297
24487
  clearTimeout(showTimeoutRef.current);
@@ -24364,9 +24554,9 @@ var CustomBubbleMenu = ({ editor }) => {
24364
24554
  );
24365
24555
  };
24366
24556
  var CustomFloatingMenu = ({ editor }) => {
24367
- const [isVisible, setIsVisible] = (0, import_react50.useState)(false);
24368
- const [position, setPosition] = (0, import_react50.useState)({ top: 0, left: 0 });
24369
- (0, import_react50.useEffect)(() => {
24557
+ const [isVisible, setIsVisible] = (0, import_react51.useState)(false);
24558
+ const [position, setPosition] = (0, import_react51.useState)({ top: 0, left: 0 });
24559
+ (0, import_react51.useEffect)(() => {
24370
24560
  const updatePosition = () => {
24371
24561
  const { state, view } = editor;
24372
24562
  const { $from, empty } = state.selection;
@@ -24684,7 +24874,7 @@ async function prepareUEditorContentForSave({
24684
24874
  }
24685
24875
 
24686
24876
  // src/components/UEditor/table-controls.tsx
24687
- var import_react51 = __toESM(require("react"), 1);
24877
+ var import_react52 = __toESM(require("react"), 1);
24688
24878
 
24689
24879
  // node_modules/prosemirror-model/dist/index.js
24690
24880
  function findDiffStart(a, b, pos) {
@@ -28849,6 +29039,19 @@ var import_lucide_react47 = require("lucide-react");
28849
29039
  var import_jsx_runtime82 = require("react/jsx-runtime");
28850
29040
  var FALLBACK_TABLE_ROW_HEIGHT = 44;
28851
29041
  var FALLBACK_TABLE_COLUMN_WIDTH = 160;
29042
+ var MENU_HOVER_PADDING = 18;
29043
+ var ROW_HANDLE_HOVER_WIDTH = 28;
29044
+ var COLUMN_HANDLE_HOVER_HEIGHT = 28;
29045
+ var ADD_COLUMN_HOVER_WIDTH = 24;
29046
+ var ADD_ROW_HOVER_HEIGHT = 24;
29047
+ var HANDLE_HOVER_RADIUS = 14;
29048
+ var DEFAULT_HOVER_STATE = {
29049
+ menuVisible: false,
29050
+ addColumnVisible: false,
29051
+ addRowVisible: false,
29052
+ rowHandleIndex: null,
29053
+ columnHandleIndex: null
29054
+ };
28852
29055
  function resolveElement(target) {
28853
29056
  if (target instanceof Element) return target;
28854
29057
  if (target instanceof Node) return target.parentElement;
@@ -28974,6 +29177,12 @@ function buildLayout(editor, surface, cell) {
28974
29177
  };
28975
29178
  }
28976
29179
  function getSelectedCell(editor) {
29180
+ const browserSelection = window.getSelection();
29181
+ const anchorElement = resolveElement(browserSelection?.anchorNode ?? null);
29182
+ const anchorCell = anchorElement?.closest?.("th,td");
29183
+ if (anchorCell instanceof HTMLTableCellElement) {
29184
+ return anchorCell;
29185
+ }
28977
29186
  const domAtPos = editor.view.domAtPos(editor.state.selection.from);
28978
29187
  return getCellFromTarget(domAtPos.node);
28979
29188
  }
@@ -29000,14 +29209,15 @@ function collectChildren(node) {
29000
29209
  }
29001
29210
  function TableControls({ editor, containerRef }) {
29002
29211
  const t = useSmartTranslations("UEditor");
29003
- const [layout, setLayout] = import_react51.default.useState(null);
29004
- const [dragPreview, setDragPreview] = import_react51.default.useState(null);
29005
- const layoutRef = import_react51.default.useRef(null);
29006
- const dragStateRef = import_react51.default.useRef(null);
29007
- import_react51.default.useEffect(() => {
29212
+ const [layout, setLayout] = import_react52.default.useState(null);
29213
+ const [dragPreview, setDragPreview] = import_react52.default.useState(null);
29214
+ const [hoverState, setHoverState] = import_react52.default.useState(DEFAULT_HOVER_STATE);
29215
+ const layoutRef = import_react52.default.useRef(null);
29216
+ const dragStateRef = import_react52.default.useRef(null);
29217
+ import_react52.default.useEffect(() => {
29008
29218
  layoutRef.current = layout;
29009
29219
  }, [layout]);
29010
- const syncFromCell = import_react51.default.useCallback((cell) => {
29220
+ const syncFromCell = import_react52.default.useCallback((cell) => {
29011
29221
  const surface = containerRef.current;
29012
29222
  if (!surface || !cell) {
29013
29223
  setLayout(null);
@@ -29015,10 +29225,10 @@ function TableControls({ editor, containerRef }) {
29015
29225
  }
29016
29226
  setLayout(buildLayout(editor, surface, cell));
29017
29227
  }, [containerRef, editor]);
29018
- const syncFromSelection = import_react51.default.useCallback(() => {
29228
+ const syncFromSelection = import_react52.default.useCallback(() => {
29019
29229
  syncFromCell(getSelectedCell(editor));
29020
29230
  }, [editor, syncFromCell]);
29021
- const refreshCurrentLayout = import_react51.default.useCallback(() => {
29231
+ const refreshCurrentLayout = import_react52.default.useCallback(() => {
29022
29232
  setLayout((prev) => {
29023
29233
  if (!prev) return prev;
29024
29234
  const surface = containerRef.current;
@@ -29028,22 +29238,55 @@ function TableControls({ editor, containerRef }) {
29028
29238
  return cell ? buildLayout(editor, surface, cell) : null;
29029
29239
  });
29030
29240
  }, [containerRef, editor]);
29031
- const clearDrag = import_react51.default.useCallback(() => {
29241
+ const clearDrag = import_react52.default.useCallback(() => {
29032
29242
  dragStateRef.current = null;
29033
29243
  setDragPreview(null);
29034
29244
  document.body.style.cursor = "";
29035
29245
  }, []);
29036
- import_react51.default.useEffect(() => {
29246
+ const updateHoverState = import_react52.default.useCallback((event) => {
29247
+ const activeLayout = layoutRef.current;
29248
+ const surface = containerRef.current;
29249
+ if (!activeLayout || !surface || dragStateRef.current) {
29250
+ setHoverState(DEFAULT_HOVER_STATE);
29251
+ return;
29252
+ }
29253
+ const surfaceRect = surface.getBoundingClientRect();
29254
+ const relativeX = event.clientX - surfaceRect.left + surface.scrollLeft;
29255
+ const relativeY = event.clientY - surfaceRect.top + surface.scrollTop;
29256
+ const rowHandleIndex = activeLayout.rowHandles.find((rowHandle) => relativeX >= activeLayout.tableLeft - ROW_HANDLE_HOVER_WIDTH && relativeX <= activeLayout.tableLeft && Math.abs(relativeY - rowHandle.center) <= HANDLE_HOVER_RADIUS)?.index ?? null;
29257
+ const columnHandleIndex = activeLayout.columnHandles.find((columnHandle) => relativeY >= activeLayout.tableTop - COLUMN_HANDLE_HOVER_HEIGHT && relativeY <= activeLayout.tableTop && Math.abs(relativeX - columnHandle.center) <= HANDLE_HOVER_RADIUS)?.index ?? null;
29258
+ const menuVisible = relativeX >= activeLayout.tableLeft - MENU_HOVER_PADDING && relativeX <= activeLayout.tableLeft + 42 && relativeY >= activeLayout.tableTop - COLUMN_HANDLE_HOVER_HEIGHT && relativeY <= activeLayout.tableTop + MENU_HOVER_PADDING;
29259
+ const addColumnVisible = relativeX >= activeLayout.tableLeft + activeLayout.tableWidth && relativeX <= activeLayout.tableLeft + activeLayout.tableWidth + ADD_COLUMN_HOVER_WIDTH && relativeY >= activeLayout.tableTop && relativeY <= activeLayout.tableTop + activeLayout.tableHeight;
29260
+ const addRowVisible = relativeY >= activeLayout.tableTop + activeLayout.tableHeight && relativeY <= activeLayout.tableTop + activeLayout.tableHeight + ADD_ROW_HOVER_HEIGHT && relativeX >= activeLayout.tableLeft && relativeX <= activeLayout.tableLeft + activeLayout.tableWidth;
29261
+ setHoverState((prev) => {
29262
+ if (prev.menuVisible === menuVisible && prev.addColumnVisible === addColumnVisible && prev.addRowVisible === addRowVisible && prev.rowHandleIndex === rowHandleIndex && prev.columnHandleIndex === columnHandleIndex) {
29263
+ return prev;
29264
+ }
29265
+ return {
29266
+ menuVisible,
29267
+ addColumnVisible,
29268
+ addRowVisible,
29269
+ rowHandleIndex,
29270
+ columnHandleIndex
29271
+ };
29272
+ });
29273
+ }, [containerRef]);
29274
+ import_react52.default.useEffect(() => {
29037
29275
  const proseMirror = editor.view.dom;
29038
29276
  const surface = containerRef.current;
29039
29277
  if (!surface) return void 0;
29040
29278
  const handleMouseOver = (event) => {
29041
29279
  if (dragStateRef.current) return;
29042
- syncFromCell(getCellFromTarget(event.target));
29280
+ const cell = getCellFromTarget(event.target);
29281
+ if (!cell) return;
29282
+ syncFromCell(cell);
29283
+ };
29284
+ const handleSurfaceMouseMove = (event) => {
29285
+ updateHoverState(event);
29043
29286
  };
29044
29287
  const handleMouseLeave = () => {
29045
29288
  if (dragStateRef.current) return;
29046
- syncFromSelection();
29289
+ setHoverState(DEFAULT_HOVER_STATE);
29047
29290
  };
29048
29291
  const handleFocusIn = () => {
29049
29292
  if (dragStateRef.current) return;
@@ -29052,6 +29295,7 @@ function TableControls({ editor, containerRef }) {
29052
29295
  proseMirror.addEventListener("mouseover", handleMouseOver);
29053
29296
  proseMirror.addEventListener("mouseleave", handleMouseLeave);
29054
29297
  proseMirror.addEventListener("focusin", handleFocusIn);
29298
+ surface.addEventListener("mousemove", handleSurfaceMouseMove);
29055
29299
  surface.addEventListener("scroll", refreshCurrentLayout, { passive: true });
29056
29300
  window.addEventListener("resize", refreshCurrentLayout);
29057
29301
  editor.on("selectionUpdate", syncFromSelection);
@@ -29061,13 +29305,14 @@ function TableControls({ editor, containerRef }) {
29061
29305
  proseMirror.removeEventListener("mouseover", handleMouseOver);
29062
29306
  proseMirror.removeEventListener("mouseleave", handleMouseLeave);
29063
29307
  proseMirror.removeEventListener("focusin", handleFocusIn);
29308
+ surface.removeEventListener("mousemove", handleSurfaceMouseMove);
29064
29309
  surface.removeEventListener("scroll", refreshCurrentLayout);
29065
29310
  window.removeEventListener("resize", refreshCurrentLayout);
29066
29311
  editor.off("selectionUpdate", syncFromSelection);
29067
29312
  editor.off("update", refreshCurrentLayout);
29068
29313
  };
29069
- }, [clearDrag, containerRef, editor, refreshCurrentLayout, syncFromCell, syncFromSelection]);
29070
- const runAtCellPos = import_react51.default.useCallback((cellPos, command, options) => {
29314
+ }, [clearDrag, containerRef, editor, refreshCurrentLayout, syncFromCell, syncFromSelection, updateHoverState]);
29315
+ const runAtCellPos = import_react52.default.useCallback((cellPos, command, options) => {
29071
29316
  if (cellPos == null) return false;
29072
29317
  focusCell(editor, cellPos);
29073
29318
  const result = command(editor.chain().focus(null, { scrollIntoView: false })).run();
@@ -29076,17 +29321,17 @@ function TableControls({ editor, containerRef }) {
29076
29321
  }
29077
29322
  return result;
29078
29323
  }, [editor, syncFromSelection]);
29079
- const runAtActiveCell = import_react51.default.useCallback((command, options) => {
29324
+ const runAtActiveCell = import_react52.default.useCallback((command, options) => {
29080
29325
  return runAtCellPos(layoutRef.current?.cellPos ?? null, command, options);
29081
29326
  }, [runAtCellPos]);
29082
- const getCurrentCornerCellPos = import_react51.default.useCallback(() => {
29327
+ const getCurrentCornerCellPos = import_react52.default.useCallback(() => {
29083
29328
  const activePos = layoutRef.current?.cellPos ?? editor.state.selection.from;
29084
29329
  return getLastCellPosFromState(editor, activePos);
29085
29330
  }, [editor]);
29086
- const runAtCornerCell = import_react51.default.useCallback((command, options) => {
29331
+ const runAtCornerCell = import_react52.default.useCallback((command, options) => {
29087
29332
  return runAtCellPos(getCurrentCornerCellPos(), command, options);
29088
29333
  }, [getCurrentCornerCellPos, runAtCellPos]);
29089
- const replaceTableAtCellPos = import_react51.default.useCallback((cellPos, updateTable) => {
29334
+ const replaceTableAtCellPos = import_react52.default.useCallback((cellPos, updateTable) => {
29090
29335
  if (cellPos == null) return false;
29091
29336
  const tableInfo = findTableInfo(editor, cellPos);
29092
29337
  if (!tableInfo) return false;
@@ -29096,10 +29341,10 @@ function TableControls({ editor, containerRef }) {
29096
29341
  requestAnimationFrame(syncFromSelection);
29097
29342
  return true;
29098
29343
  }, [editor, syncFromSelection]);
29099
- const createEmptyCellNode = import_react51.default.useCallback((cellNode) => {
29344
+ const createEmptyCellNode = import_react52.default.useCallback((cellNode) => {
29100
29345
  return cellNode.type.createAndFill(cellNode.attrs) ?? cellNode;
29101
29346
  }, []);
29102
- const duplicateRowAt = import_react51.default.useCallback((rowIndex, cellPos) => {
29347
+ const duplicateRowAt = import_react52.default.useCallback((rowIndex, cellPos) => {
29103
29348
  return replaceTableAtCellPos(cellPos, (tableNode) => {
29104
29349
  const rows = collectChildren(tableNode);
29105
29350
  const rowNode = rows[rowIndex];
@@ -29108,7 +29353,7 @@ function TableControls({ editor, containerRef }) {
29108
29353
  return tableNode.type.create(tableNode.attrs, rows);
29109
29354
  });
29110
29355
  }, [replaceTableAtCellPos]);
29111
- const clearRowAt = import_react51.default.useCallback((rowIndex, cellPos) => {
29356
+ const clearRowAt = import_react52.default.useCallback((rowIndex, cellPos) => {
29112
29357
  return replaceTableAtCellPos(cellPos, (tableNode) => {
29113
29358
  const rows = collectChildren(tableNode);
29114
29359
  const rowNode = rows[rowIndex];
@@ -29118,7 +29363,7 @@ function TableControls({ editor, containerRef }) {
29118
29363
  return tableNode.type.create(tableNode.attrs, rows);
29119
29364
  });
29120
29365
  }, [createEmptyCellNode, replaceTableAtCellPos]);
29121
- const duplicateColumnAt = import_react51.default.useCallback((columnIndex, cellPos) => {
29366
+ const duplicateColumnAt = import_react52.default.useCallback((columnIndex, cellPos) => {
29122
29367
  return replaceTableAtCellPos(cellPos, (tableNode) => {
29123
29368
  const rows = collectChildren(tableNode).map((rowNode) => {
29124
29369
  const cells = collectChildren(rowNode);
@@ -29130,7 +29375,7 @@ function TableControls({ editor, containerRef }) {
29130
29375
  return tableNode.type.create(tableNode.attrs, rows);
29131
29376
  });
29132
29377
  }, [replaceTableAtCellPos]);
29133
- const clearColumnAt = import_react51.default.useCallback((columnIndex, cellPos) => {
29378
+ const clearColumnAt = import_react52.default.useCallback((columnIndex, cellPos) => {
29134
29379
  return replaceTableAtCellPos(cellPos, (tableNode) => {
29135
29380
  const rows = collectChildren(tableNode).map((rowNode) => {
29136
29381
  const cells = collectChildren(rowNode);
@@ -29142,7 +29387,7 @@ function TableControls({ editor, containerRef }) {
29142
29387
  return tableNode.type.create(tableNode.attrs, rows);
29143
29388
  });
29144
29389
  }, [createEmptyCellNode, replaceTableAtCellPos]);
29145
- const expandTableBy = import_react51.default.useCallback((rows, cols) => {
29390
+ const expandTableBy = import_react52.default.useCallback((rows, cols) => {
29146
29391
  let ok = true;
29147
29392
  for (let index = 0; index < rows; index += 1) {
29148
29393
  ok = runAtCornerCell((chain) => chain.addRowAfter(), { sync: false });
@@ -29156,7 +29401,8 @@ function TableControls({ editor, containerRef }) {
29156
29401
  return true;
29157
29402
  }, [runAtCornerCell, syncFromSelection]);
29158
29403
  const canExpandTable = Boolean(layout);
29159
- import_react51.default.useEffect(() => {
29404
+ const controlsVisible = dragPreview !== null;
29405
+ import_react52.default.useEffect(() => {
29160
29406
  const handleMouseMove = (event) => {
29161
29407
  const dragState = dragStateRef.current;
29162
29408
  const activeLayout = layoutRef.current;
@@ -29243,7 +29489,7 @@ function TableControls({ editor, containerRef }) {
29243
29489
  window.removeEventListener("blur", clearDrag);
29244
29490
  };
29245
29491
  }, [clearDrag, containerRef, editor, expandTableBy, syncFromSelection]);
29246
- const menuItems = import_react51.default.useMemo(() => {
29492
+ const menuItems = import_react52.default.useMemo(() => {
29247
29493
  if (!layout) return [];
29248
29494
  return [
29249
29495
  {
@@ -29296,7 +29542,7 @@ function TableControls({ editor, containerRef }) {
29296
29542
  }
29297
29543
  ];
29298
29544
  }, [layout, runAtActiveCell, t]);
29299
- const getRowHandleMenuItems = import_react51.default.useCallback((rowHandle) => [
29545
+ const getRowHandleMenuItems = import_react52.default.useCallback((rowHandle) => [
29300
29546
  {
29301
29547
  label: t("tableMenu.addRowBefore"),
29302
29548
  icon: import_lucide_react47.ArrowUp,
@@ -29324,7 +29570,7 @@ function TableControls({ editor, containerRef }) {
29324
29570
  destructive: true
29325
29571
  }
29326
29572
  ], [clearRowAt, duplicateRowAt, runAtCellPos, t]);
29327
- const getColumnHandleMenuItems = import_react51.default.useCallback((columnHandle) => [
29573
+ const getColumnHandleMenuItems = import_react52.default.useCallback((columnHandle) => [
29328
29574
  {
29329
29575
  label: t("tableMenu.addColumnBefore"),
29330
29576
  icon: import_lucide_react47.ArrowLeft,
@@ -29367,107 +29613,147 @@ function TableControls({ editor, containerRef }) {
29367
29613
  const expandPreviewHeight = dragPreview?.kind === "add-row" ? layout.tableHeight + dragPreview.previewRows * layout.avgRowHeight : layout.tableHeight;
29368
29614
  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;
29369
29615
  return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(import_jsx_runtime82.Fragment, { children: [
29370
- layout.rowHandles.map((rowHandle) => /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "absolute z-30", style: { top: Math.max(8, rowHandle.center - 12), left: rowHandleLeft }, children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
29371
- DropdownMenu,
29372
- {
29373
- placement: "right",
29374
- items: getRowHandleMenuItems(rowHandle),
29375
- trigger: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
29376
- "button",
29377
- {
29378
- type: "button",
29379
- "aria-label": `${t("tableMenu.dragRow")} ${rowHandle.index + 1}`,
29380
- title: `${t("tableMenu.dragRow")} ${rowHandle.index + 1}`,
29381
- onMouseDown: (event) => {
29382
- event.preventDefault();
29383
- event.stopPropagation();
29384
- dragStateRef.current = {
29385
- kind: "row",
29386
- originIndex: rowHandle.index,
29387
- targetIndex: rowHandle.index,
29388
- anchorPos: rowHandle.cellPos
29389
- };
29390
- setDragPreview({
29391
- kind: "row",
29392
- originIndex: rowHandle.index,
29393
- targetIndex: rowHandle.index,
29394
- targetStart: rowHandle.start,
29395
- targetSize: rowHandle.size
29396
- });
29397
- document.body.style.cursor = "grabbing";
29398
- },
29399
- className: cn(
29400
- "inline-flex h-6 w-6 items-center justify-center rounded-full",
29401
- "border border-border/70 bg-background/95 text-muted-foreground shadow-sm backdrop-blur",
29402
- "transition-colors hover:bg-accent hover:text-foreground"
29403
- ),
29404
- children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react47.GripVertical, { className: "h-3.5 w-3.5" })
29405
- }
29406
- )
29407
- }
29408
- ) }, `row-handle-${rowHandle.index}`)),
29409
- layout.columnHandles.map((columnHandle) => /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "absolute z-30", style: { top: columnHandleTop, left: Math.max(8, columnHandle.center - 12) }, children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
29410
- DropdownMenu,
29411
- {
29412
- placement: "bottom-start",
29413
- items: getColumnHandleMenuItems(columnHandle),
29414
- trigger: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
29415
- "button",
29416
- {
29417
- type: "button",
29418
- "aria-label": `${t("tableMenu.dragColumn")} ${columnHandle.index + 1}`,
29419
- title: `${t("tableMenu.dragColumn")} ${columnHandle.index + 1}`,
29420
- onMouseDown: (event) => {
29421
- event.preventDefault();
29422
- event.stopPropagation();
29423
- dragStateRef.current = {
29424
- kind: "column",
29425
- originIndex: columnHandle.index,
29426
- targetIndex: columnHandle.index,
29427
- anchorPos: columnHandle.cellPos
29428
- };
29429
- setDragPreview({
29430
- kind: "column",
29431
- originIndex: columnHandle.index,
29432
- targetIndex: columnHandle.index,
29433
- targetStart: columnHandle.start,
29434
- targetSize: columnHandle.size
29435
- });
29436
- document.body.style.cursor = "grabbing";
29437
- },
29438
- className: cn(
29439
- "inline-flex h-6 w-6 items-center justify-center rounded-full",
29440
- "border border-border/70 bg-background/95 text-muted-foreground shadow-sm backdrop-blur",
29441
- "transition-colors hover:bg-accent hover:text-foreground"
29442
- ),
29443
- children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react47.GripHorizontal, { className: "h-3.5 w-3.5" })
29444
- }
29445
- )
29446
- }
29447
- ) }, `column-handle-${columnHandle.index}`)),
29448
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "pointer-events-none absolute z-30", style: { top: menuTop, left: menuLeft }, children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
29449
- DropdownMenu,
29616
+ layout.rowHandles.map((rowHandle) => {
29617
+ const visible = controlsVisible || hoverState.rowHandleIndex === rowHandle.index;
29618
+ if (!visible) return null;
29619
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
29620
+ "div",
29621
+ {
29622
+ className: "absolute z-30",
29623
+ style: {
29624
+ top: Math.max(8, rowHandle.center - 12),
29625
+ left: rowHandleLeft
29626
+ },
29627
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
29628
+ DropdownMenu,
29629
+ {
29630
+ placement: "right",
29631
+ items: getRowHandleMenuItems(rowHandle),
29632
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
29633
+ "button",
29634
+ {
29635
+ type: "button",
29636
+ "aria-label": `${t("tableMenu.dragRow")} ${rowHandle.index + 1}`,
29637
+ title: `${t("tableMenu.dragRow")} ${rowHandle.index + 1}`,
29638
+ onMouseDown: (event) => {
29639
+ event.preventDefault();
29640
+ event.stopPropagation();
29641
+ dragStateRef.current = {
29642
+ kind: "row",
29643
+ originIndex: rowHandle.index,
29644
+ targetIndex: rowHandle.index,
29645
+ anchorPos: rowHandle.cellPos
29646
+ };
29647
+ setDragPreview({
29648
+ kind: "row",
29649
+ originIndex: rowHandle.index,
29650
+ targetIndex: rowHandle.index,
29651
+ targetStart: rowHandle.start,
29652
+ targetSize: rowHandle.size
29653
+ });
29654
+ document.body.style.cursor = "grabbing";
29655
+ },
29656
+ className: cn(
29657
+ "inline-flex h-6 w-6 items-center justify-center rounded-full",
29658
+ "border border-border/70 bg-background/95 text-muted-foreground shadow-sm backdrop-blur",
29659
+ "transition-[opacity,transform,colors] duration-150 hover:bg-accent hover:text-foreground"
29660
+ ),
29661
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react47.GripVertical, { className: "h-3.5 w-3.5" })
29662
+ }
29663
+ )
29664
+ }
29665
+ )
29666
+ },
29667
+ `row-handle-${rowHandle.index}`
29668
+ );
29669
+ }),
29670
+ layout.columnHandles.map((columnHandle) => {
29671
+ const visible = controlsVisible || hoverState.columnHandleIndex === columnHandle.index;
29672
+ if (!visible) return null;
29673
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
29674
+ "div",
29675
+ {
29676
+ className: "absolute z-30",
29677
+ style: {
29678
+ top: columnHandleTop,
29679
+ left: Math.max(8, columnHandle.center - 12)
29680
+ },
29681
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
29682
+ DropdownMenu,
29683
+ {
29684
+ placement: "bottom-start",
29685
+ items: getColumnHandleMenuItems(columnHandle),
29686
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
29687
+ "button",
29688
+ {
29689
+ type: "button",
29690
+ "aria-label": `${t("tableMenu.dragColumn")} ${columnHandle.index + 1}`,
29691
+ title: `${t("tableMenu.dragColumn")} ${columnHandle.index + 1}`,
29692
+ onMouseDown: (event) => {
29693
+ event.preventDefault();
29694
+ event.stopPropagation();
29695
+ dragStateRef.current = {
29696
+ kind: "column",
29697
+ originIndex: columnHandle.index,
29698
+ targetIndex: columnHandle.index,
29699
+ anchorPos: columnHandle.cellPos
29700
+ };
29701
+ setDragPreview({
29702
+ kind: "column",
29703
+ originIndex: columnHandle.index,
29704
+ targetIndex: columnHandle.index,
29705
+ targetStart: columnHandle.start,
29706
+ targetSize: columnHandle.size
29707
+ });
29708
+ document.body.style.cursor = "grabbing";
29709
+ },
29710
+ className: cn(
29711
+ "inline-flex h-6 w-6 items-center justify-center rounded-full",
29712
+ "border border-border/70 bg-background/95 text-muted-foreground shadow-sm backdrop-blur",
29713
+ "transition-[opacity,transform,colors] duration-150 hover:bg-accent hover:text-foreground"
29714
+ ),
29715
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react47.GripHorizontal, { className: "h-3.5 w-3.5" })
29716
+ }
29717
+ )
29718
+ }
29719
+ )
29720
+ },
29721
+ `column-handle-${columnHandle.index}`
29722
+ );
29723
+ }),
29724
+ (controlsVisible || hoverState.menuVisible) && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
29725
+ "div",
29450
29726
  {
29451
- placement: "bottom-start",
29452
- items: menuItems,
29453
- trigger: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
29454
- "button",
29727
+ className: "absolute z-30",
29728
+ style: {
29729
+ top: menuTop,
29730
+ left: menuLeft
29731
+ },
29732
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
29733
+ DropdownMenu,
29455
29734
  {
29456
- type: "button",
29457
- "aria-label": t("tableMenu.openControls"),
29458
- title: t("tableMenu.openControls"),
29459
- onMouseDown: (event) => event.preventDefault(),
29460
- className: cn(
29461
- "pointer-events-auto inline-flex h-7 w-7 items-center justify-center rounded-full",
29462
- "border border-border/70 bg-background/95 text-muted-foreground shadow-sm backdrop-blur",
29463
- "transition-colors hover:bg-accent hover:text-foreground"
29464
- ),
29465
- children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react47.MoreHorizontal, { className: "h-4 w-4" })
29735
+ placement: "bottom-start",
29736
+ items: menuItems,
29737
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
29738
+ "button",
29739
+ {
29740
+ type: "button",
29741
+ "aria-label": t("tableMenu.openControls"),
29742
+ title: t("tableMenu.openControls"),
29743
+ onMouseDown: (event) => event.preventDefault(),
29744
+ className: cn(
29745
+ "pointer-events-auto inline-flex h-7 w-7 items-center justify-center rounded-full",
29746
+ "border border-border/70 bg-background/95 text-muted-foreground shadow-sm backdrop-blur",
29747
+ "transition-[opacity,transform,colors] duration-150 hover:bg-accent hover:text-foreground"
29748
+ ),
29749
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_lucide_react47.MoreHorizontal, { className: "h-4 w-4" })
29750
+ }
29751
+ )
29466
29752
  }
29467
29753
  )
29468
29754
  }
29469
- ) }),
29470
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
29755
+ ),
29756
+ (controlsVisible || hoverState.addColumnVisible) && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
29471
29757
  "button",
29472
29758
  {
29473
29759
  type: "button",
@@ -29485,13 +29771,18 @@ function TableControls({ editor, containerRef }) {
29485
29771
  className: cn(
29486
29772
  "absolute z-30 inline-flex items-center justify-center rounded-md",
29487
29773
  "border border-border/70 bg-muted/40 text-muted-foreground shadow-sm backdrop-blur",
29488
- "transition-colors hover:bg-accent hover:text-foreground disabled:opacity-50 disabled:cursor-not-allowed"
29774
+ "transition-[opacity,transform,colors] duration-150 hover:bg-accent hover:text-foreground disabled:opacity-50 disabled:cursor-not-allowed"
29489
29775
  ),
29490
- style: { top: columnRailTop, left: columnRailLeft, width: 18, height: layout.tableHeight },
29776
+ style: {
29777
+ top: columnRailTop,
29778
+ left: columnRailLeft,
29779
+ width: 18,
29780
+ height: layout.tableHeight
29781
+ },
29491
29782
  children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "text-sm font-medium leading-none", children: "+" })
29492
29783
  }
29493
29784
  ),
29494
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
29785
+ (controlsVisible || hoverState.addRowVisible) && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
29495
29786
  "button",
29496
29787
  {
29497
29788
  type: "button",
@@ -29509,9 +29800,14 @@ function TableControls({ editor, containerRef }) {
29509
29800
  className: cn(
29510
29801
  "absolute z-30 inline-flex items-center justify-center rounded-md",
29511
29802
  "border border-border/70 bg-muted/40 text-muted-foreground shadow-sm backdrop-blur",
29512
- "transition-colors hover:bg-accent hover:text-foreground disabled:opacity-50 disabled:cursor-not-allowed"
29803
+ "transition-[opacity,transform,colors] duration-150 hover:bg-accent hover:text-foreground disabled:opacity-50 disabled:cursor-not-allowed"
29513
29804
  ),
29514
- style: { top: rowRailTop, left: rowRailLeft, width: layout.tableWidth, height: 16 },
29805
+ style: {
29806
+ top: rowRailTop,
29807
+ left: rowRailLeft,
29808
+ width: layout.tableWidth,
29809
+ height: 16
29810
+ },
29515
29811
  children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "text-sm font-medium leading-none", children: "+" })
29516
29812
  }
29517
29813
  ),
@@ -29646,6 +29942,19 @@ function resolveEventElement(target) {
29646
29942
  if (target instanceof Node) return target.parentElement;
29647
29943
  return null;
29648
29944
  }
29945
+ function getSelectionTableCell(view) {
29946
+ const browserSelection = window.getSelection();
29947
+ const anchorElement = resolveEventElement(browserSelection?.anchorNode ?? null);
29948
+ const anchorCell = anchorElement?.closest?.("th,td");
29949
+ if (anchorCell instanceof HTMLElement) {
29950
+ return anchorCell;
29951
+ }
29952
+ const { from } = view.state.selection;
29953
+ const domAtPos = view.domAtPos(from);
29954
+ const element = resolveEventElement(domAtPos.node);
29955
+ const cell = element?.closest?.("th,td");
29956
+ return cell instanceof HTMLElement ? cell : null;
29957
+ }
29649
29958
  function isRowResizeHotspot(cell, clientX, clientY) {
29650
29959
  const rect = cell.getBoundingClientRect();
29651
29960
  const nearBottom = rect.bottom - clientY <= TABLE_RESIZE_HIT_ZONE;
@@ -29672,7 +29981,17 @@ function getRelativeBoundaryMetrics(surface, table, row, cell) {
29672
29981
  columnRight: cellRect.right - surfaceRect.left + surface.scrollLeft
29673
29982
  };
29674
29983
  }
29675
- var UEditor = import_react52.default.forwardRef(({
29984
+ function getRelativeCellMetrics(surface, cell) {
29985
+ const surfaceRect = surface.getBoundingClientRect();
29986
+ const cellRect = cell.getBoundingClientRect();
29987
+ return {
29988
+ left: cellRect.left - surfaceRect.left + surface.scrollLeft,
29989
+ top: cellRect.top - surfaceRect.top + surface.scrollTop,
29990
+ width: cellRect.width,
29991
+ height: cellRect.height
29992
+ };
29993
+ }
29994
+ var UEditor = import_react53.default.forwardRef(({
29676
29995
  content = "",
29677
29996
  onChange,
29678
29997
  onHtmlChange,
@@ -29695,37 +30014,70 @@ var UEditor = import_react52.default.forwardRef(({
29695
30014
  }, ref) => {
29696
30015
  const t = useSmartTranslations("UEditor");
29697
30016
  const effectivePlaceholder = placeholder ?? t("placeholder");
29698
- const inFlightPrepareRef = (0, import_react52.useRef)(null);
29699
- const editorContentRef = (0, import_react52.useRef)(null);
29700
- const tableColumnGuideRef = (0, import_react52.useRef)(null);
29701
- const tableRowGuideRef = (0, import_react52.useRef)(null);
29702
- const rowResizeStateRef = (0, import_react52.useRef)(null);
29703
- const setEditorResizeCursor = import_react52.default.useCallback((cursor) => {
30017
+ const inFlightPrepareRef = (0, import_react53.useRef)(null);
30018
+ const editorContentRef = (0, import_react53.useRef)(null);
30019
+ const tableColumnGuideRef = (0, import_react53.useRef)(null);
30020
+ const tableRowGuideRef = (0, import_react53.useRef)(null);
30021
+ const activeTableCellHighlightRef = (0, import_react53.useRef)(null);
30022
+ const hoveredTableCellRef = (0, import_react53.useRef)(null);
30023
+ const activeTableCellRef = (0, import_react53.useRef)(null);
30024
+ const rowResizeStateRef = (0, import_react53.useRef)(null);
30025
+ const setEditorResizeCursor = import_react53.default.useCallback((cursor) => {
29704
30026
  const proseMirror = editorContentRef.current?.querySelector(".ProseMirror");
29705
30027
  if (proseMirror) {
29706
30028
  proseMirror.style.cursor = cursor;
29707
30029
  }
29708
30030
  }, []);
29709
- const hideColumnGuide = import_react52.default.useCallback(() => {
30031
+ const hideColumnGuide = import_react53.default.useCallback(() => {
29710
30032
  editorContentRef.current?.classList.remove("resize-cursor");
29711
30033
  const guide = tableColumnGuideRef.current;
29712
30034
  if (guide) {
29713
30035
  guide.style.opacity = "0";
29714
30036
  }
29715
30037
  }, []);
29716
- const hideRowGuide = import_react52.default.useCallback(() => {
30038
+ const hideRowGuide = import_react53.default.useCallback(() => {
29717
30039
  editorContentRef.current?.classList.remove("resize-row-cursor");
29718
30040
  const guide = tableRowGuideRef.current;
29719
30041
  if (guide) {
29720
30042
  guide.style.opacity = "0";
29721
30043
  }
29722
30044
  }, []);
29723
- const clearAllTableResizeHover = import_react52.default.useCallback(() => {
30045
+ const clearAllTableResizeHover = import_react53.default.useCallback(() => {
29724
30046
  setEditorResizeCursor("");
29725
30047
  hideColumnGuide();
29726
30048
  hideRowGuide();
29727
30049
  }, [hideColumnGuide, hideRowGuide, setEditorResizeCursor]);
29728
- const showColumnGuide = import_react52.default.useCallback((table, row, cell) => {
30050
+ const updateActiveCellHighlight = import_react53.default.useCallback((cell) => {
30051
+ const surface = editorContentRef.current;
30052
+ const highlight = activeTableCellHighlightRef.current;
30053
+ if (!highlight) return;
30054
+ if (!surface || !cell) {
30055
+ highlight.style.display = "none";
30056
+ return;
30057
+ }
30058
+ const metrics = getRelativeCellMetrics(surface, cell);
30059
+ highlight.style.display = "block";
30060
+ highlight.style.left = `${metrics.left}px`;
30061
+ highlight.style.top = `${metrics.top}px`;
30062
+ highlight.style.width = `${metrics.width}px`;
30063
+ highlight.style.height = `${metrics.height}px`;
30064
+ }, []);
30065
+ const setActiveTableCell = import_react53.default.useCallback((cell) => {
30066
+ if (activeTableCellRef.current === cell) return;
30067
+ activeTableCellRef.current = cell;
30068
+ updateActiveCellHighlight(activeTableCellRef.current);
30069
+ }, [updateActiveCellHighlight]);
30070
+ const clearActiveTableCell = import_react53.default.useCallback(() => {
30071
+ activeTableCellRef.current = null;
30072
+ updateActiveCellHighlight(null);
30073
+ }, [updateActiveCellHighlight]);
30074
+ const setHoveredTableCell = import_react53.default.useCallback((cell) => {
30075
+ hoveredTableCellRef.current = cell;
30076
+ }, []);
30077
+ const clearHoveredTableCell = import_react53.default.useCallback(() => {
30078
+ hoveredTableCellRef.current = null;
30079
+ }, []);
30080
+ const showColumnGuide = import_react53.default.useCallback((table, row, cell) => {
29729
30081
  const surface = editorContentRef.current;
29730
30082
  const guide = tableColumnGuideRef.current;
29731
30083
  if (!surface || !guide) return;
@@ -29738,7 +30090,7 @@ var UEditor = import_react52.default.forwardRef(({
29738
30090
  surface.classList.add("resize-cursor");
29739
30091
  setEditorResizeCursor("col-resize");
29740
30092
  }, [setEditorResizeCursor]);
29741
- const showRowGuide = import_react52.default.useCallback((table, row, cell) => {
30093
+ const showRowGuide = import_react53.default.useCallback((table, row, cell) => {
29742
30094
  const surface = editorContentRef.current;
29743
30095
  const guide = tableRowGuideRef.current;
29744
30096
  if (!surface || !guide) return;
@@ -29751,11 +30103,11 @@ var UEditor = import_react52.default.forwardRef(({
29751
30103
  surface.classList.add("resize-row-cursor");
29752
30104
  setEditorResizeCursor("row-resize");
29753
30105
  }, [setEditorResizeCursor]);
29754
- const extensions = (0, import_react52.useMemo)(
30106
+ const extensions = (0, import_react53.useMemo)(
29755
30107
  () => buildUEditorExtensions({ placeholder: effectivePlaceholder, translate: t, maxCharacters, uploadImage, imageInsertMode, editable }),
29756
30108
  [effectivePlaceholder, t, maxCharacters, uploadImage, imageInsertMode, editable]
29757
30109
  );
29758
- const editor = (0, import_react53.useEditor)({
30110
+ const editor = (0, import_react54.useEditor)({
29759
30111
  immediatelyRender: false,
29760
30112
  extensions,
29761
30113
  content,
@@ -29906,7 +30258,11 @@ var UEditor = import_react52.default.forwardRef(({
29906
30258
  onJsonChange?.(editor2.getJSON());
29907
30259
  }
29908
30260
  });
29909
- (0, import_react52.useImperativeHandle)(
30261
+ const syncActiveTableCellFromSelection = import_react53.default.useCallback(() => {
30262
+ if (!editor) return;
30263
+ setActiveTableCell(getSelectionTableCell(editor.view));
30264
+ }, [editor, setActiveTableCell]);
30265
+ (0, import_react53.useImperativeHandle)(
29910
30266
  ref,
29911
30267
  () => ({
29912
30268
  prepareContentForSave: async ({ throwOnError = false } = {}) => {
@@ -29928,19 +30284,37 @@ var UEditor = import_react52.default.forwardRef(({
29928
30284
  }),
29929
30285
  [content, editor, uploadImageForSave]
29930
30286
  );
29931
- (0, import_react52.useEffect)(() => {
30287
+ (0, import_react53.useEffect)(() => {
29932
30288
  if (editor && content !== editor.getHTML()) {
29933
30289
  if (editor.isEmpty && content) {
29934
30290
  editor.commands.setContent(content);
29935
30291
  }
29936
30292
  }
29937
30293
  }, [content, editor]);
29938
- (0, import_react52.useEffect)(() => {
30294
+ (0, import_react53.useEffect)(() => {
29939
30295
  if (!editor) return void 0;
29940
30296
  const proseMirror = editor.view.dom;
30297
+ const surface = editorContentRef.current;
30298
+ let selectionSyncTimeoutId = 0;
30299
+ const scheduleActiveCellSync = (fallbackCell = null) => {
30300
+ requestAnimationFrame(() => {
30301
+ setActiveTableCell(getSelectionTableCell(editor.view) ?? fallbackCell);
30302
+ });
30303
+ window.clearTimeout(selectionSyncTimeoutId);
30304
+ selectionSyncTimeoutId = window.setTimeout(() => {
30305
+ setActiveTableCell(getSelectionTableCell(editor.view) ?? fallbackCell);
30306
+ }, 0);
30307
+ };
30308
+ const handleSelectionChange = () => {
30309
+ scheduleActiveCellSync();
30310
+ };
30311
+ const handleActiveCellLayoutChange = () => {
30312
+ updateActiveCellHighlight(activeTableCellRef.current);
30313
+ };
29941
30314
  const handleEditorMouseMove = (event) => {
29942
30315
  const activeRowResize = rowResizeStateRef.current;
29943
30316
  if (activeRowResize) {
30317
+ setHoveredTableCell(activeRowResize.cellElement);
29944
30318
  showRowGuide(activeRowResize.tableElement, activeRowResize.rowElement, activeRowResize.cellElement);
29945
30319
  return;
29946
30320
  }
@@ -29951,12 +30325,15 @@ var UEditor = import_react52.default.forwardRef(({
29951
30325
  }
29952
30326
  const cell = target.closest("th,td");
29953
30327
  if (!(cell instanceof HTMLElement)) {
30328
+ clearHoveredTableCell();
29954
30329
  clearAllTableResizeHover();
29955
30330
  return;
29956
30331
  }
30332
+ setHoveredTableCell(cell);
29957
30333
  const row = cell.closest("tr");
29958
30334
  const table = cell.closest("table");
29959
30335
  if (!(row instanceof HTMLTableRowElement) || !(table instanceof HTMLTableElement)) {
30336
+ clearHoveredTableCell();
29960
30337
  clearAllTableResizeHover();
29961
30338
  return;
29962
30339
  }
@@ -29975,6 +30352,7 @@ var UEditor = import_react52.default.forwardRef(({
29975
30352
  clearAllTableResizeHover();
29976
30353
  };
29977
30354
  const handleEditorMouseLeave = () => {
30355
+ clearHoveredTableCell();
29978
30356
  if (!rowResizeStateRef.current) {
29979
30357
  clearAllTableResizeHover();
29980
30358
  }
@@ -29982,15 +30360,24 @@ var UEditor = import_react52.default.forwardRef(({
29982
30360
  const handleEditorMouseDown = (event) => {
29983
30361
  if (event.button !== 0) return;
29984
30362
  const target = resolveEventElement(event.target);
29985
- if (!(target instanceof Element)) return;
30363
+ if (!(target instanceof Element)) {
30364
+ clearActiveTableCell();
30365
+ return;
30366
+ }
29986
30367
  const cell = target.closest("th,td");
29987
- if (!(cell instanceof HTMLTableCellElement)) return;
30368
+ if (!(cell instanceof HTMLTableCellElement)) {
30369
+ clearActiveTableCell();
30370
+ return;
30371
+ }
30372
+ setActiveTableCell(cell);
30373
+ scheduleActiveCellSync(cell);
29988
30374
  const row = cell.closest("tr");
29989
30375
  const table = cell.closest("table");
29990
30376
  if (!(row instanceof HTMLTableRowElement) || !(table instanceof HTMLTableElement)) return;
29991
30377
  if (!isRowResizeHotspot(cell, event.clientX, event.clientY)) {
29992
30378
  return;
29993
30379
  }
30380
+ setHoveredTableCell(cell);
29994
30381
  const rowInfo = findTableRowNodeInfo(editor.view, row);
29995
30382
  if (!rowInfo) return;
29996
30383
  rowResizeStateRef.current = {
@@ -30051,6 +30438,7 @@ var UEditor = import_react52.default.forwardRef(({
30051
30438
  clearPreviewRowHeight(state.rowElement);
30052
30439
  rowResizeStateRef.current = null;
30053
30440
  document.body.style.cursor = "";
30441
+ clearHoveredTableCell();
30054
30442
  clearAllTableResizeHover();
30055
30443
  };
30056
30444
  const handleWindowBlur = () => {
@@ -30059,30 +30447,53 @@ var UEditor = import_react52.default.forwardRef(({
30059
30447
  clearPreviewRowHeight(state.rowElement);
30060
30448
  rowResizeStateRef.current = null;
30061
30449
  document.body.style.cursor = "";
30450
+ clearHoveredTableCell();
30062
30451
  clearAllTableResizeHover();
30063
30452
  };
30064
30453
  proseMirror.addEventListener("mousemove", handleEditorMouseMove);
30065
30454
  proseMirror.addEventListener("mouseleave", handleEditorMouseLeave);
30066
30455
  proseMirror.addEventListener("mousedown", handleEditorMouseDown);
30456
+ proseMirror.addEventListener("click", handleSelectionChange);
30457
+ proseMirror.addEventListener("mouseup", handleSelectionChange);
30458
+ proseMirror.addEventListener("keyup", handleSelectionChange);
30459
+ proseMirror.addEventListener("focusin", handleSelectionChange);
30460
+ document.addEventListener("selectionchange", handleSelectionChange);
30461
+ surface?.addEventListener("scroll", handleActiveCellLayoutChange, { passive: true });
30462
+ window.addEventListener("resize", handleActiveCellLayoutChange);
30067
30463
  window.addEventListener("mousemove", handlePointerMove);
30068
30464
  document.addEventListener("pointermove", handlePointerMove);
30069
30465
  window.addEventListener("mouseup", handlePointerUp);
30070
30466
  document.addEventListener("pointerup", handlePointerUp);
30071
30467
  window.addEventListener("blur", handleWindowBlur);
30468
+ editor.on("selectionUpdate", syncActiveTableCellFromSelection);
30469
+ editor.on("focus", syncActiveTableCellFromSelection);
30470
+ syncActiveTableCellFromSelection();
30072
30471
  return () => {
30073
30472
  proseMirror.removeEventListener("mousemove", handleEditorMouseMove);
30074
30473
  proseMirror.removeEventListener("mouseleave", handleEditorMouseLeave);
30075
30474
  proseMirror.removeEventListener("mousedown", handleEditorMouseDown);
30475
+ proseMirror.removeEventListener("click", handleSelectionChange);
30476
+ proseMirror.removeEventListener("mouseup", handleSelectionChange);
30477
+ proseMirror.removeEventListener("keyup", handleSelectionChange);
30478
+ proseMirror.removeEventListener("focusin", handleSelectionChange);
30479
+ document.removeEventListener("selectionchange", handleSelectionChange);
30480
+ surface?.removeEventListener("scroll", handleActiveCellLayoutChange);
30481
+ window.removeEventListener("resize", handleActiveCellLayoutChange);
30076
30482
  window.removeEventListener("mousemove", handlePointerMove);
30077
30483
  document.removeEventListener("pointermove", handlePointerMove);
30078
30484
  window.removeEventListener("mouseup", handlePointerUp);
30079
30485
  document.removeEventListener("pointerup", handlePointerUp);
30080
30486
  window.removeEventListener("blur", handleWindowBlur);
30487
+ editor.off("selectionUpdate", syncActiveTableCellFromSelection);
30488
+ editor.off("focus", syncActiveTableCellFromSelection);
30489
+ window.clearTimeout(selectionSyncTimeoutId);
30081
30490
  document.body.style.cursor = "";
30491
+ clearActiveTableCell();
30492
+ clearHoveredTableCell();
30082
30493
  clearAllTableResizeHover();
30083
30494
  rowResizeStateRef.current = null;
30084
30495
  };
30085
- }, [clearAllTableResizeHover, editor, hideColumnGuide, hideRowGuide, showColumnGuide, showRowGuide]);
30496
+ }, [clearActiveTableCell, clearAllTableResizeHover, clearHoveredTableCell, editor, hideColumnGuide, hideRowGuide, setHoveredTableCell, showColumnGuide, showRowGuide, syncActiveTableCellFromSelection, updateActiveCellHighlight]);
30086
30497
  if (!editor) {
30087
30498
  return /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
30088
30499
  "div",
@@ -30134,9 +30545,17 @@ var UEditor = import_react52.default.forwardRef(({
30134
30545
  className: "pointer-events-none absolute z-20 bg-primary opacity-0 transition-opacity duration-100"
30135
30546
  }
30136
30547
  ),
30548
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
30549
+ "span",
30550
+ {
30551
+ ref: activeTableCellHighlightRef,
30552
+ "aria-hidden": "true",
30553
+ 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"
30554
+ }
30555
+ ),
30137
30556
  editable && /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(TableControls, { editor, containerRef: editorContentRef }),
30138
30557
  /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
30139
- import_react53.EditorContent,
30558
+ import_react54.EditorContent,
30140
30559
  {
30141
30560
  editor,
30142
30561
  className: "min-h-full"