@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/api-reference.json +1 -1
- package/dist/index.cjs +730 -311
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +646 -227
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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.
|
|
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:
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
20966
|
+
var import_react33 = __toESM(require("react"), 1);
|
|
20876
20967
|
function useDebounced(value, delay = 300) {
|
|
20877
|
-
const [debounced, setDebounced] =
|
|
20878
|
-
|
|
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
|
|
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 =
|
|
20915
|
-
const allLeafColumns =
|
|
20916
|
-
const columnMap =
|
|
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 =
|
|
21010
|
+
const visibleColumns = import_react34.default.useMemo(() => {
|
|
20920
21011
|
return filterVisibleColumns(columns, visibleColsSet);
|
|
20921
21012
|
}, [columns, visibleColsSet]);
|
|
20922
|
-
const leafColumns =
|
|
21013
|
+
const leafColumns = import_react34.default.useMemo(() => {
|
|
20923
21014
|
return getLeafColumnsWithFixedInheritance(visibleColumns);
|
|
20924
21015
|
}, [visibleColumns]);
|
|
20925
|
-
const headerRows =
|
|
20926
|
-
const totalColumnsWidth =
|
|
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 =
|
|
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 =
|
|
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
|
|
21068
|
+
var import_react36 = __toESM(require("react"), 1);
|
|
20978
21069
|
|
|
20979
21070
|
// src/components/DataTable/hooks/usePageSizeStorage.ts
|
|
20980
|
-
var
|
|
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 =
|
|
20994
|
-
const [overrideState, setOverrideState] =
|
|
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 =
|
|
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 =
|
|
21032
|
-
const defaultVisibleLeafKeys =
|
|
21033
|
-
const knownLeafKeysRef =
|
|
21034
|
-
const [headerAlign, setHeaderAlign] =
|
|
21035
|
-
const [visibleCols, setVisibleCols] =
|
|
21036
|
-
const [filters, setFilters] =
|
|
21037
|
-
const [sort, setSort] =
|
|
21038
|
-
const [density, setDensity] =
|
|
21039
|
-
const [curPage, setCurPage] =
|
|
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
|
-
|
|
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
|
-
|
|
21140
|
+
import_react36.default.useEffect(() => {
|
|
21050
21141
|
setCurPage(page);
|
|
21051
21142
|
}, [page]);
|
|
21052
|
-
|
|
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
|
|
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 } =
|
|
21122
|
-
const getStickyColumnStyle =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
21469
|
+
import_react38.default.useEffect(() => {
|
|
21313
21470
|
if (process.env.NODE_ENV === "development") {
|
|
21314
|
-
const warnings = validateColumns(
|
|
21471
|
+
const warnings = validateColumns(columnsWithWidthOverrides);
|
|
21315
21472
|
warnings.forEach((w) => console.warn(`[DataTable] ${w}`));
|
|
21316
21473
|
}
|
|
21317
|
-
}, [
|
|
21474
|
+
}, [columnsWithWidthOverrides]);
|
|
21318
21475
|
const debouncedFilters = useDebounced(filters, 350);
|
|
21319
21476
|
const isServerMode = Boolean(onQueryChange);
|
|
21320
|
-
const hasEmittedQuery =
|
|
21321
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
21496
|
-
const itemContext =
|
|
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 =
|
|
21513
|
-
var FormItem =
|
|
21514
|
-
const id =
|
|
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 =
|
|
21708
|
+
var FormLabel = React63.forwardRef(
|
|
21519
21709
|
({ className, children, required, ...props }, ref) => {
|
|
21520
21710
|
const { error, formItemId } = useFormField();
|
|
21521
|
-
const config =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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,
|
|
21876
|
+
const [isOpen, setIsOpen] = (0, import_react39.useState)(false);
|
|
21687
21877
|
const isHydrated = useHydrated();
|
|
21688
|
-
const triggerRef = (0,
|
|
21689
|
-
const [dropdownPosition, setDropdownPosition] = (0,
|
|
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
|
|
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,
|
|
21790
|
-
const [dropdownPosition, setDropdownPosition] = (0,
|
|
21791
|
-
const triggerButtonRef = (0,
|
|
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
|
|
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
|
|
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
|
|
21936
|
-
var
|
|
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
|
|
21975
|
-
var
|
|
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] =
|
|
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 =
|
|
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,
|
|
22337
|
+
var SlashCommandList = (0, import_react42.forwardRef)((props, ref) => {
|
|
22148
22338
|
const [selectedIndex, setSelectedIndex] = useResettingIndex2(props.items);
|
|
22149
|
-
const listRef = (0,
|
|
22150
|
-
(0,
|
|
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,
|
|
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
|
|
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
|
|
22575
|
+
var import_react43 = require("@tiptap/react");
|
|
22386
22576
|
var import_state2 = require("@tiptap/pm/state");
|
|
22387
|
-
var
|
|
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] =
|
|
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 =
|
|
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,
|
|
22595
|
+
var EmojiList = (0, import_react44.forwardRef)((props, ref) => {
|
|
22406
22596
|
const [selectedIndex, setSelectedIndex] = useResettingIndex3(props.items);
|
|
22407
|
-
(0,
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
22662
|
-
const imgRef = (0,
|
|
22663
|
-
const [isHovered, setIsHovered] = (0,
|
|
22664
|
-
const [isResizing, setIsResizing] = (0,
|
|
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,
|
|
22671
|
-
(0,
|
|
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
|
-
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
23209
|
-
const inputRef = (0,
|
|
23210
|
-
(0,
|
|
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,
|
|
23238
|
-
const [alt, setAlt] = (0,
|
|
23239
|
-
const inputRef = (0,
|
|
23240
|
-
(0,
|
|
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
|
|
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,
|
|
23308
|
-
const [activeCategory, setActiveCategory] = (0,
|
|
23309
|
-
const scrollContainerRef = (0,
|
|
23310
|
-
const categoryRefs = (0,
|
|
23311
|
-
const isUserScrolling = (0,
|
|
23312
|
-
const filteredCategories = (0,
|
|
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,
|
|
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,
|
|
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 =
|
|
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,
|
|
23524
|
-
const fileInputRef = (0,
|
|
23525
|
-
const [isUploadingImage, setIsUploadingImage] = (0,
|
|
23526
|
-
const [imageUploadError, setImageUploadError] = (0,
|
|
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
|
|
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,
|
|
24083
|
-
const items = (0,
|
|
24084
|
-
const listRef = (0,
|
|
24085
|
-
(0,
|
|
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,
|
|
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,
|
|
24139
|
-
const [showEditorColorPalette, setShowEditorColorPalette] = (0,
|
|
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,
|
|
24334
|
+
(0, import_react51.useEffect)(() => {
|
|
24145
24335
|
onKeepOpenChange?.(showLinkInput);
|
|
24146
24336
|
}, [onKeepOpenChange, showLinkInput]);
|
|
24147
|
-
(0,
|
|
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,
|
|
24286
|
-
const [position, setPosition] = (0,
|
|
24287
|
-
const menuRef = (0,
|
|
24288
|
-
const keepOpenRef = (0,
|
|
24289
|
-
const showTimeoutRef = (0,
|
|
24290
|
-
const setKeepOpen = (0,
|
|
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,
|
|
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,
|
|
24368
|
-
const [position, setPosition] = (0,
|
|
24369
|
-
(0,
|
|
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
|
|
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] =
|
|
29004
|
-
const [dragPreview, setDragPreview] =
|
|
29005
|
-
const
|
|
29006
|
-
const
|
|
29007
|
-
|
|
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 =
|
|
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 =
|
|
29228
|
+
const syncFromSelection = import_react52.default.useCallback(() => {
|
|
29019
29229
|
syncFromCell(getSelectedCell(editor));
|
|
29020
29230
|
}, [editor, syncFromCell]);
|
|
29021
|
-
const refreshCurrentLayout =
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
29331
|
+
const runAtCornerCell = import_react52.default.useCallback((command, options) => {
|
|
29087
29332
|
return runAtCellPos(getCurrentCornerCellPos(), command, options);
|
|
29088
29333
|
}, [getCurrentCornerCellPos, runAtCellPos]);
|
|
29089
|
-
const replaceTableAtCellPos =
|
|
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 =
|
|
29344
|
+
const createEmptyCellNode = import_react52.default.useCallback((cellNode) => {
|
|
29100
29345
|
return cellNode.type.createAndFill(cellNode.attrs) ?? cellNode;
|
|
29101
29346
|
}, []);
|
|
29102
|
-
const duplicateRowAt =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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) =>
|
|
29371
|
-
|
|
29372
|
-
|
|
29373
|
-
|
|
29374
|
-
|
|
29375
|
-
|
|
29376
|
-
"
|
|
29377
|
-
{
|
|
29378
|
-
|
|
29379
|
-
|
|
29380
|
-
|
|
29381
|
-
|
|
29382
|
-
|
|
29383
|
-
|
|
29384
|
-
|
|
29385
|
-
|
|
29386
|
-
|
|
29387
|
-
|
|
29388
|
-
|
|
29389
|
-
|
|
29390
|
-
|
|
29391
|
-
|
|
29392
|
-
|
|
29393
|
-
|
|
29394
|
-
|
|
29395
|
-
|
|
29396
|
-
|
|
29397
|
-
|
|
29398
|
-
|
|
29399
|
-
|
|
29400
|
-
|
|
29401
|
-
|
|
29402
|
-
|
|
29403
|
-
|
|
29404
|
-
|
|
29405
|
-
|
|
29406
|
-
|
|
29407
|
-
|
|
29408
|
-
|
|
29409
|
-
|
|
29410
|
-
|
|
29411
|
-
|
|
29412
|
-
|
|
29413
|
-
|
|
29414
|
-
|
|
29415
|
-
|
|
29416
|
-
|
|
29417
|
-
|
|
29418
|
-
|
|
29419
|
-
|
|
29420
|
-
|
|
29421
|
-
|
|
29422
|
-
|
|
29423
|
-
|
|
29424
|
-
|
|
29425
|
-
|
|
29426
|
-
|
|
29427
|
-
|
|
29428
|
-
|
|
29429
|
-
|
|
29430
|
-
|
|
29431
|
-
|
|
29432
|
-
|
|
29433
|
-
|
|
29434
|
-
|
|
29435
|
-
|
|
29436
|
-
|
|
29437
|
-
|
|
29438
|
-
|
|
29439
|
-
|
|
29440
|
-
|
|
29441
|
-
|
|
29442
|
-
|
|
29443
|
-
|
|
29444
|
-
|
|
29445
|
-
|
|
29446
|
-
|
|
29447
|
-
|
|
29448
|
-
|
|
29449
|
-
|
|
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
|
-
|
|
29452
|
-
|
|
29453
|
-
|
|
29454
|
-
|
|
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
|
-
|
|
29457
|
-
|
|
29458
|
-
|
|
29459
|
-
|
|
29460
|
-
|
|
29461
|
-
|
|
29462
|
-
|
|
29463
|
-
|
|
29464
|
-
|
|
29465
|
-
|
|
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: {
|
|
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: {
|
|
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
|
-
|
|
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,
|
|
29699
|
-
const editorContentRef = (0,
|
|
29700
|
-
const tableColumnGuideRef = (0,
|
|
29701
|
-
const tableRowGuideRef = (0,
|
|
29702
|
-
const
|
|
29703
|
-
const
|
|
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 =
|
|
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 =
|
|
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 =
|
|
30045
|
+
const clearAllTableResizeHover = import_react53.default.useCallback(() => {
|
|
29724
30046
|
setEditorResizeCursor("");
|
|
29725
30047
|
hideColumnGuide();
|
|
29726
30048
|
hideRowGuide();
|
|
29727
30049
|
}, [hideColumnGuide, hideRowGuide, setEditorResizeCursor]);
|
|
29728
|
-
const
|
|
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 =
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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))
|
|
30363
|
+
if (!(target instanceof Element)) {
|
|
30364
|
+
clearActiveTableCell();
|
|
30365
|
+
return;
|
|
30366
|
+
}
|
|
29986
30367
|
const cell = target.closest("th,td");
|
|
29987
|
-
if (!(cell instanceof HTMLTableCellElement))
|
|
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
|
-
|
|
30558
|
+
import_react54.EditorContent,
|
|
30140
30559
|
{
|
|
30141
30560
|
editor,
|
|
30142
30561
|
className: "min-h-full"
|