@kolkrabbi/kol-component 0.241.0 → 0.243.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-component",
3
- "version": "0.241.0",
3
+ "version": "0.243.0",
4
4
  "description": "The core component library",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -26,8 +26,8 @@
26
26
  "embla-carousel-react": "^8.6.0",
27
27
  "pdfjs-dist": "^6.3.289",
28
28
  "react-syntax-highlighter": "^16.1.1",
29
- "@kolkrabbi/kol-markdown": "^0.1.3",
30
- "@kolkrabbi/kol-search": "^0.3.0"
29
+ "@kolkrabbi/kol-search": "^0.3.0",
30
+ "@kolkrabbi/kol-markdown": "^0.1.3"
31
31
  },
32
32
  "peerDependencies": {
33
33
  "@kolkrabbi/kol-icons": ">=0.22.0",
@@ -187,7 +187,7 @@ const defaultPartition = (objects, prefix) => {
187
187
  const rel = prefix ? o.key.slice(prefix.length) : o.key
188
188
  const slash = rel.indexOf('/')
189
189
  if (slash !== -1) folderSet.add(rel.slice(0, slash + 1))
190
- else files.push({ ...o, displayKey: o.displayKey ?? rel })
190
+ else files.push({ ...o, displayKey: o.displayKey ?? o.displayName ?? rel })
191
191
  }
192
192
  return { folders: [...folderSet].sort(), files }
193
193
  }
@@ -440,7 +440,7 @@ function FileRow({ o, onClick, onDoubleClick, depth = 0, formatDate, thumb, cols
440
440
  {/* a file with no thumbnail draws its glyph at the FOLDER's size — one icon column (user 2026-09-25) */}
441
441
  {thumb ?? <Icon name={kindOf(o) === 'image' ? 'image' : 'file'} size={glyphSize(size)} />}
442
442
  </span>
443
- <span className={`kol-item-name min-w-0 truncate${selected ? '' : ' text-fg-default'}`}>{o.displayKey ?? o.key.split('/').pop()}</span>
443
+ <span className={`kol-item-name min-w-0 truncate${selected ? '' : ' text-fg-default'}`}>{o.displayKey ?? o.displayName ?? o.key.split('/').pop()}</span>
444
444
  </span>
445
445
  <span className="flex-1" />
446
446
  {cols && <>
@@ -588,7 +588,7 @@ function FileEditorHost({ o, client, bucket, onClose, onSaved, assets }) {
588
588
  return () => { live = false }
589
589
  }, [o.key]) // eslint-disable-line react-hooks/exhaustive-deps
590
590
  return (
591
- <DocumentEditor name={o.displayKey ?? o.key.split('/').pop()} kind={editKindOf(o)} text={text}
591
+ <DocumentEditor name={o.displayKey ?? o.displayName ?? o.key.split('/').pop()} kind={editKindOf(o)} text={text}
592
592
  savedAt={o.uploaded ? Date.parse(o.uploaded) : 0} draft={{ bucket, key: o.key }} assets={assets}
593
593
  onSave={async (next) => { const r = await client.writeText(o.key, next, bucket); onSaved?.(o.key, r, next) }}
594
594
  onClose={onClose} />
@@ -646,7 +646,7 @@ export function MediaInspector({ files, index, onClose, onPrev, onNext, mediaUrl
646
646
  shownDims?.len && formatLength(shownDims.len),
647
647
  ].filter(Boolean).join(' · ')
648
648
  const frame = {
649
- title: o.displayKey ?? o.key.split('/').pop(),
649
+ title: o.displayKey ?? o.displayName ?? o.key.split('/').pop(),
650
650
  meta: facts,
651
651
  onClose,
652
652
  /* ‹ › and n / N only when the window pages a SELECTION (user 2026-09-23: *"I only selected one
@@ -1077,6 +1077,12 @@ export function MediaLibraryBrowse({
1077
1077
  /* `bucketLevel` — keep title → bucket → folders with ONE bucket (kol-client-olina 2026-09-23).
1078
1078
  * Absent, a one-bucket consumer collapses the level as ruled 2026-09-03. */
1079
1079
  bucketLevel = false,
1080
+ /* `onPickFile(o | null)` — the selected file, reported as it changes (picker A, 2026-10-08: the
1081
+ * browse surface inside the modal card needs the selection for its Use button). Keys are
1082
+ * bucket-relative. Absent, nothing. */
1083
+ onPickFile,
1084
+ /* `o.displayName` on a listed object is its LABEL in every view, Quick Look and search (kol-fxr
1085
+ * 2026-10-08: names not unique, so the key is an id). Absent, the label is the key, as before. */
1080
1086
  }) {
1081
1087
  const [ownPrefix, setOwnPrefix] = useState('')
1082
1088
  const prefix = prefixProp ?? ownPrefix
@@ -1090,6 +1096,7 @@ export function MediaLibraryBrowse({
1090
1096
  const [settingsOpen, setSettingsOpen] = useState(false)
1091
1097
  const [trashOpen, setTrashOpen] = useState(false)
1092
1098
  const [pickedFile, setPickedFile] = useState(null)
1099
+ useEffect(() => { onPickFile?.(pickedFile) }, [pickedFile]) // eslint-disable-line react-hooks/exhaustive-deps
1093
1100
  /* ROW VIEW PICKS, and only one at a time: a click selects and fills the preview, a DOUBLE click
1094
1101
  * opens (user 2026-09-22, Finder's behaviour — "clicking shouldnt automatically open it"). The
1095
1102
  * chevron still expands in place, which is the third thing and always was. */
@@ -1940,7 +1947,7 @@ export function MediaLibraryBrowse({
1940
1947
  * settings the wall always had. */
1941
1948
  const wallKinds = new Set(settings.kinds ?? SETTINGS_BASE.kinds)
1942
1949
  const wallSource = settings.flat
1943
- ? scoped.map((o) => ({ ...o, displayKey: prefix ? o.key.slice(prefix.length) : o.key }))
1950
+ ? scoped.map((o) => ({ ...o, displayKey: o.displayName ?? (prefix ? o.key.slice(prefix.length) : o.key) }))
1944
1951
  : dirFiles
1945
1952
  const wallVisible = wallKinds.has('system') ? wallSource : wallSource.filter((o) => !isSystemFile(o.key))
1946
1953
  const wallGrouped = settings.groupVariants ? groupVariants(wallVisible) : wallVisible
@@ -1953,7 +1960,7 @@ export function MediaLibraryBrowse({
1953
1960
  * bar at `brand/og/` and `logos`, `original`, `projects` vanished with no filter set). The
1954
1961
  * columns draw every level up to the root, so a list scoped to `prefix` cut every sibling path
1955
1962
  * the moment the bar mounted. */
1956
- const filterItems = isWall ? wallFiles : sortedObjects.filter((o) => !isSystemFile(o.key)).map((o) => ({ ...o, kind: kindOf(o), poster: posterFor(o.key, keySet), displayKey: o.key }))
1963
+ const filterItems = isWall ? wallFiles : sortedObjects.filter((o) => !isSystemFile(o.key)).map((o) => ({ ...o, kind: kindOf(o), poster: posterFor(o.key, keySet), displayKey: o.displayName ?? o.key }))
1957
1964
  const filterKinds = [...new Set(filterItems.map((o) => o.kind))].sort()
1958
1965
  const filterTags = [...new Set(filterItems.flatMap((o) => o.tags ?? []))].sort()
1959
1966
  /* favourites as a one-chip group: ContentFilters matches a value, so a starred file carries one */
@@ -2261,7 +2268,7 @@ export function MediaLibraryBrowse({
2261
2268
  * that means the top hit. Arrow-then-Enter and a click go through `onSelect`, same jump. */
2262
2269
  const searchResults = rankMedia(objects, searchQuery, { limit: 50 }).map((o) => ({
2263
2270
  id: o.key,
2264
- label: o.key.split('/').pop(),
2271
+ label: o.displayName ?? o.key.split('/').pop(),
2265
2272
  hint: o.key.slice(0, o.key.lastIndexOf('/') + 1) || 'the bucket root',
2266
2273
  group: KIND_LABEL[kindOf(o)] || 'File',
2267
2274
  }))
@@ -2297,7 +2304,7 @@ export function MediaLibraryBrowse({
2297
2304
  if ((q.kinds ?? []).length && !q.kinds.includes(kindOf(o))) return false
2298
2305
  if (q.text && !filterMedia([o], q.text).length) return false
2299
2306
  return true
2300
- }).map((o) => ({ ...o, kind: kindOf(o), poster: posterFor(o.key, keySet), displayKey: o.key })) : null
2307
+ }).map((o) => ({ ...o, kind: kindOf(o), poster: posterFor(o.key, keySet), displayKey: o.displayName ?? o.key })) : null
2301
2308
  /* A TYPED QUERY IS A RESULTS LIST (user 2026-09-30, reversing "a flat results list nobody asked
2302
2309
  * for"): pruning the tree to matching paths hid the files one level down and read as "search only
2303
2310
  * finds folders". While the bar holds a query, the tree views show every hit flat, each with its
@@ -2966,7 +2973,7 @@ export function MediaLibraryLibrary({
2966
2973
 
2967
2974
  const scoped = prefix ? objects.filter((o) => o.key.startsWith(prefix)) : objects
2968
2975
  const { files: dirFiles } = partition(scoped, prefix)
2969
- const flatFiles = scoped.map((o) => ({ ...o, displayKey: prefix ? o.key.slice(prefix.length) : o.key }))
2976
+ const flatFiles = scoped.map((o) => ({ ...o, displayKey: o.displayName ?? (prefix ? o.key.slice(prefix.length) : o.key) }))
2970
2977
  const levelFiles = flat ? flatFiles : dirFiles
2971
2978
  const systemCount = levelFiles.filter((o) => isSystemFile(o.key)).length
2972
2979
  const visibleFiles = kinds.has('system') ? levelFiles : levelFiles.filter((o) => !isSystemFile(o.key))
@@ -16,7 +16,7 @@ import { kindOf } from './mediaKinds.js'
16
16
 
17
17
  const toItem = (o, nameOf) => ({
18
18
  id: o.key,
19
- title: nameOf ? nameOf(o) : o.key.slice(o.key.lastIndexOf('/') + 1) || o.key,
19
+ title: nameOf ? nameOf(o) : o.displayName ?? (o.key.slice(o.key.lastIndexOf('/') + 1) || o.key),
20
20
  keywords: [o.key],
21
21
  tags: o.tags ?? [],
22
22
  kind: o.kind ?? kindOf(o),