@kolkrabbi/kol-shell 0.3.0 → 0.4.1

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.3.0",
3
+ "version": "0.4.1",
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",
@@ -20,10 +20,10 @@
20
20
  "react-dom": "^18.3.0 || ^19.0.0"
21
21
  },
22
22
  "devDependencies": {
23
+ "@kolkrabbi/kol-component": "^0.47.0",
24
+ "@kolkrabbi/kol-framework": "^0.22.0",
23
25
  "@kolkrabbi/kol-icons": "^0.17.0",
24
- "@kolkrabbi/kol-component": "^0.44.0",
25
- "@kolkrabbi/kol-theme": "^0.42.2",
26
- "@kolkrabbi/kol-framework": "^0.20.1"
26
+ "@kolkrabbi/kol-theme": "^0.44.0"
27
27
  },
28
28
  "files": [
29
29
  "src",
package/src/GridCard.jsx CHANGED
@@ -39,7 +39,7 @@ export default function GridCard({ title, detail, preview, expanded, expandedCon
39
39
  gridRow: expanded ? 'span 2' : 'span 1',
40
40
  position: 'relative', overflow: 'hidden',
41
41
  display: 'flex', flexDirection: expanded ? 'row-reverse' : 'column',
42
- transition: 'all 300ms cubic-bezier(0.16, 1, 0.3, 1)',
42
+ transition: 'all 300ms var(--kol-ease-house)',
43
43
  }}
44
44
  >
45
45
  <div style={{
@@ -2,15 +2,50 @@ import { useEffect } from 'react'
2
2
 
3
3
  /**
4
4
  * ShortcutsOverlay — the keyboard-shortcut sheet: blurred scrim, centred
5
- * panel, one flat 2-col grid (label · keys), Esc / backdrop-click close.
5
+ * panel, a 2-col grid (label · keys), Esc / backdrop-click close.
6
6
  * Ported from the shared cut (mirror's, "copied from kol-monitor").
7
7
  *
8
8
  * `shortcuts` is a prop — feed the SAME array your settings page renders
9
9
  * (both repos hand-maintained the list twice and both pairs drifted).
10
10
  * Stacks at `--kol-z-modal`, above the rail's sticky tier.
11
11
  *
12
- * @param {Array} props.shortcuts - `[{ label, keys }]`
12
+ * TWO FORMS, DETECTED ON SHAPE (ShortcutsOverlaySections, kol-fxr 2026-08-15):
13
+ *
14
+ * flat `[{ label, keys }]` — one grid, as shipped
15
+ * sectioned `[{ section, items: [{label,keys}] }]` — headings between groups
16
+ *
17
+ * The flat form renders EXACTLY as it did before, so no existing caller moves.
18
+ * The sectioned form exists because a real keymap is grouped — kol-fxr's is
19
+ * Edit · Selection · Layer · Tools · View, and its `shortcutsBySection()`
20
+ * already emits this shape — and flattening it to adopt this component would
21
+ * have lost the grouping. That consumer kept a 99-line local overlay instead,
22
+ * which is the duplication this component exists to end.
23
+ *
24
+ * ONE GRID, NOT NESTED ONES. The headings span both columns
25
+ * (`gridColumn: 1 / -1`) so every `keys` cell in the sheet stays on the same
26
+ * axis — nesting a grid per section would let each group compute its own
27
+ * column width and the keys would stagger down the panel.
28
+ *
29
+ * `keys` is a DISPLAY STRING and is never bound — this component shows a
30
+ * keymap, it does not own one. Formatting a combo (⌘⇧Z) is the consumer's,
31
+ * next to wherever the binding actually lives.
32
+ *
33
+ * @param {Array} props.shortcuts - `[{ label, keys }]` or `[{ section, items }]`
34
+ * @param {Function} props.onClose
13
35
  */
36
+
37
+ const isSectioned = (list) => Array.isArray(list?.[0]?.items)
38
+
39
+ /* One row of the shared grid. `contents` keeps the pair on the parent grid
40
+ * rather than making the wrapper a cell of its own. */
41
+ function Row({ label, keys }) {
42
+ return (
43
+ <span className="contents">
44
+ <span>{label}</span><span className="text-fg-96">{keys}</span>
45
+ </span>
46
+ )
47
+ }
48
+
14
49
  export default function ShortcutsOverlay({ shortcuts = [], onClose }) {
15
50
  useEffect(() => {
16
51
  const onKey = (e) => { if (e.key === 'Escape') onClose?.() }
@@ -18,6 +53,8 @@ export default function ShortcutsOverlay({ shortcuts = [], onClose }) {
18
53
  return () => window.removeEventListener('keydown', onKey)
19
54
  }, [onClose])
20
55
 
56
+ const sectioned = isSectioned(shortcuts)
57
+
21
58
  return (
22
59
  <div
23
60
  onClick={onClose}
@@ -25,11 +62,23 @@ export default function ShortcutsOverlay({ shortcuts = [], onClose }) {
25
62
  style={{ display: 'grid', placeItems: 'center', backdropFilter: 'blur(2px)', zIndex: 'var(--kol-z-modal)' }}
26
63
  >
27
64
  <div className="text-fg-64 kol-helper-12 bg-surface-primary border border-fg-16" style={{ display: 'grid', gridTemplateColumns: 'auto auto', gap: '10px 62px', padding: 24, borderRadius: 4 }}>
28
- {shortcuts.map(({ label, keys }) => (
29
- <span key={label} className="contents">
30
- <span>{label}</span><span className="text-fg-96">{keys}</span>
31
- </span>
32
- ))}
65
+ {sectioned
66
+ ? shortcuts.map(({ section, items = [] }, i) => (
67
+ <span key={section} className="contents">
68
+ <span
69
+ className="text-fg-32"
70
+ style={{ gridColumn: '1 / -1', marginTop: i === 0 ? 0 : 14 }}
71
+ >
72
+ {section}
73
+ </span>
74
+ {items.map(({ label, keys }) => (
75
+ <Row key={`${section}:${label}`} label={label} keys={keys} />
76
+ ))}
77
+ </span>
78
+ ))
79
+ : shortcuts.map(({ label, keys }) => (
80
+ <Row key={label} label={label} keys={keys} />
81
+ ))}
33
82
  </div>
34
83
  </div>
35
84
  )