@kolkrabbi/kol-framework 0.36.0 → 0.37.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kolkrabbi/kol-framework",
3
- "version": "0.36.0",
3
+ "version": "0.37.0",
4
4
  "description": "KOL app shell — sidenav, layout, theme toggle, footer, heroes + brand color layer. SideNav takes nav data as props so the tree stays app-local.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -20,7 +20,7 @@
20
20
  "react-router-dom": "^6.0.0 || ^7.0.0"
21
21
  },
22
22
  "devDependencies": {
23
- "@kolkrabbi/kol-component": "^0.142.0",
23
+ "@kolkrabbi/kol-component": "^0.173.0",
24
24
  "@kolkrabbi/kol-icons": "^0.25.0"
25
25
  },
26
26
  "files": [
@@ -27,7 +27,7 @@ import { useTheme } from './theme.js'
27
27
  * that — a sidebar row is not a button.
28
28
  * iconRight bool glyph right of the text (left default)
29
29
  * label bool text on/off — off pins the square box
30
- * per rung (28/32/36; icon-only is a
30
+ * per size (22/26/32/40; icon-only is a
31
31
  * geometry condition, not a variant)
32
32
  * fullWidth bool stretches to a sidenav row
33
33
  * size 'sm' | 'md' | 'lg' moves pad + text + glyph together
@@ -102,9 +102,34 @@ const readBack = (n) => {
102
102
  * side — which EDGE the grab handle sits on. 'left' (default) is a rail on
103
103
  * the left of the viewport whose handle is on its right edge, so
104
104
  * rightward drag = wider. 'right' inverts both the pointer sign and
105
- * the arrow keys. */
105
+ * the arrow keys.
106
+ * persistWidth — remember a dragged WIDTH across sessions. **Default false**
107
+ * (sidenav-drag-width-outranks-breakpoints, kol-client-olina
108
+ * 2026-09-03; user: *"why would you want that in persistent memory?
109
+ * and even if you did, shouldnt it be an opt in via prop? off by
110
+ * default"*).
111
+ *
112
+ * It used to be unconditional, and the width was replayed on boot as
113
+ * an INLINE custom property on `:root` — which outranks every
114
+ * stylesheet rule, so one drag on a laptop killed both shipped rungs
115
+ * (`--kol-sidenav-w: 264px` and the 320px `min-width:1536px` rule)
116
+ * permanently, on every machine, with no UI saying so and no selector
117
+ * a consumer could beat. Measured at 1600×900: a stored 210 rendered
118
+ * 210 and the 1536 rung did nothing. A one-off gesture had become a
119
+ * permanent global.
120
+ *
121
+ * Off, a drag still works and lasts the session; the rail follows the
122
+ * stylesheet and its breakpoints on the next boot. On, the old
123
+ * behaviour returns for an app that genuinely wants the rail
124
+ * remembered — and it is still an inline stamp, so an app opting in is
125
+ * choosing to outrank its own breakpoints. That precedence is worth
126
+ * inverting, but it is a bigger change than this ticket asked for.
127
+ *
128
+ * STATE is untouched: collapsed/expanded still persists via
129
+ * `stateKey`, unconditionally, as it always did. The ticket says the
130
+ * two are separate questions and only asks about the width. */
106
131
  export default function useDragResize(ref, options = {}) {
107
- const { token = 'kol-sidenav', side = 'left', defaultCollapsed = false } = options
132
+ const { token = 'kol-sidenav', side = 'left', defaultCollapsed = false, persistWidth = false } = options
108
133
  /* -1 on a right-hand rail: the same rightward pointer travel that widens a
109
134
  * left rail must NARROW a right one, because its handle faces the canvas. */
110
135
  const dir = side === 'right' ? -1 : 1
@@ -127,7 +152,10 @@ export default function useDragResize(ref, options = {}) {
127
152
  setWidthPx(w)
128
153
  try {
129
154
  localStorage.setItem(names.stateKey, c ? 'collapsed' : 'expanded')
130
- if (w == null) localStorage.removeItem(names.widthKey)
155
+ /* width only when asked for; off, the key is not written AND any key a
156
+ * previous version left behind is cleared, so a consumer that bumps stops
157
+ * replaying a width it never opted into */
158
+ if (!persistWidth || w == null) localStorage.removeItem(names.widthKey)
131
159
  else localStorage.setItem(names.widthKey, String(Math.round(w)))
132
160
  } catch { /* storage blocked */ }
133
161
  }
@@ -146,7 +174,9 @@ export default function useDragResize(ref, options = {}) {
146
174
  let w = null
147
175
  let stored = null
148
176
  try {
149
- w = parseFloat(localStorage.getItem(names.widthKey)) || null
177
+ /* off → never read it, and drop a key an earlier version wrote */
178
+ if (persistWidth) w = parseFloat(localStorage.getItem(names.widthKey)) || null
179
+ else localStorage.removeItem(names.widthKey)
150
180
  stored = localStorage.getItem(names.stateKey)
151
181
  } catch { /* storage blocked */ }
152
182
  /* nothing stored → the consumer's boot state (RailSideNavPixelParity,
@@ -155,7 +185,7 @@ export default function useDragResize(ref, options = {}) {
155
185
  const c = stored ? stored === 'collapsed' : !!defaultCollapsed
156
186
  if (w) { writeWidth(names, w); setWidthPx(w) }
157
187
  if (c) { stampCollapsed(names, true); setCollapsed(true) }
158
- }, [names, defaultCollapsed])
188
+ }, [names, defaultCollapsed, persistWidth])
159
189
 
160
190
  useEffect(() => {
161
191
  const onMove = (e) => {