@sheetpane/visibility 0.0.0-stage → 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Arpit Arya
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,32 @@
1
- # Temporary Holding Version
1
+ # @sheetpane/visibility
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ **Hide and unhide rows, columns and sheets in `<sheetpane-excel>` — as changes, written into the download.**
4
+
5
+ The grid already honours what a file hides, marks it (◂▸ / ▴▾ on the headers, a double line, a
6
+ *⊘ n hidden* button for sheets) and lets anyone show it for viewing. This plugin adds editing, in
7
+ Edit:
8
+
9
+ ```js
10
+ import '@sheetpane/visibility/ui';
11
+ excel.setAttribute('plugins', 'visibility');
12
+ ```
13
+
14
+ | action | where | Windows / Linux | Mac |
15
+ |---|---|---|---|
16
+ | Hide rows / columns | the selection bar, the cell and header menus | Ctrl+Alt+9 / Ctrl+Alt+0 | ⌘⌥9 / ⌘⌥0 |
17
+ | Unhide rows / columns (select across the gap) | the same, and a click on a marker | Ctrl+Shift+9 / Ctrl+Shift+0 | ⌘⇧9 / ⌘⇧0 |
18
+ | Group / Ungroup (outline) | the selection bar, the header menu | Alt+Shift+→ / Alt+Shift+← | ⌥⇧→ / ⌥⇧← |
19
+ | Hide sheet | right-click a tab (or Shift+F10 on it) | — | — |
20
+ | Unhide sheet | the banner on a hidden sheet opened from *⊘ n hidden* | — | — |
21
+
22
+ Excel's own Ctrl+9 / Ctrl+0 belong to the browser, so the keys are Google Sheets'. On Windows,
23
+ Ctrl+Shift+0 is often taken by the input-language hotkey — the header menu always works.
24
+
25
+ - **Changes:** hiding is counted once per sheet and axis, undoable, and the download carries it
26
+ (`patchXlsx`'s `hidden` option). Revealing for viewing never is.
27
+ - **Rules:** the last visible sheet cannot be hidden ("A workbook needs one visible sheet"); a CSV
28
+ stores no hidden state, so the controls are disabled there.
29
+ - **Headless:** `visibility()` from `@sheetpane/visibility`, and the actions `setSpanHidden`,
30
+ `setSheetHidden`, `hiddenIn`, `canHideSheet`, `spanOf`.
31
+
32
+ Spec: [SR-VISIBILITY](../../records/0121_VISIBILITY.md). MIT.
@@ -0,0 +1,64 @@
1
+ import { type Plugin, type Selection, type Snapshot, type WorkbookStore } from '@sheetpane/grid';
2
+ /**
3
+ * The rows and columns a selection spans, 0-based.
4
+ * @param sel - The selection.
5
+ * @returns Its rows and columns.
6
+ */
7
+ export declare function spanOf(sel: Selection): {
8
+ rows: number[];
9
+ cols: number[];
10
+ };
11
+ /**
12
+ * Why hiding cannot be changed here, or undefined when it can: a CSV stores no hidden state.
13
+ * @param snap - The pane's snapshot.
14
+ * @returns The reason, or undefined.
15
+ */
16
+ export declare function blockedReason(snap: Snapshot): string | undefined;
17
+ /**
18
+ * Hides the selection's rows or columns — one undoable change, written into the download.
19
+ * @param store - The pane's workbook.
20
+ * @param sel - The selection.
21
+ * @param axis - `rows` or `cols`.
22
+ * @param hide - True hides; false unhides (a range across a hidden span shows it, as in Excel).
23
+ */
24
+ export declare function setSpanHidden(store: WorkbookStore, sel: Selection, axis: 'rows' | 'cols', hide: boolean): void;
25
+ /**
26
+ * Hides a sheet (`hidden`, never `veryHidden`) or unhides it; the last visible sheet stays.
27
+ * @param store - The pane's workbook.
28
+ * @param sheet - The sheet's name.
29
+ * @param hide - True hides; false unhides.
30
+ * @returns False when refused (the last visible sheet, or a CSV).
31
+ */
32
+ export declare function setSheetHidden(store: WorkbookStore, sheet: string, hide: boolean): boolean;
33
+ /**
34
+ * What a sheet hides, read from a snapshot (the file's, with the hiding changes applied) — what
35
+ * `store.hidden()` gives, for controls that see only the snapshot.
36
+ * @param snap - The pane's snapshot.
37
+ * @param sheet - The sheet's name.
38
+ * @returns Hidden rows and columns (0-based) and the sheet's state.
39
+ */
40
+ export declare function hiddenIn(snap: Snapshot, sheet: string): {
41
+ rows: number[];
42
+ cols: number[];
43
+ state: string;
44
+ };
45
+ /**
46
+ * Whether another sheet would stay visible if this one were hidden.
47
+ * @param snap - The pane's snapshot.
48
+ * @param sheet - The sheet's name.
49
+ * @returns True when the sheet may be hidden.
50
+ */
51
+ export declare function canHideSheet(snap: Snapshot, sheet: string): boolean;
52
+ /**
53
+ * The headless plugin: its presence in a pane lets a hidden-span marker unhide (Edit).
54
+ * @returns The plugin (`id: 'visibility'`).
55
+ * @example
56
+ * ```ts
57
+ * import { createWorkbook } from '@sheetpane/grid';
58
+ * import { visibility } from '@sheetpane/visibility';
59
+ * const book = createWorkbook({ plugins: [visibility()] });
60
+ * ```
61
+ * @see https://github.com/arpitarya/sheetpane/blob/main/records/0121_VISIBILITY.md
62
+ */
63
+ export declare function visibility(): Plugin;
64
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAA2B,KAAK,MAAM,EAAE,KAAK,SAAS,EAAE,KAAK,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAG1H;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAIzE;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAEhE;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAG9G;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAS1F;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAQzG;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAEnE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC"}
package/dist/index.js ADDED
@@ -0,0 +1,96 @@
1
+ // @sheetpane/visibility (W-49) — hiding and unhiding as changes. Core honours, marks and reveals what
2
+ // a file hides (SR-GRID decision 21c); this plugin is what lets an editor change it: with it in the
3
+ // pane, a marker click in Edit unhides, and `./ui` adds the controls. Headless: the actions below.
4
+ // No runtime dependency; `@sheetpane/grid` is a peer.
5
+ import { cellKey, registerPlugin } from '@sheetpane/grid';
6
+ import { parseRange, parseRef } from '@sheetpane/export';
7
+ /**
8
+ * The rows and columns a selection spans, 0-based.
9
+ * @param sel - The selection.
10
+ * @returns Its rows and columns.
11
+ */
12
+ export function spanOf(sel) {
13
+ const r = sel.range ? parseRange(sel.range) : undefined, p = parseRef(sel.ref);
14
+ const top = r ? r.top : p.row, bottom = r ? r.bottom : p.row, left = r ? r.left : p.col, right = r ? r.right : p.col;
15
+ return { rows: Array.from({ length: bottom - top + 1 }, (_, i) => top + i), cols: Array.from({ length: right - left + 1 }, (_, i) => left + i) };
16
+ }
17
+ /**
18
+ * Why hiding cannot be changed here, or undefined when it can: a CSV stores no hidden state.
19
+ * @param snap - The pane's snapshot.
20
+ * @returns The reason, or undefined.
21
+ */
22
+ export function blockedReason(snap) {
23
+ return snap.source?.kind === 'csv' ? 'CSV can’t store hidden rows' : undefined;
24
+ }
25
+ /**
26
+ * Hides the selection's rows or columns — one undoable change, written into the download.
27
+ * @param store - The pane's workbook.
28
+ * @param sel - The selection.
29
+ * @param axis - `rows` or `cols`.
30
+ * @param hide - True hides; false unhides (a range across a hidden span shows it, as in Excel).
31
+ */
32
+ export function setSpanHidden(store, sel, axis, hide) {
33
+ if (blockedReason(store.getSnapshot()))
34
+ return;
35
+ store.setHidden(sel.sheet, axis, spanOf(sel)[axis], hide);
36
+ }
37
+ /**
38
+ * Hides a sheet (`hidden`, never `veryHidden`) or unhides it; the last visible sheet stays.
39
+ * @param store - The pane's workbook.
40
+ * @param sheet - The sheet's name.
41
+ * @param hide - True hides; false unhides.
42
+ * @returns False when refused (the last visible sheet, or a CSV).
43
+ */
44
+ export function setSheetHidden(store, sheet, hide) {
45
+ if (blockedReason(store.getSnapshot()))
46
+ return false;
47
+ const ok = store.setSheetState(sheet, hide ? 'hidden' : 'visible');
48
+ // hiding the sheet in view moves to the next visible one
49
+ if (ok && hide && store.getSnapshot().selection.sheet === sheet) {
50
+ const next = store.getSnapshot().book.sheets.find((x) => x.name !== sheet && store.hidden(x.name).state === 'visible');
51
+ if (next)
52
+ store.select({ sheet: next.name, ref: 'A1' });
53
+ }
54
+ return ok;
55
+ }
56
+ /**
57
+ * What a sheet hides, read from a snapshot (the file's, with the hiding changes applied) — what
58
+ * `store.hidden()` gives, for controls that see only the snapshot.
59
+ * @param snap - The pane's snapshot.
60
+ * @param sheet - The sheet's name.
61
+ * @returns Hidden rows and columns (0-based) and the sheet's state.
62
+ */
63
+ export function hiddenIn(snap, sheet) {
64
+ const sh = snap.book?.sheets.find((x) => x.name === sheet);
65
+ const ch = (k) => snap.changes.get(cellKey(sheet, k))?.now;
66
+ return {
67
+ rows: ch('#hiddenRows') ?? sh?.hiddenRows ?? [],
68
+ cols: ch('#hiddenCols') ?? sh?.hiddenCols ?? [],
69
+ state: ch('#sheetState') ?? sh?.state ?? (sh?.hidden ? 'hidden' : 'visible'),
70
+ };
71
+ }
72
+ /**
73
+ * Whether another sheet would stay visible if this one were hidden.
74
+ * @param snap - The pane's snapshot.
75
+ * @param sheet - The sheet's name.
76
+ * @returns True when the sheet may be hidden.
77
+ */
78
+ export function canHideSheet(snap, sheet) {
79
+ return !!snap.book && snap.book.sheets.some((x) => x.name !== sheet && hiddenIn(snap, x.name).state === 'visible');
80
+ }
81
+ /**
82
+ * The headless plugin: its presence in a pane lets a hidden-span marker unhide (Edit).
83
+ * @returns The plugin (`id: 'visibility'`).
84
+ * @example
85
+ * ```ts
86
+ * import { createWorkbook } from '@sheetpane/grid';
87
+ * import { visibility } from '@sheetpane/visibility';
88
+ * const book = createWorkbook({ plugins: [visibility()] });
89
+ * ```
90
+ * @see https://github.com/arpitarya/sheetpane/blob/main/records/0121_VISIBILITY.md
91
+ */
92
+ export function visibility() {
93
+ return { id: 'visibility', provides: [] };
94
+ }
95
+ registerPlugin('visibility', () => visibility());
96
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/ui.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ import { type Plugin } from '@sheetpane/grid';
2
+ /**
3
+ * The controls: Hide and Unhide rows and columns (selection bar, cell and header menus), Group and
4
+ * Ungroup (Alt+Shift+→ / ←), and Hide sheet (tab menu).
5
+ * @returns The controls plugin (`id: 'visibility-ui'`).
6
+ * @example
7
+ * ```ts
8
+ * import '@sheetpane/visibility/ui';
9
+ * excel.setAttribute('plugins', 'visibility'); // a <sheetpane-excel>
10
+ * ```
11
+ * @see https://github.com/arpitarya/sheetpane/blob/main/records/0121_VISIBILITY.md
12
+ */
13
+ export declare function ui(): Plugin;
14
+ //# sourceMappingURL=ui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAIA,OAAO,EAA0C,KAAK,MAAM,EAAqD,MAAM,iBAAiB,CAAC;AA4CzI;;;;;;;;;;GAUG;AACH,wBAAgB,EAAE,IAAI,MAAM,CAgB3B"}
package/dist/ui.js ADDED
@@ -0,0 +1,77 @@
1
+ // @sheetpane/visibility/ui (W-49): Hide / Unhide rows, columns and sheets in the docked selection bar,
2
+ // the cell menu, the header menu and the tab menu, with Google Sheets' keys (Excel's Ctrl+9 / Ctrl+0
3
+ // are the browser's). Labels follow the selection; a CSV and the last visible sheet say why not.
4
+ import { colName, parseRange } from '@sheetpane/export';
5
+ import { registerPlugin } from '@sheetpane/grid';
6
+ import { blockedReason, canHideSheet, hiddenIn, setSheetHidden, setSpanHidden, spanOf, visibility } from './index.js';
7
+ const span = (axis, sel) => {
8
+ const list = spanOf(sel)[axis], a = list[0], b = list[list.length - 1];
9
+ const n = (i) => (axis === 'rows' ? String(i + 1) : colName(i));
10
+ return a === b ? `${axis === 'rows' ? 'row' : 'column'} ${n(a)}` : `${axis === 'rows' ? 'rows' : 'columns'} ${n(a)}–${n(b)}`;
11
+ };
12
+ const hiddenInside = (snap, sel, axis) => {
13
+ const h = new Set(hiddenIn(snap, sel.sheet)[axis]);
14
+ return spanOf(sel)[axis].some((i) => h.has(i));
15
+ };
16
+ function spanControl(axis, hide, shortcut) {
17
+ const verb = hide ? 'Hide' : 'Unhide';
18
+ return {
19
+ id: `visibility-${hide ? 'hide' : 'unhide'}-${axis}`, slot: 'selbar', group: 'visibility', mode: 'edit', shortcut,
20
+ label: `${verb} ${axis === 'rows' ? 'rows' : 'columns'}`,
21
+ labelFor: (_s, sel) => `${verb} ${span(axis, sel)}`,
22
+ menus: ['cell', 'header'],
23
+ // Unhide needs a selection across the hidden span; Hide needs something to hide
24
+ disabled: (snap, sel) => !!blockedReason(snap) || (!hide && !hiddenInside(snap, sel, axis)),
25
+ disabledReason: (snap, sel) => blockedReason(snap) ?? (!hide && !hiddenInside(snap, sel, axis) ? `Select across the hidden ${axis === 'rows' ? 'rows' : 'columns'} to unhide them` : undefined),
26
+ run: (store, sel) => setSpanHidden(store, sel, axis, hide),
27
+ };
28
+ }
29
+ /** Group (+1 level) or ungroup (−1): whole columns selected → columns, else rows. */
30
+ function groupControl(delta) {
31
+ const axisOf = (snap, sel) => {
32
+ const sheet = snap.book?.sheets.find((x) => x.name === sel.sheet), r = sel.range ? parseRange(sel.range) : undefined;
33
+ return r && sheet && r.top === 0 && r.bottom >= sheet.rows.length - 1 && sheet.rows.length > 1 ? 'cols' : 'rows';
34
+ };
35
+ const verb = delta > 0 ? 'Group' : 'Ungroup';
36
+ return {
37
+ id: `visibility-${delta > 0 ? 'group' : 'ungroup'}`, slot: 'selbar', group: 'visibility-outline', mode: 'edit', label: verb,
38
+ shortcut: delta > 0 ? 'Alt+Shift+ArrowRight' : 'Alt+Shift+ArrowLeft', menus: ['header'],
39
+ labelFor: (snap, sel) => `${verb} ${span(axisOf(snap, sel), sel)}`,
40
+ disabled: (snap) => !!blockedReason(snap),
41
+ disabledReason: (snap) => blockedReason(snap),
42
+ run: (store, sel) => { if (!blockedReason(store.getSnapshot())) {
43
+ const axis = axisOf(store.getSnapshot(), sel);
44
+ store.setOutline(sel.sheet, axis, spanOf(sel)[axis], delta);
45
+ } },
46
+ };
47
+ }
48
+ /**
49
+ * The controls: Hide and Unhide rows and columns (selection bar, cell and header menus), Group and
50
+ * Ungroup (Alt+Shift+→ / ←), and Hide sheet (tab menu).
51
+ * @returns The controls plugin (`id: 'visibility-ui'`).
52
+ * @example
53
+ * ```ts
54
+ * import '@sheetpane/visibility/ui';
55
+ * excel.setAttribute('plugins', 'visibility'); // a <sheetpane-excel>
56
+ * ```
57
+ * @see https://github.com/arpitarya/sheetpane/blob/main/records/0121_VISIBILITY.md
58
+ */
59
+ export function ui() {
60
+ const controls = [
61
+ spanControl('rows', true, 'Mod+Alt+9'),
62
+ spanControl('cols', true, 'Mod+Alt+0'),
63
+ spanControl('rows', false, 'Mod+Shift+9'),
64
+ spanControl('cols', false, 'Mod+Shift+0'),
65
+ groupControl(1), groupControl(-1),
66
+ {
67
+ id: 'visibility-hide-sheet', slot: 'selbar', group: 'visibility', mode: 'edit', label: 'Hide sheet', menus: ['tab'],
68
+ labelFor: (_s, sel) => `Hide sheet ${sel.sheet}`,
69
+ disabled: (snap, sel) => !!blockedReason(snap) || !canHideSheet(snap, sel.sheet),
70
+ disabledReason: (snap, sel) => blockedReason(snap) ?? (!canHideSheet(snap, sel.sheet) ? 'A workbook needs one visible sheet' : undefined),
71
+ run: (store, sel) => { setSheetHidden(store, sel.sheet, true); },
72
+ },
73
+ ];
74
+ return { id: 'visibility-ui', provides: [], controls };
75
+ }
76
+ registerPlugin('visibility', () => [visibility(), ui()]);
77
+ //# sourceMappingURL=ui.js.map
package/dist/ui.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,51 @@
1
1
  {
2
2
  "name": "@sheetpane/visibility",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.0",
4
+ "description": "Hide and unhide rows, columns and sheets for sheetpane — menus, Google Sheets' shortcuts, a click on the grid's hidden-span markers — written into the download. Core already honours and marks what a file hides.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/arpitarya/sheetpane.git",
9
+ "directory": "packages/visibility"
10
+ },
11
+ "type": "module",
12
+ "sideEffects": [
13
+ "./dist/index.js",
14
+ "./dist/ui.js",
15
+ "./src/index.ts",
16
+ "./src/ui.ts"
17
+ ],
18
+ "engines": {
19
+ "node": ">=22"
20
+ },
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/index.d.ts",
24
+ "import": "./dist/index.js"
25
+ },
26
+ "./ui": {
27
+ "types": "./dist/ui.d.ts",
28
+ "import": "./dist/ui.js"
29
+ }
30
+ },
31
+ "files": [
32
+ "dist"
33
+ ],
34
+ "peerDependencies": {
35
+ "@sheetpane/grid": "0.1.0"
36
+ },
37
+ "dependencies": {
38
+ "@sheetpane/export": "0.1.0",
39
+ "@sheetpane/skills": "0.1.0"
40
+ },
41
+ "devDependencies": {
42
+ "@sheetpane/grid": "0.1.0"
43
+ },
44
+ "publishConfig": {
45
+ "access": "public"
46
+ },
47
+ "scripts": {
48
+ "build": "tsc -p tsconfig.build.json",
49
+ "typecheck": "tsc -p tsconfig.json --noEmit"
50
+ }
6
51
  }