@kolkrabbi/kol-shell 0.47.0 → 0.49.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 +5 -5
- package/src/CatalogPage.jsx +36 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kolkrabbi/kol-shell",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.49.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "KOL application shell — fixed 48px NavRail + AppShell layout root, PageShell/PageHeader scaffolds, ContentFilters catalog organism, GridCard, SettingsScaffold, WalkthroughPanel, ShortcutsOverlay. App chrome (kol-framework owns site chrome). Nav items, content, shortcuts and settings are consumer-injected. Sits above @kolkrabbi/kol-{theme,component,framework}.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -14,16 +14,16 @@
|
|
|
14
14
|
"peerDependencies": {
|
|
15
15
|
"@kolkrabbi/kol-component": ">=0.174.0",
|
|
16
16
|
"@kolkrabbi/kol-icons": ">=0.16.0",
|
|
17
|
-
"@kolkrabbi/kol-theme": ">=0.
|
|
17
|
+
"@kolkrabbi/kol-theme": ">=0.138.0",
|
|
18
18
|
"gsap": "^3.13.0",
|
|
19
19
|
"react": "^18.3.0 || ^19.0.0",
|
|
20
20
|
"react-dom": "^18.3.0 || ^19.0.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@kolkrabbi/kol-component": "^0.176.0",
|
|
24
|
-
"@kolkrabbi/kol-framework": "^0.41.0",
|
|
25
23
|
"@kolkrabbi/kol-icons": "^0.25.0",
|
|
26
|
-
"@kolkrabbi/kol-
|
|
24
|
+
"@kolkrabbi/kol-component": "^0.177.0",
|
|
25
|
+
"@kolkrabbi/kol-framework": "^0.42.0",
|
|
26
|
+
"@kolkrabbi/kol-theme": "^0.138.0"
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
29
|
"src",
|
package/src/CatalogPage.jsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useCallback, useRef, useState } from 'react'
|
|
1
2
|
import { ContentCard, ContentFilters, ContentRow } from '@kolkrabbi/kol-component'
|
|
2
3
|
import PageShell from './PageShell.jsx'
|
|
3
4
|
import { PageHeader } from '@kolkrabbi/kol-component'
|
|
@@ -52,7 +53,8 @@ import WalkthroughPanel from './WalkthroughPanel.jsx'
|
|
|
52
53
|
* `bleed` (default) fills the window — the app tier; `capped` centres on the
|
|
53
54
|
* framework container — the site tier, so a brand book adopting this page keeps its geometry
|
|
54
55
|
* @param {ReactNode} trailingActions the header's RIGHT slot (ContentFilters' — MediaLibrary's SELECT / FLAT); never empty beside the divider
|
|
55
|
-
* @param {number} minColumn the grid track's floor in px (default 160)
|
|
56
|
+
* @param {number} minColumn the grid track's floor in px (default 160) — a minimum, never a count
|
|
57
|
+
* @param {number} maxColumns the grid's ceiling (default 6, the ruling); a three-deck shelf passes 3 and the tracks share the width
|
|
56
58
|
* @param {string} cardVariant the grid card's variant, per page (default `catalog`); `toCard` may return `variant` per card
|
|
57
59
|
* @param {'catalog'|'file'} rowVariant the list row (default `catalog`, the 36px no-thumb row); `file` = the 48px thumb row, for a catalog whose grid shows a cover —
|
|
58
60
|
* its slots (`date` · `size` · `meta` · `selected`) come from `toCard` like everything else
|
|
@@ -103,6 +105,10 @@ export default function CatalogPage({
|
|
|
103
105
|
/* the grid track's floor. 160 is a 26-tile catalog's; a shelf of three decks
|
|
104
106
|
wants ~280 so the cards read at all. A ceiling of 6 tracks still applies. */
|
|
105
107
|
minColumn = 160,
|
|
108
|
+
/* the ceiling — the six-column ruling is a MAXIMUM; a three-deck shelf says 3
|
|
109
|
+
(kol-client-olina 2026-09-03; user: "why are the cards so small? they could
|
|
110
|
+
use 2 columns each" — raising the floor to force it was backwards) */
|
|
111
|
+
maxColumns = 6,
|
|
106
112
|
/* the LIST row's variant. `catalog` (default) is the 36px GridCard row — title
|
|
107
113
|
and detail on one line, no thumb — which is what every app-tier list was
|
|
108
114
|
ruled on (CatalogPageMonitorParity). A catalog whose grid shows a cover
|
|
@@ -124,8 +130,32 @@ export default function CatalogPage({
|
|
|
124
130
|
style,
|
|
125
131
|
}) {
|
|
126
132
|
const open = walkthrough?.open === true
|
|
133
|
+
/* THE TRACK COUNT, MEASURED (CatalogFilterFirstGroupTrackCount, 2026-09-03).
|
|
134
|
+
* `.kol-catalog-grid` and `.kol-filters-first` both read `--kol-catalog-n`
|
|
135
|
+
* from the page: up to 6 tracks, none narrower than `minColumn`, gap 24 —
|
|
136
|
+
* `min(6, floor((W + 24) / (minColumn + 24)))`, exactly what the old inline
|
|
137
|
+
* `auto-fill` resolved to, now a number the filter row can read too. In JS
|
|
138
|
+
* because the CSS form (`round()` over a length ÷ length) is Chromium-only —
|
|
139
|
+
* theme 0.137.0 rendered ONE column in Firefox. `undefined` until measured
|
|
140
|
+
* → the theme's fallback of 6, the pre-0.137.0 geometry. */
|
|
141
|
+
const [cols, setCols] = useState(null)
|
|
142
|
+
const observer = useRef(null)
|
|
143
|
+
/* a CALLBACK ref: the grid mounts and unmounts with the layout toggle, and a
|
|
144
|
+
* callback ref sees both — an effect keyed on a value out of this scope does
|
|
145
|
+
* not (the first cut referenced `renderItem`'s `layout` here and threw) */
|
|
146
|
+
const gridRef = useCallback((el) => {
|
|
147
|
+
observer.current?.disconnect()
|
|
148
|
+
observer.current = null
|
|
149
|
+
if (!el) return
|
|
150
|
+
const measure = (W) => setCols((c) => { const n = Math.max(1, Math.min(maxColumns, Math.floor((W + 24) / (minColumn + 24)))); return c === n ? c : n })
|
|
151
|
+
measure(el.getBoundingClientRect().width)
|
|
152
|
+
const ro = new ResizeObserver(([entry]) => measure(entry.contentRect.width))
|
|
153
|
+
ro.observe(el)
|
|
154
|
+
observer.current = ro
|
|
155
|
+
}, [minColumn, maxColumns])
|
|
156
|
+
|
|
127
157
|
return (
|
|
128
|
-
<PageShell width={width} className={className} style={{ overflow: 'hidden', '--kol-catalog-
|
|
158
|
+
<PageShell width={width} className={className} style={{ overflow: 'hidden', '--kol-catalog-n': cols ?? undefined, ...style }}>
|
|
129
159
|
{header && <PageHeader {...header} />}
|
|
130
160
|
<div style={{ flex: 1, position: 'relative' }}>
|
|
131
161
|
{open && <WalkthroughPanel steps={walkthrough.steps} iconComponent={walkthrough.iconComponent} />}
|
|
@@ -161,10 +191,10 @@ export default function CatalogPage({
|
|
|
161
191
|
* six-column ruling — below the ceiling the hide-set is
|
|
162
192
|
* desktop-only geometry. */
|
|
163
193
|
return (
|
|
164
|
-
/* the catalog grid is a CLASS (`.kol-catalog-grid`, kol-theme ≥0.
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
<div className={layout === 'list' ? undefined : 'kol-catalog-grid'} style={layout === 'list' ? (listLayout === 'stack' ? { display: 'flex', flexDirection: 'column', gap: 8 } : { display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(min(100%, max(240px, calc((100% - 3 * 8px) / 4))), 1fr))', gap: 8 }) : undefined}>
|
|
194
|
+
/* the catalog grid is a CLASS (`.kol-catalog-grid`, kol-theme ≥0.138.0) reading
|
|
195
|
+
* `--kol-catalog-n`, the count measured above and set on PageShell — the same
|
|
196
|
+
* number the filter row's first group reads */
|
|
197
|
+
<div ref={layout === 'list' ? undefined : gridRef} className={layout === 'list' ? undefined : 'kol-catalog-grid'} style={layout === 'list' ? (listLayout === 'stack' ? { display: 'flex', flexDirection: 'column', gap: 8 } : { display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(min(100%, max(240px, calc((100% - 3 * 8px) / 4))), 1fr))', gap: 8 }) : undefined}>
|
|
168
198
|
{rows.map((item, i) => {
|
|
169
199
|
if (hidden.has(i)) return null
|
|
170
200
|
const c = cards[i]
|