@kolkrabbi/kol-component 0.140.0 → 0.142.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 +1 -1
- package/src/index.js +3 -0
- package/src/molecules/ContentRow.jsx +10 -2
- package/src/utilities/useGrabEdge.js +61 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kolkrabbi/kol-component",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.142.0",
|
|
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",
|
package/src/index.js
CHANGED
|
@@ -152,6 +152,9 @@ export { parseFrontmatter } from './utilities/frontmatter.js'
|
|
|
152
152
|
export { readCover } from './utilities/id3.js'
|
|
153
153
|
export { kindOf, extOf, isSystemFile, KINDS, KIND_LABEL, DEFAULT_KINDS, isSegment, groupSegments, groupVariants, posterFor, partition } from './utilities/mediaKinds.js'
|
|
154
154
|
export { nearestRatio, RATIOS } from './utilities/ratios.js'
|
|
155
|
+
/* the grab gesture — shared so kol-shell's NavRail and kol-framework's
|
|
156
|
+
* useDragResize wear ONE implementation (OneGrabGestureBothRails, 2026-08-30) */
|
|
157
|
+
export { default as useGrabEdge } from './utilities/useGrabEdge.js'
|
|
155
158
|
export { default as markdownToHtml, inlineToHtml } from './utilities/markdownToHtml.js'
|
|
156
159
|
export { default as RecordManager } from './organisms/RecordManager.jsx'
|
|
157
160
|
export { default as SpectrumGrid } from './organisms/SpectrumGrid.jsx'
|
|
@@ -87,8 +87,16 @@ const BOX = {
|
|
|
87
87
|
* variant NAME — so the two boxes agreed on every number and still disagreed
|
|
88
88
|
* about the vertical spread. Deriving one box from another while a second map
|
|
89
89
|
* is keyed by name is the drift the derive was meant to end. */
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
/* NO `hover` KEY (TypefaceRowHoverBg, kol-website 2026-08-30, the third
|
|
91
|
+
* pass on this row). `showcase` has `frameHover` and no `hover` at all, so a
|
|
92
|
+
* work row answers a pointer with a border step alone; this row also washed
|
|
93
|
+
* its background and read as a different interaction from every other listing.
|
|
94
|
+
*
|
|
95
|
+
* The three passes are the lesson: the ask was "make it look like /work" and
|
|
96
|
+
* each ticket named only the state someone had looked at — rest colours, then
|
|
97
|
+
* the derive's collateral, then this. When a user says make X look like Y,
|
|
98
|
+
* diff EVERY state: rest, hover, selected, focus. */
|
|
99
|
+
bg: 'var(--kol-surface-secondary)', frame: 'transparent', frameHover: 'var(--kol-fg-08)' },
|
|
92
100
|
}
|
|
93
101
|
|
|
94
102
|
/* `default` → `file` (user 2026-08-29). The variant was named after being the
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { useEffect } from 'react'
|
|
2
|
+
import { GRAB } from './motion.js'
|
|
3
|
+
import gsap from 'gsap'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* useGrabEdge — the proximity-wake grab pill, for ANY resizable edge.
|
|
7
|
+
*
|
|
8
|
+
* Lifted out of kol-shell's `NavRail` 2026-08-30 (OneGrabGestureBothRails,
|
|
9
|
+
* kol-fxr — user: *"why dont we use the grab animation and other sidenav
|
|
10
|
+
* settings to be consistent?"*). fxr's `/labs` renders two rails on one screen,
|
|
11
|
+
* the shell's on the left and a params rail on the right, and only the left one
|
|
12
|
+
* came alive as the cursor neared it. Two implementations of one gesture in two
|
|
13
|
+
* packages, and neither was consumer code, so no consumer could converge them.
|
|
14
|
+
*
|
|
15
|
+
* It lives in kol-component because that is the only package BOTH rails can
|
|
16
|
+
* reach: kol-shell dropped its kol-framework peer in 0.16.0, so shell cannot
|
|
17
|
+
* import framework's hook and framework cannot import shell's. `gsap` and the
|
|
18
|
+
* `GRAB` tuning constants were already here.
|
|
19
|
+
*
|
|
20
|
+
* WHAT IT DOES. Watches the pointer; within `GRAB.near` of the handle's centre
|
|
21
|
+
* line it adds `is-near` (hysteresis out at `GRAB.sleep`, so the pill does not
|
|
22
|
+
* flicker on the boundary) and travels the pill along the edge to meet the
|
|
23
|
+
* cursor — bipolar from the middle across `GRAB.range` of the height, so it
|
|
24
|
+
* never rides up under a logomark. `GRAB.stick` is the dwell: a move smaller
|
|
25
|
+
* than that leaves the pill where it is, which is what stops it twitching.
|
|
26
|
+
*
|
|
27
|
+
* The element needs the `.kol-rail-grab` class for the drawing (kol-animation.css);
|
|
28
|
+
* this hook only supplies `is-near` and `--kol-rail-grab-y`.
|
|
29
|
+
*
|
|
30
|
+
* @param {React.RefObject<HTMLElement>} ref the grab handle
|
|
31
|
+
*/
|
|
32
|
+
export default function useGrabEdge(ref) {
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
let raf = 0
|
|
35
|
+
const onMove = ({ clientX, clientY }) => {
|
|
36
|
+
if (raf) return
|
|
37
|
+
raf = requestAnimationFrame(() => {
|
|
38
|
+
raf = 0
|
|
39
|
+
const h = ref.current
|
|
40
|
+
if (!h) return
|
|
41
|
+
const r = h.getBoundingClientRect()
|
|
42
|
+
const dist = Math.abs(clientX - (r.left + r.width / 2))
|
|
43
|
+
const near = dist <= GRAB.near || (h.classList.contains('is-near') && dist <= GRAB.sleep)
|
|
44
|
+
h.classList.toggle('is-near', near)
|
|
45
|
+
if (!near) return
|
|
46
|
+
/* the travel band: bipolar from the middle, GRAB.range of the height */
|
|
47
|
+
const edge = (r.height * (1 - GRAB.range)) / 2
|
|
48
|
+
const along = Math.min(Math.max(clientY - r.top, edge), r.height - edge)
|
|
49
|
+
if (h.dataset.grabSeeded && Math.abs(along - Number(h.dataset.grabTarget)) < GRAB.stick) return
|
|
50
|
+
h.dataset.grabTarget = String(along)
|
|
51
|
+
const vars = { '--kol-rail-grab-y': `${along}px` }
|
|
52
|
+
/* the CSS fallback is 50%, a percentage — nothing to tween from, so the
|
|
53
|
+
* first sighting sets and every move after tweens */
|
|
54
|
+
if (h.dataset.grabSeeded) gsap.to(h, { ...vars, ...GRAB.travel, overwrite: 'auto' })
|
|
55
|
+
else { gsap.set(h, vars); h.dataset.grabSeeded = '1' }
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
window.addEventListener('pointermove', onMove)
|
|
59
|
+
return () => { window.removeEventListener('pointermove', onMove); cancelAnimationFrame(raf) }
|
|
60
|
+
}, [ref])
|
|
61
|
+
}
|