cursedbelt 5.8.0 → 5.9.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.
@@ -1 +1 @@
1
- {"version":3,"file":"FilterRail.d.ts","sourceRoot":"","sources":["../../../src/react/filter-rail/FilterRail.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FilterRail.d.ts","sourceRoot":"","sources":["../../../src/react/filter-rail/FilterRail.tsx"],"names":[],"mappings":"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"}
@@ -1,11 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { ChevronsLeft, ChevronsRight } from 'lucide-react';
3
- import { useCallback, useRef, useState } from 'react';
4
3
  import { ScrollArea } from '../components/ScrollArea.js';
5
4
  import { cn } from '../lib/cn.js';
6
5
  import { Tooltip } from '../components/Tooltip.js';
7
6
  import { TAP_TARGET, TAP_TARGET_ALWAYS, TAP_TARGET_HEIGHT } from '../lib/tapTarget.js';
8
- import { clampRailWidth, MAX_RAIL_PX, MIN_RAIL_PX, readRailWidth, writeRailWidth } from './railWidth.js';
7
+ import { RailResizeHandle, useRailResize } from './railResize.js';
9
8
  /**
10
9
  * The rail's body — one long scroller, or a flex column that hands its leftover height to a
11
10
  * section that asked for it.
@@ -65,56 +64,10 @@ function RailBody({ filling, children }) {
65
64
  * {@link FilterRailSection.selected}.
66
65
  */
67
66
  export function FilterRail({ sections, selected, onSelect, label, collapsed = false, onCollapsedChange, header, footer, width = 'w-56', resizeKey, className, }) {
68
- const navRef = useRef(null);
69
- const [dragged, setDragged] = useState(() => resizeKey ? readRailWidth(resizeKey) : null);
70
- const resizing = Boolean(resizeKey) && !collapsed;
71
- const onResizePointerDown = useCallback((event) => {
72
- if (!resizeKey || event.button !== 0)
73
- return;
74
- const handle = event.currentTarget;
75
- const startX = event.clientX;
76
- const startWidth = navRef.current?.getBoundingClientRect().width ?? MIN_RAIL_PX;
77
- let latest = startWidth;
78
- handle.setPointerCapture?.(event.pointerId);
79
- const move = (moveEvent) => {
80
- latest = clampRailWidth(startWidth + moveEvent.clientX - startX);
81
- setDragged(latest);
82
- };
83
- const end = () => {
84
- handle.releasePointerCapture?.(event.pointerId);
85
- handle.removeEventListener('pointermove', move);
86
- handle.removeEventListener('pointerup', end);
87
- handle.removeEventListener('pointercancel', end);
88
- // Remembered on RELEASE — a drag is one decision, not sixty a second.
89
- writeRailWidth(resizeKey, latest);
90
- };
91
- handle.addEventListener('pointermove', move);
92
- handle.addEventListener('pointerup', end);
93
- handle.addEventListener('pointercancel', end);
94
- event.preventDefault();
95
- }, [resizeKey]);
96
- const onResizeKey = useCallback((event) => {
97
- if (!resizeKey)
98
- return;
99
- const step = event.shiftKey ? 64 : 16;
100
- const delta = event.key === 'ArrowRight' ? step : event.key === 'ArrowLeft' ? -step : 0;
101
- if (!delta)
102
- return;
103
- event.preventDefault();
104
- const next = clampRailWidth((dragged ?? navRef.current?.getBoundingClientRect().width ?? MIN_RAIL_PX) + delta);
105
- setDragged(next);
106
- writeRailWidth(resizeKey, next);
107
- }, [resizeKey, dragged]);
108
- return (_jsxs("nav", { ref: navRef, "aria-label": label, "data-cb-filter-rail": collapsed ? 'collapsed' : 'expanded', className: cn('flex h-full min-h-0 shrink-0 flex-col border-r border-border bg-surface', collapsed ? 'w-14' : dragged !== null && resizing ? undefined : width, resizing && 'relative', className), ...(resizing && dragged !== null ? { style: { width: dragged } } : {}), children: [resizing ? (_jsx("div", { role: 'separator', "aria-orientation": 'vertical', "aria-label": `Resize ${label}`, "aria-valuemin": MIN_RAIL_PX, "aria-valuemax": MAX_RAIL_PX, "aria-valuenow": Math.round(dragged ?? navRef.current?.getBoundingClientRect().width ?? MIN_RAIL_PX), tabIndex: 0, "data-cb-rail-resize": '', onPointerDown: onResizePointerDown, onKeyDown: onResizeKey, onDoubleClick: () => {
109
- setDragged(null);
110
- if (resizeKey)
111
- writeRailWidth(resizeKey, null);
112
- },
113
- // A 1px edge you cannot hit is not a handle: the hotspot is 12px, centred on the
114
- // border, and only the hairline tints — no layout shift, like `PanelSeparator`.
115
- // Only utilities the stylesheet already ships, so the handle adds no CSS to any app
116
- // (`fixtureAppCss.spec.ts` budgets that).
117
- className: 'absolute inset-y-0 -right-1.5 z-20 w-3 cursor-col-resize touch-none bg-transparent transition-colors hover:bg-accent/20 active:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring' })) : null, onCollapsedChange ? (_jsxs("div", { className: cn('flex flex-none items-center px-2 pt-2', collapsed && 'justify-center'), children: [!collapsed && _jsx("span", { className: 'flex-1' }), _jsx(Tooltip, { content: collapsed ? `Expand ${label}` : `Collapse ${label}`, children: _jsx("button", { type: 'button',
67
+ // The drag, the keys, the clamp, the storage and the reset are `railResize.tsx`, shared with
68
+ // every sidebar that is not a FilterRail (music's LibraryRail).
69
+ const rail = useRailResize({ resizeKey, label, enabled: !collapsed });
70
+ return (_jsxs("nav", { ref: rail.railRef, "aria-label": label, "data-cb-filter-rail": collapsed ? 'collapsed' : 'expanded', className: cn('flex h-full min-h-0 shrink-0 flex-col border-r border-border bg-surface', collapsed ? 'w-14' : rail.width !== null ? undefined : width, rail.active && 'relative', className), ...(rail.style ? { style: rail.style } : {}), children: [_jsx(RailResizeHandle, { rail: rail }), onCollapsedChange ? (_jsxs("div", { className: cn('flex flex-none items-center px-2 pt-2', collapsed && 'justify-center'), children: [!collapsed && _jsx("span", { className: 'flex-1' }), _jsx(Tooltip, { content: collapsed ? `Expand ${label}` : `Collapse ${label}`, children: _jsx("button", { type: 'button',
118
71
  // guardrails-ignore no-raw-action-button: the rail's own chrome control — an
119
72
  // IconButton here would pull the Button/Tooltip graph into every rail consumer.
120
73
  onClick: () => onCollapsedChange(!collapsed), "aria-label": collapsed ? `Expand ${label}` : `Collapse ${label}`, "aria-expanded": !collapsed, className: `grid size-8 place-items-center rounded-md text-muted-foreground transition-colors hover:bg-card-raised hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${TAP_TARGET} [&_svg]:size-4`, children: collapsed ? _jsx(ChevronsRight, {}) : _jsx(ChevronsLeft, {}) }) })] })) : null, header && !collapsed ? _jsx("div", { className: 'flex-none px-2 pt-2', children: header }) : null, _jsx(RailBody, { filling: sections.some((section) => section.fill === true), children: sections.map((section) => (_jsxs("div", { className: cn('mb-3 last:mb-0',
@@ -1 +1 @@
1
- {"version":3,"file":"FilterRail.js","sourceRoot":"","sources":["../../../src/react/filter-rail/FilterRail.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FilterRail.js","sourceRoot":"","sources":["../../../src/react/filter-rail/FilterRail.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE3D,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AA8IlE;;;;;;;GAOG;AACH,SAAS,QAAQ,CAAC,EAAE,OAAO,EAAE,QAAQ,EAA6C;IAChF,IAAI,CAAC,OAAO;QACV,OAAO,CACL,KAAC,UAAU,IAAC,IAAI,QAAC,KAAK,EAAC,SAAS,EAAC,SAAS,EAAC,WAAW,YACnD,QAAQ,GACE,CACd,CAAC;IACJ,OAAO,cAAK,SAAS,EAAC,wCAAwC,YAAE,QAAQ,GAAO,CAAC;AAClF,CAAC;AA4BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,MAAM,UAAU,UAAU,CAAC,EACzB,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,KAAK,EACL,SAAS,GAAG,KAAK,EACjB,iBAAiB,EACjB,MAAM,EACN,MAAM,EACN,KAAK,GAAG,MAAM,EACd,SAAS,EACT,SAAS,GACO;IAChB,6FAA6F;IAC7F,gEAAgE;IAChE,MAAM,IAAI,GAAG,aAAa,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC;IACtE,OAAO,CACL,eACE,GAAG,EAAE,IAAI,CAAC,OAAO,gBACL,KAAK,yBACI,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,EACzD,SAAS,EAAE,EAAE,CACX,yEAAyE,EACzE,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,EAC5D,IAAI,CAAC,MAAM,IAAI,UAAU,EACzB,SAAS,CACV,KACG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAE7C,KAAC,gBAAgB,IAAC,IAAI,EAAE,IAAI,GAAI,EAC/B,iBAAiB,CAAC,CAAC,CAAC,CACnB,eAAK,SAAS,EAAE,EAAE,CAAC,uCAAuC,EAAE,SAAS,IAAI,gBAAgB,CAAC,aACvF,CAAC,SAAS,IAAI,eAAM,SAAS,EAAC,QAAQ,GAAG,EAC1C,KAAC,OAAO,IAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC,YAAY,KAAK,EAAE,YACnE,iBACE,IAAI,EAAC,QAAQ;4BACb,6EAA6E;4BAC7E,gFAAgF;4BAChF,OAAO,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,CAAC,SAAS,CAAC,gBAChC,SAAS,CAAC,CAAC,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC,YAAY,KAAK,EAAE,mBAChD,CAAC,SAAS,EACzB,SAAS,EAAE,wMAAwM,UAAU,iBAAiB,YAE7O,SAAS,CAAC,CAAC,CAAC,KAAC,aAAa,KAAG,CAAC,CAAC,CAAC,KAAC,YAAY,KAAG,GAC1C,GACD,IACN,CACP,CAAC,CAAC,CAAC,IAAI,EAIP,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,cAAK,SAAS,EAAC,qBAAqB,YAAE,MAAM,GAAO,CAAC,CAAC,CAAC,IAAI,EAElF,KAAC,QAAQ,IAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC,YACjE,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CACzB,eAEE,SAAS,EAAE,EAAE,CACX,gBAAgB;oBAChB,+EAA+E;oBAC/E,2EAA2E;oBAC3E,EAAE;oBACF,iFAAiF;oBACjF,iFAAiF;oBACjF,gFAAgF;oBAChF,8EAA8E;oBAC9E,kFAAkF;oBAClF,8EAA8E;oBAC9E,6EAA6E;oBAC7E,wEAAwE;oBACxE,OAAO,CAAC,IAAI,IAAI,oCAAoC,CACrD,aAEA,OAAO,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAC7B,eAAK,SAAS,EAAC,wDAAwD,aACrE,eAAM,SAAS,EAAC,8EAA8E,YAC3F,OAAO,CAAC,KAAK,GACT,EACN,OAAO,CAAC,MAAM,IACX,CACP,CAAC,CAAC,CAAC,IAAI,EAGP,OAAO,CAAC,KAAK,IAAI,SAAS,CAAC,CAAC,CAAC,CAC5B,6BAAiB,MAAM,EAAC,SAAS,EAAC,gCAAgC,GAAG,CACtE,CAAC,CAAC,CAAC,IAAI,EACP,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAC5B,KAAC,aAAa,IAEZ,IAAI,EAAE,IAAI;4BACV,iFAAiF;4BACjF,MAAM,EAAE,IAAI,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAClF,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,QAAQ,IALjC,IAAI,CAAC,EAAE,CAMZ,CACH,CAAC,EACD,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,KAxChC,OAAO,CAAC,EAAE,CAyCX,CACP,CAAC,GACO,EAEV,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CACtB,cAAK,SAAS,EAAC,0CAA0C,YAAE,MAAM,GAAO,CACzE,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,EACrB,IAAI,EACJ,MAAM,EACN,SAAS,EACT,QAAQ,GAMT;IACC,oFAAoF;IACpF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAEtF,OAAO,CAEL,wCAKyB,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,4BACvC,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,EACzE,SAAS,EAAE,EAAE,CACX,8DAA8D;QAC9D,8EAA8E;QAC9E,yEAAyE;QACzE,IAAI,CAAC,UAAU;YACb,oFAAoF,CACvF;QACD,iFAAiF;QACjF,oFAAoF;QACpF,6EAA6E;QAC7E,KAAK,EACH,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK;YACtB,CAAC,CAAC,EAAE,kBAAkB,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,GAAG,KAAK,EAAE;YAC/D,CAAC,CAAC,SAAS,EAEf,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,EACrD,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,EACvD,MAAM,EAAE,IAAI,CAAC,MAAM,aAElB,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAC,gBAAgB,IAAC,IAAI,EAAE,IAAI,GAAI,CAAC,CAAC,CAAC,IAAI,EACnE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAGlB,cAAK,SAAS,EAAC,gBAAgB,YAAE,IAAI,CAAC,WAAW,GAAO,CACzD,CAAC,CAAC,CAAC,CACF,8BACE,KAAC,gBAAgB,IACf,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,KAAK,GACZ,EACD,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAC1B,qCACsB,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAC9C,SAAS,EAAE,EAAE,CACX,wDAAwD,iBAAiB,EAAE;wBAC3E,4EAA4E;wBAC5E,2EAA2E;wBAC3E,0EAA0E;wBAC1E,uEAAuE;wBACvE,6EAA6E;wBAC7E,2EAA2E;wBAC3E,qEAAqE;wBACrE,2BAA2B;wBAC3B,wEAAwE;wBACxE,2EAA2E;wBAC3E,yEAAyE;wBACzE,2EAA2E;wBAC3E,cAAc;wBACd,yGAAyG;wBACzG,wEAAwE;wBACxE,4EAA4E;wBAC5E,yCAAyC;wBACzC,MAAM;4BACJ,CAAC,CAAC,aAAa;4BACf,CAAC,CAAC,uEAAuE;gCACvE,uEAAuE;gCACvE,qFAAqF,CAC1F,YAEA,IAAI,CAAC,KAAK,GACN,CACR,CAAC,CAAC,CAAC,IAAI,IACP,CACJ,IACG,CACP,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,gBAAgB,CAAC,EAAE,IAAI,EAA4B;IAC1D,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,aAAa,CAAC,CAAC;IACzF,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;QACnD,OAAO,8BAAkB,MAAM,EAAC,SAAS,EAAC,cAAc,GAAG,CAAC;IAC9D,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,KAAK,UAAU,CAAC;IAC5C,OAAO,CACL,iBACE,IAAI,EAAC,QAAQ;QACb,sFAAsF;QACtF,iFAAiF;QACjF,OAAO,EAAE,IAAI,CAAC,cAAc,mBACb,QAAQ,gBACX,QAAQ,CAAC,CAAC,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,EAAE;QAC5D,sFAAsF;QACtF,sFAAsF;QACtF,2EAA2E;QAC3E,SAAS,EAAC,uNAAuN,YAEhO,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GACd,CACV,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,EACxB,IAAI,EACJ,MAAM,EACN,SAAS,EACT,QAAQ,EACR,KAAK,GAON;IACC,OAAO,CAIL,KAAC,OAAO,IAAC,OAAO,EAAE,KAAK,YACrB,kBACE,IAAI,EAAC,QAAQ;YACb,8EAA8E;YAC9E,yEAAyE;YACzE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,EAClD,QAAQ,EAAE,IAAI,CAAC,QAAQ,kBACT,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,sBACvB,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAC5C,SAAS,EAAE,EAAE;YACX,4EAA4E;YAC5E,qEAAqE;YACrE,gGAAgG,EAChG,yEAAyE;YACzE,mFAAmF;YACnF,SAAS;gBACP,CAAC,CAAC,0BAA0B,UAAU,EAAE;gBACxC,CAAC,CAAC,iBAAiB,iBAAiB,EAAE,EACxC,IAAI,CAAC,QAAQ,IAAI,+BAA+B;YAChD,2EAA2E;YAC3E,kFAAkF;YAClF,kFAAkF;YAClF,MAAM;gBACJ,CAAC,CAAC,oFAAoF;gBACtF,CAAC,CAAC,sCAAsC,CAC3C,aAEA,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CACX,8BAAkB,MAAM,EAAC,SAAS,EAAC,wDAAwD,YACxF,IAAI,CAAC,IAAI,GACL,CACR,CAAC,CAAC,CAAC,IAAI,EACP,SAAS,CAAC,CAAC,CAAC;gBACX,6EAA6E;gBAC7E,wDAAwD;gBACxD,CAAC,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAC7C,8BAAkB,MAAM,EAAC,SAAS,EAAC,uBAAuB,YACvD,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,GAChC,CACR,CAAC,CAAC,CAAC,IAAI,CACT,CAAC,CAAC,CAAC,CACF,8BACE,gBAAM,SAAS,EAAC,8BAA8B,aAC5C,eAAM,SAAS,EAAC,UAAU,YAAE,IAAI,CAAC,KAAK,GAAQ,EAC7C,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAEX,eAAM,SAAS,EAAC,6CAA6C,YAAE,IAAI,CAAC,IAAI,GAAQ,CACjF,CAAC,CAAC,CAAC,IAAI,IACH,EACN,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,CAC1B,eAAM,SAAS,EAAC,qDAAqD,YAClE,IAAI,CAAC,KAAK,GACN,CACR,CAAC,CAAC,CAAC,IAAI,EACP,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,eAAM,SAAS,EAAC,UAAU,YAAE,IAAI,CAAC,SAAS,GAAQ,CAAC,CAAC,CAAC,IAAI,IAC1E,CACJ,EAEA,SAAS,IAAI,KAAK,CAAC,CAAC,CAAC,eAAM,SAAS,EAAC,SAAS,YAAE,KAAK,GAAQ,CAAC,CAAC,CAAC,IAAI,IAC9D,GACD,CACX,CAAC;AACJ,CAAC"}
@@ -1,2 +1,3 @@
1
1
  export { FilterRail, type FilterRailItem, type FilterRailProps, type FilterRailSection, } from './FilterRail.js';
2
+ export { RailResizeHandle, type RailResize, type UseRailResizeOptions, useRailResize } from './railResize.js';
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/react/filter-rail/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,iBAAiB,GACvB,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/react/filter-rail/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,iBAAiB,GACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,KAAK,UAAU,EAAE,KAAK,oBAAoB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1,2 +1,3 @@
1
1
  export { FilterRail, } from './FilterRail.js';
2
+ export { RailResizeHandle, useRailResize } from './railResize.js';
2
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/react/filter-rail/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,GAIX,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/react/filter-rail/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,GAIX,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAA8C,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Drag a sidebar's right edge to resize it, like VS Code's side bar — the gesture half, for
3
+ * any rail, not only `FilterRail`.
4
+ *
5
+ * Owner, 2026-09-24: *"the cb filetree sidebars should allow grabbing their right edge and
6
+ * dragging to resize them like in vscode."* 5.8.0 shipped the handle INSIDE `FilterRail`; the
7
+ * sidebars in music (`LibraryRail`) and others are their own columns around a `FileTree`, so
8
+ * the handle came out here once rather than being copied into each app. `FilterRail` uses
9
+ * exactly this, so there is one gesture to get right:
10
+ *
11
+ * - **pointer capture**, or the drag ends the first time the pointer outruns the strip;
12
+ * - **←/→** (Shift for bigger steps), because a drag-only control is one some people cannot
13
+ * reach;
14
+ * - **a `separator` role with real `aria-value*`**, the ARIA splitter pattern;
15
+ * - **double-click resets** to the rail's own default width, and forgets the stored one;
16
+ * - remembered on RELEASE — a drag is one decision, not sixty writes a second.
17
+ *
18
+ * Clamp and storage are `railWidth.ts`, so the width is announced through `preferenceSync`
19
+ * like every other viewer preference.
20
+ */
21
+ import type { CSSProperties, KeyboardEvent as ReactKeyboardEvent, PointerEvent as ReactPointerEvent, RefObject } from 'react';
22
+ export interface UseRailResizeOptions {
23
+ /** Where the width is remembered. Absent: not resizable — no handle, no stored width. */
24
+ resizeKey: string | undefined;
25
+ /** The rail's accessible name; the handle announces as "Resize <label>". */
26
+ label: string;
27
+ /** False hides the handle and drops the dragged width (a collapsed rail). Default true. */
28
+ enabled?: boolean;
29
+ }
30
+ export interface RailResize<E extends HTMLElement = HTMLElement> {
31
+ /** Put on the rail element — the handle measures it to start a drag. */
32
+ railRef: RefObject<E | null>;
33
+ /** Whether a handle is drawn: a `resizeKey` was given and `enabled` is true. */
34
+ active: boolean;
35
+ /** The dragged width in px, or `null` for "the rail's own default width". Null while inactive. */
36
+ width: number | null;
37
+ /** `{ width }` while there is a dragged width, else `undefined` — spread onto the rail's `style`. */
38
+ style: CSSProperties | undefined;
39
+ /** Forget the dragged width (what a double-click on the handle does). */
40
+ reset: () => void;
41
+ /** @internal — read by `RailResizeHandle`. */
42
+ readonly handle: {
43
+ label: string;
44
+ onPointerDown: (event: ReactPointerEvent<HTMLElement>) => void;
45
+ onKeyDown: (event: ReactKeyboardEvent<HTMLElement>) => void;
46
+ /** The rail's current rendered width, for `aria-valuenow` before any drag. */
47
+ measure: () => number;
48
+ };
49
+ }
50
+ export declare function useRailResize<E extends HTMLElement = HTMLElement>({ resizeKey, label, enabled, }: UseRailResizeOptions): RailResize<E>;
51
+ /**
52
+ * The handle itself — a 12px hotspot centred on the rail's right border. The RAIL must be
53
+ * `position: relative` (the handle is absolutely positioned against it). Renders nothing while
54
+ * the resize is inactive.
55
+ *
56
+ * Only utilities the stylesheet already ships, so it adds no CSS to any app that imports the
57
+ * `filter-rail` area (`fixtureAppCss.spec.ts` budgets that).
58
+ */
59
+ export declare function RailResizeHandle({ rail, className }: {
60
+ rail: RailResize;
61
+ className?: string;
62
+ }): import("react").JSX.Element | null;
63
+ //# sourceMappingURL=railResize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"railResize.d.ts","sourceRoot":"","sources":["../../../src/react/filter-rail/railResize.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,IAAI,kBAAkB,EAAE,YAAY,IAAI,iBAAiB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAK9H,MAAM,WAAW,oBAAoB;IACnC,yFAAyF;IACzF,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,2FAA2F;IAC3F,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW;IAC7D,wEAAwE;IACxE,OAAO,EAAE,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7B,gFAAgF;IAChF,MAAM,EAAE,OAAO,CAAC;IAChB,kGAAkG;IAClG,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,qGAAqG;IACrG,KAAK,EAAE,aAAa,GAAG,SAAS,CAAC;IACjC,yEAAyE;IACzE,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,8CAA8C;IAC9C,QAAQ,CAAC,MAAM,EAAE;QACf,KAAK,EAAE,MAAM,CAAC;QACd,aAAa,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;QAC/D,SAAS,EAAE,CAAC,KAAK,EAAE,kBAAkB,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;QAC5D,8EAA8E;QAC9E,OAAO,EAAE,MAAM,MAAM,CAAC;KACvB,CAAC;CACH;AAED,wBAAgB,aAAa,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EAAE,EACjE,SAAS,EACT,KAAK,EACL,OAAc,GACf,EAAE,oBAAoB,GAAG,UAAU,CAAC,CAAC,CAAC,CA6DtC;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,sCAyB7F"}
@@ -0,0 +1,79 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useCallback, useRef, useState } from 'react';
3
+ import { cn } from '../lib/cn.js';
4
+ import { clampRailWidth, MAX_RAIL_PX, MIN_RAIL_PX, readRailWidth, writeRailWidth } from './railWidth.js';
5
+ export function useRailResize({ resizeKey, label, enabled = true, }) {
6
+ const railRef = useRef(null);
7
+ const [dragged, setDragged] = useState(() => (resizeKey ? readRailWidth(resizeKey) : null));
8
+ const active = Boolean(resizeKey) && enabled;
9
+ const measure = useCallback(() => railRef.current?.getBoundingClientRect().width ?? MIN_RAIL_PX, []);
10
+ const onPointerDown = useCallback((event) => {
11
+ if (!resizeKey || event.button !== 0)
12
+ return;
13
+ const handle = event.currentTarget;
14
+ const startX = event.clientX;
15
+ const startWidth = measure();
16
+ let latest = startWidth;
17
+ handle.setPointerCapture?.(event.pointerId);
18
+ const move = (moveEvent) => {
19
+ latest = clampRailWidth(startWidth + moveEvent.clientX - startX);
20
+ setDragged(latest);
21
+ };
22
+ const end = () => {
23
+ if (handle.hasPointerCapture?.(event.pointerId))
24
+ handle.releasePointerCapture(event.pointerId);
25
+ handle.removeEventListener('pointermove', move);
26
+ handle.removeEventListener('pointerup', end);
27
+ handle.removeEventListener('pointercancel', end);
28
+ writeRailWidth(resizeKey, latest);
29
+ };
30
+ handle.addEventListener('pointermove', move);
31
+ handle.addEventListener('pointerup', end);
32
+ handle.addEventListener('pointercancel', end);
33
+ event.preventDefault();
34
+ }, [resizeKey, measure]);
35
+ const onKeyDown = useCallback((event) => {
36
+ if (!resizeKey)
37
+ return;
38
+ const step = event.shiftKey ? 64 : 16;
39
+ const delta = event.key === 'ArrowRight' ? step : event.key === 'ArrowLeft' ? -step : 0;
40
+ if (!delta)
41
+ return;
42
+ event.preventDefault();
43
+ const next = clampRailWidth((dragged ?? measure()) + delta);
44
+ setDragged(next);
45
+ writeRailWidth(resizeKey, next);
46
+ }, [resizeKey, dragged, measure]);
47
+ const reset = useCallback(() => {
48
+ setDragged(null);
49
+ if (resizeKey)
50
+ writeRailWidth(resizeKey, null);
51
+ }, [resizeKey]);
52
+ const width = active ? dragged : null;
53
+ return {
54
+ railRef,
55
+ active,
56
+ width,
57
+ style: width === null ? undefined : { width },
58
+ reset,
59
+ handle: { label, onPointerDown, onKeyDown, measure },
60
+ };
61
+ }
62
+ /**
63
+ * The handle itself — a 12px hotspot centred on the rail's right border. The RAIL must be
64
+ * `position: relative` (the handle is absolutely positioned against it). Renders nothing while
65
+ * the resize is inactive.
66
+ *
67
+ * Only utilities the stylesheet already ships, so it adds no CSS to any app that imports the
68
+ * `filter-rail` area (`fixtureAppCss.spec.ts` budgets that).
69
+ */
70
+ export function RailResizeHandle({ rail, className }) {
71
+ if (!rail.active)
72
+ return null;
73
+ const { label, onPointerDown, onKeyDown, measure } = rail.handle;
74
+ return (_jsx("div", { role: 'separator', "aria-orientation": 'vertical', "aria-label": `Resize ${label}`, "aria-valuemin": MIN_RAIL_PX, "aria-valuemax": MAX_RAIL_PX, "aria-valuenow": Math.round(rail.width ?? measure()), tabIndex: 0, "data-cb-rail-resize": '', onPointerDown: onPointerDown, onKeyDown: onKeyDown, onDoubleClick: rail.reset,
75
+ // A 1px edge you cannot hit is not a handle: the hotspot is 12px, centred on the border,
76
+ // and only the hairline tints — no layout shift, like `PanelSeparator`.
77
+ className: cn('absolute inset-y-0 -right-1.5 z-20 w-3 cursor-col-resize touch-none bg-transparent transition-colors hover:bg-accent/20 active:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring', className) }));
78
+ }
79
+ //# sourceMappingURL=railResize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"railResize.js","sourceRoot":"","sources":["../../../src/react/filter-rail/railResize.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cursedbelt",
3
- "version": "5.8.0",
3
+ "version": "5.9.0",
4
4
  "license": "ISC",
5
5
  "type": "module",
6
6
  "description": "The React design system of the cursedbelt split — components, styles, theme. cursedbelt-core below it; server tier in cursedbelt-server.",
@@ -1,11 +1,10 @@
1
1
  import { ChevronsLeft, ChevronsRight } from 'lucide-react';
2
- import type { DragEvent, PointerEvent as ReactPointerEvent, ReactNode } from 'react';
3
- import { useCallback, useRef, useState } from 'react';
2
+ import type { DragEvent, ReactNode } from 'react';
4
3
  import { ScrollArea } from '../components/ScrollArea.js';
5
4
  import { cn } from '../lib/cn.js';
6
5
  import { Tooltip } from '../components/Tooltip.js';
7
6
  import { TAP_TARGET, TAP_TARGET_ALWAYS, TAP_TARGET_HEIGHT } from '../lib/tapTarget.js';
8
- import { clampRailWidth, MAX_RAIL_PX, MIN_RAIL_PX, readRailWidth, writeRailWidth } from './railWidth.js';
7
+ import { RailResizeHandle, useRailResize } from './railResize.js';
9
8
 
10
9
  export interface FilterRailItem {
11
10
  /** Stable key, and the value handed to `onSelect`. */
@@ -249,90 +248,23 @@ export function FilterRail({
249
248
  resizeKey,
250
249
  className,
251
250
  }: FilterRailProps) {
252
- const navRef = useRef<HTMLElement | null>(null);
253
- const [dragged, setDragged] = useState<number | null>(() =>
254
- resizeKey ? readRailWidth(resizeKey) : null,
255
- );
256
- const resizing = Boolean(resizeKey) && !collapsed;
257
- const onResizePointerDown = useCallback(
258
- (event: ReactPointerEvent<HTMLDivElement>) => {
259
- if (!resizeKey || event.button !== 0) return;
260
- const handle = event.currentTarget;
261
- const startX = event.clientX;
262
- const startWidth = navRef.current?.getBoundingClientRect().width ?? MIN_RAIL_PX;
263
- let latest = startWidth;
264
- handle.setPointerCapture?.(event.pointerId);
265
- const move = (moveEvent: PointerEvent) => {
266
- latest = clampRailWidth(startWidth + moveEvent.clientX - startX);
267
- setDragged(latest);
268
- };
269
- const end = () => {
270
- handle.releasePointerCapture?.(event.pointerId);
271
- handle.removeEventListener('pointermove', move);
272
- handle.removeEventListener('pointerup', end);
273
- handle.removeEventListener('pointercancel', end);
274
- // Remembered on RELEASE — a drag is one decision, not sixty a second.
275
- writeRailWidth(resizeKey, latest);
276
- };
277
- handle.addEventListener('pointermove', move);
278
- handle.addEventListener('pointerup', end);
279
- handle.addEventListener('pointercancel', end);
280
- event.preventDefault();
281
- },
282
- [resizeKey],
283
- );
284
- const onResizeKey = useCallback(
285
- (event: React.KeyboardEvent<HTMLDivElement>) => {
286
- if (!resizeKey) return;
287
- const step = event.shiftKey ? 64 : 16;
288
- const delta = event.key === 'ArrowRight' ? step : event.key === 'ArrowLeft' ? -step : 0;
289
- if (!delta) return;
290
- event.preventDefault();
291
- const next = clampRailWidth(
292
- (dragged ?? navRef.current?.getBoundingClientRect().width ?? MIN_RAIL_PX) + delta,
293
- );
294
- setDragged(next);
295
- writeRailWidth(resizeKey, next);
296
- },
297
- [resizeKey, dragged],
298
- );
251
+ // The drag, the keys, the clamp, the storage and the reset are `railResize.tsx`, shared with
252
+ // every sidebar that is not a FilterRail (music's LibraryRail).
253
+ const rail = useRailResize({ resizeKey, label, enabled: !collapsed });
299
254
  return (
300
255
  <nav
301
- ref={navRef}
256
+ ref={rail.railRef}
302
257
  aria-label={label}
303
258
  data-cb-filter-rail={collapsed ? 'collapsed' : 'expanded'}
304
259
  className={cn(
305
260
  'flex h-full min-h-0 shrink-0 flex-col border-r border-border bg-surface',
306
- collapsed ? 'w-14' : dragged !== null && resizing ? undefined : width,
307
- resizing && 'relative',
261
+ collapsed ? 'w-14' : rail.width !== null ? undefined : width,
262
+ rail.active && 'relative',
308
263
  className,
309
264
  )}
310
- {...(resizing && dragged !== null ? { style: { width: dragged } } : {})}
265
+ {...(rail.style ? { style: rail.style } : {})}
311
266
  >
312
- {resizing ? (
313
- // biome-ignore lint/a11y/useSemanticElements: an <hr> cannot take focus or a drag; a focusable separator is the ARIA splitter pattern.
314
- <div
315
- role='separator'
316
- aria-orientation='vertical'
317
- aria-label={`Resize ${label}`}
318
- aria-valuemin={MIN_RAIL_PX}
319
- aria-valuemax={MAX_RAIL_PX}
320
- aria-valuenow={Math.round(dragged ?? navRef.current?.getBoundingClientRect().width ?? MIN_RAIL_PX)}
321
- tabIndex={0}
322
- data-cb-rail-resize=''
323
- onPointerDown={onResizePointerDown}
324
- onKeyDown={onResizeKey}
325
- onDoubleClick={() => {
326
- setDragged(null);
327
- if (resizeKey) writeRailWidth(resizeKey, null);
328
- }}
329
- // A 1px edge you cannot hit is not a handle: the hotspot is 12px, centred on the
330
- // border, and only the hairline tints — no layout shift, like `PanelSeparator`.
331
- // Only utilities the stylesheet already ships, so the handle adds no CSS to any app
332
- // (`fixtureAppCss.spec.ts` budgets that).
333
- className='absolute inset-y-0 -right-1.5 z-20 w-3 cursor-col-resize touch-none bg-transparent transition-colors hover:bg-accent/20 active:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring'
334
- />
335
- ) : null}
267
+ <RailResizeHandle rail={rail} />
336
268
  {onCollapsedChange ? (
337
269
  <div className={cn('flex flex-none items-center px-2 pt-2', collapsed && 'justify-center')}>
338
270
  {!collapsed && <span className='flex-1' />}
@@ -4,3 +4,4 @@ export {
4
4
  type FilterRailProps,
5
5
  type FilterRailSection,
6
6
  } from './FilterRail.js';
7
+ export { RailResizeHandle, type RailResize, type UseRailResizeOptions, useRailResize } from './railResize.js';
@@ -0,0 +1,92 @@
1
+ import { afterEach, describe, expect, test } from 'bun:test';
2
+ import { cleanup, fireEvent, render } from '@testing-library/react';
3
+ import { RailResizeHandle, useRailResize } from './railResize.js';
4
+
5
+ afterEach(() => {
6
+ cleanup();
7
+ globalThis.localStorage?.clear();
8
+ });
9
+
10
+ /**
11
+ * A sidebar that is NOT a FilterRail — music's `LibraryRail` shape: its own element, its own
12
+ * default width in CSS, the shared handle inside. This is the seam every such rail passes
13
+ * through, so it is where the gesture is proved.
14
+ */
15
+ function Sidebar({ resizeKey, enabled }: { resizeKey?: string; enabled?: boolean }) {
16
+ const rail = useRailResize<HTMLElement>({ resizeKey, label: 'Library', enabled });
17
+ return (
18
+ <aside ref={rail.railRef} data-width={rail.width ?? 'default'} style={rail.style} className='relative'>
19
+ <RailResizeHandle rail={rail} />
20
+ </aside>
21
+ );
22
+ }
23
+
24
+ const parts = (container: HTMLElement) => ({
25
+ aside: container.querySelector('aside') as HTMLElement,
26
+ handle: container.querySelector('[data-cb-rail-resize]') as HTMLElement | null,
27
+ });
28
+
29
+ describe('useRailResize + RailResizeHandle', () => {
30
+ test('no key — no handle, no width', () => {
31
+ const { aside, handle } = parts(render(<Sidebar />).container);
32
+ expect(handle).toBeNull();
33
+ expect(aside.style.width).toBe('');
34
+ });
35
+
36
+ test('a pointer drag widens by the distance moved and is remembered on release, not before', () => {
37
+ globalThis.localStorage?.setItem('t:rail', '300');
38
+ const { aside, handle } = parts(render(<Sidebar resizeKey='t:rail' />).container);
39
+ expect(aside.style.width).toBe('300px');
40
+ // happy-dom lays nothing out, so the drag starts from a measured 0 — the delta is the point.
41
+ fireEvent.pointerDown(handle as HTMLElement, { button: 0, clientX: 100, pointerId: 1 });
42
+ fireEvent.pointerMove(handle as HTMLElement, { clientX: 350, pointerId: 1 });
43
+ expect(aside.style.width).toBe('250px');
44
+ expect(globalThis.localStorage?.getItem('t:rail')).toBe('300');
45
+ fireEvent.pointerUp(handle as HTMLElement, { clientX: 350, pointerId: 1 });
46
+ expect(globalThis.localStorage?.getItem('t:rail')).toBe('250');
47
+ // Released: further moves do nothing.
48
+ fireEvent.pointerMove(handle as HTMLElement, { clientX: 600, pointerId: 1 });
49
+ expect(aside.style.width).toBe('250px');
50
+ });
51
+
52
+ test('a drag past either bound stops at it', () => {
53
+ const { aside, handle } = parts(render(<Sidebar resizeKey='t:rail' />).container);
54
+ fireEvent.pointerDown(handle as HTMLElement, { button: 0, clientX: 0, pointerId: 1 });
55
+ fireEvent.pointerMove(handle as HTMLElement, { clientX: 5000, pointerId: 1 });
56
+ expect(aside.style.width).toBe('640px');
57
+ fireEvent.pointerMove(handle as HTMLElement, { clientX: 10, pointerId: 1 });
58
+ expect(aside.style.width).toBe('160px');
59
+ });
60
+
61
+ test('a right-button press is not a drag', () => {
62
+ const { aside, handle } = parts(render(<Sidebar resizeKey='t:rail' />).container);
63
+ fireEvent.pointerDown(handle as HTMLElement, { button: 2, clientX: 0, pointerId: 1 });
64
+ fireEvent.pointerMove(handle as HTMLElement, { clientX: 400, pointerId: 1 });
65
+ expect(aside.style.width).toBe('');
66
+ });
67
+
68
+ test('←/→ step it (Shift for more), announce it, and a double-click forgets it', () => {
69
+ globalThis.localStorage?.setItem('t:rail', '300');
70
+ const { aside, handle } = parts(render(<Sidebar resizeKey='t:rail' />).container);
71
+ const h = handle as HTMLElement;
72
+ expect(h.getAttribute('role')).toBe('separator');
73
+ expect(h.getAttribute('aria-label')).toBe('Resize Library');
74
+ fireEvent.keyDown(h, { key: 'ArrowLeft' });
75
+ expect(aside.style.width).toBe('284px');
76
+ fireEvent.keyDown(h, { key: 'ArrowRight', shiftKey: true });
77
+ expect(aside.style.width).toBe('348px');
78
+ expect(h.getAttribute('aria-valuenow')).toBe('348');
79
+ expect(globalThis.localStorage?.getItem('t:rail')).toBe('348');
80
+ fireEvent.doubleClick(h);
81
+ expect(aside.style.width).toBe('');
82
+ expect(aside.dataset.width).toBe('default');
83
+ expect(globalThis.localStorage?.getItem('t:rail')).toBeNull();
84
+ });
85
+
86
+ test('disabled (a collapsed rail) — no handle, and the stored width is not applied', () => {
87
+ globalThis.localStorage?.setItem('t:rail', '300');
88
+ const { aside, handle } = parts(render(<Sidebar resizeKey='t:rail' enabled={false} />).container);
89
+ expect(handle).toBeNull();
90
+ expect(aside.style.width).toBe('');
91
+ });
92
+ });
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Drag a sidebar's right edge to resize it, like VS Code's side bar — the gesture half, for
3
+ * any rail, not only `FilterRail`.
4
+ *
5
+ * Owner, 2026-09-24: *"the cb filetree sidebars should allow grabbing their right edge and
6
+ * dragging to resize them like in vscode."* 5.8.0 shipped the handle INSIDE `FilterRail`; the
7
+ * sidebars in music (`LibraryRail`) and others are their own columns around a `FileTree`, so
8
+ * the handle came out here once rather than being copied into each app. `FilterRail` uses
9
+ * exactly this, so there is one gesture to get right:
10
+ *
11
+ * - **pointer capture**, or the drag ends the first time the pointer outruns the strip;
12
+ * - **←/→** (Shift for bigger steps), because a drag-only control is one some people cannot
13
+ * reach;
14
+ * - **a `separator` role with real `aria-value*`**, the ARIA splitter pattern;
15
+ * - **double-click resets** to the rail's own default width, and forgets the stored one;
16
+ * - remembered on RELEASE — a drag is one decision, not sixty writes a second.
17
+ *
18
+ * Clamp and storage are `railWidth.ts`, so the width is announced through `preferenceSync`
19
+ * like every other viewer preference.
20
+ */
21
+ import type { CSSProperties, KeyboardEvent as ReactKeyboardEvent, PointerEvent as ReactPointerEvent, RefObject } from 'react';
22
+ import { useCallback, useRef, useState } from 'react';
23
+ import { cn } from '../lib/cn.js';
24
+ import { clampRailWidth, MAX_RAIL_PX, MIN_RAIL_PX, readRailWidth, writeRailWidth } from './railWidth.js';
25
+
26
+ export interface UseRailResizeOptions {
27
+ /** Where the width is remembered. Absent: not resizable — no handle, no stored width. */
28
+ resizeKey: string | undefined;
29
+ /** The rail's accessible name; the handle announces as "Resize <label>". */
30
+ label: string;
31
+ /** False hides the handle and drops the dragged width (a collapsed rail). Default true. */
32
+ enabled?: boolean;
33
+ }
34
+
35
+ export interface RailResize<E extends HTMLElement = HTMLElement> {
36
+ /** Put on the rail element — the handle measures it to start a drag. */
37
+ railRef: RefObject<E | null>;
38
+ /** Whether a handle is drawn: a `resizeKey` was given and `enabled` is true. */
39
+ active: boolean;
40
+ /** The dragged width in px, or `null` for "the rail's own default width". Null while inactive. */
41
+ width: number | null;
42
+ /** `{ width }` while there is a dragged width, else `undefined` — spread onto the rail's `style`. */
43
+ style: CSSProperties | undefined;
44
+ /** Forget the dragged width (what a double-click on the handle does). */
45
+ reset: () => void;
46
+ /** @internal — read by `RailResizeHandle`. */
47
+ readonly handle: {
48
+ label: string;
49
+ onPointerDown: (event: ReactPointerEvent<HTMLElement>) => void;
50
+ onKeyDown: (event: ReactKeyboardEvent<HTMLElement>) => void;
51
+ /** The rail's current rendered width, for `aria-valuenow` before any drag. */
52
+ measure: () => number;
53
+ };
54
+ }
55
+
56
+ export function useRailResize<E extends HTMLElement = HTMLElement>({
57
+ resizeKey,
58
+ label,
59
+ enabled = true,
60
+ }: UseRailResizeOptions): RailResize<E> {
61
+ const railRef = useRef<E | null>(null);
62
+ const [dragged, setDragged] = useState<number | null>(() => (resizeKey ? readRailWidth(resizeKey) : null));
63
+ const active = Boolean(resizeKey) && enabled;
64
+ const measure = useCallback(() => railRef.current?.getBoundingClientRect().width ?? MIN_RAIL_PX, []);
65
+
66
+ const onPointerDown = useCallback(
67
+ (event: ReactPointerEvent<HTMLElement>) => {
68
+ if (!resizeKey || event.button !== 0) return;
69
+ const handle = event.currentTarget;
70
+ const startX = event.clientX;
71
+ const startWidth = measure();
72
+ let latest = startWidth;
73
+ handle.setPointerCapture?.(event.pointerId);
74
+ const move = (moveEvent: PointerEvent) => {
75
+ latest = clampRailWidth(startWidth + moveEvent.clientX - startX);
76
+ setDragged(latest);
77
+ };
78
+ const end = () => {
79
+ if (handle.hasPointerCapture?.(event.pointerId)) handle.releasePointerCapture(event.pointerId);
80
+ handle.removeEventListener('pointermove', move);
81
+ handle.removeEventListener('pointerup', end);
82
+ handle.removeEventListener('pointercancel', end);
83
+ writeRailWidth(resizeKey, latest);
84
+ };
85
+ handle.addEventListener('pointermove', move);
86
+ handle.addEventListener('pointerup', end);
87
+ handle.addEventListener('pointercancel', end);
88
+ event.preventDefault();
89
+ },
90
+ [resizeKey, measure],
91
+ );
92
+
93
+ const onKeyDown = useCallback(
94
+ (event: ReactKeyboardEvent<HTMLElement>) => {
95
+ if (!resizeKey) return;
96
+ const step = event.shiftKey ? 64 : 16;
97
+ const delta = event.key === 'ArrowRight' ? step : event.key === 'ArrowLeft' ? -step : 0;
98
+ if (!delta) return;
99
+ event.preventDefault();
100
+ const next = clampRailWidth((dragged ?? measure()) + delta);
101
+ setDragged(next);
102
+ writeRailWidth(resizeKey, next);
103
+ },
104
+ [resizeKey, dragged, measure],
105
+ );
106
+
107
+ const reset = useCallback(() => {
108
+ setDragged(null);
109
+ if (resizeKey) writeRailWidth(resizeKey, null);
110
+ }, [resizeKey]);
111
+
112
+ const width = active ? dragged : null;
113
+ return {
114
+ railRef,
115
+ active,
116
+ width,
117
+ style: width === null ? undefined : { width },
118
+ reset,
119
+ handle: { label, onPointerDown, onKeyDown, measure },
120
+ };
121
+ }
122
+
123
+ /**
124
+ * The handle itself — a 12px hotspot centred on the rail's right border. The RAIL must be
125
+ * `position: relative` (the handle is absolutely positioned against it). Renders nothing while
126
+ * the resize is inactive.
127
+ *
128
+ * Only utilities the stylesheet already ships, so it adds no CSS to any app that imports the
129
+ * `filter-rail` area (`fixtureAppCss.spec.ts` budgets that).
130
+ */
131
+ export function RailResizeHandle({ rail, className }: { rail: RailResize; className?: string }) {
132
+ if (!rail.active) return null;
133
+ const { label, onPointerDown, onKeyDown, measure } = rail.handle;
134
+ return (
135
+ // biome-ignore lint/a11y/useSemanticElements: an <hr> cannot take focus or a drag; a focusable separator is the ARIA splitter pattern.
136
+ <div
137
+ role='separator'
138
+ aria-orientation='vertical'
139
+ aria-label={`Resize ${label}`}
140
+ aria-valuemin={MIN_RAIL_PX}
141
+ aria-valuemax={MAX_RAIL_PX}
142
+ aria-valuenow={Math.round(rail.width ?? measure())}
143
+ tabIndex={0}
144
+ data-cb-rail-resize=''
145
+ onPointerDown={onPointerDown}
146
+ onKeyDown={onKeyDown}
147
+ onDoubleClick={rail.reset}
148
+ // A 1px edge you cannot hit is not a handle: the hotspot is 12px, centred on the border,
149
+ // and only the hairline tints — no layout shift, like `PanelSeparator`.
150
+ className={cn(
151
+ 'absolute inset-y-0 -right-1.5 z-20 w-3 cursor-col-resize touch-none bg-transparent transition-colors hover:bg-accent/20 active:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
152
+ className,
153
+ )}
154
+ />
155
+ );
156
+ }