@kolkrabbi/kol-workshop 0.31.0 → 0.32.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 +6 -6
- package/src/shell/ShellLayout.jsx +44 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kolkrabbi/kol-workshop",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.32.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "KOL workshop/docs system — a handrolled markdown engine, search, tag system (incl. a d3 tag graph), docs viewer, and docs shell. Sits above @kolkrabbi/kol-{theme,icons,component,framework}; content is consumer-injected (the package never globs docs).",
|
|
6
6
|
"license": "MIT",
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"d3": "^7.9.0",
|
|
16
|
-
"@kolkrabbi/kol-search": "^0.2.0",
|
|
17
16
|
"@kolkrabbi/kol-brand": "^0.1.3",
|
|
18
|
-
"@kolkrabbi/kol-markdown": "^0.1.2"
|
|
17
|
+
"@kolkrabbi/kol-markdown": "^0.1.2",
|
|
18
|
+
"@kolkrabbi/kol-search": "^0.2.0"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
21
21
|
"@kolkrabbi/kol-component": ">=0.228.0",
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@kolkrabbi/kol-component": "^0.230.0",
|
|
31
|
-
"@kolkrabbi/kol-
|
|
32
|
-
"@kolkrabbi/kol-theme": "^0.
|
|
33
|
-
"@kolkrabbi/kol-
|
|
31
|
+
"@kolkrabbi/kol-icons": "^0.30.0",
|
|
32
|
+
"@kolkrabbi/kol-theme": "^0.158.0",
|
|
33
|
+
"@kolkrabbi/kol-framework": "^0.47.0"
|
|
34
34
|
},
|
|
35
35
|
"files": [
|
|
36
36
|
"src",
|
|
@@ -79,9 +79,39 @@ export const SHELL_SCROLL_ROOT = '#shell-scroll'
|
|
|
79
79
|
* overflow (`.shell-rail`, kol-components-workshop.css): exactly one region
|
|
80
80
|
* tall, a seam toward the page, the chrome inset inside the seam.
|
|
81
81
|
* overflow-x-hidden (2026-07-30): long tree rows must not scroll sideways. */
|
|
82
|
-
|
|
82
|
+
/* RESIZABLE RAILS (2026-09-30, the names audit; Round 3 Q3 — decided on the recommendation, the
|
|
83
|
+
* user asleep, for review). A 6px grab strip on the edge facing the page: drag to set the width
|
|
84
|
+
* (200–420, remembered), double-click to reset to the shell's 256. The width is the shell's own
|
|
85
|
+
* token, `--kol-shell-nav-w` / `--kol-shell-toc-w`, set on the shell root, so the grid tracks and
|
|
86
|
+
* the rail's own box follow it. */
|
|
87
|
+
const RAIL_MIN = 200
|
|
88
|
+
const RAIL_MAX = 420
|
|
89
|
+
const RailGrip = ({ side, width, onChange }) => {
|
|
90
|
+
const start = (e) => {
|
|
91
|
+
e.preventDefault()
|
|
92
|
+
const x0 = e.clientX
|
|
93
|
+
const w0 = width
|
|
94
|
+
const move = (m) => onChange(Math.round(Math.min(RAIL_MAX, Math.max(RAIL_MIN, w0 + (side === 'end' ? m.clientX - x0 : x0 - m.clientX)))))
|
|
95
|
+
const up = () => { window.removeEventListener('pointermove', move); window.removeEventListener('pointerup', up) }
|
|
96
|
+
window.addEventListener('pointermove', move)
|
|
97
|
+
window.addEventListener('pointerup', up)
|
|
98
|
+
}
|
|
99
|
+
return (
|
|
100
|
+
<div
|
|
101
|
+
role="separator"
|
|
102
|
+
aria-orientation="vertical"
|
|
103
|
+
aria-label="Resize rail"
|
|
104
|
+
onPointerDown={start}
|
|
105
|
+
onDoubleClick={() => onChange(null)}
|
|
106
|
+
className={`absolute top-0 hidden h-full w-1.5 cursor-col-resize hover:bg-oq-08 lg:block ${side === 'end' ? 'right-0' : 'left-0'}`}
|
|
107
|
+
/>
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const NavColumn = ({ children, grip }) => (
|
|
83
112
|
<aside aria-label="Navigation" className="shell-rail shell-rail--nav shell-sidebar-sticky hidden lg:block pt-6 md:pt-6 lg:pt-8 pb-8">
|
|
84
113
|
{children}
|
|
114
|
+
{grip}
|
|
85
115
|
</aside>
|
|
86
116
|
)
|
|
87
117
|
|
|
@@ -118,8 +148,9 @@ const MainColumn = ({ children, fullHeight, width = 'canvas', padStart, padEnd }
|
|
|
118
148
|
/* `xl`, not `lg` — the grid only declares a third column at xl (gridCols
|
|
119
149
|
* below). The breakpoint here and the one in gridCols are one decision and
|
|
120
150
|
* must not be stated twice differently. */
|
|
121
|
-
const TocColumn = ({ children }) => (
|
|
151
|
+
const TocColumn = ({ children, grip }) => (
|
|
122
152
|
<aside aria-label="Table of contents" className="shell-rail shell-rail--toc shell-sidebar-sticky hidden xl:block pt-6 md:pt-6 lg:pt-8 pb-8">
|
|
153
|
+
{grip}
|
|
123
154
|
{/* The width is the grid track (--kol-shell-toc-w). An empty rail still
|
|
124
155
|
* holds its column (user ruling 2026-08-01): a rail that disappears
|
|
125
156
|
* re-flows main and the same page ends up at two widths. */}
|
|
@@ -164,6 +195,10 @@ const ShellLayout = ({ routes = [], basePath = '/', brand: brandProp, brandLogoS
|
|
|
164
195
|
const [prefs, setPrefs] = useState(readSettings)
|
|
165
196
|
const setPref = (key, value) => setPrefs((p) => { const next = { ...p, [key]: value }; writeSettings(next); return next })
|
|
166
197
|
const [navCollapsed, setNavCollapsed] = useState(() => readSettings().navHidden === true)
|
|
198
|
+
/* rail widths — null = the shell's token; a number is the viewer's own (remembered) */
|
|
199
|
+
const [navW, setNavW] = useState(() => readSettings().navW ?? null)
|
|
200
|
+
const [tocW, setTocW] = useState(() => readSettings().tocW ?? null)
|
|
201
|
+
const setRailW = (key, set) => (w) => { set(w); writeSettings({ ...readSettings(), [key]: w }) }
|
|
167
202
|
const [tocCollapsed, setTocCollapsed] = useState(() => readSettings().tocHidden === true)
|
|
168
203
|
const [isSettingsOpen, setIsSettingsOpen] = useState(false)
|
|
169
204
|
/* ONE QUERY (user ruling 2026-08-01). The palette's text used to live here
|
|
@@ -430,13 +465,17 @@ const ShellLayout = ({ routes = [], basePath = '/', brand: brandProp, brandLogoS
|
|
|
430
465
|
<ShellContentWidthContext.Provider value={setContentWidth}>
|
|
431
466
|
<ShellTocCollapsedContext.Provider value={setTocCollapsed}>
|
|
432
467
|
<ShellNavCollapsedContext.Provider value={setNavCollapsed}>
|
|
433
|
-
<div
|
|
468
|
+
<div
|
|
469
|
+
className="fixed inset-0 flex flex-col bg-surface-primary text-auto"
|
|
470
|
+
style={{ ...(navW ? { '--kol-shell-nav-w': `${navW}px` } : {}), ...(tocW ? { '--kol-shell-toc-w': `${tocW}px` } : {}) }}
|
|
471
|
+
>
|
|
434
472
|
<ShellHeader
|
|
435
473
|
brand={brand}
|
|
436
474
|
nav={navItems}
|
|
437
475
|
isActive={isActive}
|
|
438
476
|
onNavigate={handleNavigate}
|
|
439
477
|
actions={searchTrigger}
|
|
478
|
+
menuBelowLg
|
|
440
479
|
onMenuClick={() => {
|
|
441
480
|
if (window.matchMedia('(min-width: 1024px)').matches) {
|
|
442
481
|
/* Both rails to ONE target state — independent `!p` flips made
|
|
@@ -464,7 +503,7 @@ const ShellLayout = ({ routes = [], basePath = '/', brand: brandProp, brandLogoS
|
|
|
464
503
|
>
|
|
465
504
|
<div className={`shell-content-grid grid ${gridCols}`} data-layout={layoutType} style={{ paddingInline: 'var(--kol-pad-chrome-x)' }}>
|
|
466
505
|
{showNav && (
|
|
467
|
-
<NavColumn>
|
|
506
|
+
<NavColumn grip={<RailGrip side="end" width={navW ?? 256} onChange={setRailW('navW', setNavW)} />}>
|
|
468
507
|
{renderSidebar ? renderSidebar({ activeRoute }) : <ShellSidebar routes={routes} basePath={basePath} />}
|
|
469
508
|
</NavColumn>
|
|
470
509
|
)}
|
|
@@ -482,7 +521,7 @@ const ShellLayout = ({ routes = [], basePath = '/', brand: brandProp, brandLogoS
|
|
|
482
521
|
* the grid's third track so main keeps one width across
|
|
483
522
|
* every route (user ruling 2026-08-01). */}
|
|
484
523
|
{showToc && (
|
|
485
|
-
<TocColumn>
|
|
524
|
+
<TocColumn grip={<RailGrip side="start" width={tocW ?? 256} onChange={setRailW('tocW', setTocW)} />}>
|
|
486
525
|
{effectiveTocContent}
|
|
487
526
|
</TocColumn>
|
|
488
527
|
)}
|