@kolkrabbi/kol-shell 0.64.0 → 0.66.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.64.0",
3
+ "version": "0.66.0",
4
4
  "private": false,
5
5
  "description": "The application shell",
6
6
  "license": "MIT",
@@ -12,7 +12,7 @@
12
12
  "./src/*": "./src/*"
13
13
  },
14
14
  "peerDependencies": {
15
- "@kolkrabbi/kol-component": ">=0.246.0",
15
+ "@kolkrabbi/kol-component": ">=0.266.0",
16
16
  "@kolkrabbi/kol-icons": ">=0.16.0",
17
17
  "@kolkrabbi/kol-theme": ">=0.165.0",
18
18
  "gsap": "^3.13.0",
@@ -20,10 +20,10 @@
20
20
  "react-dom": "^18.3.0 || ^19.0.0"
21
21
  },
22
22
  "devDependencies": {
23
- "@kolkrabbi/kol-framework": "^0.49.0",
23
+ "@kolkrabbi/kol-component": "^0.266.0",
24
+ "@kolkrabbi/kol-icons": "^0.39.0",
24
25
  "@kolkrabbi/kol-theme": "^0.174.0",
25
- "@kolkrabbi/kol-icons": "^0.38.0",
26
- "@kolkrabbi/kol-component": "^0.261.0"
26
+ "@kolkrabbi/kol-framework": "^0.50.0"
27
27
  },
28
28
  "files": [
29
29
  "src",
package/src/AppHub.jsx CHANGED
@@ -2,9 +2,10 @@ import { useEffect, useState } from 'react'
2
2
  import AppShell from './AppShell.jsx'
3
3
  import HubHome from './HubHome.jsx'
4
4
  import HubSettings from './HubSettings.jsx'
5
- import { ShortcutsOverlay } from '@kolkrabbi/kol-component'
5
+ import HubDev from './HubDev.jsx'
6
+ import { CommandOverlay } from '@kolkrabbi/kol-component'
6
7
 
7
- /* taxonomy-ok: organism — nests AppShell / HubHome / HubSettings / ShortcutsOverlay (relative) */
8
+ /* taxonomy-ok: organism — nests AppShell / HubHome / HubSettings / HubDev (relative) + kol-component's CommandOverlay */
8
9
 
9
10
  /**
10
11
  * AppHub — An app's shell and hub in one. Shell + Hub in one call; the app passes its Tool as children (the app anatomy,
@@ -37,6 +38,9 @@ import { ShortcutsOverlay } from '@kolkrabbi/kol-component'
37
38
  * OPT-IN like AppShell's `bottomItems` (apps review 2026-09-29: *"not sure it makes sense
38
39
  * to neccessarily have settings manditory part of the rail"*) — no `settings`, no rail
39
40
  * row, no route, no `,` key. It was pinned whether the app had settings or not.
41
+ * @param {Object} dev HubDev's props (`tabs`, `title`, `subtitle`) + `path` (default `/dev`). OPT-IN, and only on
42
+ * a dev server (`import.meta.env.DEV`; `always: true` overrides) — a `code` row above
43
+ * Settings (CompareGridDevTab, kol-monitor 2026-10-17)
40
44
  * @param {Array} shortcuts `[{ section, items: [{ id, label, combo }] }]` — the sheet AND Settings
41
45
  * @param {ReactNode} themeToggle Settings' masthead toggle (a node — kol-framework is not a peer)
42
46
  * @param {string} shortcutsKey default `s`; `null` turns the sheet key off (a tool that owns S)
@@ -55,6 +59,7 @@ export default function AppHub({
55
59
  home,
56
60
  walkthrough,
57
61
  settings,
62
+ dev,
58
63
  shortcuts = [],
59
64
  themeToggle,
60
65
  settingsPath = '/settings',
@@ -65,6 +70,7 @@ export default function AppHub({
65
70
  children,
66
71
  }) {
67
72
  const [sheet, setSheet] = useState(false)
73
+ const [sheetQuery, setSheetQuery] = useState('')
68
74
 
69
75
  useEffect(() => {
70
76
  if (!shortcutsKey) return undefined
@@ -79,12 +85,18 @@ export default function AppHub({
79
85
  return () => window.removeEventListener('keydown', onKey)
80
86
  }, [shortcutsKey])
81
87
 
88
+ /* the dev page is a dev server's only — a production build never routes it or draws its row */
89
+ const devOn = !!dev && (dev.always || !!import.meta.env?.DEV)
90
+ const devPath = dev?.path ?? '/dev'
91
+ const { path: _dp, always: _da, ...devProps } = dev ?? {}
82
92
  const page = home && currentPath === homePath
83
93
  ? <HubHome app={app} iconComponent={iconComponent} walkthrough={walkthrough} {...home} />
84
94
  : settings && currentPath === settingsPath
85
95
  ? <HubSettings app={app} shortcuts={shortcuts} themeToggle={themeToggle} {...settings} />
86
- : children
87
- const bottom = settings ? SETTINGS_ROW(settingsPath) : []
96
+ : devOn && (currentPath === devPath || currentPath?.startsWith(`${devPath}/`))
97
+ ? <HubDev storageKey={`kol-dev-tab:${app.name ?? 'app'}`} {...devProps} />
98
+ : children
99
+ const bottom = [...(devOn ? [{ icon: 'code', path: devPath, label: 'Dev' }] : []), ...(settings ? SETTINGS_ROW(settingsPath) : [])]
88
100
  /* the phone bar lists Home as a tab — the rail draws it as the mark, the bar has no mark */
89
101
  const barItems = [...(home ? [{ icon: 'home-01', path: homePath, label: 'Home' }] : []), ...items, ...bottom]
90
102
 
@@ -111,7 +123,9 @@ export default function AppHub({
111
123
  {...shell}
112
124
  >
113
125
  {page}
114
- {sheet && <ShortcutsOverlay shortcuts={shortcuts} onClose={() => setSheet(false)} />}
126
+ {/* THE SHEET IS THE OVERLAY'S SHORTCUTS MODE (5.3, 2026-10-17): the whole keymap at a glance, this page's
127
+ * first, the rest under Elsewhere; typing filters, Enter runs a row */}
128
+ <CommandOverlay open={sheet} mode="shortcuts" shortcuts={shortcuts} currentPath={currentPath} query={sheetQuery} onQueryChange={setSheetQuery} onClose={() => { setSheet(false); setSheetQuery('') }} />
115
129
  </AppShell>
116
130
  )
117
131
  }
package/src/AppStudio.jsx CHANGED
@@ -37,6 +37,7 @@ import PageShell from './PageShell.jsx'
37
37
  * @param {Object} [use] `{ children, path, label, icon }` — the tool
38
38
  * @param {Array} [pages] `[{ path, icon, label, children }]` — opt-in pages, after Use
39
39
  * @param {Object} [settings] HubSettings' props
40
+ * @param {Object} [dev] HubDev's props — AppHub's `dev`: a dev server's `code` page at `/dev`
40
41
  * @param {'mono'|'display'} [masthead='mono']
41
42
  * @param {Object} [shell] any AppShell prop, spread last
42
43
  */
@@ -51,6 +52,7 @@ export default function AppStudio({
51
52
  use,
52
53
  pages = [],
53
54
  settings,
55
+ dev,
54
56
  walkthrough,
55
57
  shortcuts,
56
58
  themeToggle,
@@ -92,6 +94,7 @@ export default function AppStudio({
92
94
  home={home}
93
95
  walkthrough={walkthrough}
94
96
  settings={settings}
97
+ dev={dev}
95
98
  shortcuts={shortcuts}
96
99
  themeToggle={themeToggle}
97
100
  shortcutsKey={shortcutsKey}
package/src/HubDev.jsx ADDED
@@ -0,0 +1,45 @@
1
+ import { useState } from 'react'
2
+ import { PageHeader, TabsRow } from '@kolkrabbi/kol-component'
3
+ import PageShell from './PageShell.jsx'
4
+
5
+ /* taxonomy-ok: organism — nests PageShell (relative) + kol-component's PageHeader / TabsRow */
6
+
7
+ const read = (key, fallback) => { try { return localStorage.getItem(key) ?? fallback } catch { return fallback } }
8
+ const write = (key, value) => { try { localStorage.setItem(key, value) } catch { /* private mode: the tab just resets */ } }
9
+
10
+ /**
11
+ * HubDev — A hub's development page. The one rail row for everything that is not the app yet: experiments,
12
+ * references, comparisons (CompareGridDevTab, kol-monitor 2026-10-17 — user: *"I would also maybe add
13
+ * instructions for making the dev tab to the hub … localhost only using the </> icon"*). Each app had built
14
+ * this page by hand and each read differently; this is the page made once, for reading.
15
+ *
16
+ * The shape: a small mono masthead with one line saying what the page is, the tabs on their own row under
17
+ * it, the active tab's one-line description, then the tab's content at full width. Detail belongs in the
18
+ * content's own toggles, not in more text here. The open tab is remembered per app.
19
+ *
20
+ * Rendered by `AppHub` / `AppStudio` from their `dev` prop, only on a dev server (`import.meta.env.DEV`),
21
+ * at `/dev`, behind the `code` rail row.
22
+ *
23
+ * @param {Array} tabs `[{ value, label, description?, content }]`
24
+ * @param {string} [title='Dev']
25
+ * @param {string} [subtitle] one line: what the page is
26
+ * @param {string} [storageKey] where the open tab is remembered
27
+ */
28
+ export default function HubDev({ tabs = [], title = 'Dev', subtitle = 'Experiments and reference, not the app', storageKey = 'kol-dev-tab' }) {
29
+ const [stored, setStored] = useState(() => read(storageKey, tabs[0]?.value))
30
+ const active = tabs.find((t) => t.value === stored) ?? tabs[0]
31
+ const pick = (v) => { setStored(v); write(storageKey, v) }
32
+
33
+ return (
34
+ <PageShell className="gap-6">
35
+ <PageHeader size="sm" voice="mono" title={title} subtitle={subtitle} />
36
+ {tabs.length > 1 && (
37
+ <div className="flex flex-col gap-2 border-b border-fg-08 pb-4">
38
+ <TabsRow look="text" tabs={tabs.map(({ value, label }) => ({ value, label }))} value={active?.value} onChange={pick} tracked />
39
+ {active?.description && <p className="kol-helper-12 text-meta">{active.description}</p>}
40
+ </div>
41
+ )}
42
+ {active && <div className="min-w-0">{active.content}</div>}
43
+ </PageShell>
44
+ )
45
+ }
package/src/PhoneNav.jsx CHANGED
@@ -1,5 +1,5 @@
1
1
  import { useEffect, useState } from 'react'
2
- import { Button, MobileTabBar } from '@kolkrabbi/kol-component'
2
+ import { Button, TabsRow } from '@kolkrabbi/kol-component'
3
3
 
4
4
  /* taxonomy-ok: molecule — MobileTabBar + a More sheet of Buttons */
5
5
 
@@ -68,7 +68,9 @@ export default function PhoneNav({ items = [], currentPath = '/', onNavigate })
68
68
  ))}
69
69
  </div>
70
70
  )}
71
- <MobileTabBar
71
+ <TabsRow
72
+ look="stacked"
73
+ placement="phone"
72
74
  tabs={tabs}
73
75
  value={value}
74
76
  onChange={(v) => (v === MORE ? setOpen((o) => !o) : onNavigate?.(v))}
package/src/TabStrip.jsx CHANGED
@@ -1,34 +1,9 @@
1
+ import { TabsRow } from '@kolkrabbi/kol-component'
2
+
1
3
  /**
2
- * TabStrip — A row of text tabs. the flat text-tab idiom both shells use twice (ContentFilters
3
- * view-mode/layout spans, Settings tabs): `kol-helper-14`, active
4
- * `text-fg-96`, rest `text-fg-32 hover:text-fg-48`.
5
- *
6
- * No auto-casing — labels render exactly as authored (the source repos'
7
- * `text-transform: uppercase` dropped per the DS law; author "GRID" if you
8
- * want GRID). `tracked` adds the 1px letter-spacing the view-mode strips
9
- * carried.
10
- *
11
- * SINGLE-SELECT ONLY. A `Set` form for multi-select was added 2026-08-15 so the
12
- * retired ContentFilters fork could render filter values through this — and
13
- * removed the same day with it. A multi-select, handler-carrying, active/rest
14
- * chip is a `Tag`; building a second one here under another name in another
15
- * package is exactly the duplication kol-shell exists to end.
16
- *
17
- * @param {Array} props.options `[{ value, label }]`
4
+ * @deprecated 2026-10-17 — alias of kol-component's `TabsRow look="text"` (TabsStackedLayout: one tab component). Drops when nobody imports it (04-retirements.md).
5
+ * TabStrip — Old name for TabsRow's text look. Same props: `options` (`{ value, label }`) · `value` · `onChange` · `size` · `tracked` · `className` · `style`.
18
6
  */
19
- export default function TabStrip({ options = [], value, onChange, size = 14, tracked = false, className = 'gap-6', style }) {
20
- return (
21
- <div className={`flex items-center ${className}`.trim()} style={style}>
22
- {options.map((opt) => (
23
- <span
24
- key={opt.value}
25
- onClick={() => onChange?.(opt.value)}
26
- className={`kol-helper-${size} cursor-pointer select-none ${value === opt.value ? 'text-fg-96' : 'text-fg-32 hover:text-fg-48'}`}
27
- style={tracked ? { letterSpacing: 1 } : undefined}
28
- >
29
- {opt.label}
30
- </span>
31
- ))}
32
- </div>
33
- )
7
+ export default function TabStrip({ options = [], className = 'gap-6', ...rest }) {
8
+ return <TabsRow look="text" tabs={options} className={className} {...rest} />
34
9
  }
package/src/index.js CHANGED
@@ -26,7 +26,7 @@ export { default as TabStrip } from './TabStrip.jsx'
26
26
  export { default as SettingsScaffold } from './SettingsScaffold.jsx'
27
27
  export { default as WalkthroughPanel } from './WalkthroughPanel.jsx'
28
28
  /* lives in kol-component since 0.228.0 — re-exported so every kol-shell import keeps resolving */
29
- export { ShortcutsOverlay } from '@kolkrabbi/kol-component'
29
+ export { ShortcutsOverlay, shortcutInScope } from '@kolkrabbi/kol-component'
30
30
  export { default as Logomark } from './Logomark.jsx'
31
31
  // the app tier, shipped once (ShellHomeSystem, kol-fxr 2026-08-27)
32
32
  export { default as CatalogPage } from './CatalogPage.jsx'
@@ -37,6 +37,7 @@ export { default as TouchDeviceOverlay, useTouchPrimary } from './TouchDeviceOve
37
37
  export { default as AppHub } from './AppHub.jsx'
38
38
  export { default as HubHome } from './HubHome.jsx'
39
39
  export { default as HubSettings } from './HubSettings.jsx'
40
+ export { default as HubDev } from './HubDev.jsx'
40
41
  // the Studio — the Hub + Home · Library · Create · Use · pages · Settings, the workstation (apps review §6c, 2026-09-29)
41
42
  export { default as AppStudio } from './AppStudio.jsx'
42
43
  // a consumer slot in the opened rail — the page portals into it (NavRailConsumerSlot, kol-monitor 2026-10-15)