@kolkrabbi/kol-component 0.232.0 → 0.234.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 +5 -5
- package/src/atoms/ActionButton.jsx +1 -1
- package/src/atoms/AnimatedTitle.jsx +1 -1
- package/src/atoms/AudioPlayer.jsx +1 -1
- package/src/atoms/Avatar.jsx +1 -1
- package/src/atoms/Badge.jsx +1 -1
- package/src/atoms/Figure.jsx +1 -1
- package/src/atoms/FileIcon.jsx +1 -1
- package/src/atoms/Kbd.jsx +1 -1
- package/src/atoms/Pill.jsx +1 -1
- package/src/atoms/Tag.jsx +12 -1
- package/src/atoms/Textarea.jsx +2 -2
- package/src/atoms/ToggleSwitch.jsx +1 -1
- package/src/atoms/XYPad.jsx +1 -1
- package/src/molecules/AlignmentGrid.jsx +1 -1
- package/src/molecules/AudioSheet.jsx +1 -1
- package/src/molecules/CodeBlock.jsx +1 -1
- package/src/molecules/ColorRamp.jsx +1 -1
- package/src/molecules/ContentItem.jsx +1 -1
- package/src/molecules/ContentRow.jsx +1 -1
- package/src/molecules/CopyButton.jsx +1 -1
- package/src/molecules/DocFrontmatter.jsx +1 -1
- package/src/molecules/DocPage.jsx +1 -1
- package/src/molecules/DocsToc.jsx +1 -1
- package/src/molecules/Dropdown.jsx +1 -1
- package/src/molecules/DropdownTagFilter.jsx +1 -0
- package/src/molecules/EmptyState.jsx +1 -1
- package/src/molecules/FieldRow.jsx +1 -2
- package/src/molecules/ImageBlock.jsx +1 -1
- package/src/molecules/KindPreview.jsx +1 -1
- package/src/molecules/MediaTile.jsx +2 -2
- package/src/molecules/MenuPopover.jsx +1 -1
- package/src/molecules/OptionRow.jsx +29 -20
- package/src/molecules/PageHeader.jsx +1 -1
- package/src/molecules/PlaybackBar.jsx +1 -1
- package/src/molecules/ProfileCard.jsx +1 -1
- package/src/molecules/QuantityInput.jsx +1 -1
- package/src/molecules/QuickLookFrame.jsx +1 -1
- package/src/molecules/RowMenuButton.jsx +1 -1
- package/src/molecules/SectionText.jsx +1 -1
- package/src/molecules/ShapeDropdown.jsx +1 -1
- package/src/molecules/ShellDrawer.jsx +1 -1
- package/src/molecules/SortControls.jsx +1 -1
- package/src/molecules/SpecList.jsx +1 -1
- package/src/molecules/SplitToolButton.jsx +2 -2
- package/src/molecules/Stepper.jsx +1 -1
- package/src/molecules/SwatchControls.jsx +2 -2
- package/src/molecules/TabsRow.jsx +1 -1
- package/src/molecules/TiltBento.jsx +1 -1
- package/src/molecules/VideoBlock.jsx +1 -1
- package/src/molecules/VideoSheet.jsx +1 -1
- package/src/organisms/Canvas.jsx +3 -3
- package/src/organisms/ColumnBrowser.jsx +14 -8
- package/src/organisms/ContentCollection.jsx +1 -1
- package/src/organisms/CurveEditor.jsx +1 -1
- package/src/organisms/DocumentEditor.jsx +1 -1
- package/src/organisms/FeaturedCarousel.jsx +1 -1
- package/src/organisms/FramedMediaBand.jsx +1 -1
- package/src/organisms/GalleryCarousel.jsx +1 -1
- package/src/organisms/KeyframeEditor.jsx +1 -1
- package/src/organisms/LayerStack.jsx +2 -2
- package/src/organisms/MediaLibrary.jsx +2 -2
- package/src/organisms/MediaLibraryExplorer.jsx +1 -1
- package/src/organisms/MediaLibraryPages.jsx +16 -14
- package/src/organisms/MediaTileGallery.jsx +1 -1
- package/src/organisms/RecordManager.jsx +1 -1
- package/src/organisms/SectionCards.jsx +1 -1
- package/src/organisms/SectionCta.jsx +1 -1
- package/src/organisms/SectionFaq.jsx +1 -1
- package/src/organisms/SectionHero.jsx +1 -1
- package/src/organisms/SectionNewsletter.jsx +1 -1
- package/src/organisms/SectionSplit.jsx +1 -1
- package/src/organisms/SettingsPanel.jsx +8 -8
- package/src/organisms/ShellSearchOverlay.jsx +1 -1
- package/src/organisms/ShortcutsOverlay.jsx +1 -1
- package/src/organisms/SpectrumControls.jsx +4 -4
- package/src/organisms/SpectrumGrid.jsx +1 -1
- package/src/organisms/ToolPalette.jsx +1 -1
- package/src/utilities/AsciiCursor.jsx +1 -1
- package/src/utilities/AssetGrid.jsx +1 -1
- package/src/utilities/ButtonGroup.jsx +1 -1
- package/src/utilities/CropOverlay.jsx +1 -1
- package/src/utilities/CurveOverlay.jsx +1 -1
- package/src/utilities/ErrorBoundary.jsx +1 -1
- package/src/utilities/ExitPreview.jsx +1 -1
- package/src/utilities/FullscreenOverlay.jsx +1 -1
- package/src/utilities/OverlayGlassPanel.jsx +1 -1
- package/src/utilities/Popover.jsx +1 -1
- package/src/utilities/ProsePreview.jsx +1 -1
- package/src/utilities/TiltCard.jsx +1 -1
- package/src/utilities/TransparentX.jsx +1 -1
|
@@ -4,7 +4,7 @@ import { PopoverPanel, usePopover, Tooltip } from '../utilities/Popover.jsx'
|
|
|
4
4
|
import { glyphSize } from '../hooks/glyphLadders.js'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* SplitToolButton — single-trigger split tool button + variant menu (the
|
|
7
|
+
* SplitToolButton — A tool button with a variant menu. single-trigger split tool button + variant menu (the
|
|
8
8
|
* tool-palette idiom: Select · Text · [Shape ◢] · Pattern). A pinned-square
|
|
9
9
|
* quiet/pressed trigger shows the current variant while the group is `active`
|
|
10
10
|
* (else the `lastPicked` variant) plus a corner fold indicator; ONE click both
|
|
@@ -65,7 +65,7 @@ import { glyphSize } from '../hooks/glyphLadders.js'
|
|
|
65
65
|
* @param {string} props.className - Additional classes on the trigger
|
|
66
66
|
*/
|
|
67
67
|
|
|
68
|
-
/* Corner fold marker — `fold-indicator`, promoted into kol-icon-set-
|
|
68
|
+
/* Corner fold marker — `fold-indicator`, promoted into kol-icon-set-interface
|
|
69
69
|
* 2026-09-03 from kol-fxr's own drawing (editor-set-is-behind-its-source); the
|
|
70
70
|
* comment that stood here said it did not exist yet and should be promoted, so
|
|
71
71
|
* this is that. Lives inside the button so it dims with kol-btn-quiet and
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Stepper — number input + chevron buttons, built on the .kol-control shell.
|
|
2
|
+
* Stepper — A number input with step buttons. number input + chevron buttons, built on the .kol-control shell.
|
|
3
3
|
*
|
|
4
4
|
* size="xs" / "sm" (default) / "md" / "lg" — matched padding + type class.
|
|
5
5
|
* Chevron scale follows the size: 6 / 8 / 10 / 12 px each, stacked. xs is the
|
|
@@ -92,7 +92,7 @@ export function SwatchStack({
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
/**
|
|
95
|
-
* EyedropPick — eyedropper icon button + a sample chip of the sampled color.
|
|
95
|
+
* EyedropPick — Sample a color from the screen. eyedropper icon button + a sample chip of the sampled color.
|
|
96
96
|
* The button is hidden when the browser EyeDropper API is unavailable (no
|
|
97
97
|
* affordance for an action that can't run); when supported but unusable pass
|
|
98
98
|
* `disabled` to dim it. `onPick` is the app seam where EyeDropper + canvas
|
|
@@ -173,7 +173,7 @@ function NoneMarker({ onClear }) {
|
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
/**
|
|
176
|
-
* SwatchControls —
|
|
176
|
+
* SwatchControls — Fill and stroke swatches with an eyedropper. The composed colour-panel top row: SwatchStack (fill /
|
|
177
177
|
* stroke paint chips + swap + none) alongside EyedropPick (eyedropper +
|
|
178
178
|
* sample chip). Fully controlled and store-free; the app owns the swap, clear,
|
|
179
179
|
* and pick handlers.
|
|
@@ -5,7 +5,7 @@ import { Icon } from '@kolkrabbi/kol-icons'
|
|
|
5
5
|
/* taxonomy-ok: nests kol-icons's Icon */
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* TabsRow — labeled underline tab strip: text tabs where the active tab gets
|
|
8
|
+
* TabsRow — Text tabs with an underline. labeled underline tab strip: text tabs where the active tab gets
|
|
9
9
|
* a 2px bottom underline and emphasis color; inactive tabs are muted and
|
|
10
10
|
* brighten on hover. Optional leading close button and trailing minimise
|
|
11
11
|
* chevron render only when their handlers are passed — no outer chrome, the
|
|
@@ -64,7 +64,7 @@ function Media({ src, poster, className }) {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
|
-
* TiltBento — media hover-card for grid/bento walls, the Tilt family's composed
|
|
67
|
+
* TiltBento — A tilting media card for bento walls. media hover-card for grid/bento walls, the Tilt family's composed
|
|
68
68
|
* tile (was `BentoCard` until 2026-08-27, user ruling: the three tilting things
|
|
69
69
|
* in the estate are ONE prefix family — `TiltCard` the bare frame, `TiltBento`
|
|
70
70
|
* this tile, `useTilt` the one hook; `BentoCard` is the alias on the retirement
|
|
@@ -15,7 +15,7 @@ export function getEmbedUrl(url) {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* VideoBlock — a captioned prose video: the DS Figure shell (optional label,
|
|
18
|
+
* VideoBlock — A captioned video for prose. a captioned prose video: the DS Figure shell (optional label,
|
|
19
19
|
* aspect-locked bordered frame, optional figcaption) wrapping either an
|
|
20
20
|
* <iframe> embed (YouTube/Vimeo, auto-parsed from `url`) or a native <video>
|
|
21
21
|
* file player. Embed wins when `url` parses; otherwise the `file` player runs.
|
|
@@ -5,7 +5,7 @@ import QuickLookFrame from './QuickLookFrame.jsx'
|
|
|
5
5
|
/* taxonomy-ok: molecule — nests PlaybackBar + QuickLookFrame (relative). */
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* VideoSheet — video in the Quick Look window: the frame at the video's own aspect ratio, the
|
|
8
|
+
* VideoSheet — A video in the preview window. video in the Quick Look window: the frame at the video's own aspect ratio, the
|
|
9
9
|
* QuickTime bar docked in the window's footer (2026-09-23 — it floated over the picture, which
|
|
10
10
|
* made video the one kind whose controls sat on the media). No native controls; click on the
|
|
11
11
|
* video toggles play; no autoplay (user 2026-09-23 — Quick Look opens paused), `playsInline`, `preload="metadata"`.
|
package/src/organisms/Canvas.jsx
CHANGED
|
@@ -419,7 +419,7 @@ function isTypingTarget(el) {
|
|
|
419
419
|
}
|
|
420
420
|
|
|
421
421
|
/**
|
|
422
|
-
* PanZoomViewport — infinite-canvas viewport (pan + zoom), and the one that
|
|
422
|
+
* PanZoomViewport — An infinite canvas to pan and zoom. infinite-canvas viewport (pan + zoom), and the one that
|
|
423
423
|
* publishes `CanvasZoomContext`.
|
|
424
424
|
*
|
|
425
425
|
* Pan: hold Space + drag (cursor grab/grabbing), or two-finger trackpad
|
|
@@ -787,7 +787,7 @@ export function useFrameGeom(containerRef, virtualWidth = CANVAS_VIRTUAL_W) {
|
|
|
787
787
|
}
|
|
788
788
|
|
|
789
789
|
/**
|
|
790
|
-
* CanvasRuler — top + left rulers in virtual-canvas px, mapped through the
|
|
790
|
+
* CanvasRuler — Rulers along the canvas edges. top + left rulers in virtual-canvas px, mapped through the
|
|
791
791
|
* measured frame geometry (see useFrameGeom).
|
|
792
792
|
*
|
|
793
793
|
* Dragging off a ruler starts a new guide: the ruler only ANNOUNCES the
|
|
@@ -900,7 +900,7 @@ function GuideLine({ axis, screenPos, interactive, onGrab }) {
|
|
|
900
900
|
}
|
|
901
901
|
|
|
902
902
|
/**
|
|
903
|
-
* CanvasGuides — ruler guides rendered at the viewport level so each line
|
|
903
|
+
* CanvasGuides — Guide lines across the whole canvas. ruler guides rendered at the viewport level so each line
|
|
904
904
|
* spans the entire visible canvas area instead of clipping to the letterbox
|
|
905
905
|
* frame. Positions are stored in virtual canvas px and threaded down as props
|
|
906
906
|
* — the viewport is chrome and owns no guide state; the screen mapping is the
|
|
@@ -12,7 +12,7 @@ import useMarquee from '../hooks/useMarquee.js'
|
|
|
12
12
|
import { GRAB_COLUMN } from '../utilities/motion.js'
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* ColumnBrowser — Finder-style Miller columns over a flat key space (kol-r2b2's
|
|
15
|
+
* ColumnBrowser — Finder-style columns over a bucket. Finder-style Miller columns over a flat key space (kol-r2b2's
|
|
16
16
|
* `src/ColumnBrowser.jsx`, built and ruled there first — user 2026-08-27: "make
|
|
17
17
|
* it locally first, then ship it" — and shipped verbatim; ticket ColumnBrowser).
|
|
18
18
|
* The listing surface's FOLDER view: it replaces the folder rows above the
|
|
@@ -249,7 +249,7 @@ const ZONE_BOX = 44
|
|
|
249
249
|
* without the stack: the columns pass none, so a desktop row is byte-identical
|
|
250
250
|
* to what it was. */
|
|
251
251
|
function Row({
|
|
252
|
-
icon, label, active, cursor = false, trailing, onClick, muted = false, size = 'md',
|
|
252
|
+
icon, label, active, trail = false, cursor = false, trailing, onClick, muted = false, size = 'md',
|
|
253
253
|
indent = 0, meta, zones = false, thumb, onDisclose, disclosed, onContextMenu, drop, dropFiles, markKey,
|
|
254
254
|
}) {
|
|
255
255
|
const [over, setOver] = useState(false)
|
|
@@ -275,15 +275,18 @@ function Row({
|
|
|
275
275
|
},
|
|
276
276
|
} : {}
|
|
277
277
|
/* THE DESKTOP ROW IS AN OptionRow (2026-09-30) — the palette's row, on the control ramp, so a size
|
|
278
|
-
* setting scales height
|
|
279
|
-
*
|
|
280
|
-
*
|
|
278
|
+
* setting scales height and glyph; the name keeps ONE type in every view (`kol-item-name`, the
|
|
279
|
+
* grid's), as Finder does. The deepest selection takes the pressed (white) fill, the folders on the
|
|
280
|
+
* way to it the trail; hover and the bare cursor paint nothing (the 2026-09-02 ruling). The `zones`
|
|
281
|
+
* row below is the phone's and keeps its own. */
|
|
281
282
|
if (!zones) return (
|
|
282
283
|
<OptionRow
|
|
283
284
|
as="li"
|
|
284
285
|
size={size}
|
|
285
|
-
|
|
286
|
-
|
|
286
|
+
type="kol-item-name"
|
|
287
|
+
hover={false}
|
|
288
|
+
selected={active && !trail}
|
|
289
|
+
trail={active && trail}
|
|
287
290
|
muted={muted && !cursor}
|
|
288
291
|
icon={icon}
|
|
289
292
|
label={label}
|
|
@@ -1039,8 +1042,11 @@ export default function ColumnBrowser({
|
|
|
1039
1042
|
label={f.replace(/\/$/, '')}
|
|
1040
1043
|
markKey={level + f}
|
|
1041
1044
|
active={f === activeFolder || isPicked(level + f)}
|
|
1045
|
+
/* a folder on the path is the TRAIL unless it is the deepest pick — the column after
|
|
1046
|
+
* it is its own contents with nothing chosen, and no file is showing */
|
|
1047
|
+
trail={f === activeFolder && !isPicked(level + f) && (!!shown || k < levels.length - 2)}
|
|
1042
1048
|
cursor={cursorActive && cursor.col === k && cursor.idx === i}
|
|
1043
|
-
trailing={<Icon name="chevron-right" size={12} className=
|
|
1049
|
+
trailing={<Icon name="chevron-right" size={12} className={f === activeFolder && !shown && k === levels.length - 2 ? '' : 'text-oq-32'} />}
|
|
1044
1050
|
onContextMenu={onRowContextMenu && ((e) => onRowContextMenu(e, { type: 'folder', path: level + f }))}
|
|
1045
1051
|
drop={dragFor?.(level + f)}
|
|
1046
1052
|
dropFiles={onDropFiles ? (list) => onDropFiles(list, level + f) : undefined}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import usePrefersReducedMotion from '../hooks/usePrefersReducedMotion.js'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* ContentCollection — the container half of the content-card system: the
|
|
4
|
+
* ContentCollection — A grid or list of content items. the container half of the content-card system: the
|
|
5
5
|
* grid/list switch plus the motion that belongs to it. Animation lives in
|
|
6
6
|
* the wrapper — the only place it can (06-content-card-system.md §6);
|
|
7
7
|
* cards never animate themselves.
|
|
@@ -109,7 +109,7 @@ function TermRow({ term, onSet, onRemove, canRemove }) {
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
/**
|
|
112
|
-
* CurveEditor — curve authoring: a kind picker, per-kind ranges and
|
|
112
|
+
* CurveEditor — Author a curve by kind and expression. curve authoring: a kind picker, per-kind ranges and
|
|
113
113
|
* EXPRESSION fields, and the epicycle term list.
|
|
114
114
|
*
|
|
115
115
|
* Lifted from kol-fxr's editor (`compose/inspectors/CurveEditor.jsx`,
|
|
@@ -11,7 +11,7 @@ import { splitFrontmatter, joinFrontmatter } from '@kolkrabbi/kol-markdown'
|
|
|
11
11
|
import { readDraft, writeDraft, clearDraft } from '../utilities/localDrafts.js'
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* DocumentEditor — write a text file: open one, or make a new one (media D1 plan v2, 2026-09-26).
|
|
14
|
+
* DocumentEditor — Open or write a text file. write a text file: open one, or make a new one (media D1 plan v2, 2026-09-26).
|
|
15
15
|
*
|
|
16
16
|
* The concept is kol-olina's brand notes page (NoteEdit): a title, a markdown body, Write / Preview,
|
|
17
17
|
* attachments from the bucket, a page for writing something NEW rather than a button hidden in a
|
|
@@ -85,7 +85,7 @@ function SlideMedia({ media, active = true, onEnded, onTimeUpdate }) {
|
|
|
85
85
|
* the one hero (SectionHeroRound2); this stays as its engine and renders
|
|
86
86
|
* unchanged. Removed from the barrel at the next major.
|
|
87
87
|
*
|
|
88
|
-
* FeaturedCarousel — a full-width carousel of featured media: each wide slide
|
|
88
|
+
* FeaturedCarousel — A full-width carousel of featured media. a full-width carousel of featured media: each wide slide
|
|
89
89
|
* is a fixed-height frame with an image or HLS-video background and a centered
|
|
90
90
|
* OverlayGlassPanel (title / description / CTA), plus prev/next and optional
|
|
91
91
|
* autoplay with a progress bar.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Image from '../atoms/Image'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* FramedMediaBand — full-width media breather band: a centered, aspect-locked
|
|
4
|
+
* FramedMediaBand — A full-width band with one framed image. full-width media breather band: a centered, aspect-locked
|
|
5
5
|
* frame (bordered surface-secondary panel, rounded) holding one object-cover
|
|
6
6
|
* image. Extracted from the foundry TypefacePage, where it sat inlined 5x
|
|
7
7
|
* verbatim between content sections. The double radius (`rounded` panel,
|
|
@@ -9,7 +9,7 @@ import MediaViewer from './MediaViewer.jsx'
|
|
|
9
9
|
const DRAG_THRESHOLD_SQ = 25
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* GalleryCarousel — the project-detail media gallery: a horizontal, drag-scroll
|
|
12
|
+
* GalleryCarousel — A shelf of media that opens fullscreen. the project-detail media gallery: a horizontal, drag-scroll
|
|
13
13
|
* shelf of image/video tiles where clicking a tile opens THE shared fullscreen
|
|
14
14
|
* MediaViewer starting at that tile.
|
|
15
15
|
*
|
|
@@ -22,7 +22,7 @@ export const DEFAULT_KEYFRAMES = [
|
|
|
22
22
|
]
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
* KeyframeEditor — a keyframe list over a pose track, kept sorted by `t`.
|
|
25
|
+
* KeyframeEditor — A sorted list of keyframes. a keyframe list over a pose track, kept sorted by `t`.
|
|
26
26
|
*
|
|
27
27
|
* { t: 0..1, rot: [x, y, z] RADIANS, pos: [x, y, z], scale, ease }
|
|
28
28
|
*
|
|
@@ -207,7 +207,7 @@ function CanvasRow({ IconC, active, collapsed, onToggleCollapse, onSelect }) {
|
|
|
207
207
|
}
|
|
208
208
|
|
|
209
209
|
/**
|
|
210
|
-
* LayerStack — the layers panel: a z-stacked tree of rows with HTML5 drag to
|
|
210
|
+
* LayerStack — The layers panel. the layers panel: a z-stacked tree of rows with HTML5 drag to
|
|
211
211
|
* reorder AND reparent in one gesture, hover-revealed eye + lock toggles,
|
|
212
212
|
* inline rename, collapsible containers, and a Canvas root row above it all.
|
|
213
213
|
*
|
|
@@ -440,7 +440,7 @@ export default function LayerStack({
|
|
|
440
440
|
}
|
|
441
441
|
|
|
442
442
|
/**
|
|
443
|
-
* AddLayerButton — the `+` that opens a menu of layer types. Lives in the
|
|
443
|
+
* AddLayerButton — Add a layer from a menu. the `+` that opens a menu of layer types. Lives in the
|
|
444
444
|
* panel's tab row, not the stack footer (the source's placement). One entry
|
|
445
445
|
* may expand inline to a kind picker so adding "a shape" doesn't silently
|
|
446
446
|
* default to the first kind.
|
|
@@ -19,7 +19,7 @@ import { SettingsChipRow, chipCls } from './SettingsPanel.jsx'
|
|
|
19
19
|
import { filterMedia } from '../utilities/mediaSearch.js'
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* MediaLibrary — a browser over an object bucket, in two views over one
|
|
22
|
+
* MediaLibrary — Browse and pick files from a bucket. a browser over an object bucket, in two views over one
|
|
23
23
|
* headless core. Consolidates four consumer forks (kol-ds-fxr, kol-labs-single,
|
|
24
24
|
* kol-client-kolkrabbi, kol-website/brand — 9 files, ~1542 lines) that had
|
|
25
25
|
* already diverged: only fxr carried the canvas-taint fix, only labs carried
|
|
@@ -263,7 +263,7 @@ function sortFiles(files, { by, dir }) {
|
|
|
263
263
|
}
|
|
264
264
|
|
|
265
265
|
/**
|
|
266
|
-
* MediaLibraryProvider — the headless core: one list call, then a
|
|
266
|
+
* MediaLibraryProvider — The data core behind the media views. the headless core: one list call, then a
|
|
267
267
|
* PREFIX-SCOPED view over it: the folders directly under the prefix, the
|
|
268
268
|
* files at that level (or the whole subtree in `flat`), the kind allow-list,
|
|
269
269
|
* the search, the sort with direction, and paging.
|
|
@@ -4,7 +4,7 @@ import { useModal } from '../molecules/Modal.jsx'
|
|
|
4
4
|
import useMediaQuery from '../hooks/useMediaQuery.js'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* MediaLibraryExplorer — the media surface, and since 2026-09-22 a thin name for it.
|
|
7
|
+
* MediaLibraryExplorer — The media browser. the media surface, and since 2026-09-22 a thin name for it.
|
|
8
8
|
*
|
|
9
9
|
* IT USED TO BE THE MERGE ITSELF: it held a BROWSE · FILES switch and mounted one of two pages,
|
|
10
10
|
* each of which listed the bucket, drew its own header and printed its own count. The user's read
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Fragment, createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'
|
|
2
2
|
import formatSize from '../utilities/formatSize.js'
|
|
3
|
-
import { ROW_HEIGHT,
|
|
3
|
+
import { ROW_HEIGHT, ROW_FILL } from '../molecules/OptionRow.jsx'
|
|
4
4
|
import { glyphSize } from '../hooks/glyphLadders.js'
|
|
5
5
|
import { Icon } from '@kolkrabbi/kol-icons'
|
|
6
6
|
import Button from '../atoms/Button.jsx'
|
|
@@ -303,7 +303,9 @@ function TagEditor({ tags = [], onChange, suggestions = [] }) {
|
|
|
303
303
|
|
|
304
304
|
/* THE ROWS VIEW'S STEP ON THE CONTROL RAMP (user 2026-09-30) — the same `rowSize` the columns take,
|
|
305
305
|
* handed down by context rather than threaded through every subtree level. These rows keep their
|
|
306
|
-
* own anatomy (twisty, drag hit, table columns) and take
|
|
306
|
+
* own anatomy (twisty, drag hit, table columns) and take the ramp's box and glyph, OptionRow's
|
|
307
|
+
* fills (picked = the pressed white, the folder you are in = the trail) and the one item type,
|
|
308
|
+
* `kol-item-name`, that the columns and the grid use. */
|
|
307
309
|
const RowSize = createContext('md')
|
|
308
310
|
|
|
309
311
|
/* `depth` indents a row under the folder it was expanded from; `expanded`/`onToggle` draw the
|
|
@@ -341,7 +343,7 @@ function FolderRow({ name, icon = 'folder', onClick, onDoubleClick, depth = 0, e
|
|
|
341
343
|
return (
|
|
342
344
|
/* THE COLUMN BROWSER'S ROW (user 2026-09-22): `kol-column-browser-row` carries the 4px pill
|
|
343
345
|
* inset, the selected fill and the drop fill; no divider, as the columns have none. */
|
|
344
|
-
<li onContextMenu={onContextMenu} {...dropProps} data-marquee-key={markKey} data-hit-zone data-drop-over={over || undefined} className={`kol-column-browser-row flex items-center gap-3 border border-transparent px-3 ${ROW_HEIGHT[size]} transition-colors${selected ?
|
|
346
|
+
<li onContextMenu={onContextMenu} {...dropProps} data-marquee-key={markKey} data-hit-zone data-drop-over={over || undefined} className={`kol-column-browser-row flex items-center gap-3 border border-transparent px-3 ${ROW_HEIGHT[size]} transition-colors${selected ? ` is-selected ${ROW_FILL.selected}` : ''}${current ? ' is-current' : ''}${current && !selected ? ` ${ROW_FILL.trail}` : ''}`} style={{ paddingLeft: depth * 20 + 12 }} onClick={onClick} onDoubleClick={onDoubleClick}>
|
|
345
347
|
{onToggle ? (
|
|
346
348
|
<button type="button" aria-label={expanded ? `Collapse ${name}` : `Expand ${name}`} aria-expanded={!!expanded}
|
|
347
349
|
onClick={(e) => { e.stopPropagation(); onToggle() }}
|
|
@@ -353,11 +355,11 @@ function FolderRow({ name, icon = 'folder', onClick, onDoubleClick, depth = 0, e
|
|
|
353
355
|
{/* THE FOLDER GLYPH IS THE ONE ICON LEFT, so it fills its box (user 2026-09-23: *"only folder
|
|
354
356
|
should use icon, and it should be bigger"*). Every other kind now renders its own bytes. */}
|
|
355
357
|
<span data-hit {...hitDrag} className="kol-row-hit flex items-center gap-3 min-w-0">
|
|
356
|
-
<span className=
|
|
358
|
+
<span className={`shrink-0 flex items-center justify-center${selected ? '' : ' text-oq-48'}`}><Icon name={icon} size={glyphSize(size)} /></span>
|
|
357
359
|
{/* NO TRAILING SLASH (user 2026-09-22). `partition` hands folders back as `audio/` because a
|
|
358
360
|
slash is what marks one in a flat key space; that is storage's spelling, not a label, and
|
|
359
361
|
`ColumnBrowser` has always stripped it. The glyph says "folder". */}
|
|
360
|
-
<span className={
|
|
362
|
+
<span className={`kol-item-name min-w-0 truncate${selected ? '' : ' text-fg-default'}`}>{name.replace(/\/$/, '')}</span>
|
|
361
363
|
</span>
|
|
362
364
|
<span className="flex-1" />
|
|
363
365
|
{/* THE FOLDER'S COUNT SITS IN THE DATE COLUMN and the size column takes a dash — the columns
|
|
@@ -365,8 +367,8 @@ function FolderRow({ name, icon = 'folder', onClick, onDoubleClick, depth = 0, e
|
|
|
365
367
|
promised a click that opens, and a click now SELECTS (opening is a double-click). */}
|
|
366
368
|
{cols && <>
|
|
367
369
|
{cols.tags != null && <span className="shrink-0" style={{ width: cols.tags }} />}
|
|
368
|
-
<span className=
|
|
369
|
-
<span className=
|
|
370
|
+
<span className={`kol-item-name ${selected ? "opacity-60" : "text-fg-32"} shrink-0 truncate`} style={{ width: cols.date }}>{meta}</span>
|
|
371
|
+
<span className={`kol-item-name ${selected ? "opacity-60" : "text-fg-24"} shrink-0 truncate`} style={{ width: cols.size }}>—</span>
|
|
370
372
|
</>}
|
|
371
373
|
<RowMenuButton onOpen={onContextMenu} className="-my-1 -mr-1" />
|
|
372
374
|
</li>
|
|
@@ -430,21 +432,21 @@ function FileRow({ o, onClick, onDoubleClick, depth = 0, formatDate, thumb, cols
|
|
|
430
432
|
const size = useContext(RowSize)
|
|
431
433
|
const dragProps = drag ? { draggable: true, onDragStart: (e) => { e.stopPropagation(); drag.onDragStart(e, o.key) } } : {}
|
|
432
434
|
return (
|
|
433
|
-
<li onContextMenu={onContextMenu} data-marquee-key={markKey ?? o.key} data-hit-zone className={`kol-column-browser-row flex items-center gap-3 border border-transparent px-3 ${ROW_HEIGHT[size]} transition-colors${selected ?
|
|
435
|
+
<li onContextMenu={onContextMenu} data-marquee-key={markKey ?? o.key} data-hit-zone className={`kol-column-browser-row flex items-center gap-3 border border-transparent px-3 ${ROW_HEIGHT[size]} transition-colors${selected ? ` is-selected ${ROW_FILL.selected}` : ''}`} style={{ paddingLeft: depth * 20 + 12 }} onClick={onClick} onDoubleClick={onDoubleClick}>
|
|
434
436
|
<span className="w-4 shrink-0" />
|
|
435
437
|
{/* the hit — icon and name, as in the folder row above */}
|
|
436
438
|
<span data-hit {...dragProps} className="kol-row-hit flex items-center gap-3 min-w-0">
|
|
437
|
-
<span className=
|
|
439
|
+
<span className={`shrink-0 flex items-center justify-center overflow-hidden rounded${selected ? '' : ' text-oq-48'}`} style={{ width: glyphSize(size), height: glyphSize(size) }}>
|
|
438
440
|
{/* a file with no thumbnail draws its glyph at the FOLDER's size — one icon column (user 2026-09-25) */}
|
|
439
441
|
{thumb ?? <Icon name={kindOf(o) === 'image' ? 'image' : 'file'} size={glyphSize(size)} />}
|
|
440
442
|
</span>
|
|
441
|
-
<span className={
|
|
443
|
+
<span className={`kol-item-name min-w-0 truncate${selected ? '' : ' text-fg-default'}`}>{o.displayKey ?? o.key.split('/').pop()}</span>
|
|
442
444
|
</span>
|
|
443
445
|
<span className="flex-1" />
|
|
444
446
|
{cols && <>
|
|
445
|
-
{cols.tags != null && <span className=
|
|
446
|
-
<span className=
|
|
447
|
-
<span className=
|
|
447
|
+
{cols.tags != null && <span className={`kol-item-name ${selected ? "opacity-60" : "text-fg-48"} shrink-0 truncate`} style={{ width: cols.tags }}>{(o.tags ?? []).map((t) => `#${t}`).join(' ')}</span>}
|
|
448
|
+
<span className={`kol-item-name ${selected ? "opacity-60" : "text-fg-32"} shrink-0 truncate`} style={{ width: cols.date }}>{formatDate?.(o.uploaded)}</span>
|
|
449
|
+
<span className={`kol-item-name ${selected ? "opacity-60" : "text-fg-32"} shrink-0 truncate`} style={{ width: cols.size }}>{formatSize(o.size)}</span>
|
|
448
450
|
</>}
|
|
449
451
|
<RowMenuButton onOpen={onContextMenu} className="-my-1 -mr-1" />
|
|
450
452
|
</li>
|
|
@@ -594,7 +596,7 @@ function FileEditorHost({ o, client, bucket, onClose, onSaved, assets }) {
|
|
|
594
596
|
}
|
|
595
597
|
|
|
596
598
|
/**
|
|
597
|
-
* MediaInspector — the full-screen viewer for one file in a set: image, video
|
|
599
|
+
* MediaInspector — View one file at full size. the full-screen viewer for one file in a set: image, video
|
|
598
600
|
* (scrubbable, audio on), audio, or a document page, in one `QuickLookFrame`, with
|
|
599
601
|
* prev / next fixed at the viewport edges.
|
|
600
602
|
*
|
|
@@ -2,7 +2,7 @@ import { useState } from 'react'
|
|
|
2
2
|
import MediaViewer from './MediaViewer.jsx'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* MediaTileGallery — a stack or grid of framed media tiles that open THE
|
|
5
|
+
* MediaTileGallery — Media tiles that open a fullscreen viewer. a stack or grid of framed media tiles that open THE
|
|
6
6
|
* shared fullscreen MediaViewer at the clicked tile, paged across all items
|
|
7
7
|
* (the monorepo's FullscreenGallery recreated on the shared viewer instead of
|
|
8
8
|
* its nav-less single image; the AssetFigure/AssetGrid deps are dropped —
|
|
@@ -35,7 +35,7 @@ const ToolbarIcon = ({ name, label, onClick, active = false, triggerClassName })
|
|
|
35
35
|
)
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
|
-
* RecordManager — full-screen CMS record surface (lobby: RecordManager,
|
|
38
|
+
* RecordManager — A full-screen CMS record editor. full-screen CMS record surface (lobby: RecordManager,
|
|
39
39
|
* reference: Framer CMS). A reorderable record table plus a slide-over detail
|
|
40
40
|
* panel of FieldRows.
|
|
41
41
|
*
|
|
@@ -6,7 +6,7 @@ import useSectionTheme from '../hooks/useSectionTheme.js'
|
|
|
6
6
|
import { minHeightClass } from './sectionHeights.js'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* SectionCards — the "N-up feature cards" band: a `SectionText` header over a
|
|
9
|
+
* SectionCards — A header over a row of feature cards. the "N-up feature cards" band: a `SectionText` header over a
|
|
10
10
|
* responsive row of `SectionCardItem` cards, capped by an optional centred
|
|
11
11
|
* action row. `FeaturesCardSection` is this component under its old name and
|
|
12
12
|
* prop names (`headerLabel` → `headline`, `headerDescription` → `body`,
|
|
@@ -5,7 +5,7 @@ import SectionText from '../molecules/SectionText.jsx'
|
|
|
5
5
|
import { minHeightClass } from './sectionHeights.js'
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* SectionCta — the editorial two-column contact/CTA band: a large display
|
|
8
|
+
* SectionCta — A closing call-to-action band. the editorial two-column contact/CTA band: a large display
|
|
9
9
|
* wordmark on the left (e.g. "/ CONNECT") and a right column of stacked
|
|
10
10
|
* label-over-value rows, each a `SectionText` (label in the helper voice,
|
|
11
11
|
* value as a heading-01; a row with `href` renders its value as a link).
|
|
@@ -6,7 +6,7 @@ import SectionText from '../molecules/SectionText.jsx'
|
|
|
6
6
|
import { minHeightClass } from './sectionHeights.js'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* SectionFaq — a `SectionText` header over an `Accordion` of question /
|
|
9
|
+
* SectionFaq — Questions and answers in an accordion. a `SectionText` header over an `Accordion` of question /
|
|
10
10
|
* answer items. The one NEW surface in the section family (SectionSet,
|
|
11
11
|
* 2026-08-26) — the behaviour already shipped in the Accordion molecule; this
|
|
12
12
|
* is the section around it.
|
|
@@ -85,7 +85,7 @@ function MediaLayer({ media }) {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
/**
|
|
88
|
-
* SectionHero — the full-bleed media hero: cover-fit background media (image
|
|
88
|
+
* SectionHero — Full-bleed media hero with a glass panel. the full-bleed media hero: cover-fit background media (image
|
|
89
89
|
* or video) filling a fixed-height section, an optional surface scrim, and
|
|
90
90
|
* the text in a glass panel over it. `FullBleedHero` is this component under
|
|
91
91
|
* its old name (alias kept).
|
|
@@ -8,7 +8,7 @@ import useSectionTheme from '../hooks/useSectionTheme.js'
|
|
|
8
8
|
import { minHeightClass } from './sectionHeights.js'
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* SectionNewsletter — the newsletter card of the section family
|
|
11
|
+
* SectionNewsletter — A newsletter signup card. the newsletter card of the section family
|
|
12
12
|
* (SectionNewsletter, kol-website 2026-08-27 — user: the newsletter as a card
|
|
13
13
|
* in the family, same ladder, same cap, content centred on y, not its own
|
|
14
14
|
* thing). `SectionText` (label · headline · body, centred) with the email
|
|
@@ -6,7 +6,7 @@ import useSectionTheme from '../hooks/useSectionTheme.js'
|
|
|
6
6
|
import { minHeightClass } from './sectionHeights.js'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* SectionSplit — the media-and-text split section, on `SectionText` (the
|
|
9
|
+
* SectionSplit — Text beside media. the media-and-text split section, on `SectionText` (the
|
|
10
10
|
* text column) beside the media frame. Two columns at/above 901px, one
|
|
11
11
|
* stacked column below. `FeatureSplit` is this component under its old name
|
|
12
12
|
* and old prop names (kept as an alias — see FeatureSplit.jsx).
|
|
@@ -9,7 +9,7 @@ import FullscreenOverlay from '../utilities/FullscreenOverlay.jsx'
|
|
|
9
9
|
import { Tooltip } from '../utilities/Popover.jsx'
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* SettingsPanel — a settings surface for the thing you are looking at: you
|
|
12
|
+
* SettingsPanel — Settings beside the thing they change. a settings surface for the thing you are looking at: you
|
|
13
13
|
* change how a list looks WHILE looking at it, so it is a slide-over (or an
|
|
14
14
|
* overlay), never a route (SettingsPanel, kol-r2b2 2026-08-26 — the
|
|
15
15
|
* per-bucket display settings: kinds allow-list, structure, loading, layout).
|
|
@@ -107,7 +107,7 @@ export default function SettingsPanel({
|
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
/**
|
|
110
|
-
* SettingsRow — a `LabeledControl inline` (SettingsPanelApproved, 2026-08-27):
|
|
110
|
+
* SettingsRow — One labelled setting. a `LabeledControl inline` (SettingsPanelApproved, 2026-08-27):
|
|
111
111
|
* uppercase label (`kol-helper-10` tracked, meta ink) in a 160px column, the
|
|
112
112
|
* control fills the rest. A switch sits at the far right (`align="end"`, the
|
|
113
113
|
* default); a dropdown fills the row (`align="fill"`). No hint sentences on the
|
|
@@ -127,7 +127,7 @@ export function SettingsRow({ label, hint, align = 'end', labelWidth = 160, chil
|
|
|
127
127
|
)
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
/** SettingsSwitch — the row's on/off control: the DS ToggleSwitch, bare, sm.
|
|
130
|
+
/** SettingsSwitch — An on/off setting. the row's on/off control: the DS ToggleSwitch, bare, sm.
|
|
131
131
|
* `disabledHint` rides a DS `Tooltip` so a switch that cannot act says why;
|
|
132
132
|
* inside a row's `hint` it wins while hovered, as the native `title` did. */
|
|
133
133
|
export function SettingsSwitch({ on = false, onChange, disabled = false, disabledHint, label, title }) {
|
|
@@ -144,7 +144,7 @@ export function SettingsSwitch({ on = false, onChange, disabled = false, disable
|
|
|
144
144
|
return tip ? <Tooltip label={tip}>{toggle}</Tooltip> : toggle
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
/** LabeledControlSection — a section of LabeledControls: the EYEBROW
|
|
147
|
+
/** LabeledControlSection — A titled section of labelled controls. a section of LabeledControls: the EYEBROW
|
|
148
148
|
* (`kol-eyebrow text-fg-80`) standing apart from the rows (gap-3), the rows in
|
|
149
149
|
* their own stack — `rowGap` 1 for switch rows (24 tall already), 2 for
|
|
150
150
|
* dropdown rows. `divided` = a hairline above (between sections).
|
|
@@ -161,7 +161,7 @@ export function LabeledControlSection({ label, divided = false, rowGap = 2, chil
|
|
|
161
161
|
)
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
/** SettingsChoice — the row's one-of-N control: the DS Dropdown, sm · primary
|
|
164
|
+
/** SettingsChoice — A one-of-many setting. the row's one-of-N control: the DS Dropdown, sm · primary
|
|
165
165
|
* (SettingsPanelEyebrowAndDropdowns — user: "put the toggles inside a dropdown,
|
|
166
166
|
* because it's super messy like it is"). Options are values or `{ value, label }`;
|
|
167
167
|
* width is the call site's (`className="w-40"`).
|
|
@@ -189,7 +189,7 @@ export const CHIP_CLS = 'kol-control kol-control-sm kol-mono-12'
|
|
|
189
189
|
export const chipCls = (on) => `${CHIP_CLS} ${on ? 'kol-control--filled' : 'text-meta hover:text-emphasis'}`
|
|
190
190
|
|
|
191
191
|
/**
|
|
192
|
-
* SettingsMulti — a many-of-N control as ONE Dropdown (SettingsPanelApproved,
|
|
192
|
+
* SettingsMulti — A many-of-many setting in one dropdown. a many-of-N control as ONE Dropdown (SettingsPanelApproved,
|
|
193
193
|
* 2026-08-27 — the kinds row): the trigger reads `N of M <noun>`, every entry
|
|
194
194
|
* toggles and `✓` marks the ones that are on. No grouping.
|
|
195
195
|
* @param {Array} options [{ value, label }]
|
|
@@ -210,7 +210,7 @@ export function SettingsMulti({ options = [], selected = [], onToggle, noun = 'k
|
|
|
210
210
|
}
|
|
211
211
|
|
|
212
212
|
/**
|
|
213
|
-
* SettingsChipRow — a wrap of toggle chips with optional counts (an
|
|
213
|
+
* SettingsChipRow — A row of toggle chips. a wrap of toggle chips with optional counts (an
|
|
214
214
|
* allow-list: every chip sets a default, never a gate). `allChip` puts an
|
|
215
215
|
* "all" chip first — the same control chip, filled when every option is on
|
|
216
216
|
* (SettingsPanelEyebrowAndDropdowns — user: "Show all in ghost mode? makes no
|
|
@@ -247,7 +247,7 @@ export function SettingsChipRow({ options = [], selected = [], onToggle, allChip
|
|
|
247
247
|
)
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
-
/** SettingsFooter — a Divider, then one `IconFrame refresh` (primary · sm) at the
|
|
250
|
+
/** SettingsFooter — Reset settings to their defaults. a Divider, then one `IconFrame refresh` (primary · sm) at the
|
|
251
251
|
* right = reset to defaults (SettingsPanelApproved, 2026-08-27). No status word,
|
|
252
252
|
* no text button. `customised` is accepted for compatibility and unused.
|
|
253
253
|
*
|
|
@@ -59,7 +59,7 @@ export function HighlightMatch({ label, query, ranges }) {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
/**
|
|
62
|
-
* ShellSearchOverlay — the ⌘K command palette: fullscreen dim + centered
|
|
62
|
+
* ShellSearchOverlay — The ⌘K search palette. the ⌘K command palette: fullscreen dim + centered
|
|
63
63
|
* panel, a bare SearchInput on top, result rows beneath (HighlightMatch
|
|
64
64
|
* label, dim hint line, right-aligned group label). Distinct from Modal
|
|
65
65
|
* (prompt/confirm only) — this is the search/command primitive.
|
|
@@ -2,7 +2,7 @@ import { useEffect } from 'react'
|
|
|
2
2
|
import SettingsSections from './SettingsSections.jsx'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* ShortcutsOverlay — the keyboard-shortcut sheet: blurred scrim, centred
|
|
5
|
+
* ShortcutsOverlay — The keyboard shortcut sheet. the keyboard-shortcut sheet: blurred scrim, centred
|
|
6
6
|
* panel, a 2-col grid (label · keys), Esc / backdrop-click close.
|
|
7
7
|
* Ported from the shared cut (mirror's, "copied from kol-monitor").
|
|
8
8
|
*
|
|
@@ -41,7 +41,7 @@ const HUE_GRADIENT =
|
|
|
41
41
|
'linear-gradient(to right, hsl(0,100%,50%), hsl(60,100%,50%), hsl(120,100%,50%), hsl(180,100%,50%), hsl(240,100%,50%), hsl(300,100%,50%), hsl(360,100%,50%))'
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
|
-
* HueStrip — 1D hue slider: a rainbow bar with a draggable knob. Pointer
|
|
44
|
+
* HueStrip — A hue slider. 1D hue slider: a rainbow bar with a draggable knob. Pointer
|
|
45
45
|
* drag anywhere on the strip; focus + Left/Right (or Down/Up) arrow keys
|
|
46
46
|
* nudge hue by 1° (role="slider").
|
|
47
47
|
*
|
|
@@ -116,7 +116,7 @@ export function HueStrip({ hue, onChange }) {
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
/**
|
|
119
|
-
* SBSquare — 2D saturation/value picker: white→hue horizontal gradient with
|
|
119
|
+
* SBSquare — Pick saturation and value on a square. 2D saturation/value picker: white→hue horizontal gradient with
|
|
120
120
|
* a black overlay fading upward, crosshair handle. Fills its container
|
|
121
121
|
* (consumer owns the size — and the rounding: apply `rounded-[var(--kol-radius-xs)]
|
|
122
122
|
* overflow-hidden` on the wrapper). Focus + arrow keys nudge: Left/Right =
|
|
@@ -233,7 +233,7 @@ function vertexAt(angleRad) {
|
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
/**
|
|
236
|
-
* WheelTriangle — HSV color wheel: conic hue ring with an inscribed,
|
|
236
|
+
* WheelTriangle — A hue wheel with a value triangle. HSV color wheel: conic hue ring with an inscribed,
|
|
237
237
|
* rotating HSV triangle for saturation/value. Ring press snaps hue to the
|
|
238
238
|
* cursor angle and drags; triangle press grabs the SV handle with a
|
|
239
239
|
* cursor↔handle offset so fine tuning never teleports it. Focus + arrow
|
|
@@ -478,7 +478,7 @@ function SvgHandle({ cx, cy, r = 2.4 }) {
|
|
|
478
478
|
}
|
|
479
479
|
|
|
480
480
|
/**
|
|
481
|
-
* SpectrumControls —
|
|
481
|
+
* SpectrumControls — A hue strip over a saturation square. The composed classic square picker: HueStrip stacked
|
|
482
482
|
* over a fill-height SBSquare, per the source color panel's Hue mode layout
|
|
483
483
|
* (SBSquare wrapped in `rounded-[var(--kol-radius-xs)] overflow-hidden`, see its comment).
|
|
484
484
|
* Fills its container — the consumer owns the outer size. For the ring
|
|
@@ -4,7 +4,7 @@ import { resolveCssVar, resolveCssColor, isLight } from '../hooks/cssVar.js'
|
|
|
4
4
|
import { Tooltip } from '../utilities/Popover.jsx'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* SpectrumGrid — matrix view of the whole ramp system: rows = ramps, columns =
|
|
7
|
+
* SpectrumGrid — Every ramp by every stop. matrix view of the whole ramp system: rows = ramps, columns =
|
|
8
8
|
* stops (50 → 900). Each cell is a ColorSwatch tile with the stop number and
|
|
9
9
|
* hex printed over it (text color contrast-corrected via isLight), so the whole
|
|
10
10
|
* palette is scannable in one grid.
|
|
@@ -5,7 +5,7 @@ import SplitToolButton from '../molecules/SplitToolButton.jsx'
|
|
|
5
5
|
import { Tooltip } from '../utilities/Popover.jsx'
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* ToolPalette — the editor's tool bar as one row (kol-fxr `shell/panels/ToolPalette.jsx`,
|
|
8
|
+
* ToolPalette — The editor's tool bar. the editor's tool bar as one row (kol-fxr `shell/panels/ToolPalette.jsx`,
|
|
9
9
|
* editor-panels-the-held-specs A3, 2026-09-25). Four kinds of cell, all on one pinned-square rung:
|
|
10
10
|
*
|
|
11
11
|
* - `tool` — arms a mode; lit while `activeId` is its id
|