@ricsam/react-spreadsheets 0.0.3 → 0.0.4

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.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/react-spreadsheets",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "type": "module"
5
5
  }
package/dist/styles.css CHANGED
@@ -16,12 +16,8 @@
16
16
  * ---------------------------------------------------------------------------
17
17
  * Light / dark
18
18
  * ---------------------------------------------------------------------------
19
- * Colors resolve through `light-dark()`, which follows the inherited
20
- * `color-scheme`. The grid deliberately does NOT declare `color-scheme` on
21
- * `.rsp-root`, because doing so would override a `color-scheme` pin set by an
22
- * ancestor and de-sync the grid from the surrounding page.
23
- *
24
- * To pin a subtree, set `color-scheme` on any ancestor (or on `.rsp-root`):
19
+ * By default the grid follows the user's OS preference. To pin a subtree, set
20
+ * `color-scheme` on the grid root or on any ancestor:
25
21
  *
26
22
  * .workbook-stage { color-scheme: light; } // always light
27
23
  * .workbook-stage { color-scheme: dark; } // always dark
@@ -30,26 +26,90 @@
30
26
  *
31
27
  * <FormulaWorkbook className="rsp-theme-light" />
32
28
  * <FormulaWorkbook className="rsp-theme-dark" />
29
+ *
30
+ * Implementation note — why not `light-dark()`?
31
+ * ---------------------------------------------------------------------------
32
+ * `light-dark()` would be the natural choice, but bundlers that target
33
+ * browsers without native support (Vite's Lightning CSS, for example) lower it
34
+ * to a pair of switch custom properties that are only emitted in rules which
35
+ * *also* declare `color-scheme`. Tokens declared once on a shared root then
36
+ * compute to an invalid value like `#ffffff #0f1523`, and every themed surface
37
+ * silently falls back to `transparent` / inherited text — a failure that only
38
+ * appears in a production build.
39
+ *
40
+ * Instead the same space-toggle trick is applied directly, using our own
41
+ * `--rsp-light` / `--rsp-dark` switches. Exactly one of the two is set to
42
+ * `initial` (making its `var()` fall back to the color) while the other is set
43
+ * to a single space (contributing nothing), so each token resolves to one
44
+ * color. This is plain custom-property substitution that no bundler rewrites,
45
+ * and it inherits, so an ancestor's pin still wins.
46
+ *
47
+ * A plain stylesheet cannot read an ancestor's `color-scheme`, so the component
48
+ * resolves it from the mounted element and reflects the result onto the grid
49
+ * root as `data-rsp-scheme`. That covers a pin declared in CSS, inline, or via
50
+ * the helper classes. The media query below is the pre-resolution default.
33
51
  */
34
52
 
35
- :root {
53
+ /* Default: follow the OS preference. */
54
+ :root,
55
+ .rsp-root {
56
+ --rsp-light: initial;
57
+ --rsp-dark: ;
58
+ }
59
+
60
+ @media (prefers-color-scheme: dark) {
61
+ :root,
62
+ .rsp-root {
63
+ --rsp-light: ;
64
+ --rsp-dark: initial;
65
+ }
66
+ }
67
+
68
+ /* Resolved by the component from the inherited `color-scheme`, so a pin set in
69
+ CSS, inline, or via the helper classes below is all honoured. */
70
+ [data-rsp-scheme="light"] {
71
+ --rsp-light: initial;
72
+ --rsp-dark: ;
73
+ }
74
+
75
+ [data-rsp-scheme="dark"] {
76
+ --rsp-light: ;
77
+ --rsp-dark: initial;
78
+ }
79
+
80
+ /* Explicit opt-in pins. `color-scheme` is set too so native scrollbars and
81
+ form controls agree with the token switch. */
82
+ .rsp-theme-light {
83
+ color-scheme: light;
84
+ --rsp-light: initial;
85
+ --rsp-dark: ;
86
+ }
87
+
88
+ .rsp-theme-dark {
89
+ color-scheme: dark;
90
+ --rsp-light: ;
91
+ --rsp-dark: initial;
92
+ }
93
+
94
+ :root,
95
+ .rsp-root {
36
96
  /* Surfaces */
37
- --rsp-bg: light-dark(#ffffff, #0f1523);
38
- --rsp-surface: light-dark(#ffffff, #151c2c);
39
- --rsp-header-bg: light-dark(#f7f8fa, #1a2233);
40
- --rsp-header-active-bg: light-dark(#e9edf5, #24304a);
41
- --rsp-corner-bg: light-dark(#eef1f6, #1a2233);
42
- --rsp-editor-bg: light-dark(#ffffff, #1a2233);
97
+ --rsp-bg: var(--rsp-light, #ffffff) var(--rsp-dark, #0f1523);
98
+ --rsp-surface: var(--rsp-light, #ffffff) var(--rsp-dark, #151c2c);
99
+ --rsp-header-bg: var(--rsp-light, #f7f8fa) var(--rsp-dark, #1a2233);
100
+ --rsp-header-active-bg: var(--rsp-light, #e9edf5) var(--rsp-dark, #24304a);
101
+ --rsp-corner-bg: var(--rsp-light, #eef1f6) var(--rsp-dark, #1a2233);
102
+ --rsp-editor-bg: var(--rsp-light, #ffffff) var(--rsp-dark, #1a2233);
43
103
 
44
104
  /* Lines */
45
- --rsp-border: light-dark(#e3e7ee, #2a3346);
46
- --rsp-corner-border: light-dark(#d7dce6, #2a3346);
47
- --rsp-gridline: light-dark(#e8ebf1, #232c3d);
105
+ --rsp-border: var(--rsp-light, #e3e7ee) var(--rsp-dark, #2a3346);
106
+ --rsp-corner-border: var(--rsp-light, #d7dce6) var(--rsp-dark, #2a3346);
107
+ --rsp-gridline: var(--rsp-light, #e8ebf1) var(--rsp-dark, #232c3d);
48
108
 
49
109
  /* Text */
50
- --rsp-text: light-dark(#101828, #e8ecf4);
51
- --rsp-header-text: light-dark(#5a6478, #99a4bb);
52
- --rsp-muted-text: light-dark(#6b7280, #8c97ad);
110
+ --rsp-text: var(--rsp-light, #101828) var(--rsp-dark, #e8ecf4);
111
+ --rsp-header-text: var(--rsp-light, #5a6478) var(--rsp-dark, #99a4bb);
112
+ --rsp-muted-text: var(--rsp-light, #6b7280) var(--rsp-dark, #8c97ad);
53
113
 
54
114
  /* Accent / selection.
55
115
  NOTE: `@ricsam/selection-manager` paints the selection *perimeter* as an
@@ -57,25 +117,25 @@
57
117
  The default accent stays in that blue family so the perimeter agrees with
58
118
  the rest of the chrome out of the box. Overriding `--rsp-accent` with a
59
119
  distant hue will make the perimeter read slightly differently. */
60
- --rsp-accent: light-dark(#2196f3, #58a6ff);
120
+ --rsp-accent: var(--rsp-light, #2196f3) var(--rsp-dark, #58a6ff);
61
121
  --rsp-accent-contrast: #ffffff;
62
- --rsp-selection-bg: light-dark(#e8f2fe, #17304f);
63
- --rsp-selection-range-bg: light-dark(#f1f7fe, #14263d);
64
- --rsp-hover-bg: light-dark(#f5f7fa, #1c2436);
65
- --rsp-focus-ring: light-dark(rgba(33, 150, 243, 0.22), rgba(88, 166, 255, 0.28));
122
+ --rsp-selection-bg: var(--rsp-light, #e8f2fe) var(--rsp-dark, #17304f);
123
+ --rsp-selection-range-bg: var(--rsp-light, #f1f7fe) var(--rsp-dark, #14263d);
124
+ --rsp-hover-bg: var(--rsp-light, #f5f7fa) var(--rsp-dark, #1c2436);
125
+ --rsp-focus-ring: var(--rsp-light, rgba(33, 150, 243, 0.22)) var(--rsp-dark, rgba(88, 166, 255, 0.28));
66
126
 
67
127
  /* Danger (delete buttons, invalid input) */
68
- --rsp-danger: light-dark(#d92d20, #ff8a80);
69
- --rsp-danger-bg: light-dark(#fef3f2, #3a1512);
128
+ --rsp-danger: var(--rsp-light, #d92d20) var(--rsp-dark, #ff8a80);
129
+ --rsp-danger-bg: var(--rsp-light, #fef3f2) var(--rsp-dark, #3a1512);
70
130
 
71
131
  /* Tables (consumed by the workbook's inline cell styles) */
72
- --rsp-table-header-bg: light-dark(#2196f3, #1c3a5e);
73
- --rsp-table-header-color: light-dark(#ffffff, #e8ecf4);
74
- --rsp-table-header-border: light-dark(#1877c9, #2a5384);
75
- --rsp-table-even-row-bg: light-dark(#f7f9fc, #161e2e);
76
- --rsp-table-odd-row-bg: light-dark(#ffffff, #131a28);
77
- --rsp-table-border-color: light-dark(#2196f3, #34405c);
78
- --rsp-table-border-light: light-dark(#dfe4ec, #2a3346);
132
+ --rsp-table-header-bg: var(--rsp-light, #2196f3) var(--rsp-dark, #1c3a5e);
133
+ --rsp-table-header-color: var(--rsp-light, #ffffff) var(--rsp-dark, #e8ecf4);
134
+ --rsp-table-header-border: var(--rsp-light, #1877c9) var(--rsp-dark, #2a5384);
135
+ --rsp-table-even-row-bg: var(--rsp-light, #f7f9fc) var(--rsp-dark, #161e2e);
136
+ --rsp-table-odd-row-bg: var(--rsp-light, #ffffff) var(--rsp-dark, #131a28);
137
+ --rsp-table-border-color: var(--rsp-light, #2196f3) var(--rsp-dark, #34405c);
138
+ --rsp-table-border-light: var(--rsp-light, #dfe4ec) var(--rsp-dark, #2a3346);
79
139
 
80
140
  /* Typography */
81
141
  --rsp-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
@@ -107,7 +167,8 @@
107
167
  }
108
168
 
109
169
  .rsp-root {
110
- /* No `color-scheme` here on purpose — see the file header. */
170
+ /* No `color-scheme` here on purpose: declaring it would override a pin set by
171
+ an ancestor. See the file header. */
111
172
  color: var(--rsp-text);
112
173
  font-family: var(--rsp-font-family);
113
174
  }
@@ -0,0 +1,16 @@
1
+ import { type ColorScheme } from "./use-color-scheme";
2
+ /**
3
+ * Props for a `.rsp-root` element so its light/dark tokens match the inherited
4
+ * `color-scheme`.
5
+ *
6
+ * A stylesheet cannot branch on an *ancestor's* `color-scheme`, and the
7
+ * `light-dark()` function is rewritten by some bundlers into switch variables
8
+ * that only exist next to a `color-scheme` declaration (see `styles.css`).
9
+ * Resolving the scheme from the mounted element and reflecting it as
10
+ * `data-rsp-scheme` keeps the tokens correct without the component declaring
11
+ * `color-scheme` itself, which would override a consumer's pin.
12
+ */
13
+ export declare function useSchemeRoot(): {
14
+ ref: (element: HTMLElement | null) => void;
15
+ "data-rsp-scheme": ColorScheme;
16
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ricsam/react-spreadsheets",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "description": "Headless-friendly React spreadsheet and workbook components: infinite virtualized grid, zoom, resizing, clipboard, fill handles and formula-engine bindings.",
5
5
  "type": "module",
6
6
  "module": "./dist/mjs/lib.mjs",