@xcelsior/ui-spreadsheets 1.3.5 → 1.4.0
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/.omc/state/idle-notif-cooldown.json +1 -1
- package/dist/index.d.mts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +250 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +271 -31
- package/dist/index.mjs.map +1 -1
- package/dist/styles/globals.css +40 -8
- package/dist/styles/globals.css.map +1 -1
- package/package.json +2 -2
- package/src/components/ColumnHeaderActions.tsx +37 -1
- package/src/components/Spreadsheet.tsx +20 -0
- package/src/components/SpreadsheetHeader.tsx +2 -0
- package/src/components/SpreadsheetSettingsModal.tsx +197 -5
- package/src/components/SpreadsheetToolbar.tsx +25 -0
- package/src/hooks/useSpreadsheetPinning.ts +13 -2
- package/src/types.ts +11 -0
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/components/Spreadsheet.tsx
|
|
2
|
-
import { useCallback as useCallback11, useEffect as useEffect8, useMemo as
|
|
2
|
+
import { useCallback as useCallback11, useEffect as useEffect8, useMemo as useMemo8, useRef as useRef10, useState as useState16, startTransition } from "react";
|
|
3
3
|
|
|
4
4
|
// ../../../node_modules/.pnpm/react-icons@4.12.0_react@18.3.1/node_modules/react-icons/lib/esm/iconBase.js
|
|
5
5
|
import React2 from "react";
|
|
@@ -96,6 +96,9 @@ function HiDotsVertical(props) {
|
|
|
96
96
|
function HiExclamation(props) {
|
|
97
97
|
return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 20 20", "fill": "currentColor", "aria-hidden": "true" }, "child": [{ "tag": "path", "attr": { "fillRule": "evenodd", "d": "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z", "clipRule": "evenodd" } }] })(props);
|
|
98
98
|
}
|
|
99
|
+
function HiEyeOff(props) {
|
|
100
|
+
return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 20 20", "fill": "currentColor", "aria-hidden": "true" }, "child": [{ "tag": "path", "attr": { "fillRule": "evenodd", "d": "M3.707 2.293a1 1 0 00-1.414 1.414l14 14a1 1 0 001.414-1.414l-1.473-1.473A10.014 10.014 0 0019.542 10C18.268 5.943 14.478 3 10 3a9.958 9.958 0 00-4.512 1.074l-1.78-1.781zm4.261 4.26l1.514 1.515a2.003 2.003 0 012.45 2.45l1.514 1.514a4 4 0 00-5.478-5.478z", "clipRule": "evenodd" } }, { "tag": "path", "attr": { "d": "M12.454 16.697L9.75 13.992a4 4 0 01-3.742-3.741L2.335 6.578A9.98 9.98 0 00.458 10c1.274 4.057 5.065 7 9.542 7 .847 0 1.669-.105 2.454-.303z" } }] })(props);
|
|
101
|
+
}
|
|
99
102
|
function HiEye(props) {
|
|
100
103
|
return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 20 20", "fill": "currentColor", "aria-hidden": "true" }, "child": [{ "tag": "path", "attr": { "d": "M10 12a2 2 0 100-4 2 2 0 000 4z" } }, { "tag": "path", "attr": { "fillRule": "evenodd", "d": "M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z", "clipRule": "evenodd" } }] })(props);
|
|
101
104
|
}
|
|
@@ -1324,6 +1327,9 @@ var SpreadsheetToolbar = ({
|
|
|
1324
1327
|
onClearFilter,
|
|
1325
1328
|
showFiltersPanel,
|
|
1326
1329
|
onToggleFiltersPanel,
|
|
1330
|
+
hiddenColumnCount = 0,
|
|
1331
|
+
onShowAllColumns,
|
|
1332
|
+
onManageColumns,
|
|
1327
1333
|
className
|
|
1328
1334
|
}) => {
|
|
1329
1335
|
const [showMoreMenu, setShowMoreMenu] = React3.useState(false);
|
|
@@ -1543,6 +1549,31 @@ var SpreadsheetToolbar = ({
|
|
|
1543
1549
|
]
|
|
1544
1550
|
}
|
|
1545
1551
|
),
|
|
1552
|
+
hiddenColumnCount > 0 && /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-1.5 px-2.5 py-1.5 bg-amber-50 border border-amber-200 rounded text-xs text-amber-700", children: [
|
|
1553
|
+
/* @__PURE__ */ jsxs4("span", { className: "font-medium", children: [
|
|
1554
|
+
hiddenColumnCount,
|
|
1555
|
+
" hidden"
|
|
1556
|
+
] }),
|
|
1557
|
+
/* @__PURE__ */ jsx4(
|
|
1558
|
+
"button",
|
|
1559
|
+
{
|
|
1560
|
+
type: "button",
|
|
1561
|
+
onClick: onShowAllColumns,
|
|
1562
|
+
className: "text-amber-800 underline hover:text-amber-900 transition-colors",
|
|
1563
|
+
children: "Show"
|
|
1564
|
+
}
|
|
1565
|
+
),
|
|
1566
|
+
/* @__PURE__ */ jsx4("span", { className: "text-amber-300", children: "|" }),
|
|
1567
|
+
/* @__PURE__ */ jsx4(
|
|
1568
|
+
"button",
|
|
1569
|
+
{
|
|
1570
|
+
type: "button",
|
|
1571
|
+
onClick: onManageColumns,
|
|
1572
|
+
className: "text-amber-800 underline hover:text-amber-900 transition-colors",
|
|
1573
|
+
children: "Manage"
|
|
1574
|
+
}
|
|
1575
|
+
)
|
|
1576
|
+
] }),
|
|
1546
1577
|
/* @__PURE__ */ jsxs4("div", { className: "relative", ref: menuRef, children: [
|
|
1547
1578
|
/* @__PURE__ */ jsxs4(
|
|
1548
1579
|
"button",
|
|
@@ -1644,7 +1675,7 @@ function MdOutlinePushPin(props) {
|
|
|
1644
1675
|
}
|
|
1645
1676
|
|
|
1646
1677
|
// src/components/ColumnHeaderActions.tsx
|
|
1647
|
-
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1678
|
+
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1648
1679
|
function ColumnHeaderActions({
|
|
1649
1680
|
enableFiltering = false,
|
|
1650
1681
|
enableHighlighting = false,
|
|
@@ -1666,7 +1697,8 @@ function ColumnHeaderActions({
|
|
|
1666
1697
|
resolvedWidth,
|
|
1667
1698
|
enableDuplicateCheck = false,
|
|
1668
1699
|
hasDuplicateCheck = false,
|
|
1669
|
-
onDuplicateCheckClick
|
|
1700
|
+
onDuplicateCheckClick,
|
|
1701
|
+
onHideClick
|
|
1670
1702
|
}) {
|
|
1671
1703
|
const [overflowOpen, setOverflowOpen] = useState3(false);
|
|
1672
1704
|
const overflowRef = useRef3(null);
|
|
@@ -1814,7 +1846,26 @@ function ColumnHeaderActions({
|
|
|
1814
1846
|
"Check Duplicates"
|
|
1815
1847
|
]
|
|
1816
1848
|
}
|
|
1817
|
-
)
|
|
1849
|
+
),
|
|
1850
|
+
onHideClick && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1851
|
+
/* @__PURE__ */ jsx5("div", { className: "border-t border-gray-100 my-1" }),
|
|
1852
|
+
/* @__PURE__ */ jsxs5(
|
|
1853
|
+
"button",
|
|
1854
|
+
{
|
|
1855
|
+
type: "button",
|
|
1856
|
+
onClick: (e) => {
|
|
1857
|
+
e.stopPropagation();
|
|
1858
|
+
onHideClick();
|
|
1859
|
+
setOverflowOpen(false);
|
|
1860
|
+
},
|
|
1861
|
+
className: "flex items-center gap-2 w-full px-3 py-1.5 text-xs hover:bg-gray-100 text-left text-gray-700",
|
|
1862
|
+
children: [
|
|
1863
|
+
/* @__PURE__ */ jsx5(HiEyeOff, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
1864
|
+
"Hide column"
|
|
1865
|
+
]
|
|
1866
|
+
}
|
|
1867
|
+
)
|
|
1868
|
+
] })
|
|
1818
1869
|
]
|
|
1819
1870
|
}
|
|
1820
1871
|
),
|
|
@@ -1902,6 +1953,19 @@ function ColumnHeaderActions({
|
|
|
1902
1953
|
title: "Check duplicates",
|
|
1903
1954
|
children: /* @__PURE__ */ jsx5(HiExclamation, { className: "h-3 w-3" })
|
|
1904
1955
|
}
|
|
1956
|
+
),
|
|
1957
|
+
onHideClick && /* @__PURE__ */ jsx5(
|
|
1958
|
+
"button",
|
|
1959
|
+
{
|
|
1960
|
+
type: "button",
|
|
1961
|
+
onClick: (e) => {
|
|
1962
|
+
e.stopPropagation();
|
|
1963
|
+
onHideClick();
|
|
1964
|
+
},
|
|
1965
|
+
className: "p-0.5 hover:bg-gray-200 rounded text-gray-400 opacity-0 group-hover:opacity-100 transition-opacity",
|
|
1966
|
+
title: "Hide column",
|
|
1967
|
+
children: /* @__PURE__ */ jsx5(HiEyeOff, { className: "h-3 w-3" })
|
|
1968
|
+
}
|
|
1905
1969
|
)
|
|
1906
1970
|
] });
|
|
1907
1971
|
}
|
|
@@ -1930,6 +1994,7 @@ var SpreadsheetHeader = ({
|
|
|
1930
1994
|
hasDuplicateCheck = false,
|
|
1931
1995
|
onDuplicateCheckClick,
|
|
1932
1996
|
duplicateCount,
|
|
1997
|
+
onHideClick,
|
|
1933
1998
|
resizeHandleProps,
|
|
1934
1999
|
resolvedWidth,
|
|
1935
2000
|
topOffset = 0,
|
|
@@ -2013,7 +2078,8 @@ var SpreadsheetHeader = ({
|
|
|
2013
2078
|
resolvedWidth,
|
|
2014
2079
|
enableDuplicateCheck: true,
|
|
2015
2080
|
hasDuplicateCheck,
|
|
2016
|
-
onDuplicateCheckClick
|
|
2081
|
+
onDuplicateCheckClick,
|
|
2082
|
+
onHideClick
|
|
2017
2083
|
}
|
|
2018
2084
|
)
|
|
2019
2085
|
] }),
|
|
@@ -2065,7 +2131,8 @@ function useSpreadsheetPinning({
|
|
|
2065
2131
|
showRowIndex = true,
|
|
2066
2132
|
defaultPinnedColumns = [],
|
|
2067
2133
|
defaultPinnedRightColumns = [],
|
|
2068
|
-
getColumnWidth
|
|
2134
|
+
getColumnWidth,
|
|
2135
|
+
hiddenColumns = []
|
|
2069
2136
|
}) {
|
|
2070
2137
|
const [pinnedColumns, setPinnedColumns] = useState4(() => {
|
|
2071
2138
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -2152,9 +2219,13 @@ function useSpreadsheetPinning({
|
|
|
2152
2219
|
return newSet;
|
|
2153
2220
|
});
|
|
2154
2221
|
}, []);
|
|
2222
|
+
const hiddenColumnsSet = useMemo(() => new Set(hiddenColumns), [hiddenColumns]);
|
|
2155
2223
|
const visibleColumns = useMemo(() => {
|
|
2156
2224
|
if (!columns || !Array.isArray(columns) || columns.length === 0) return [];
|
|
2157
2225
|
let result = [...columns];
|
|
2226
|
+
if (hiddenColumnsSet.size > 0) {
|
|
2227
|
+
result = result.filter((column) => !hiddenColumnsSet.has(column.id));
|
|
2228
|
+
}
|
|
2158
2229
|
if (columnGroups && Array.isArray(columnGroups)) {
|
|
2159
2230
|
result = result.filter((column) => {
|
|
2160
2231
|
const group = columnGroups.find((g) => g.columns.includes(column.id));
|
|
@@ -2164,7 +2235,7 @@ function useSpreadsheetPinning({
|
|
|
2164
2235
|
});
|
|
2165
2236
|
}
|
|
2166
2237
|
return result;
|
|
2167
|
-
}, [columns, columnGroups, collapsedGroups, pinnedColumns]);
|
|
2238
|
+
}, [columns, columnGroups, collapsedGroups, pinnedColumns, hiddenColumnsSet]);
|
|
2168
2239
|
useEffect4(() => {
|
|
2169
2240
|
requestAnimationFrame(() => measureColumnWidths());
|
|
2170
2241
|
}, [measureColumnWidths, visibleColumns, pinnedColumns]);
|
|
@@ -2418,7 +2489,7 @@ function ColorPickerPopover({
|
|
|
2418
2489
|
ColorPickerPopover.displayName = "ColorPickerPopover";
|
|
2419
2490
|
|
|
2420
2491
|
// src/components/SpreadsheetSettingsModal.tsx
|
|
2421
|
-
import { useState as useState6, useEffect as useEffect5 } from "react";
|
|
2492
|
+
import { useState as useState6, useEffect as useEffect5, useMemo as useMemo2 } from "react";
|
|
2422
2493
|
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
2423
2494
|
var DEFAULT_SETTINGS = {
|
|
2424
2495
|
defaultPinnedColumns: [],
|
|
@@ -2434,14 +2505,24 @@ var SpreadsheetSettingsModal = ({
|
|
|
2434
2505
|
settings,
|
|
2435
2506
|
onSave,
|
|
2436
2507
|
columns,
|
|
2508
|
+
columnGroups,
|
|
2437
2509
|
title = "Spreadsheet Settings",
|
|
2438
2510
|
pageSizeOptions = [25, 50, 100, 200]
|
|
2439
2511
|
}) => {
|
|
2440
|
-
const [activeTab, setActiveTab] = useState6("
|
|
2512
|
+
const [activeTab, setActiveTab] = useState6("visibility");
|
|
2441
2513
|
const [localSettings, setLocalSettings] = useState6(settings);
|
|
2442
2514
|
useEffect5(() => {
|
|
2443
2515
|
setLocalSettings(settings);
|
|
2444
2516
|
}, [settings]);
|
|
2517
|
+
const hiddenColumnsSet = useMemo2(
|
|
2518
|
+
() => new Set(localSettings.hiddenColumns ?? []),
|
|
2519
|
+
[localSettings.hiddenColumns]
|
|
2520
|
+
);
|
|
2521
|
+
const ungroupedColumns = useMemo2(() => {
|
|
2522
|
+
if (!columnGroups?.length) return columns;
|
|
2523
|
+
const groupedIds = new Set(columnGroups.flatMap((g) => g.columns));
|
|
2524
|
+
return columns.filter((c) => !groupedIds.has(c.id));
|
|
2525
|
+
}, [columns, columnGroups]);
|
|
2445
2526
|
if (!isOpen) return null;
|
|
2446
2527
|
const handleSave = () => {
|
|
2447
2528
|
onSave(localSettings);
|
|
@@ -2489,7 +2570,23 @@ var SpreadsheetSettingsModal = ({
|
|
|
2489
2570
|
onSave(newSettings);
|
|
2490
2571
|
}
|
|
2491
2572
|
};
|
|
2573
|
+
const hiddenCount = hiddenColumnsSet.size;
|
|
2574
|
+
const toggleColumnVisibility = (columnId) => {
|
|
2575
|
+
const isHidden = hiddenColumnsSet.has(columnId);
|
|
2576
|
+
const newHidden = isHidden ? (localSettings.hiddenColumns ?? []).filter((id) => id !== columnId) : [...localSettings.hiddenColumns ?? [], columnId];
|
|
2577
|
+
setLocalSettings({ ...localSettings, hiddenColumns: newHidden });
|
|
2578
|
+
};
|
|
2579
|
+
const setGroupVisibility = (groupColumnIds, visible) => {
|
|
2580
|
+
const currentHidden = new Set(localSettings.hiddenColumns ?? []);
|
|
2581
|
+
if (visible) {
|
|
2582
|
+
groupColumnIds.forEach((id) => currentHidden.delete(id));
|
|
2583
|
+
} else {
|
|
2584
|
+
groupColumnIds.forEach((id) => currentHidden.add(id));
|
|
2585
|
+
}
|
|
2586
|
+
setLocalSettings({ ...localSettings, hiddenColumns: Array.from(currentHidden) });
|
|
2587
|
+
};
|
|
2492
2588
|
const tabs = [
|
|
2589
|
+
{ id: "visibility", label: `Column Visibility${hiddenCount > 0 ? ` (${hiddenCount})` : ""}`, Icon: HiEyeOff },
|
|
2493
2590
|
{ id: "columns", label: "Pinned Columns", Icon: HiViewBoards },
|
|
2494
2591
|
{ id: "sorting", label: "Default Sorting", Icon: HiSortAscending },
|
|
2495
2592
|
{ id: "display", label: "Display Options", Icon: HiEye }
|
|
@@ -2512,7 +2609,7 @@ var SpreadsheetSettingsModal = ({
|
|
|
2512
2609
|
"aria-label": "Close settings"
|
|
2513
2610
|
}
|
|
2514
2611
|
),
|
|
2515
|
-
/* @__PURE__ */ jsxs9("div", { className: "bg-white rounded-lg w-[
|
|
2612
|
+
/* @__PURE__ */ jsxs9("div", { className: "bg-white rounded-lg w-[70%] max-w-1/2 max-h-[70vh] flex flex-col shadow-xl relative z-10", children: [
|
|
2516
2613
|
/* @__PURE__ */ jsxs9("div", { className: "px-6 py-5 border-b border-gray-200 flex items-center justify-between", children: [
|
|
2517
2614
|
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-3", children: [
|
|
2518
2615
|
/* @__PURE__ */ jsx9(HiCog, { className: "h-6 w-6 text-blue-600" }),
|
|
@@ -2542,6 +2639,131 @@ var SpreadsheetSettingsModal = ({
|
|
|
2542
2639
|
tab.id
|
|
2543
2640
|
)) }),
|
|
2544
2641
|
/* @__PURE__ */ jsxs9("div", { className: "flex-1 overflow-auto p-6", children: [
|
|
2642
|
+
activeTab === "visibility" && /* @__PURE__ */ jsxs9("div", { children: [
|
|
2643
|
+
/* @__PURE__ */ jsxs9("div", { className: "p-4 bg-amber-50 border border-amber-200 rounded-lg mb-4 flex gap-3", children: [
|
|
2644
|
+
/* @__PURE__ */ jsx9(HiEyeOff, { className: "h-4 w-4 text-amber-600 shrink-0 mt-0.5" }),
|
|
2645
|
+
/* @__PURE__ */ jsxs9("div", { children: [
|
|
2646
|
+
/* @__PURE__ */ jsx9("p", { className: "text-sm font-semibold text-gray-900 mb-1", children: "Column Visibility" }),
|
|
2647
|
+
/* @__PURE__ */ jsxs9("p", { className: "text-sm text-gray-600", children: [
|
|
2648
|
+
"Toggle columns on or off. Hidden columns are removed from the table but their data is preserved.",
|
|
2649
|
+
hiddenCount > 0 && /* @__PURE__ */ jsxs9("span", { className: "ml-1 font-medium text-amber-700", children: [
|
|
2650
|
+
hiddenCount,
|
|
2651
|
+
" column",
|
|
2652
|
+
hiddenCount !== 1 ? "s" : "",
|
|
2653
|
+
" hidden."
|
|
2654
|
+
] })
|
|
2655
|
+
] })
|
|
2656
|
+
] })
|
|
2657
|
+
] }),
|
|
2658
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex gap-2 mb-4", children: [
|
|
2659
|
+
/* @__PURE__ */ jsx9(
|
|
2660
|
+
"button",
|
|
2661
|
+
{
|
|
2662
|
+
type: "button",
|
|
2663
|
+
onClick: () => setLocalSettings({ ...localSettings, hiddenColumns: [] }),
|
|
2664
|
+
className: "px-3 py-1.5 text-xs font-medium text-green-700 bg-green-50 border border-green-200 rounded-lg hover:bg-green-100 transition-colors",
|
|
2665
|
+
children: "Show All"
|
|
2666
|
+
}
|
|
2667
|
+
),
|
|
2668
|
+
/* @__PURE__ */ jsx9(
|
|
2669
|
+
"button",
|
|
2670
|
+
{
|
|
2671
|
+
type: "button",
|
|
2672
|
+
onClick: () => setLocalSettings({
|
|
2673
|
+
...localSettings,
|
|
2674
|
+
hiddenColumns: columns.map((c) => c.id)
|
|
2675
|
+
}),
|
|
2676
|
+
className: "px-3 py-1.5 text-xs font-medium text-red-700 bg-red-50 border border-red-200 rounded-lg hover:bg-red-100 transition-colors",
|
|
2677
|
+
children: "Hide All"
|
|
2678
|
+
}
|
|
2679
|
+
)
|
|
2680
|
+
] }),
|
|
2681
|
+
columnGroups?.map((group) => {
|
|
2682
|
+
const groupCols = columns.filter((c) => group.columns.includes(c.id));
|
|
2683
|
+
if (groupCols.length === 0) return null;
|
|
2684
|
+
const hiddenInGroup = groupCols.filter((c) => hiddenColumnsSet.has(c.id)).length;
|
|
2685
|
+
const allHidden = hiddenInGroup === groupCols.length;
|
|
2686
|
+
const allVisible = hiddenInGroup === 0;
|
|
2687
|
+
return /* @__PURE__ */ jsxs9("div", { className: "mb-4", children: [
|
|
2688
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between mb-2", children: [
|
|
2689
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
|
|
2690
|
+
/* @__PURE__ */ jsx9(
|
|
2691
|
+
"div",
|
|
2692
|
+
{
|
|
2693
|
+
className: "w-3 h-3 rounded-sm",
|
|
2694
|
+
style: { backgroundColor: group.headerColor }
|
|
2695
|
+
}
|
|
2696
|
+
),
|
|
2697
|
+
/* @__PURE__ */ jsx9("span", { className: "text-sm font-medium text-gray-900", children: group.label }),
|
|
2698
|
+
/* @__PURE__ */ jsxs9("span", { className: "text-xs text-gray-500", children: [
|
|
2699
|
+
"(",
|
|
2700
|
+
groupCols.length - hiddenInGroup,
|
|
2701
|
+
"/",
|
|
2702
|
+
groupCols.length,
|
|
2703
|
+
")"
|
|
2704
|
+
] })
|
|
2705
|
+
] }),
|
|
2706
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex gap-1", children: [
|
|
2707
|
+
/* @__PURE__ */ jsx9(
|
|
2708
|
+
"button",
|
|
2709
|
+
{
|
|
2710
|
+
type: "button",
|
|
2711
|
+
onClick: () => setGroupVisibility(group.columns, true),
|
|
2712
|
+
disabled: allVisible,
|
|
2713
|
+
className: "px-2 py-0.5 text-xs text-green-700 hover:bg-green-50 rounded transition-colors disabled:opacity-40 disabled:cursor-not-allowed",
|
|
2714
|
+
children: "Show all"
|
|
2715
|
+
}
|
|
2716
|
+
),
|
|
2717
|
+
/* @__PURE__ */ jsx9(
|
|
2718
|
+
"button",
|
|
2719
|
+
{
|
|
2720
|
+
type: "button",
|
|
2721
|
+
onClick: () => setGroupVisibility(group.columns, false),
|
|
2722
|
+
disabled: allHidden,
|
|
2723
|
+
className: "px-2 py-0.5 text-xs text-red-700 hover:bg-red-50 rounded transition-colors disabled:opacity-40 disabled:cursor-not-allowed",
|
|
2724
|
+
children: "Hide all"
|
|
2725
|
+
}
|
|
2726
|
+
)
|
|
2727
|
+
] })
|
|
2728
|
+
] }),
|
|
2729
|
+
/* @__PURE__ */ jsx9("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2", children: groupCols.map((column) => {
|
|
2730
|
+
const isHidden = hiddenColumnsSet.has(column.id);
|
|
2731
|
+
return /* @__PURE__ */ jsxs9(
|
|
2732
|
+
"button",
|
|
2733
|
+
{
|
|
2734
|
+
type: "button",
|
|
2735
|
+
onClick: () => toggleColumnVisibility(column.id),
|
|
2736
|
+
className: `flex items-center gap-2 p-3 rounded-lg border transition-colors text-left ${isHidden ? "bg-gray-100 border-gray-200 text-gray-400" : "bg-green-50 border-green-300 text-green-800"}`,
|
|
2737
|
+
children: [
|
|
2738
|
+
isHidden ? /* @__PURE__ */ jsx9(HiEyeOff, { className: "h-4 w-4 shrink-0" }) : /* @__PURE__ */ jsx9(HiEye, { className: "h-4 w-4 shrink-0" }),
|
|
2739
|
+
/* @__PURE__ */ jsx9("span", { className: "text-sm flex-1 truncate", children: column.label })
|
|
2740
|
+
]
|
|
2741
|
+
},
|
|
2742
|
+
column.id
|
|
2743
|
+
);
|
|
2744
|
+
}) })
|
|
2745
|
+
] }, group.id);
|
|
2746
|
+
}),
|
|
2747
|
+
ungroupedColumns.length > 0 && /* @__PURE__ */ jsxs9("div", { className: "mb-4", children: [
|
|
2748
|
+
columnGroups?.length ? /* @__PURE__ */ jsx9("div", { className: "flex items-center gap-2 mb-2", children: /* @__PURE__ */ jsx9("span", { className: "text-sm font-medium text-gray-900", children: "Other" }) }) : null,
|
|
2749
|
+
/* @__PURE__ */ jsx9("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2", children: ungroupedColumns.map((column) => {
|
|
2750
|
+
const isHidden = hiddenColumnsSet.has(column.id);
|
|
2751
|
+
return /* @__PURE__ */ jsxs9(
|
|
2752
|
+
"button",
|
|
2753
|
+
{
|
|
2754
|
+
type: "button",
|
|
2755
|
+
onClick: () => toggleColumnVisibility(column.id),
|
|
2756
|
+
className: `flex items-center gap-2 p-3 rounded-lg border transition-colors text-left ${isHidden ? "bg-gray-100 border-gray-200 text-gray-400" : "bg-green-50 border-green-300 text-green-800"}`,
|
|
2757
|
+
children: [
|
|
2758
|
+
isHidden ? /* @__PURE__ */ jsx9(HiEyeOff, { className: "h-4 w-4 shrink-0" }) : /* @__PURE__ */ jsx9(HiEye, { className: "h-4 w-4 shrink-0" }),
|
|
2759
|
+
/* @__PURE__ */ jsx9("span", { className: "text-sm flex-1 truncate", children: column.label })
|
|
2760
|
+
]
|
|
2761
|
+
},
|
|
2762
|
+
column.id
|
|
2763
|
+
);
|
|
2764
|
+
}) })
|
|
2765
|
+
] })
|
|
2766
|
+
] }),
|
|
2545
2767
|
activeTab === "columns" && /* @__PURE__ */ jsxs9("div", { children: [
|
|
2546
2768
|
/* @__PURE__ */ jsxs9("div", { className: "p-4 bg-blue-50 border border-blue-200 rounded-lg mb-4 flex gap-3", children: [
|
|
2547
2769
|
/* @__PURE__ */ jsx9(HiViewBoards, { className: "h-4 w-4 text-blue-600 shrink-0 mt-0.5" }),
|
|
@@ -2972,7 +3194,7 @@ function ShortcutRow({ label, keys }) {
|
|
|
2972
3194
|
KeyboardShortcutsModal.displayName = "KeyboardShortcutsModal";
|
|
2973
3195
|
|
|
2974
3196
|
// src/components/RowContextMenu.tsx
|
|
2975
|
-
import { useMemo as
|
|
3197
|
+
import { useMemo as useMemo3 } from "react";
|
|
2976
3198
|
import { ContextMenu, ContextMenuItem } from "@xcelsior/design-system";
|
|
2977
3199
|
import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2978
3200
|
function RowContextMenu({
|
|
@@ -2982,7 +3204,7 @@ function RowContextMenu({
|
|
|
2982
3204
|
compactMode = false,
|
|
2983
3205
|
className
|
|
2984
3206
|
}) {
|
|
2985
|
-
const visibleItems =
|
|
3207
|
+
const visibleItems = useMemo3(() => {
|
|
2986
3208
|
return items.filter((item) => !item.visible || item.visible(row));
|
|
2987
3209
|
}, [items, row]);
|
|
2988
3210
|
if (visibleItems.length === 0) {
|
|
@@ -3038,7 +3260,7 @@ RowContextMenu.displayName = "RowContextMenu";
|
|
|
3038
3260
|
import { Pagination } from "@xcelsior/design-system";
|
|
3039
3261
|
|
|
3040
3262
|
// src/hooks/useSpreadsheetFiltering.ts
|
|
3041
|
-
import { useCallback as useCallback4, useMemo as
|
|
3263
|
+
import { useCallback as useCallback4, useMemo as useMemo4, useState as useState8 } from "react";
|
|
3042
3264
|
import { FilterChain, LazyArray } from "@xcelsior/utils";
|
|
3043
3265
|
function useSpreadsheetFiltering({
|
|
3044
3266
|
data,
|
|
@@ -3239,7 +3461,7 @@ function useSpreadsheetFiltering({
|
|
|
3239
3461
|
},
|
|
3240
3462
|
[sortConfig?.columnId]
|
|
3241
3463
|
);
|
|
3242
|
-
const filteredData =
|
|
3464
|
+
const filteredData = useMemo4(() => {
|
|
3243
3465
|
if (!data || !Array.isArray(data)) return LazyArray.empty();
|
|
3244
3466
|
if (serverSide) {
|
|
3245
3467
|
return LazyArray.from(data);
|
|
@@ -3340,7 +3562,7 @@ function useSpreadsheetFiltering({
|
|
|
3340
3562
|
}
|
|
3341
3563
|
|
|
3342
3564
|
// src/hooks/useSpreadsheetDuplicates.ts
|
|
3343
|
-
import { useCallback as useCallback5, useMemo as
|
|
3565
|
+
import { useCallback as useCallback5, useMemo as useMemo5, useState as useState9 } from "react";
|
|
3344
3566
|
function normalizeValue(value) {
|
|
3345
3567
|
if (value === null || value === void 0 || value === "") {
|
|
3346
3568
|
return "__blank__";
|
|
@@ -3359,10 +3581,10 @@ function useSpreadsheetDuplicates({
|
|
|
3359
3581
|
const [localDuplicateCheckColumns, setLocalDuplicateCheckColumns] = useState9(
|
|
3360
3582
|
() => new Set(duplicateCheckColumns)
|
|
3361
3583
|
);
|
|
3362
|
-
const duplicateCheckColumnsSet =
|
|
3584
|
+
const duplicateCheckColumnsSet = useMemo5(() => {
|
|
3363
3585
|
return new Set(duplicateCheckColumns);
|
|
3364
3586
|
}, [duplicateCheckColumns]);
|
|
3365
|
-
const { duplicateRowIds, valueCounts } =
|
|
3587
|
+
const { duplicateRowIds, valueCounts } = useMemo5(() => {
|
|
3366
3588
|
const duplicateRowIds2 = /* @__PURE__ */ new Map();
|
|
3367
3589
|
const valueCounts2 = /* @__PURE__ */ new Map();
|
|
3368
3590
|
const activeColumns = duplicateCheckColumnsSet.size > 0 ? duplicateCheckColumnsSet : localDuplicateCheckColumns;
|
|
@@ -3965,7 +4187,7 @@ function useSpreadsheetKeyboardShortcuts({
|
|
|
3965
4187
|
}
|
|
3966
4188
|
|
|
3967
4189
|
// src/hooks/useSpreadsheetSelection.ts
|
|
3968
|
-
import { useCallback as useCallback9, useState as useState14, useRef as useRef8, useMemo as
|
|
4190
|
+
import { useCallback as useCallback9, useState as useState14, useRef as useRef8, useMemo as useMemo6 } from "react";
|
|
3969
4191
|
function useSpreadsheetSelection({
|
|
3970
4192
|
data,
|
|
3971
4193
|
columns,
|
|
@@ -3979,14 +4201,14 @@ function useSpreadsheetSelection({
|
|
|
3979
4201
|
const [isDragging, setIsDragging] = useState14(false);
|
|
3980
4202
|
const [clipboardData, setClipboardData] = useState14(null);
|
|
3981
4203
|
const anchorCell = useRef8(null);
|
|
3982
|
-
const rowIndexMap =
|
|
4204
|
+
const rowIndexMap = useMemo6(() => {
|
|
3983
4205
|
const map = /* @__PURE__ */ new Map();
|
|
3984
4206
|
data.forEach((row, index) => {
|
|
3985
4207
|
map.set(getRowId(row), index);
|
|
3986
4208
|
});
|
|
3987
4209
|
return map;
|
|
3988
4210
|
}, [data, getRowId]);
|
|
3989
|
-
const columnIndexMap =
|
|
4211
|
+
const columnIndexMap = useMemo6(() => {
|
|
3990
4212
|
const map = /* @__PURE__ */ new Map();
|
|
3991
4213
|
columns.forEach((col, index) => {
|
|
3992
4214
|
map.set(col.id, index);
|
|
@@ -4385,12 +4607,12 @@ function useSpreadsheetSelection({
|
|
|
4385
4607
|
}
|
|
4386
4608
|
|
|
4387
4609
|
// src/hooks/useSpreadsheetSummary.ts
|
|
4388
|
-
import { useMemo as
|
|
4610
|
+
import { useMemo as useMemo7 } from "react";
|
|
4389
4611
|
function useSpreadsheetSummary({
|
|
4390
4612
|
selectedCellValues,
|
|
4391
4613
|
columns
|
|
4392
4614
|
}) {
|
|
4393
|
-
const summary =
|
|
4615
|
+
const summary = useMemo7(() => {
|
|
4394
4616
|
if (selectedCellValues.length === 0) return null;
|
|
4395
4617
|
const numericValues = [];
|
|
4396
4618
|
for (const { position, value } of selectedCellValues) {
|
|
@@ -4512,7 +4734,7 @@ function useSpreadsheetColumnResize({
|
|
|
4512
4734
|
}
|
|
4513
4735
|
|
|
4514
4736
|
// src/components/SelectionSummaryBar.tsx
|
|
4515
|
-
import { Fragment as
|
|
4737
|
+
import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
4516
4738
|
function SelectionSummaryBar({
|
|
4517
4739
|
summary,
|
|
4518
4740
|
focusedCell,
|
|
@@ -4539,7 +4761,7 @@ function SelectionSummaryBar({
|
|
|
4539
4761
|
}
|
|
4540
4762
|
if (!addressDisplay && !summary) return null;
|
|
4541
4763
|
return /* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between px-3 py-1.5 bg-gray-50 border-t border-gray-200 text-xs text-gray-600", children: [
|
|
4542
|
-
/* @__PURE__ */ jsx13("div", { className: "flex items-center gap-2 min-w-0", children: addressDisplay && /* @__PURE__ */ jsxs13(
|
|
4764
|
+
/* @__PURE__ */ jsx13("div", { className: "flex items-center gap-2 min-w-0", children: addressDisplay && /* @__PURE__ */ jsxs13(Fragment4, { children: [
|
|
4543
4765
|
/* @__PURE__ */ jsx13("span", { className: "font-medium text-gray-500 bg-white px-2 py-0.5 rounded border border-gray-200 shrink-0", children: addressDisplay }),
|
|
4544
4766
|
valueDisplay && /* @__PURE__ */ jsx13("span", { className: "text-gray-700 truncate", title: valueDisplay, children: valueDisplay })
|
|
4545
4767
|
] }) }),
|
|
@@ -4626,7 +4848,8 @@ function Spreadsheet({
|
|
|
4626
4848
|
defaultPageSize: initialSettings?.defaultPageSize ?? 25,
|
|
4627
4849
|
defaultZoom: initialSettings?.defaultZoom ?? 100,
|
|
4628
4850
|
autoSave: initialSettings?.autoSave ?? true,
|
|
4629
|
-
compactView: initialSettings?.compactView ?? false
|
|
4851
|
+
compactView: initialSettings?.compactView ?? false,
|
|
4852
|
+
hiddenColumns: initialSettings?.hiddenColumns ?? []
|
|
4630
4853
|
});
|
|
4631
4854
|
const {
|
|
4632
4855
|
isCellDuplicate,
|
|
@@ -4653,6 +4876,15 @@ function Spreadsheet({
|
|
|
4653
4876
|
},
|
|
4654
4877
|
[toggleDuplicateCheck, duplicateCheckColumns, onDuplicateCheckChange]
|
|
4655
4878
|
);
|
|
4879
|
+
const handleHideColumn = useCallback11(
|
|
4880
|
+
(columnId) => {
|
|
4881
|
+
setSpreadsheetSettings((prev) => ({
|
|
4882
|
+
...prev,
|
|
4883
|
+
hiddenColumns: [...prev.hiddenColumns ?? [], columnId]
|
|
4884
|
+
}));
|
|
4885
|
+
},
|
|
4886
|
+
[]
|
|
4887
|
+
);
|
|
4656
4888
|
const [isProcessing, setIsProcessing] = useState16(false);
|
|
4657
4889
|
const {
|
|
4658
4890
|
filters,
|
|
@@ -4727,7 +4959,8 @@ function Spreadsheet({
|
|
|
4727
4959
|
columnGroups,
|
|
4728
4960
|
defaultPinnedColumns: initialSettings?.defaultPinnedColumns,
|
|
4729
4961
|
defaultPinnedRightColumns: initialSettings?.defaultPinnedRightColumns,
|
|
4730
|
-
getColumnWidth
|
|
4962
|
+
getColumnWidth,
|
|
4963
|
+
hiddenColumns: spreadsheetSettings.hiddenColumns
|
|
4731
4964
|
});
|
|
4732
4965
|
const {
|
|
4733
4966
|
getCellComments,
|
|
@@ -4883,7 +5116,7 @@ function Spreadsheet({
|
|
|
4883
5116
|
}
|
|
4884
5117
|
markAsChanged();
|
|
4885
5118
|
}, [popRedoEntry, onCellsEdit, markAsChanged]);
|
|
4886
|
-
const paginatedData =
|
|
5119
|
+
const paginatedData = useMemo8(() => {
|
|
4887
5120
|
if (serverSide) {
|
|
4888
5121
|
return filteredData.toArray();
|
|
4889
5122
|
}
|
|
@@ -4915,7 +5148,7 @@ function Spreadsheet({
|
|
|
4915
5148
|
getRowId,
|
|
4916
5149
|
enableCellEditing
|
|
4917
5150
|
});
|
|
4918
|
-
const selectedCellValues =
|
|
5151
|
+
const selectedCellValues = useMemo8(() => getSelectedCellValues(), [getSelectedCellValues]);
|
|
4919
5152
|
const { summary: selectionSummary, hasNumericValues } = useSpreadsheetSummary({
|
|
4920
5153
|
selectedCellValues,
|
|
4921
5154
|
columns: visibleColumns
|
|
@@ -5154,7 +5387,7 @@ function Spreadsheet({
|
|
|
5154
5387
|
const handleRowIndexHighlightClick = useCallback11(() => {
|
|
5155
5388
|
setHighlightPickerColumn(ROW_INDEX_COLUMN_ID);
|
|
5156
5389
|
}, [setHighlightPickerColumn]);
|
|
5157
|
-
const columnRenderItems =
|
|
5390
|
+
const columnRenderItems = useMemo8(() => {
|
|
5158
5391
|
if (!columnGroups || columnGroups.length === 0) {
|
|
5159
5392
|
return visibleColumns.map((col) => ({
|
|
5160
5393
|
type: "column",
|
|
@@ -5184,7 +5417,7 @@ function Spreadsheet({
|
|
|
5184
5417
|
}
|
|
5185
5418
|
return items;
|
|
5186
5419
|
}, [columnGroups, collapsedGroups, visibleColumns]);
|
|
5187
|
-
const groupHeaderItems =
|
|
5420
|
+
const groupHeaderItems = useMemo8(() => {
|
|
5188
5421
|
if (!columnGroups || columnGroups.length === 0) return null;
|
|
5189
5422
|
const items = [];
|
|
5190
5423
|
for (const group of columnGroups) {
|
|
@@ -5235,7 +5468,12 @@ function Spreadsheet({
|
|
|
5235
5468
|
onSave: handleSave,
|
|
5236
5469
|
onSettings: () => setShowSettingsModal(true),
|
|
5237
5470
|
onShowShortcuts: () => setShowKeyboardShortcuts(true),
|
|
5238
|
-
menuItems: toolbarMenuItems
|
|
5471
|
+
menuItems: toolbarMenuItems,
|
|
5472
|
+
hiddenColumnCount: spreadsheetSettings.hiddenColumns?.length ?? 0,
|
|
5473
|
+
onShowAllColumns: () => {
|
|
5474
|
+
setSpreadsheetSettings((prev) => ({ ...prev, hiddenColumns: [] }));
|
|
5475
|
+
},
|
|
5476
|
+
onManageColumns: () => setShowSettingsModal(true)
|
|
5239
5477
|
}
|
|
5240
5478
|
),
|
|
5241
5479
|
/* @__PURE__ */ jsxs14("div", { ref: tableRef, className: cn("flex-1 overflow-auto border border-gray-200 rounded spreadsheet-scroll-container relative", isResizing && "select-none"), onMouseUp: handleMouseUp, children: [
|
|
@@ -5343,6 +5581,7 @@ function Spreadsheet({
|
|
|
5343
5581
|
activeFilterColumn === column.id ? null : column.id
|
|
5344
5582
|
),
|
|
5345
5583
|
onPinClick: () => handleTogglePin(column.id),
|
|
5584
|
+
onHideClick: () => handleHideColumn(column.id),
|
|
5346
5585
|
onHighlightClick: enableHighlighting ? () => setHighlightPickerColumn(column.id) : void 0,
|
|
5347
5586
|
resizeHandleProps: getResizeHandleProps(
|
|
5348
5587
|
column.id,
|
|
@@ -5788,6 +6027,7 @@ function Spreadsheet({
|
|
|
5788
6027
|
onSettingsChange?.(newSettings);
|
|
5789
6028
|
},
|
|
5790
6029
|
columns: columns || [],
|
|
6030
|
+
columnGroups,
|
|
5791
6031
|
title: "Spreadsheet Settings",
|
|
5792
6032
|
pageSizeOptions
|
|
5793
6033
|
}
|