@chalabi/svelte-sheets 2.0.5 → 2.0.7

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/Readme.md CHANGED
@@ -88,6 +88,22 @@ Common flags:
88
88
  - `editable`: false to disable edits (equivalent to readOnly)
89
89
  - `disableHover`: true to disable hover-based selection updates
90
90
 
91
+ Boolean cells (Checkboxes):
92
+
93
+ - `booleanColumns`: array of column indices to render as checkboxes (e.g., `[2, 5]`)
94
+ - `booleanRows`: array of row indices to render as checkboxes (e.g., `[3, 7]`)
95
+
96
+ Boolean cells display a checkmark (✓) for `true` values and a crossed circle (⦻) for `false` values. Users can click to toggle between true/false. The first row (headers) is automatically excluded from boolean rendering.
97
+
98
+ Example:
99
+ ```js
100
+ let options = {
101
+ tableHeight: "70vh",
102
+ booleanColumns: [5], // Column 5 will show checkboxes
103
+ booleanRows: [10], // Row 10 will show checkboxes
104
+ };
105
+ ```
106
+
91
107
  Theme:
92
108
 
93
109
  - `theme`: set to `"dark"` for the bundled dark tokens (default is `"light"`)
package/dist/Sheet.svelte CHANGED
@@ -18,8 +18,9 @@ var __rest = (this && this.__rest) || function (s, e) {
18
18
  }
19
19
  return t;
20
20
  };
21
- import { onMount, tick } from "svelte";
21
+ import { onMount, tick, createEventDispatcher } from "svelte";
22
22
  import * as XLSX from "xlsx";
23
+ const dispatch = createEventDispatcher();
23
24
  import { resizable } from "./actions/index.js";
24
25
  import { draggable } from "./actions/draggable.js";
25
26
  import { defaultconfig } from "./defaultconfig.js";
@@ -190,6 +191,53 @@ export function onInputChange(value, row, column) {
190
191
  data[row.i][column.i] = value;
191
192
  }
192
193
  }
194
+ function isBooleanCell(colIndex, rowIndex) {
195
+ var _a, _b;
196
+ // Don't treat first row as boolean (headers)
197
+ if (rowIndex === 0)
198
+ return false;
199
+ return (((_a = config.booleanColumns) === null || _a === void 0 ? void 0 : _a.includes(colIndex)) ||
200
+ ((_b = config.booleanRows) === null || _b === void 0 ? void 0 : _b.includes(rowIndex)));
201
+ }
202
+ function toggleBooleanCell(colIndex, rowIndex) {
203
+ var _a, _b;
204
+ if (isReadOnly)
205
+ return;
206
+ if ((_a = columns[colIndex]) === null || _a === void 0 ? void 0 : _a.readOnly)
207
+ return;
208
+ if (!isBooleanCell(colIndex, rowIndex))
209
+ return;
210
+ cmdz = true;
211
+ const currentValue = (_b = data[rowIndex]) === null || _b === void 0 ? void 0 : _b[colIndex];
212
+ const newValue = !currentValue;
213
+ if (rowIndex > data.length - 1) {
214
+ data = [
215
+ ...data,
216
+ ...Array.from({ length: rowIndex - data.length + 1 }, (v, i) => {
217
+ if (i == rowIndex) {
218
+ return Array.from({ length: columns.length }, (_, i) => {
219
+ if (i == colIndex) {
220
+ return newValue;
221
+ }
222
+ else {
223
+ return "";
224
+ }
225
+ });
226
+ }
227
+ else {
228
+ return Array.from({ length: columns.length }, (_) => "");
229
+ }
230
+ }),
231
+ ];
232
+ }
233
+ else {
234
+ data[rowIndex][colIndex] = newValue;
235
+ }
236
+ // Dispatch inputchange event for boolean toggle
237
+ dispatch('inputchange', { value: newValue, row: { i: rowIndex }, column: { i: colIndex } });
238
+ historyPush(data, rows, columns, style);
239
+ cmdz = false;
240
+ }
193
241
  function refresh(data, viewport_height, viewport_width) {
194
242
  return __awaiter(this, void 0, void 0, function* () {
195
243
  if (!viewport)
@@ -990,6 +1038,7 @@ function historyPush(data, rows, columns, style) {
990
1038
  on:dblclick={(_) =>
991
1039
  !isReadOnly &&
992
1040
  !(columns[x.i] && columns[x.i].readOnly) &&
1041
+ !isBooleanCell(x.i, r.i) &&
993
1042
  (edition = [x.i, r.i])}
994
1043
  class:readonly={columns[x.i] && columns[x.i].readOnly}
995
1044
  style={computeStyles(
@@ -1002,7 +1051,7 @@ function historyPush(data, rows, columns, style) {
1002
1051
  r.data && r.data[x.i + 1]
1003
1052
  )}
1004
1053
  >
1005
- {#if String(edition) == String([x.i, r.i])}
1054
+ {#if String(edition) == String([x.i, r.i]) && !isBooleanCell(x.i, r.i)}
1006
1055
  <input
1007
1056
  autofocus
1008
1057
  on:blur={(e) => {
@@ -1015,6 +1064,20 @@ function historyPush(data, rows, columns, style) {
1015
1064
  x.i
1016
1065
  )}px; height: ${getRowHeight(r.i)}px; min-height: 22px;`}
1017
1066
  />
1067
+ {:else if isBooleanCell(x.i, r.i)}
1068
+ <span
1069
+ class="boolean-cell"
1070
+ class:readonly={columns[x.i] && columns[x.i].readOnly}
1071
+ on:click|stopPropagation={() => toggleBooleanCell(x.i, r.i)}
1072
+ role="button"
1073
+ tabindex="-1"
1074
+ >
1075
+ {#if r.data && r.data[x.i]}
1076
+ <span class="checkmark">✓</span>
1077
+ {:else}
1078
+ <span class="crossmark">⦻</span>
1079
+ {/if}
1080
+ </span>
1018
1081
  {:else}{(r.data && r.data[x.i]) || ""}{/if}
1019
1082
  </td>
1020
1083
  {/each}
@@ -1243,4 +1306,28 @@ function historyPush(data, rows, columns, style) {
1243
1306
  .hidden {
1244
1307
  display: none;
1245
1308
  }
1309
+ .boolean-cell {
1310
+ display: flex;
1311
+ align-items: center;
1312
+ justify-content: center;
1313
+ width: 100%;
1314
+ height: 100%;
1315
+ cursor: pointer;
1316
+ user-select: none;
1317
+ }
1318
+ .boolean-cell.readonly {
1319
+ cursor: default;
1320
+ }
1321
+ .checkmark {
1322
+ font-size: 18px;
1323
+ font-weight: bold;
1324
+ color: var(--sheet-accent);
1325
+ line-height: 1;
1326
+ }
1327
+ .crossmark {
1328
+ font-size: 18px;
1329
+ font-weight: bold;
1330
+ color: #ef4444;
1331
+ line-height: 1;
1332
+ }
1246
1333
  </style>
@@ -34,6 +34,8 @@ declare const Sheet: $$__sveltets_2_IsomorphicComponent<{
34
34
  endX?: number;
35
35
  onInputChange?: (value: any, row: any, column: any) => void;
36
36
  }, {
37
+ inputchange: CustomEvent<any>;
38
+ } & {
37
39
  [evt: string]: CustomEvent<any>;
38
40
  }, {}, {
39
41
  onInputChange: (value: any, row: any, column: any) => void;
@@ -8,6 +8,8 @@ export declare const defaultconfig: {
8
8
  nestedHeaders: any;
9
9
  defaultColWidth: number;
10
10
  defaultColAlign: string;
11
+ booleanColumns: number[];
12
+ booleanRows: number[];
11
13
  minSpareRows: number;
12
14
  minSpareCols: number;
13
15
  minDimensions: number[];
@@ -17,6 +17,10 @@ export const defaultconfig = {
17
17
  // Column width that is used by default
18
18
  defaultColWidth: 50,
19
19
  defaultColAlign: "center",
20
+ // Boolean columns for checkbox mode
21
+ booleanColumns: [],
22
+ // Boolean rows for checkbox mode
23
+ booleanRows: [],
20
24
  // Spare rows and columns
21
25
  minSpareRows: 0,
22
26
  minSpareCols: 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chalabi/svelte-sheets",
3
- "version": "2.0.5",
3
+ "version": "2.0.7",
4
4
  "description": "Run your excel sheet in the browser!",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",