@kolkrabbi/kol-framework 0.35.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 +3 -3
- package/src/ThemeToggle.jsx +1 -1
- package/src/useDragResize.js +53 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kolkrabbi/kol-framework",
|
|
3
|
-
"version": "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,8 +20,8 @@
|
|
|
20
20
|
"react-router-dom": "^6.0.0 || ^7.0.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@kolkrabbi/kol-component": "^0.
|
|
24
|
-
"@kolkrabbi/kol-icons": "^0.
|
|
23
|
+
"@kolkrabbi/kol-component": "^0.173.0",
|
|
24
|
+
"@kolkrabbi/kol-icons": "^0.25.0"
|
|
25
25
|
},
|
|
26
26
|
"files": [
|
|
27
27
|
"src",
|
package/src/ThemeToggle.jsx
CHANGED
|
@@ -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
|
|
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
|
package/src/useDragResize.js
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import { useEffect, useMemo, useRef, useState } from 'react'
|
|
2
|
+
/* THE SAME GRAB AS THE SHELL RAIL (OneGrabGestureBothRails, kol-fxr 2026-08-30 —
|
|
3
|
+
* user: *"why dont we use the grab animation and other sidenav settings to be
|
|
4
|
+
* consistent?"*). fxr's /labs shows both rails at once and only the left one
|
|
5
|
+
* woke as the cursor neared it, because each package had built the gesture
|
|
6
|
+
* itself. The hook lives in kol-component, the one package both can reach —
|
|
7
|
+
* kol-shell dropped its framework peer in 0.16.0, so neither could import the
|
|
8
|
+
* other's. */
|
|
9
|
+
import { useGrabEdge } from '@kolkrabbi/kol-component'
|
|
2
10
|
|
|
3
11
|
/* Grab-edge resize + collapse for SideNav — THE single control since 0.17.0
|
|
4
12
|
* (user build order 2026-08-09, completing the SideNavGrabResize brief: the
|
|
@@ -94,14 +102,44 @@ const readBack = (n) => {
|
|
|
94
102
|
* side — which EDGE the grab handle sits on. 'left' (default) is a rail on
|
|
95
103
|
* the left of the viewport whose handle is on its right edge, so
|
|
96
104
|
* rightward drag = wider. 'right' inverts both the pointer sign and
|
|
97
|
-
* 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. */
|
|
98
131
|
export default function useDragResize(ref, options = {}) {
|
|
99
|
-
const { token = 'kol-sidenav', side = 'left', defaultCollapsed = false } = options
|
|
132
|
+
const { token = 'kol-sidenav', side = 'left', defaultCollapsed = false, persistWidth = false } = options
|
|
100
133
|
/* -1 on a right-hand rail: the same rightward pointer travel that widens a
|
|
101
134
|
* left rail must NARROW a right one, because its handle faces the canvas. */
|
|
102
135
|
const dir = side === 'right' ? -1 : 1
|
|
103
136
|
const names = useMemo(() => buildNames(token), [token])
|
|
104
137
|
|
|
138
|
+
/* the handle's own ref, so the shared gesture can find it. Returned in
|
|
139
|
+
* `grabProps`, so a consumer already spreading those gets the wake, the
|
|
140
|
+
* travel and the dwell with no change. */
|
|
141
|
+
const grabRef = useRef(null)
|
|
142
|
+
useGrabEdge(grabRef)
|
|
105
143
|
const drag = useRef(null) // { startX, startW, snapPx, maxPx, moved } during a drag
|
|
106
144
|
const defaultPx = useRef(null)
|
|
107
145
|
const collapsedPx = useRef(null)
|
|
@@ -114,7 +152,10 @@ export default function useDragResize(ref, options = {}) {
|
|
|
114
152
|
setWidthPx(w)
|
|
115
153
|
try {
|
|
116
154
|
localStorage.setItem(names.stateKey, c ? 'collapsed' : 'expanded')
|
|
117
|
-
|
|
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)
|
|
118
159
|
else localStorage.setItem(names.widthKey, String(Math.round(w)))
|
|
119
160
|
} catch { /* storage blocked */ }
|
|
120
161
|
}
|
|
@@ -133,7 +174,9 @@ export default function useDragResize(ref, options = {}) {
|
|
|
133
174
|
let w = null
|
|
134
175
|
let stored = null
|
|
135
176
|
try {
|
|
136
|
-
|
|
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)
|
|
137
180
|
stored = localStorage.getItem(names.stateKey)
|
|
138
181
|
} catch { /* storage blocked */ }
|
|
139
182
|
/* nothing stored → the consumer's boot state (RailSideNavPixelParity,
|
|
@@ -142,7 +185,7 @@ export default function useDragResize(ref, options = {}) {
|
|
|
142
185
|
const c = stored ? stored === 'collapsed' : !!defaultCollapsed
|
|
143
186
|
if (w) { writeWidth(names, w); setWidthPx(w) }
|
|
144
187
|
if (c) { stampCollapsed(names, true); setCollapsed(true) }
|
|
145
|
-
}, [names, defaultCollapsed])
|
|
188
|
+
}, [names, defaultCollapsed, persistWidth])
|
|
146
189
|
|
|
147
190
|
useEffect(() => {
|
|
148
191
|
const onMove = (e) => {
|
|
@@ -249,6 +292,11 @@ export default function useDragResize(ref, options = {}) {
|
|
|
249
292
|
collapsed,
|
|
250
293
|
toggleCollapsed,
|
|
251
294
|
grabProps: {
|
|
295
|
+
ref: grabRef,
|
|
296
|
+
/* the pill is drawn by `.kol-rail-grab` (kol-animation.css) — the hook
|
|
297
|
+
* only supplies `is-near` and `--kol-rail-grab-y`. A consumer's own
|
|
298
|
+
* className, spread after this, still wins. */
|
|
299
|
+
className: 'kol-rail-grab',
|
|
252
300
|
role: 'separator',
|
|
253
301
|
'aria-orientation': 'vertical',
|
|
254
302
|
'aria-label': 'Resize navigation',
|