@particle-academy/fancy-sheets 0.4.1 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +97 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +97 -30
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1237,10 +1237,15 @@ function getRecalculationOrder(graph) {
|
|
|
1237
1237
|
|
|
1238
1238
|
// src/hooks/use-spreadsheet-store.ts
|
|
1239
1239
|
function recalculateWorkbook(workbook) {
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
}
|
|
1240
|
+
const recalculated = [];
|
|
1241
|
+
for (const sheet of workbook.sheets) {
|
|
1242
|
+
recalculated.push(recalculateSheet(sheet, recalculated));
|
|
1243
|
+
}
|
|
1244
|
+
const finalSheets = [];
|
|
1245
|
+
for (const sheet of recalculated) {
|
|
1246
|
+
finalSheets.push(recalculateSheet(sheet, recalculated));
|
|
1247
|
+
}
|
|
1248
|
+
return { ...workbook, sheets: finalSheets };
|
|
1244
1249
|
}
|
|
1245
1250
|
function createInitialState(data) {
|
|
1246
1251
|
const workbook = data ?? createEmptyWorkbook();
|
|
@@ -1340,10 +1345,11 @@ function reducer(state, action) {
|
|
|
1340
1345
|
const sheet = getActiveSheet(state);
|
|
1341
1346
|
const existing = sheet.cells[action.address];
|
|
1342
1347
|
if (existing?.format) cellData.format = existing.format;
|
|
1343
|
-
const
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
});
|
|
1348
|
+
const updatedWorkbook = updateActiveSheet(state, (s) => ({
|
|
1349
|
+
...s,
|
|
1350
|
+
cells: { ...s.cells, [action.address]: cellData }
|
|
1351
|
+
}));
|
|
1352
|
+
const workbook = recalculateWorkbook(updatedWorkbook);
|
|
1347
1353
|
return { ...state, workbook, ...history };
|
|
1348
1354
|
}
|
|
1349
1355
|
case "SET_CELL_FORMAT": {
|
|
@@ -1601,7 +1607,7 @@ function ColumnResizeHandle({ colIndex }) {
|
|
|
1601
1607
|
}
|
|
1602
1608
|
ColumnResizeHandle.displayName = "ColumnResizeHandle";
|
|
1603
1609
|
function ColumnHeaders() {
|
|
1604
|
-
const { columnCount, rowCount, rowHeight, getColumnWidth, selection, selectRange, _isDragging } = useSpreadsheet();
|
|
1610
|
+
const { columnCount, rowCount, rowHeight, getColumnWidth, selection, selectRange, _isDragging, isCellSelected } = useSpreadsheet();
|
|
1605
1611
|
const handleColumnMouseDown = react.useCallback(
|
|
1606
1612
|
(colIdx, e) => {
|
|
1607
1613
|
if (e.button !== 0) return;
|
|
@@ -1645,28 +1651,35 @@ function ColumnHeaders() {
|
|
|
1645
1651
|
style: { width: 48, minWidth: 48 }
|
|
1646
1652
|
}
|
|
1647
1653
|
),
|
|
1648
|
-
Array.from({ length: columnCount }, (_, i) =>
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1654
|
+
Array.from({ length: columnCount }, (_, i) => {
|
|
1655
|
+
const isColSelected = isCellSelected(toAddress(0, i));
|
|
1656
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1657
|
+
"div",
|
|
1658
|
+
{
|
|
1659
|
+
className: reactFancy.cn(
|
|
1660
|
+
"relative flex shrink-0 cursor-pointer items-center justify-center border-r border-zinc-300 text-[11px] font-medium select-none hover:bg-zinc-200 dark:border-zinc-600 dark:hover:bg-zinc-700",
|
|
1661
|
+
isColSelected ? "bg-blue-100 text-blue-700 dark:bg-blue-900/50 dark:text-blue-300" : "text-zinc-500 dark:text-zinc-400"
|
|
1662
|
+
),
|
|
1663
|
+
style: { width: getColumnWidth(i), minWidth: getColumnWidth(i) },
|
|
1664
|
+
onMouseDown: (e) => handleColumnMouseDown(i, e),
|
|
1665
|
+
onMouseEnter: () => handleColumnMouseEnter(i),
|
|
1666
|
+
onMouseUp: handleMouseUp,
|
|
1667
|
+
children: [
|
|
1668
|
+
columnToLetter(i),
|
|
1669
|
+
/* @__PURE__ */ jsxRuntime.jsx(ColumnResizeHandle, { colIndex: i })
|
|
1670
|
+
]
|
|
1671
|
+
},
|
|
1672
|
+
i
|
|
1673
|
+
);
|
|
1674
|
+
})
|
|
1663
1675
|
]
|
|
1664
1676
|
}
|
|
1665
1677
|
);
|
|
1666
1678
|
}
|
|
1667
1679
|
ColumnHeaders.displayName = "ColumnHeaders";
|
|
1668
1680
|
function RowHeader({ rowIndex }) {
|
|
1669
|
-
const { rowHeight, columnCount, selection, selectRange, _isDragging } = useSpreadsheet();
|
|
1681
|
+
const { rowHeight, columnCount, selection, selectRange, _isDragging, isCellSelected } = useSpreadsheet();
|
|
1682
|
+
const isRowSelected = isCellSelected(toAddress(rowIndex, 0));
|
|
1670
1683
|
const handleMouseDown = react.useCallback(
|
|
1671
1684
|
(e) => {
|
|
1672
1685
|
if (e.button !== 0) return;
|
|
@@ -1697,7 +1710,10 @@ function RowHeader({ rowIndex }) {
|
|
|
1697
1710
|
"div",
|
|
1698
1711
|
{
|
|
1699
1712
|
"data-fancy-sheets-row-header": "",
|
|
1700
|
-
className:
|
|
1713
|
+
className: reactFancy.cn(
|
|
1714
|
+
"flex shrink-0 cursor-pointer items-center justify-center border-r border-b border-zinc-300 text-[11px] font-medium select-none hover:bg-zinc-200 dark:border-zinc-600 dark:hover:bg-zinc-700",
|
|
1715
|
+
isRowSelected ? "bg-blue-100 text-blue-700 dark:bg-blue-900/50 dark:text-blue-300" : "bg-zinc-100 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400"
|
|
1716
|
+
),
|
|
1701
1717
|
style: { width: 48, minWidth: 48, height: rowHeight },
|
|
1702
1718
|
onMouseDown: handleMouseDown,
|
|
1703
1719
|
onMouseEnter: handleMouseEnter,
|
|
@@ -1726,21 +1742,24 @@ function serialToDateTimeStr(serial) {
|
|
|
1726
1742
|
}
|
|
1727
1743
|
function isDateFormula(formula) {
|
|
1728
1744
|
if (!formula) return false;
|
|
1729
|
-
const f = formula.toUpperCase();
|
|
1730
|
-
return /^(TODAY|NOW|DATE|EDATE)\
|
|
1745
|
+
const f = formula.trim().toUpperCase();
|
|
1746
|
+
return /^(TODAY|NOW|DATE|EDATE)\s*\(/.test(f);
|
|
1731
1747
|
}
|
|
1732
1748
|
function formatCellValue(val, cell) {
|
|
1733
1749
|
if (val === null || val === void 0) return "";
|
|
1734
1750
|
const fmt = cell?.format?.displayFormat;
|
|
1735
1751
|
if (typeof val === "number") {
|
|
1752
|
+
const dec = cell?.format?.decimals;
|
|
1736
1753
|
if (fmt === "date") return serialToDateStr(val);
|
|
1737
1754
|
if (fmt === "datetime") return serialToDateTimeStr(val);
|
|
1738
|
-
if (fmt === "percentage") return (val * 100).toFixed(1) + "%";
|
|
1739
|
-
if (fmt === "currency") return "$" + val.toFixed(2);
|
|
1755
|
+
if (fmt === "percentage") return (val * 100).toFixed(dec ?? 1) + "%";
|
|
1756
|
+
if (fmt === "currency") return "$" + val.toFixed(dec ?? 2);
|
|
1757
|
+
if (fmt === "number" && dec !== void 0) return val.toFixed(dec);
|
|
1740
1758
|
if (fmt === "auto" || !fmt) {
|
|
1741
1759
|
if (cell?.formula && isDateFormula(cell.formula)) {
|
|
1742
1760
|
return val % 1 === 0 ? serialToDateStr(val) : serialToDateTimeStr(val);
|
|
1743
1761
|
}
|
|
1762
|
+
if (dec !== void 0) return val.toFixed(dec);
|
|
1744
1763
|
}
|
|
1745
1764
|
}
|
|
1746
1765
|
if (typeof val === "boolean") return val ? "TRUE" : "FALSE";
|
|
@@ -2184,6 +2203,8 @@ function DefaultToolbar() {
|
|
|
2184
2203
|
const isBold = cell?.format?.bold ?? false;
|
|
2185
2204
|
const isItalic = cell?.format?.italic ?? false;
|
|
2186
2205
|
const textAlign = cell?.format?.textAlign ?? "left";
|
|
2206
|
+
const displayFormat = cell?.format?.displayFormat ?? "auto";
|
|
2207
|
+
const decimals = cell?.format?.decimals;
|
|
2187
2208
|
const selectedAddresses = [selection.activeCell];
|
|
2188
2209
|
const handleFormulaBarChange = (e) => {
|
|
2189
2210
|
if (editingCell) {
|
|
@@ -2295,6 +2316,52 @@ function DefaultToolbar() {
|
|
|
2295
2316
|
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "19", y1: "3", x2: "19", y2: "21", strokeDasharray: "3 3" })
|
|
2296
2317
|
] })
|
|
2297
2318
|
}
|
|
2319
|
+
),
|
|
2320
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-1 h-4 w-px bg-zinc-200 dark:bg-zinc-700" }),
|
|
2321
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2322
|
+
"select",
|
|
2323
|
+
{
|
|
2324
|
+
className: "h-6 rounded border border-zinc-200 bg-transparent px-1 text-[11px] text-zinc-600 outline-none hover:border-zinc-300 dark:border-zinc-700 dark:text-zinc-400 dark:hover:border-zinc-600",
|
|
2325
|
+
value: displayFormat,
|
|
2326
|
+
onChange: (e) => setCellFormat(selectedAddresses, { displayFormat: e.target.value }),
|
|
2327
|
+
disabled: readOnly,
|
|
2328
|
+
title: "Cell format",
|
|
2329
|
+
children: [
|
|
2330
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "auto", children: "Auto" }),
|
|
2331
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "text", children: "Text" }),
|
|
2332
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "number", children: "Number" }),
|
|
2333
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "currency", children: "Currency ($)" }),
|
|
2334
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "percentage", children: "Percentage (%)" }),
|
|
2335
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "date", children: "Date" }),
|
|
2336
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "datetime", children: "Date & Time" })
|
|
2337
|
+
]
|
|
2338
|
+
}
|
|
2339
|
+
),
|
|
2340
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2341
|
+
"button",
|
|
2342
|
+
{
|
|
2343
|
+
className: btnClass,
|
|
2344
|
+
onClick: () => setCellFormat(selectedAddresses, { decimals: Math.max(0, (decimals ?? 0) - 1) }),
|
|
2345
|
+
disabled: readOnly || (decimals ?? 0) <= 0,
|
|
2346
|
+
title: "Decrease decimal places",
|
|
2347
|
+
children: [
|
|
2348
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px]", children: ".0" }),
|
|
2349
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[8px]", children: "\u2190" })
|
|
2350
|
+
]
|
|
2351
|
+
}
|
|
2352
|
+
),
|
|
2353
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2354
|
+
"button",
|
|
2355
|
+
{
|
|
2356
|
+
className: btnClass,
|
|
2357
|
+
onClick: () => setCellFormat(selectedAddresses, { decimals: (decimals ?? 0) + 1 }),
|
|
2358
|
+
disabled: readOnly,
|
|
2359
|
+
title: "Increase decimal places",
|
|
2360
|
+
children: [
|
|
2361
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px]", children: ".00" }),
|
|
2362
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[8px]", children: "\u2192" })
|
|
2363
|
+
]
|
|
2364
|
+
}
|
|
2298
2365
|
)
|
|
2299
2366
|
] }),
|
|
2300
2367
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { "data-fancy-sheets-formula-bar": "", className: "flex items-center gap-2 border-b border-zinc-200 px-2 py-1 dark:border-zinc-700", children: [
|