@kolkrabbi/kol-component 0.216.0 → 0.217.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.
@@ -1,116 +1,31 @@
1
1
  import { useState } from 'react'
2
- import Divider from '../atoms/Divider.jsx'
3
- import { MediaLibraryBrowse, MediaLibraryLibrary } from './MediaLibraryPages.jsx'
2
+ import { MediaLibraryBrowse } from './MediaLibraryPages.jsx'
4
3
 
5
4
  /**
6
- * MediaLibraryExplorer — the browse tree and the file wall as TWO VIEWS OF ONE
7
- * SURFACE, which is what `MediaLibraryPages` has called them in its own comments
8
- * since 2026-09-04 while shipping them as two pages a consumer stacks by hand.
5
+ * MediaLibraryExplorer — the media surface, and since 2026-09-22 a thin name for it.
9
6
  *
10
- * WHAT WAS WRONG WITH THE STACK (kol-r2b2, the apps-tier ticket):
11
- * - Both pages rendered ALWAYS, the browser at a fixed 800px, so the wall and
12
- * the upload drop zone sat below the fold. Pressing Upload scrolled you past
13
- * a full-height browser to reach the target.
14
- * - Both rendered `LibraryHeader`, so the consumer passed `header={false}` to
15
- * suppress a duplicate wordmark, bucket dropdown and gear.
16
- * - Both printed a stats line, so the consumer passed `stats={false}` too.
17
- * - Both called `useBucketLibrary`, so one bucket was listed twice into two
18
- * object lists that could disagree.
19
- * - Every shared seam had to be handed to both by the consumer, which is the
20
- * divergence-defect family the pages' own comments document at length.
7
+ * IT USED TO BE THE MERGE ITSELF: it held a BROWSE · FILES switch and mounted one of two pages,
8
+ * each of which listed the bucket, drew its own header and printed its own count. The user's read
9
+ * of that (2026-09-22) ended it — *"they both just display files … 4 views, not 2 modes each with
10
+ * 2 views"* — so the surface is ONE page now with four views (columns · rows · grid · list), one
11
+ * listing, one header, one count line and one filter bar, and this component only carries the
12
+ * view state for a consumer that wants to own it.
21
13
  *
22
- * WHAT THIS DOES: holds the view, mounts exactly one page, and hands it the
23
- * seams once. One page mounted means one header, one stats line, one listing and
24
- * one body — every symptom above falls out of that rather than being patched.
14
+ * `MediaLibraryBrowse` and `MediaLibraryLibrary` remain exported: the first IS the surface, the
15
+ * second is the standalone wall a site embeds without a tree (kol-website's asset page).
25
16
  *
26
- * WHAT IT DOES NOT DO: it does not hoist `useBucketLibrary` into itself. The two
27
- * pages keep their own state, so switching views re-lists the bucket and drops
28
- * column scroll position and selection. Against this repo's fixture that is
29
- * free; against a live bucket it is a 30s-cached GET. Hoisting the hook and the
30
- * header into a true shared parent is the deeper fix and it is a rewrite of both
31
- * page bodies — worth doing, not worth blocking the surface on.
32
- *
33
- * `prefix` stays OWNED BY THE CONSUMER (it already was), so the folder you are
34
- * in survives the switch even though the page instance does not.
35
- *
36
- * ADDITIVE. `variant="browse"` and `variant="library"` are untouched, so
37
- * kol-r2b2 and kol-client-olina keep rendering exactly what they render today.
17
+ * @param {'columns'|'rows'|'grid'|'list'} view controlled view; omit and the page reads its own setting
18
+ * @param {Function} onViewChange (view) => void
19
+ * @param {'columns'|'rows'|'grid'|'list'} defaultView first view when uncontrolled and nothing is stored
38
20
  */
39
-
40
- const VIEWS = [
41
- { value: 'browse', label: 'BROWSE' },
42
- { value: 'files', label: 'FILES' },
43
- ]
44
-
45
- export default function MediaLibraryExplorer({
46
- view: viewProp,
47
- onViewChange,
48
- defaultView = 'browse',
49
- headerActions,
50
- className = '',
51
- ...pageProps
52
- }) {
53
- const [ownView, setOwnView] = useState(defaultView)
54
- const view = viewProp ?? ownView
55
- const setView = (v) => { setOwnView(v); onViewChange?.(v) }
56
-
57
- /* The switch rides `headerActions` rather than being a fourth thing in the
58
- * header's own markup: the header already has a slot for consumer chrome, and
59
- * putting the view control there keeps it beside the bucket dropdown where
60
- * every reference product puts it. The consumer's own actions follow it.
61
- *
62
- * HIDDEN BELOW `md`. At 390 the header carries a wordmark, a bucket dropdown
63
- * and up to four icons; adding a two-segment strip pushed the strip off the
64
- * right edge and truncated the wordmark to three glyphs. The pages already
65
- * take the mobile tab pill (`tabs` / `activeTab` / `onTabChange`), which is
66
- * the same control for the same question — so the phone keeps the pill and
67
- * the desktop keeps the strip, rather than both competing for one row.
68
- *
69
- * BARE TEXT, NOT A `SegmentedToggle`. This surface already has a switch
70
- * idiom and uses it twice — ROW·COLUMN on the crumb line and SELECT·FLAT on
71
- * the filter bar are both `kol-helper-14`, `oq-96` active over `oq-48` at
72
- * rest, letterspacing 1, no frame. A boxed toggle put a bordered chip next to
73
- * an unbordered dropdown and two unbordered switches, which read as a style
74
- * break because it was one. Same control, third instance, same treatment.
75
- *
76
- * AND IT SITS LAST, RIGHT OF A DIVIDER. The crumb row directly beneath this
77
- * header reads `[list][columns] │ ROW COLUMN` — icons, divider, text switch.
78
- * Placed before the icons the header mirrored the row under it, which is the
79
- * same inconsistency in a different direction. Icons left, divider, text
80
- * right; two rows, one arrangement. It rides `headerTrailing` rather than
81
- * `headerActions` because the gear is rendered by the header itself and the
82
- * switch has to clear it. */
83
- /* THE GAPS ARE THE CRUMB ROW'S, MEASURED: `gap-6` (24px) around the divider,
84
- * `gap-4` (16px) between the two labels. Built flat at gap-4 throughout, the
85
- * divider sat 8px too tight against the icons and the row below it did not
86
- * line up with the row above. Two nested containers, same two numbers. */
87
- /* `ml-4` IS NOT DECORATION. The divider needs 24px on BOTH sides to match the
88
- * crumb row, where its own `gap-6` container supplies both. Here the LEFT gap
89
- * comes from the header's `gap-2` between this group and the gear — 8px — so
90
- * the divider sat tight against the icons and open against the text. 8 + 16
91
- * puts it back on 24. */
92
- const trailing = (
93
- <span className="max-md:hidden flex items-center gap-6 ml-4">
94
- <Divider variant="vertical" />
95
- <span className="flex items-center gap-4">
96
- {VIEWS.map((opt) => (
97
- <span key={opt.value} role="button" onClick={() => setView(opt.value)}
98
- aria-pressed={view === opt.value}
99
- className={`kol-helper-14 cursor-pointer select-none ${view === opt.value ? 'text-oq-96' : 'text-oq-48 hover:text-oq-64'}`}
100
- style={{ letterSpacing: 1 }}>
101
- {opt.label}
102
- </span>
103
- ))}
104
- </span>
105
- </span>
21
+ export default function MediaLibraryExplorer({ view, onViewChange, defaultView, ...pageProps }) {
22
+ const [ownView, setOwnView] = useState(view ?? defaultView)
23
+ const current = view ?? ownView
24
+ return (
25
+ <MediaLibraryBrowse
26
+ {...pageProps}
27
+ view={current}
28
+ onViewChange={(v) => { setOwnView(v); onViewChange?.(v) }}
29
+ />
106
30
  )
107
-
108
- const shared = { ...pageProps, headerActions, headerTrailing: trailing, className }
109
-
110
- /* `header` and `stats` are NOT forwarded and NOT accepted. One surface prints
111
- * one header and one count; a consumer suppressing either is the workaround
112
- * this component exists to delete. */
113
- return view === 'files'
114
- ? <MediaLibraryLibrary {...shared} />
115
- : <MediaLibraryBrowse {...shared} />
116
31
  }