@kolkrabbi/kol-component 0.97.0 → 0.97.2
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-component",
|
|
3
|
-
"version": "0.97.
|
|
3
|
+
"version": "0.97.2",
|
|
4
4
|
"description": "KOL design-system components — atoms through organisms, emitting canonical kol-* classes. Pairs with @kolkrabbi/kol-theme for styling.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -35,6 +35,7 @@ import { Icon } from '@kolkrabbi/kol-icons'
|
|
|
35
35
|
* @param {Function} onPrefix (prefix) => void
|
|
36
36
|
* @param {{files: object[], index: number}|null} quickLook the open Quick Look, or null
|
|
37
37
|
* @param {Function} onQuickLook (quickLook|null) => void — space opens / closes, ↑/↓ step while open
|
|
38
|
+
* @param {Function} onPick (file|null) => void — the picked file whenever it changes (a folder pick or an outside prefix change → null)
|
|
38
39
|
* @param {Function} urlOf (o) => string — the object's public URL for the preview image
|
|
39
40
|
* @param {Function} kindOf (o) => 'image' | 'video' | 'audio' | string
|
|
40
41
|
* @param {Object} kindLabel kind → label shown when there is no visual preview
|
|
@@ -141,6 +142,7 @@ export default function ColumnBrowser({
|
|
|
141
142
|
onPrefix = () => {},
|
|
142
143
|
quickLook = null,
|
|
143
144
|
onQuickLook,
|
|
145
|
+
onPick,
|
|
144
146
|
urlOf,
|
|
145
147
|
kindOf = defaultKindOf,
|
|
146
148
|
kindLabel = DEFAULT_KIND_LABEL,
|
|
@@ -149,8 +151,17 @@ export default function ColumnBrowser({
|
|
|
149
151
|
className = '',
|
|
150
152
|
}) {
|
|
151
153
|
const [picked, setPicked] = useState(null)
|
|
154
|
+
/* `onPick` (ColumnBrowserOnPick, kol-r2b2 2026-08-27): the picked file, for
|
|
155
|
+
* a Finder-style breadcrumb — fired whenever it changes; a folder pick or an
|
|
156
|
+
* outside prefix change fires null */
|
|
157
|
+
const pick = (o) => { setPicked(o); onPick?.(o) }
|
|
158
|
+
useEffect(() => { if (picked) pick(null) }, [prefix]) // eslint-disable-line react-hooks/exhaustive-deps
|
|
152
159
|
// Keyboard cursor: which column, which row. Clicks keep it in sync.
|
|
153
160
|
const [cursor, setCursor] = useState({ col: 0, idx: 0 })
|
|
161
|
+
/* the cursor is NOT drawn until the keyboard is used (ColumnBrowserCursorStart,
|
|
162
|
+
* kol-r2b2 2026-08-27): at rest it sat on row 0 beside the open folder and
|
|
163
|
+
* read as a second selection. Arrows arm it; a click seeds it. */
|
|
164
|
+
const [cursorActive, setCursorActive] = useState(false)
|
|
154
165
|
const rootRef = useRef(null)
|
|
155
166
|
|
|
156
167
|
const levelsOf = (pfx) => {
|
|
@@ -167,8 +178,8 @@ export default function ColumnBrowser({
|
|
|
167
178
|
}
|
|
168
179
|
const land = (level, item) => {
|
|
169
180
|
if (!item) return
|
|
170
|
-
if (item.type === 'folder') {
|
|
171
|
-
else
|
|
181
|
+
if (item.type === 'folder') { pick(null); onPrefix(level + item.name) }
|
|
182
|
+
else pick(item.o)
|
|
172
183
|
}
|
|
173
184
|
|
|
174
185
|
const onKeyDown = (e) => {
|
|
@@ -181,6 +192,7 @@ export default function ColumnBrowser({
|
|
|
181
192
|
}
|
|
182
193
|
if (!['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) return
|
|
183
194
|
e.preventDefault()
|
|
195
|
+
setCursorActive(true)
|
|
184
196
|
const lv = levelsOf(prefix)
|
|
185
197
|
const col = Math.min(cursor.col, lv.length - 1)
|
|
186
198
|
const items = itemsAt(lv[col])
|
|
@@ -201,7 +213,7 @@ export default function ColumnBrowser({
|
|
|
201
213
|
const opened = lv[col].slice(lv[col - 1].length)
|
|
202
214
|
const idx = Math.max(0, parentItems.findIndex((it) => it.type === 'folder' && it.name === opened))
|
|
203
215
|
setCursor({ col: col - 1, idx })
|
|
204
|
-
|
|
216
|
+
pick(null)
|
|
205
217
|
onPrefix(lv[col])
|
|
206
218
|
}
|
|
207
219
|
}
|
|
@@ -223,7 +235,7 @@ export default function ColumnBrowser({
|
|
|
223
235
|
do { idx += step } while (items[idx] && items[idx].type !== 'file')
|
|
224
236
|
if (!items[idx]) return
|
|
225
237
|
setCursor({ col, idx })
|
|
226
|
-
|
|
238
|
+
pick(items[idx].o)
|
|
227
239
|
const siblings = items.filter((it) => it.type === 'file').map((it) => it.o)
|
|
228
240
|
onQuickLook?.({ files: siblings, index: siblings.findIndex((o) => o.key === items[idx].o.key) })
|
|
229
241
|
}
|
|
@@ -260,9 +272,9 @@ export default function ColumnBrowser({
|
|
|
260
272
|
icon="folder"
|
|
261
273
|
label={f.replace(/\/$/, '')}
|
|
262
274
|
active={f === activeFolder}
|
|
263
|
-
cursor={cursor.col === k && cursor.idx === i}
|
|
275
|
+
cursor={cursorActive && cursor.col === k && cursor.idx === i}
|
|
264
276
|
trailing={<Icon name="chevron-right" size={12} className="text-fg-32" />}
|
|
265
|
-
onClick={() => { setCursor({ col: k, idx: i }); rootRef.current?.focus();
|
|
277
|
+
onClick={() => { setCursor({ col: k, idx: i }); setCursorActive(true); rootRef.current?.focus(); pick(null); onPrefix(level + f) }}
|
|
266
278
|
/>
|
|
267
279
|
))}
|
|
268
280
|
{files.map((o, i) => (
|
|
@@ -272,8 +284,8 @@ export default function ColumnBrowser({
|
|
|
272
284
|
label={o.displayKey ?? o.key}
|
|
273
285
|
muted={shown?.key !== o.key}
|
|
274
286
|
active={shown?.key === o.key}
|
|
275
|
-
cursor={cursor.col === k && cursor.idx === folders.length + i}
|
|
276
|
-
onClick={() => { setCursor({ col: k, idx: folders.length + i }); rootRef.current?.focus();
|
|
287
|
+
cursor={cursorActive && cursor.col === k && cursor.idx === folders.length + i}
|
|
288
|
+
onClick={() => { setCursor({ col: k, idx: folders.length + i }); setCursorActive(true); rootRef.current?.focus(); pick(o) }}
|
|
277
289
|
/>
|
|
278
290
|
))}
|
|
279
291
|
{folders.length === 0 && files.length === 0 && (
|