@kolkrabbi/kol-shell 0.42.0 → 0.44.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 +4 -4
- package/src/CatalogPage.jsx +17 -3
- package/src/PageShell.jsx +27 -25
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kolkrabbi/kol-shell",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.44.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.136.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
23
|
"@kolkrabbi/kol-component": "^0.176.0",
|
|
24
|
-
"@kolkrabbi/kol-framework": "^0.
|
|
24
|
+
"@kolkrabbi/kol-framework": "^0.41.0",
|
|
25
25
|
"@kolkrabbi/kol-icons": "^0.25.0",
|
|
26
|
-
"@kolkrabbi/kol-theme": "^0.
|
|
26
|
+
"@kolkrabbi/kol-theme": "^0.136.0"
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
29
|
"src",
|
package/src/CatalogPage.jsx
CHANGED
|
@@ -45,6 +45,11 @@ import WalkthroughPanel from './WalkthroughPanel.jsx'
|
|
|
45
45
|
* @param {string} defaultLayout 'grid' (default) | 'list'
|
|
46
46
|
* @param {{steps: Array, open: boolean, iconComponent?: ElementType}} walkthrough the panel over the catalog
|
|
47
47
|
* @param {ReactNode} actions the bottom row's buttons
|
|
48
|
+
* @param {'bleed'|'capped'} width the page's TIER, forwarded to PageShell (two-page-scaffolds-one-job, 2026-09-03):
|
|
49
|
+
* `bleed` (default) fills the window — the app tier; `capped` centres on the
|
|
50
|
+
* framework container — the site tier, so a brand book adopting this page keeps its geometry
|
|
51
|
+
* @param {ReactNode} trailingActions the header's RIGHT slot (ContentFilters' — MediaLibrary's SELECT / FLAT); never empty beside the divider
|
|
52
|
+
* @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
|
|
48
53
|
* @param {ElementType} iconComponent icon renderer seam for ContentFilters
|
|
49
54
|
* @param {boolean} showCountOnlyWhenFiltering (default true)
|
|
50
55
|
* @param {Object} filtersProps spread onto ContentFilters last — e.g. `{ mutuallyExclusiveFilters: ['category', 'u_label'] }`
|
|
@@ -70,6 +75,7 @@ function computeHiddenSet(items, expandedIdx) {
|
|
|
70
75
|
|
|
71
76
|
export default function CatalogPage({
|
|
72
77
|
header,
|
|
78
|
+
width = 'bleed',
|
|
73
79
|
items = [],
|
|
74
80
|
toCard,
|
|
75
81
|
filtersTitle,
|
|
@@ -83,6 +89,13 @@ export default function CatalogPage({
|
|
|
83
89
|
defaultLayout = 'grid',
|
|
84
90
|
walkthrough,
|
|
85
91
|
actions,
|
|
92
|
+
/* the header's RIGHT slot — where MediaLibrary puts SELECT / FLAT. CatalogPage
|
|
93
|
+
shipped with no way to fill it, so every catalog page rendered an empty slot
|
|
94
|
+
beside the divider (kol-client-olina 2026-09-03, on /slide-deck). */
|
|
95
|
+
trailingActions,
|
|
96
|
+
/* the grid track's floor. 160 is a 26-tile catalog's; a shelf of three decks
|
|
97
|
+
wants ~280 so the cards read at all. A ceiling of 6 tracks still applies. */
|
|
98
|
+
minColumn = 160,
|
|
86
99
|
iconComponent,
|
|
87
100
|
showCountOnlyWhenFiltering = true,
|
|
88
101
|
filtersProps,
|
|
@@ -92,7 +105,7 @@ export default function CatalogPage({
|
|
|
92
105
|
}) {
|
|
93
106
|
const open = walkthrough?.open === true
|
|
94
107
|
return (
|
|
95
|
-
<PageShell className={className} style={{ overflow: 'hidden', ...style }}>
|
|
108
|
+
<PageShell width={width} className={className} style={{ overflow: 'hidden', ...style }}>
|
|
96
109
|
{header && <PageHeader {...header} />}
|
|
97
110
|
<div style={{ flex: 1, position: 'relative' }}>
|
|
98
111
|
{open && <WalkthroughPanel steps={walkthrough.steps} iconComponent={walkthrough.iconComponent} />}
|
|
@@ -105,6 +118,7 @@ export default function CatalogPage({
|
|
|
105
118
|
showCountOnlyWhenFiltering={showCountOnlyWhenFiltering}
|
|
106
119
|
iconComponent={iconComponent}
|
|
107
120
|
viewModeOptions={views}
|
|
121
|
+
trailingActions={trailingActions}
|
|
108
122
|
viewMode={view}
|
|
109
123
|
onViewModeChange={onViewChange}
|
|
110
124
|
defaultViewMode={defaultView}
|
|
@@ -127,13 +141,13 @@ export default function CatalogPage({
|
|
|
127
141
|
* six-column ruling — below the ceiling the hide-set is
|
|
128
142
|
* desktop-only geometry. */
|
|
129
143
|
return (
|
|
130
|
-
<div style={{ display: 'grid', gridTemplateColumns: layout === 'list' ? 'repeat(auto-fill, minmax(min(100%, max(240px, calc((100% - 3 * 8px) / 4))), 1fr))' :
|
|
144
|
+
<div style={{ display: 'grid', gridTemplateColumns: layout === 'list' ? 'repeat(auto-fill, minmax(min(100%, max(240px, calc((100% - 3 * 8px) / 4))), 1fr))' : `repeat(auto-fill, minmax(min(100%, max(${minColumn}px, calc((100% - 5 * 24px) / 6))), 1fr))`, gap: layout === 'list' ? 8 : 24 }}>
|
|
131
145
|
{rows.map((item, i) => {
|
|
132
146
|
if (hidden.has(i)) return null
|
|
133
147
|
const c = cards[i]
|
|
134
148
|
const key = c.key ?? item.key ?? item.id ?? item.name ?? i
|
|
135
149
|
return layout === 'list'
|
|
136
|
-
? <ContentRow key={key} variant="catalog" title={c.title} detail={c.detail} actions={c.actions} onClick={c.onClick} href={c.href} onNavigate={c.onNavigate} />
|
|
150
|
+
? <ContentRow key={key} variant="catalog" media={c.media} ratio={c.ratio} title={c.title} detail={c.detail} actions={c.actions} onClick={c.onClick} href={c.href} onNavigate={c.onNavigate} />
|
|
137
151
|
: <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} />
|
|
138
152
|
})}
|
|
139
153
|
</div>
|
package/src/PageShell.jsx
CHANGED
|
@@ -6,8 +6,19 @@
|
|
|
6
6
|
* `mode="fixed"`: height 100vh, overflow hidden — pair with a `flex:1
|
|
7
7
|
* overflow:auto` body (the settings idiom; SettingsScaffold does this).
|
|
8
8
|
*
|
|
9
|
-
* Gutter is `--kol-shell-page-pad` (kol-theme)
|
|
10
|
-
*
|
|
9
|
+
* Gutter is `--kol-shell-page-pad` (kol-theme) — since theme 0.135.0 an alias
|
|
10
|
+
* of `--kol-pad-section-x`, the ONE page-content ladder every `.kol-page`
|
|
11
|
+
* wears (two-page-scaffolds-one-job, kol-client-olina 2026-09-03: two ladders
|
|
12
|
+
* for one job agreed only at 48). `PageBleed` breaks it for full-width embeds
|
|
13
|
+
* (monitor's rack bleed).
|
|
14
|
+
*
|
|
15
|
+
* THE GEOMETRY IS A CLASS — `.kol-shell-page` (+ `--fixed`, `--capped`), in
|
|
16
|
+
* kol-components-shell.css — so a consumer has a selector to reach; inline is
|
|
17
|
+
* the `style` prop only. `width` is the TIER: `bleed` (default) fills the
|
|
18
|
+
* window, the app tier; `capped` takes the framework container ladder and
|
|
19
|
+
* centres, the site tier — the one real difference between this and a
|
|
20
|
+
* `.kol-page`, and a prop so a site adopting the shipped catalog page does
|
|
21
|
+
* not silently get app geometry.
|
|
11
22
|
*
|
|
12
23
|
* `scrollbar-gutter: stable` on both modes (PageShellScrollbarGutter,
|
|
13
24
|
* kol-monitor 2026-08-28 — user: "Create is the odd one out"). A page's content
|
|
@@ -39,40 +50,31 @@
|
|
|
39
50
|
* `AppShell pageWash`, a transparent wash over the shell's primary back —
|
|
40
51
|
* the lightness steps up and the structure stays visible, which an opaque
|
|
41
52
|
* surface swap would hide. The ink stays `text-auto` (surface-on-primary).
|
|
53
|
+
* ONE OWNER PER PIXEL (2026-09-03): the variable means what is LEFT to paint.
|
|
54
|
+
* kol-shell's `AppShell` hands the wash down for this to paint; kol-framework's
|
|
55
|
+
* `PageLayout` paints it on its own plane and hands down `transparent`, so a
|
|
56
|
+
* PageShell inside it does not paint it again (it used to — two 0.02 layers).
|
|
57
|
+
*
|
|
58
|
+
* @param {'scroll'|'fixed'} mode scroll (default) | fixed — see above
|
|
59
|
+
* @param {'bleed'|'capped'} width bleed (default, the app tier) | capped (the site tier — `--kol-container-max`, centred)
|
|
60
|
+
* @param {string} className
|
|
61
|
+
* @param {object} style inline — the one thing that stays inline
|
|
42
62
|
*/
|
|
43
|
-
export default function PageShell({ mode = 'scroll', className = '', style, children }) {
|
|
44
|
-
const modeStyle =
|
|
45
|
-
mode === 'fixed'
|
|
46
|
-
? { height: '100vh', overflow: 'hidden' }
|
|
47
|
-
: { minHeight: '100vh' }
|
|
63
|
+
export default function PageShell({ mode = 'scroll', width = 'bleed', className = '', style, children }) {
|
|
48
64
|
return (
|
|
49
65
|
<div
|
|
50
|
-
className={`text-auto ${className}`.trim()}
|
|
51
|
-
style={
|
|
52
|
-
background: 'var(--kol-shell-page-wash, var(--kol-surface-primary))',
|
|
53
|
-
padding: 'var(--kol-shell-page-pad)',
|
|
54
|
-
scrollbarGutter: 'stable',
|
|
55
|
-
display: 'flex',
|
|
56
|
-
flexDirection: 'column',
|
|
57
|
-
...modeStyle,
|
|
58
|
-
...style,
|
|
59
|
-
}}
|
|
66
|
+
className={`kol-shell-page${mode === 'fixed' ? ' kol-shell-page--fixed' : ''}${width === 'capped' ? ' kol-shell-page--capped' : ''} text-auto ${className}`.trim()}
|
|
67
|
+
style={style}
|
|
60
68
|
>
|
|
61
69
|
{children}
|
|
62
70
|
</div>
|
|
63
71
|
)
|
|
64
72
|
}
|
|
65
73
|
|
|
66
|
-
/** Full-bleed slot — cancels PageShell's horizontal gutter. */
|
|
74
|
+
/** Full-bleed slot — cancels PageShell's horizontal gutter (`.kol-shell-page-bleed`). */
|
|
67
75
|
export function PageBleed({ style, children }) {
|
|
68
76
|
return (
|
|
69
|
-
<div
|
|
70
|
-
style={{
|
|
71
|
-
marginLeft: 'calc(var(--kol-shell-page-pad) * -1)',
|
|
72
|
-
marginRight: 'calc(var(--kol-shell-page-pad) * -1)',
|
|
73
|
-
...style,
|
|
74
|
-
}}
|
|
75
|
-
>
|
|
77
|
+
<div className="kol-shell-page-bleed" style={style}>
|
|
76
78
|
{children}
|
|
77
79
|
</div>
|
|
78
80
|
)
|