@kolkrabbi/kol-shell 0.46.0 → 0.47.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-shell",
3
- "version": "0.46.0",
3
+ "version": "0.47.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",
@@ -18,8 +18,11 @@ import WalkthroughPanel from './WalkthroughPanel.jsx'
18
18
  *
19
19
  * Semantics are the consumer's: what RECENT / SAVED mean, what an item is,
20
20
  * what a click does. `toCard(item, { view, layout })` → `{ key, title, detail,
21
- * media, actions, onClick, href, onNavigate, expanded, expandedContent, fit, ratio }` is
22
- * the whole contract `expanded` / `expandedContent` reach `ContentCard catalog`'s
21
+ * …every prop ContentCard / ContentRow takes }` `title`, `detail`, `media`,
22
+ * `actions`, `onClick`, `href`, `onNavigate`, `expanded`, `expandedContent`, `fit`,
23
+ * `ratio`, `date`, `size`, `meta`, `tags`, `selected`, `variant`, … — is the whole
24
+ * contract: the return is SPREAD onto the card or the row (user ruling 2026-09-03,
25
+ * a composition forwards the whole contract of what it composes) — `expanded` / `expandedContent` reach `ContentCard catalog`'s
23
26
  * 2×2 cell (ShellHomeSystemMonitorGaps, kol-monitor 2026-08-27) — and the page
24
27
  * HIDES the cell's three neighbours itself (CatalogPageMonitorParity: the
25
28
  * consumer never sees the filtered row order, so it cannot; monitor's
@@ -50,7 +53,10 @@ import WalkthroughPanel from './WalkthroughPanel.jsx'
50
53
  * framework container — the site tier, so a brand book adopting this page keeps its geometry
51
54
  * @param {ReactNode} trailingActions the header's RIGHT slot (ContentFilters' — MediaLibrary's SELECT / FLAT); never empty beside the divider
52
55
  * @param {number} minColumn the grid track's floor in px (default 160); a shelf of three decks passes 280 — the six-track ceiling still applies
53
- * @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
56
+ * @param {string} cardVariant the grid card's variant, per page (default `catalog`); `toCard` may return `variant` per card
57
+ * @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
+ * its slots (`date` · `size` · `meta` · `selected`) come from `toCard` like everything else
59
+ * @param {'grid'|'stack'} listLayout the list's container (default `grid`, rows four across — monitor's ruling); `stack` = one row per line
54
60
  * @param {ElementType} iconComponent icon renderer seam for ContentFilters
55
61
  * @param {boolean} showCountOnlyWhenFiltering (default true)
56
62
  * @param {Object} filtersProps spread onto ContentFilters last — e.g. `{ mutuallyExclusiveFilters: ['category', 'u_label'] }`
@@ -103,6 +109,13 @@ export default function CatalogPage({
103
109
  passes `file`: the 48px thumb row, so the list shows the same cover small
104
110
  (kol-client-olina 2026-09-03; user, on the bare row: "ugly ugly ugly"). */
105
111
  rowVariant = 'catalog',
112
+ /* the GRID card's variant, per page; `toCard` may return `variant` per card */
113
+ cardVariant = 'catalog',
114
+ /* the LIST's container. `grid` (default) is monitor's ruling — rows four across
115
+ on a 240 floor, gap 8 (the documented `repeat(4, 1fr)`). `stack` is one row per
116
+ line, which is what a list of files is (MediaLibrary stacks); olina's deck list
117
+ rendered three 300px rows side by side (user: "why is it tiny?"). */
118
+ listLayout = 'grid',
106
119
  iconComponent,
107
120
  showCountOnlyWhenFiltering = true,
108
121
  filtersProps,
@@ -151,14 +164,25 @@ export default function CatalogPage({
151
164
  /* the catalog grid is a CLASS (`.kol-catalog-grid`, kol-theme ≥0.137.0) so the
152
165
  * filter row's first group can read the track count it renders; `minColumn`
153
166
  * reaches it as `--kol-catalog-min` on the page (set on PageShell above) */
154
- <div className={layout === 'list' ? undefined : 'kol-catalog-grid'} style={layout === 'list' ? { display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(min(100%, max(240px, calc((100% - 3 * 8px) / 4))), 1fr))', gap: 8 } : undefined}>
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}>
155
168
  {rows.map((item, i) => {
156
169
  if (hidden.has(i)) return null
157
170
  const c = cards[i]
158
171
  const key = c.key ?? item.key ?? item.id ?? item.name ?? i
172
+ /* A COMPOSITION FORWARDS THE WHOLE CONTRACT OF WHAT IT COMPOSES (user
173
+ * 2026-09-03: "why wouldn't we as standard practice ALLOW VARIANT CHANGE
174
+ * EVERY TIME WE USE THOSE CONTENT CARDS?"). Five tickets on this file in
175
+ * one day were the same defect — a key missing from `toCard` because no
176
+ * prior consumer had needed it: `ratio`, `trailingActions`, `rowVariant`,
177
+ * `date` / `size`, the list container. So `toCard`'s return is SPREAD
178
+ * onto the card and the row: every prop either takes is reachable per
179
+ * card, today and for props not written yet; `variant` per card beats
180
+ * the page's `cardVariant` / `rowVariant`; `fit` keeps its `cover`
181
+ * default. `key` is React's and is lifted out first. */
182
+ const { key: _key, ...forwarded } = c
159
183
  return layout === 'list'
160
- ? <ContentRow key={key} variant={rowVariant} media={c.media} ratio={c.ratio} title={c.title} detail={c.detail} actions={c.actions} onClick={c.onClick} href={c.href} onNavigate={c.onNavigate} />
161
- : <ContentCard key={key} variant="catalog" fit={c.fit ?? 'cover'} ratio={c.ratio} title={c.title} detail={c.detail} media={c.media} actions={c.actions} onClick={c.onClick} href={c.href} onNavigate={c.onNavigate} expanded={c.expanded} expandedContent={c.expandedContent} />
184
+ ? <ContentRow key={key} {...forwarded} variant={c.variant ?? rowVariant} />
185
+ : <ContentCard key={key} {...forwarded} variant={c.variant ?? cardVariant} fit={c.fit ?? 'cover'} />
162
186
  })}
163
187
  </div>
164
188
  )