@particle-academy/fancy-sheets 0.4.1 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1601,7 +1601,7 @@ function ColumnResizeHandle({ colIndex }) {
1601
1601
  }
1602
1602
  ColumnResizeHandle.displayName = "ColumnResizeHandle";
1603
1603
  function ColumnHeaders() {
1604
- const { columnCount, rowCount, rowHeight, getColumnWidth, selection, selectRange, _isDragging } = useSpreadsheet();
1604
+ const { columnCount, rowCount, rowHeight, getColumnWidth, selection, selectRange, _isDragging, isCellSelected } = useSpreadsheet();
1605
1605
  const handleColumnMouseDown = react.useCallback(
1606
1606
  (colIdx, e) => {
1607
1607
  if (e.button !== 0) return;
@@ -1645,28 +1645,35 @@ function ColumnHeaders() {
1645
1645
  style: { width: 48, minWidth: 48 }
1646
1646
  }
1647
1647
  ),
1648
- Array.from({ length: columnCount }, (_, i) => /* @__PURE__ */ jsxRuntime.jsxs(
1649
- "div",
1650
- {
1651
- className: "relative flex shrink-0 cursor-pointer items-center justify-center border-r border-zinc-300 text-[11px] font-medium text-zinc-500 select-none hover:bg-zinc-200 dark:border-zinc-600 dark:text-zinc-400 dark:hover:bg-zinc-700",
1652
- style: { width: getColumnWidth(i), minWidth: getColumnWidth(i) },
1653
- onMouseDown: (e) => handleColumnMouseDown(i, e),
1654
- onMouseEnter: () => handleColumnMouseEnter(i),
1655
- onMouseUp: handleMouseUp,
1656
- children: [
1657
- columnToLetter(i),
1658
- /* @__PURE__ */ jsxRuntime.jsx(ColumnResizeHandle, { colIndex: i })
1659
- ]
1660
- },
1661
- i
1662
- ))
1648
+ Array.from({ length: columnCount }, (_, i) => {
1649
+ const isColSelected = isCellSelected(toAddress(0, i));
1650
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1651
+ "div",
1652
+ {
1653
+ className: reactFancy.cn(
1654
+ "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",
1655
+ isColSelected ? "bg-blue-100 text-blue-700 dark:bg-blue-900/50 dark:text-blue-300" : "text-zinc-500 dark:text-zinc-400"
1656
+ ),
1657
+ style: { width: getColumnWidth(i), minWidth: getColumnWidth(i) },
1658
+ onMouseDown: (e) => handleColumnMouseDown(i, e),
1659
+ onMouseEnter: () => handleColumnMouseEnter(i),
1660
+ onMouseUp: handleMouseUp,
1661
+ children: [
1662
+ columnToLetter(i),
1663
+ /* @__PURE__ */ jsxRuntime.jsx(ColumnResizeHandle, { colIndex: i })
1664
+ ]
1665
+ },
1666
+ i
1667
+ );
1668
+ })
1663
1669
  ]
1664
1670
  }
1665
1671
  );
1666
1672
  }
1667
1673
  ColumnHeaders.displayName = "ColumnHeaders";
1668
1674
  function RowHeader({ rowIndex }) {
1669
- const { rowHeight, columnCount, selection, selectRange, _isDragging } = useSpreadsheet();
1675
+ const { rowHeight, columnCount, selection, selectRange, _isDragging, isCellSelected } = useSpreadsheet();
1676
+ const isRowSelected = isCellSelected(toAddress(rowIndex, 0));
1670
1677
  const handleMouseDown = react.useCallback(
1671
1678
  (e) => {
1672
1679
  if (e.button !== 0) return;
@@ -1697,7 +1704,10 @@ function RowHeader({ rowIndex }) {
1697
1704
  "div",
1698
1705
  {
1699
1706
  "data-fancy-sheets-row-header": "",
1700
- className: "flex shrink-0 cursor-pointer items-center justify-center border-r border-b border-zinc-300 bg-zinc-100 text-[11px] font-medium text-zinc-500 select-none hover:bg-zinc-200 dark:border-zinc-600 dark:bg-zinc-800 dark:text-zinc-400 dark:hover:bg-zinc-700",
1707
+ className: reactFancy.cn(
1708
+ "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",
1709
+ 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"
1710
+ ),
1701
1711
  style: { width: 48, minWidth: 48, height: rowHeight },
1702
1712
  onMouseDown: handleMouseDown,
1703
1713
  onMouseEnter: handleMouseEnter,
@@ -1726,21 +1736,24 @@ function serialToDateTimeStr(serial) {
1726
1736
  }
1727
1737
  function isDateFormula(formula) {
1728
1738
  if (!formula) return false;
1729
- const f = formula.toUpperCase();
1730
- return /^(TODAY|NOW|DATE|EDATE)\b/.test(f) || /\b(TODAY|NOW|DATE|EDATE)\s*\(/.test(f);
1739
+ const f = formula.trim().toUpperCase();
1740
+ return /^(TODAY|NOW|DATE|EDATE)\s*\(/.test(f);
1731
1741
  }
1732
1742
  function formatCellValue(val, cell) {
1733
1743
  if (val === null || val === void 0) return "";
1734
1744
  const fmt = cell?.format?.displayFormat;
1735
1745
  if (typeof val === "number") {
1746
+ const dec = cell?.format?.decimals;
1736
1747
  if (fmt === "date") return serialToDateStr(val);
1737
1748
  if (fmt === "datetime") return serialToDateTimeStr(val);
1738
- if (fmt === "percentage") return (val * 100).toFixed(1) + "%";
1739
- if (fmt === "currency") return "$" + val.toFixed(2);
1749
+ if (fmt === "percentage") return (val * 100).toFixed(dec ?? 1) + "%";
1750
+ if (fmt === "currency") return "$" + val.toFixed(dec ?? 2);
1751
+ if (fmt === "number" && dec !== void 0) return val.toFixed(dec);
1740
1752
  if (fmt === "auto" || !fmt) {
1741
1753
  if (cell?.formula && isDateFormula(cell.formula)) {
1742
1754
  return val % 1 === 0 ? serialToDateStr(val) : serialToDateTimeStr(val);
1743
1755
  }
1756
+ if (dec !== void 0) return val.toFixed(dec);
1744
1757
  }
1745
1758
  }
1746
1759
  if (typeof val === "boolean") return val ? "TRUE" : "FALSE";
@@ -2184,6 +2197,8 @@ function DefaultToolbar() {
2184
2197
  const isBold = cell?.format?.bold ?? false;
2185
2198
  const isItalic = cell?.format?.italic ?? false;
2186
2199
  const textAlign = cell?.format?.textAlign ?? "left";
2200
+ const displayFormat = cell?.format?.displayFormat ?? "auto";
2201
+ const decimals = cell?.format?.decimals;
2187
2202
  const selectedAddresses = [selection.activeCell];
2188
2203
  const handleFormulaBarChange = (e) => {
2189
2204
  if (editingCell) {
@@ -2295,6 +2310,52 @@ function DefaultToolbar() {
2295
2310
  /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "19", y1: "3", x2: "19", y2: "21", strokeDasharray: "3 3" })
2296
2311
  ] })
2297
2312
  }
2313
+ ),
2314
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-1 h-4 w-px bg-zinc-200 dark:bg-zinc-700" }),
2315
+ /* @__PURE__ */ jsxRuntime.jsxs(
2316
+ "select",
2317
+ {
2318
+ 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",
2319
+ value: displayFormat,
2320
+ onChange: (e) => setCellFormat(selectedAddresses, { displayFormat: e.target.value }),
2321
+ disabled: readOnly,
2322
+ title: "Cell format",
2323
+ children: [
2324
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "auto", children: "Auto" }),
2325
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "text", children: "Text" }),
2326
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "number", children: "Number" }),
2327
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "currency", children: "Currency ($)" }),
2328
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "percentage", children: "Percentage (%)" }),
2329
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "date", children: "Date" }),
2330
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "datetime", children: "Date & Time" })
2331
+ ]
2332
+ }
2333
+ ),
2334
+ /* @__PURE__ */ jsxRuntime.jsxs(
2335
+ "button",
2336
+ {
2337
+ className: btnClass,
2338
+ onClick: () => setCellFormat(selectedAddresses, { decimals: Math.max(0, (decimals ?? 0) - 1) }),
2339
+ disabled: readOnly || (decimals ?? 0) <= 0,
2340
+ title: "Decrease decimal places",
2341
+ children: [
2342
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px]", children: ".0" }),
2343
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[8px]", children: "\u2190" })
2344
+ ]
2345
+ }
2346
+ ),
2347
+ /* @__PURE__ */ jsxRuntime.jsxs(
2348
+ "button",
2349
+ {
2350
+ className: btnClass,
2351
+ onClick: () => setCellFormat(selectedAddresses, { decimals: (decimals ?? 0) + 1 }),
2352
+ disabled: readOnly,
2353
+ title: "Increase decimal places",
2354
+ children: [
2355
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px]", children: ".00" }),
2356
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[8px]", children: "\u2192" })
2357
+ ]
2358
+ }
2298
2359
  )
2299
2360
  ] }),
2300
2361
  /* @__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: [