@activecollab/components 2.0.372 → 2.0.373

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.
Files changed (46) hide show
  1. package/dist/cjs/components/StackedCard/StackedCard.js +103 -19
  2. package/dist/cjs/components/StackedCard/StackedCard.js.map +1 -1
  3. package/dist/cjs/components/StackedCard/Styles.js +22 -17
  4. package/dist/cjs/components/StackedCard/Styles.js.map +1 -1
  5. package/dist/cjs/components/StackedCard/index.js +22 -0
  6. package/dist/cjs/components/StackedCard/index.js.map +1 -1
  7. package/dist/cjs/components/StackedCard/resizePolicy.js +238 -0
  8. package/dist/cjs/components/StackedCard/resizePolicy.js.map +1 -0
  9. package/dist/cjs/components/StackedCard/resizePolicy.test.js +474 -0
  10. package/dist/cjs/components/StackedCard/resizePolicy.test.js.map +1 -0
  11. package/dist/cjs/components/StackedCard/useStackedCardResize.js +145 -0
  12. package/dist/cjs/components/StackedCard/useStackedCardResize.js.map +1 -0
  13. package/dist/esm/components/StackedCard/StackedCard.d.ts +44 -3
  14. package/dist/esm/components/StackedCard/StackedCard.d.ts.map +1 -1
  15. package/dist/esm/components/StackedCard/StackedCard.js +102 -19
  16. package/dist/esm/components/StackedCard/StackedCard.js.map +1 -1
  17. package/dist/esm/components/StackedCard/Styles.d.ts +4 -1
  18. package/dist/esm/components/StackedCard/Styles.d.ts.map +1 -1
  19. package/dist/esm/components/StackedCard/Styles.js +22 -17
  20. package/dist/esm/components/StackedCard/Styles.js.map +1 -1
  21. package/dist/esm/components/StackedCard/index.d.ts +2 -0
  22. package/dist/esm/components/StackedCard/index.d.ts.map +1 -1
  23. package/dist/esm/components/StackedCard/index.js +2 -0
  24. package/dist/esm/components/StackedCard/index.js.map +1 -1
  25. package/dist/esm/components/StackedCard/resizePolicy.d.ts +111 -0
  26. package/dist/esm/components/StackedCard/resizePolicy.d.ts.map +1 -0
  27. package/dist/esm/{presentation/stackedCard → components/StackedCard}/resizePolicy.js +93 -48
  28. package/dist/esm/components/StackedCard/resizePolicy.js.map +1 -0
  29. package/dist/esm/components/StackedCard/resizePolicy.test.d.ts +2 -0
  30. package/dist/esm/components/StackedCard/resizePolicy.test.d.ts.map +1 -0
  31. package/dist/esm/components/StackedCard/resizePolicy.test.js +470 -0
  32. package/dist/esm/components/StackedCard/resizePolicy.test.js.map +1 -0
  33. package/dist/esm/components/StackedCard/useStackedCardResize.d.ts +62 -0
  34. package/dist/esm/components/StackedCard/useStackedCardResize.d.ts.map +1 -0
  35. package/dist/esm/components/StackedCard/useStackedCardResize.js +137 -0
  36. package/dist/esm/components/StackedCard/useStackedCardResize.js.map +1 -0
  37. package/dist/index.js +500 -36
  38. package/dist/index.js.map +1 -1
  39. package/dist/index.min.js +1 -1
  40. package/dist/index.min.js.map +1 -1
  41. package/package.json +1 -1
  42. package/dist/cjs/presentation/stackedCard/resizePolicy.js +0 -183
  43. package/dist/cjs/presentation/stackedCard/resizePolicy.js.map +0 -1
  44. package/dist/esm/presentation/stackedCard/resizePolicy.d.ts +0 -97
  45. package/dist/esm/presentation/stackedCard/resizePolicy.d.ts.map +0 -1
  46. package/dist/esm/presentation/stackedCard/resizePolicy.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStackedCardResize.js","names":["_react","require","_resizePolicy","sameSize","a","b","w","h","useStackedCardResize","exports","_ref","size","policy","cardId","contentMin","_ref$axis","axis","_ref$scale","scale","_ref$label","label","onResize","onResizeCommit","pointerStart","useRef","latest","current","dirty","policyRef","axisRef","scaleRef","contentMinRef","readContentMin","useCallback","source","emitPreview","next","handlePointerDown","e","_setPointerCapture","_ref2","start","makeStart","x","clientX","y","clientY","target","setPointerCapture","call","pointerId","preventDefault","handlePointerMove","ps","z","applyResize","dx","dy","constrain","shiftKey","endPointer","handleKeyDown","keyboardResize","key","handleKeyUp","isResizeKey","role","tabIndex","measurePercent","onPointerDown","onPointerMove","onPointerUp","onLostPointerCapture","onKeyDown","onKeyUp"],"sources":["../../../../src/components/StackedCard/useStackedCardResize.ts"],"sourcesContent":["import React, { useCallback, useRef } from \"react\";\n\nimport {\n StackedCardContentMin,\n StackedCardResizeAxis,\n StackedCardResizePolicy,\n StackedCardResizeSource,\n StackedCardResizeStart,\n StackedCardSize,\n applyResize,\n isResizeKey,\n keyboardResize,\n makeStart,\n measurePercent,\n} from \"./resizePolicy\";\n\n/**\n * The one place pointer and keyboard input meet the resize policy.\n *\n * `StackedCard`'s built-in grip reports raw deltas and knows no policy — enough\n * for a host that just tracks a width. This hook is the full contract: it\n * captures the gesture start, funnels both inputs through the pure policy in\n * `resizePolicy.ts`, streams preview events and fires exactly ONE commit per\n * gesture. It returns the props to spread on the grip, including the live\n * separator ARIA.\n *\n * Preview versus commit (spec §7e): the continuous stream is live feedback\n * only. A host creates an undo entry on the COMMIT, never on a preview — and a\n * gesture that never changed the size commits nothing at all, so a bare click\n * on the grip is not a change.\n *\n * The hook never touches the card's content: the intrinsic minimum is read\n * through `contentMin`, which may be a getter so a card that measures its own\n * footer can answer at the moment it is asked.\n */\n\nexport interface UseStackedCardResizeArgs {\n /** The card's current size, owned by the host. */\n size: StackedCardSize;\n policy: StackedCardResizePolicy;\n /** Id of the element the grip resizes — becomes `aria-controls`. */\n cardId: string;\n /** The card's intrinsic minimum; a getter is read at the moment it is needed. */\n contentMin: StackedCardContentMin | (() => StackedCardContentMin);\n /** `width` locks the vertical axis (auto-height cards). Defaults to `both`. */\n axis?: StackedCardResizeAxis;\n /**\n * Pointer deltas are divided by this before they reach the policy, so a grip\n * inside a zoomed canvas tracks the cursor exactly. Keyboard nudges are\n * already in the host's units and pass straight through. Defaults to 1.\n */\n scale?: number;\n /** Accessible name for the grip. Defaults to \"Resize card\". */\n label?: string;\n /** Live feedback during the gesture. Never an undoable change. */\n onResize: (next: StackedCardSize, source: StackedCardResizeSource) => void;\n /** Fires once per gesture, and only if the size actually changed. */\n onResizeCommit: (\n final: StackedCardSize,\n source: StackedCardResizeSource\n ) => void;\n}\n\n/** The props to spread on the grip — `StackedCard`'s `resizeHandleProps`. */\nexport interface StackedCardResizeHandleProps {\n role: \"separator\";\n tabIndex: 0;\n \"aria-label\": string;\n \"aria-controls\": string;\n \"aria-valuemin\": number;\n \"aria-valuemax\": number;\n \"aria-valuenow\": number;\n onPointerDown: (e: React.PointerEvent) => void;\n onPointerMove: (e: React.PointerEvent) => void;\n onPointerUp: (e: React.PointerEvent) => void;\n onLostPointerCapture: (e: React.PointerEvent) => void;\n onKeyDown: (e: React.KeyboardEvent) => void;\n onKeyUp: (e: React.KeyboardEvent) => void;\n}\n\nconst sameSize = (a: StackedCardSize, b: StackedCardSize): boolean =>\n a.w === b.w && a.h === b.h;\n\nexport const useStackedCardResize = ({\n size,\n policy,\n cardId,\n contentMin,\n axis = \"both\",\n scale = 1,\n label = \"Resize card\",\n onResize,\n onResizeCommit,\n}: UseStackedCardResizeArgs): StackedCardResizeHandleProps => {\n // The pointer gesture's anchor: the size + content-min captured on pointer\n // down, plus the pointer origin the delta is measured from.\n const pointerStart = useRef<{\n start: StackedCardResizeStart;\n x: number;\n y: number;\n } | null>(null);\n // Mirrors the latest emitted size so pointer-up / key-up can commit exactly\n // what preview last showed, without a stale closure.\n const latest = useRef<StackedCardSize>(size);\n latest.current = size;\n // Whether this gesture actually moved the card. A bare click, or a Home on an\n // axis with no floor, leaves it false and commits nothing.\n const dirty = useRef(false);\n\n // Read through refs so the handlers below can stay stable across renders\n // while still seeing the current policy, axis and zoom.\n const policyRef = useRef(policy);\n policyRef.current = policy;\n const axisRef = useRef(axis);\n axisRef.current = axis;\n const scaleRef = useRef(scale);\n scaleRef.current = scale;\n const contentMinRef = useRef(contentMin);\n contentMinRef.current = contentMin;\n\n const readContentMin = useCallback((): StackedCardContentMin => {\n const source = contentMinRef.current;\n return typeof source === \"function\" ? source() : source;\n }, []);\n\n const emitPreview = useCallback(\n (next: StackedCardSize, source: StackedCardResizeSource) => {\n // Nothing changed — not a preview, and not something to commit later.\n if (sameSize(next, latest.current)) return;\n latest.current = next;\n dirty.current = true;\n onResize(next, source);\n },\n [onResize]\n );\n\n const handlePointerDown = useCallback(\n (e: React.PointerEvent) => {\n pointerStart.current = {\n start: makeStart(latest.current, readContentMin()),\n x: e.clientX,\n y: e.clientY,\n };\n dirty.current = false;\n (e.target as HTMLElement).setPointerCapture?.(e.pointerId);\n e.preventDefault();\n },\n [readContentMin]\n );\n\n const handlePointerMove = useCallback(\n (e: React.PointerEvent) => {\n const ps = pointerStart.current;\n if (!ps) return;\n const z = scaleRef.current || 1;\n const next = applyResize(\n ps.start,\n { dx: (e.clientX - ps.x) / z, dy: (e.clientY - ps.y) / z },\n policyRef.current,\n // Shift held during a free-form drag = temporary proportional lock.\n { constrain: e.shiftKey, axis: axisRef.current }\n );\n emitPreview(next, \"pointer\");\n },\n [emitPreview]\n );\n\n const endPointer = useCallback(() => {\n if (!pointerStart.current) return;\n pointerStart.current = null;\n if (dirty.current) onResizeCommit(latest.current, \"pointer\");\n dirty.current = false;\n }, [onResizeCommit]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n const next = keyboardResize(\n e.key,\n latest.current,\n policyRef.current,\n readContentMin(),\n { shiftKey: e.shiftKey, axis: axisRef.current }\n );\n if (!next) return;\n // The key is ours even when it resolves to no movement (already pinned at\n // a bound), so the browser must not also scroll the surface.\n e.preventDefault();\n emitPreview(next, \"keyboard\");\n },\n [emitPreview, readContentMin]\n );\n\n const handleKeyUp = useCallback(\n (e: React.KeyboardEvent) => {\n if (!isResizeKey(e.key)) return;\n // The gesture end for the keyboard is the key release: one commit per\n // hold, mirroring pointer-up after a stream of moves.\n if (dirty.current) onResizeCommit(latest.current, \"keyboard\");\n dirty.current = false;\n },\n [onResizeCommit]\n );\n\n return {\n role: \"separator\",\n tabIndex: 0,\n \"aria-label\": label,\n \"aria-controls\": cardId,\n \"aria-valuemin\": 0,\n \"aria-valuemax\": 100,\n \"aria-valuenow\": measurePercent(size, policy, readContentMin()),\n onPointerDown: handlePointerDown,\n onPointerMove: handlePointerMove,\n onPointerUp: endPointer,\n onLostPointerCapture: endPointer,\n onKeyDown: handleKeyDown,\n onKeyUp: handleKeyUp,\n };\n};\n"],"mappings":"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","ignoreList":[]}
@@ -1,4 +1,5 @@
1
1
  import React, { ReactNode } from "react";
2
+ import { StackedCardResizeAxis, StackedCardResizeSource } from "./resizePolicy";
2
3
  /**
3
4
  * StackedCard — the hollow shell for cards on drag-and-drop surfaces.
4
5
  *
@@ -24,6 +25,24 @@ import React, { ReactNode } from "react";
24
25
  * `isDragPreview`. The shell forwards its ref and spreads DOM props, so a host
25
26
  * can attach `tabIndex`, ARIA, pointer and keyboard handlers to it.
26
27
  *
28
+ * ── Resize ────────────────────────────────────────────────────────────────
29
+ * The grip is opt-in (`resizable`) and reports intent as a gesture: one
30
+ * `onResizeStart`, a stream of `onResizeDelta` previews measured FROM THE
31
+ * GESTURE START, and one `onResizeCommit` at the end — and only if the gesture
32
+ * moved anything. A host applies previews for live feedback and records an undo
33
+ * entry on the commit alone (spec §7e).
34
+ *
35
+ * Because the deltas are gesture-relative rather than incremental, a host can
36
+ * resolve every event against the size it snapshotted on start, and never has
37
+ * to keep a running accumulator. That is what makes a slow, few-pixels-at-a-time
38
+ * drag keep growing instead of stalling under a snap step.
39
+ *
40
+ * The grip itself is a focusable `role="separator"` and handles arrow keys
41
+ * (Shift for a coarse nudge). For the full policy — bounds, proportional mode,
42
+ * step snapping, content minimums, Home/End and the live `aria-valuenow` — use
43
+ * `useStackedCardResize` and spread its result through `resizeHandleProps`;
44
+ * those handlers then own the grip and the three callbacks above stay quiet.
45
+ *
27
46
  * ── Theming ───────────────────────────────────────────────────────────────
28
47
  * Colours resolve through `--sc-*` custom properties with built-in fallbacks:
29
48
  * `--sc-selection-ring` (selection / focus / entered) and the cover scrim
@@ -58,16 +77,38 @@ export interface IStackedCardProps extends Omit<React.HTMLAttributes<HTMLDivElem
58
77
  forceHover?: boolean;
59
78
  /** Show the bottom-right resize grip. Opt-in, off by default. */
60
79
  resizable?: boolean;
80
+ /**
81
+ * Which axes the grip offers, as a cursor: `width` reads as a horizontal
82
+ * handle for an auto-height card. Purely the affordance — what a delta means
83
+ * is still the host's call. Defaults to `both`.
84
+ */
85
+ resizeAxis?: StackedCardResizeAxis;
86
+ /** Accessible name for the resize grip. Defaults to "Resize card". */
87
+ resizeLabel?: string;
61
88
  /**
62
89
  * Draws the emphasis border down the left edge. A data colour, passed in by
63
90
  * the caller (high priority, a label colour) — never baked into the shell.
64
91
  */
65
92
  priorityColor?: string;
93
+ /** Fired once when a resize gesture begins, before the first delta. */
94
+ onResizeStart?: (source: StackedCardResizeSource) => void;
95
+ /**
96
+ * Fired throughout a resize gesture with the delta measured FROM THE GESTURE
97
+ * START — not from the previous event. The card reports; the host decides what
98
+ * a delta means. Previews are live feedback, never an undoable change.
99
+ */
100
+ onResizeDelta?: (dx: number, dy: number, source: StackedCardResizeSource) => void;
101
+ /**
102
+ * Fired once when the gesture ends (pointer up, lost pointer capture, key up),
103
+ * and only if it moved the card. A bare click on the grip is not a change.
104
+ */
105
+ onResizeCommit?: (source: StackedCardResizeSource) => void;
66
106
  /**
67
- * Fired while the resize grip is dragged, with the pointer delta since the
68
- * last event. The card reports the deltas; the host decides what they mean.
107
+ * Props spread onto the grip, overriding the built-in behaviour entirely
108
+ * this is where `useStackedCardResize`'s return value goes when a host wants
109
+ * the full policy instead of raw deltas.
69
110
  */
70
- onResizeDelta?: (dx: number, dy: number) => void;
111
+ resizeHandleProps?: React.HTMLAttributes<HTMLSpanElement>;
71
112
  children: ReactNode;
72
113
  }
73
114
  export declare const StackedCard: React.ForwardRefExoticComponent<IStackedCardProps & React.RefAttributes<HTMLDivElement>>;
@@ -1 +1 @@
1
- {"version":3,"file":"StackedCard.d.ts","sourceRoot":"","sources":["../../../../src/components/StackedCard/StackedCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAgB,SAAS,EAAuB,MAAM,OAAO,CAAC;AAQ5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,MAAM,WAAW,iBACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC;IAC9D,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,mFAAmF;IACnF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iEAAiE;IACjE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,aAAa,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,eAAO,MAAM,WAAW,0FA0EvB,CAAC"}
1
+ {"version":3,"file":"StackedCard.d.ts","sourceRoot":"","sources":["../../../../src/components/StackedCard/StackedCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAgB,SAAS,EAAuB,MAAM,OAAO,CAAC;AAM5E,OAAO,EAGL,qBAAqB,EACrB,uBAAuB,EAExB,MAAM,gBAAgB,CAAC;AAGxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAEH,MAAM,WAAW,iBACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC;IAC9D,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,mFAAmF;IACnF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iEAAiE;IACjE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uEAAuE;IACvE,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,uBAAuB,KAAK,IAAI,CAAC;IAC1D;;;;OAIG;IACH,aAAa,CAAC,EAAE,CACd,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,uBAAuB,KAC5B,IAAI,CAAC;IACV;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,uBAAuB,KAAK,IAAI,CAAC;IAC3D;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;IAC1D,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,eAAO,MAAM,WAAW,0FAwKvB,CAAC"}
@@ -1,10 +1,11 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
3
- const _excluded = ["selected", "disabled", "pending", "isDragSource", "isDragPreview", "entered", "forceHover", "resizable", "priorityColor", "onResizeDelta", "className", "children"];
3
+ const _excluded = ["selected", "disabled", "pending", "isDragSource", "isDragPreview", "entered", "forceHover", "resizable", "resizeAxis", "resizeLabel", "priorityColor", "onResizeStart", "onResizeDelta", "onResizeCommit", "resizeHandleProps", "className", "children"];
4
4
  import React, { useCallback, useRef } from "react";
5
5
  import classnames from "classnames";
6
6
  import { STACKED_CARD_CONTROL_CLASS } from "./constants";
7
7
  import { StackedCardResizeHandleGlyph } from "./Glyphs";
8
+ import { DEFAULT_KEYBOARD_STEP, SHIFT_STEP_MULTIPLIER, isResizeKey } from "./resizePolicy";
8
9
  import { StyledStackedCard, StyledStackedCardResizeHandle } from "./Styles";
9
10
 
10
11
  /**
@@ -32,6 +33,24 @@ import { StyledStackedCard, StyledStackedCardResizeHandle } from "./Styles";
32
33
  * `isDragPreview`. The shell forwards its ref and spreads DOM props, so a host
33
34
  * can attach `tabIndex`, ARIA, pointer and keyboard handlers to it.
34
35
  *
36
+ * ── Resize ────────────────────────────────────────────────────────────────
37
+ * The grip is opt-in (`resizable`) and reports intent as a gesture: one
38
+ * `onResizeStart`, a stream of `onResizeDelta` previews measured FROM THE
39
+ * GESTURE START, and one `onResizeCommit` at the end — and only if the gesture
40
+ * moved anything. A host applies previews for live feedback and records an undo
41
+ * entry on the commit alone (spec §7e).
42
+ *
43
+ * Because the deltas are gesture-relative rather than incremental, a host can
44
+ * resolve every event against the size it snapshotted on start, and never has
45
+ * to keep a running accumulator. That is what makes a slow, few-pixels-at-a-time
46
+ * drag keep growing instead of stalling under a snap step.
47
+ *
48
+ * The grip itself is a focusable `role="separator"` and handles arrow keys
49
+ * (Shift for a coarse nudge). For the full policy — bounds, proportional mode,
50
+ * step snapping, content minimums, Home/End and the live `aria-valuenow` — use
51
+ * `useStackedCardResize` and spread its result through `resizeHandleProps`;
52
+ * those handlers then own the grip and the three callbacks above stay quiet.
53
+ *
35
54
  * ── Theming ───────────────────────────────────────────────────────────────
36
55
  * Colours resolve through `--sc-*` custom properties with built-in fallbacks:
37
56
  * `--sc-selection-ring` (selection / focus / entered) and the cover scrim
@@ -48,31 +67,88 @@ export const StackedCard = /*#__PURE__*/React.forwardRef((_ref, ref) => {
48
67
  entered = _ref.entered,
49
68
  forceHover = _ref.forceHover,
50
69
  resizable = _ref.resizable,
70
+ _ref$resizeAxis = _ref.resizeAxis,
71
+ resizeAxis = _ref$resizeAxis === void 0 ? "both" : _ref$resizeAxis,
72
+ _ref$resizeLabel = _ref.resizeLabel,
73
+ resizeLabel = _ref$resizeLabel === void 0 ? "Resize card" : _ref$resizeLabel,
51
74
  priorityColor = _ref.priorityColor,
75
+ onResizeStart = _ref.onResizeStart,
52
76
  onResizeDelta = _ref.onResizeDelta,
77
+ onResizeCommit = _ref.onResizeCommit,
78
+ resizeHandleProps = _ref.resizeHandleProps,
53
79
  className = _ref.className,
54
80
  children = _ref.children,
55
81
  rest = _objectWithoutPropertiesLoose(_ref, _excluded);
56
- const dragOrigin = useRef(null);
82
+ /**
83
+ * One live gesture. `x`/`y` anchor a pointer drag; `dx`/`dy` carry the
84
+ * running total a keyboard gesture has nudged. `moved` gates the commit, so
85
+ * a click that never travelled is not a change.
86
+ */
87
+ const gesture = useRef(null);
88
+ const emitDelta = useCallback((dx, dy) => {
89
+ const g = gesture.current;
90
+ if (!g) return;
91
+ if (dx !== 0 || dy !== 0) g.moved = true;
92
+ onResizeDelta == null || onResizeDelta(dx, dy, g.source);
93
+ }, [onResizeDelta]);
94
+ const endGesture = useCallback(() => {
95
+ const g = gesture.current;
96
+ if (!g) return;
97
+ gesture.current = null;
98
+ if (g.moved) onResizeCommit == null || onResizeCommit(g.source);
99
+ }, [onResizeCommit]);
57
100
  const handlePointerDown = useCallback(e => {
58
- dragOrigin.current = {
101
+ gesture.current = {
102
+ source: "pointer",
59
103
  x: e.clientX,
60
- y: e.clientY
104
+ y: e.clientY,
105
+ dx: 0,
106
+ dy: 0,
107
+ moved: false
61
108
  };
62
- e.target.setPointerCapture(e.pointerId);
109
+ e.target.setPointerCapture == null || e.target.setPointerCapture(e.pointerId);
63
110
  e.preventDefault();
64
- }, []);
111
+ onResizeStart == null || onResizeStart("pointer");
112
+ }, [onResizeStart]);
65
113
  const handlePointerMove = useCallback(e => {
66
- if (!dragOrigin.current || !onResizeDelta) return;
67
- onResizeDelta(e.clientX - dragOrigin.current.x, e.clientY - dragOrigin.current.y);
68
- dragOrigin.current = {
69
- x: e.clientX,
70
- y: e.clientY
71
- };
72
- }, [onResizeDelta]);
73
- const handlePointerUp = useCallback(() => {
74
- dragOrigin.current = null;
75
- }, []);
114
+ const g = gesture.current;
115
+ if (!g || g.source !== "pointer") return;
116
+ // Measured from the gesture start, so the host resolves every event
117
+ // against one snapshot instead of accumulating.
118
+ emitDelta(e.clientX - g.x, e.clientY - g.y);
119
+ }, [emitDelta]);
120
+
121
+ /**
122
+ * Arrows nudge the running total; Shift makes it coarse. Home and End need
123
+ * bounds to resolve, which the bare shell does not have — they fall through
124
+ * to `useStackedCardResize`, or to the browser.
125
+ */
126
+ const handleKeyDown = useCallback(e => {
127
+ const step = DEFAULT_KEYBOARD_STEP * (e.shiftKey ? SHIFT_STEP_MULTIPLIER : 1);
128
+ let dx = 0;
129
+ let dy = 0;
130
+ if (e.key === "ArrowRight") dx = step;else if (e.key === "ArrowLeft") dx = -step;else if (e.key === "ArrowDown") dy = step;else if (e.key === "ArrowUp") dy = -step;else return;
131
+ e.preventDefault();
132
+ if (!gesture.current || gesture.current.source !== "keyboard") {
133
+ gesture.current = {
134
+ source: "keyboard",
135
+ x: 0,
136
+ y: 0,
137
+ dx: 0,
138
+ dy: 0,
139
+ moved: false
140
+ };
141
+ onResizeStart == null || onResizeStart("keyboard");
142
+ }
143
+ const g = gesture.current;
144
+ g.dx += dx;
145
+ g.dy += dy;
146
+ emitDelta(g.dx, g.dy);
147
+ }, [emitDelta, onResizeStart]);
148
+ const handleKeyUp = useCallback(e => {
149
+ // One commit per hold, mirroring pointer-up after a stream of moves.
150
+ if (isResizeKey(e.key)) endGesture();
151
+ }, [endGesture]);
76
152
  return /*#__PURE__*/React.createElement(StyledStackedCard, _extends({
77
153
  ref: ref,
78
154
  $selected: selected,
@@ -84,12 +160,19 @@ export const StackedCard = /*#__PURE__*/React.forwardRef((_ref, ref) => {
84
160
  $forceHover: forceHover,
85
161
  $priorityColor: priorityColor,
86
162
  className: classnames("c-stacked-card", className)
87
- }, rest), children, resizable ? /*#__PURE__*/React.createElement(StyledStackedCardResizeHandle, {
163
+ }, rest), children, resizable ? /*#__PURE__*/React.createElement(StyledStackedCardResizeHandle, _extends({
164
+ $axis: resizeAxis,
88
165
  className: classnames("c-stacked-card__resize-handle", STACKED_CARD_CONTROL_CLASS),
166
+ role: "separator",
167
+ tabIndex: 0,
168
+ "aria-label": resizeLabel,
89
169
  onPointerDown: handlePointerDown,
90
170
  onPointerMove: handlePointerMove,
91
- onPointerUp: handlePointerUp
92
- }, /*#__PURE__*/React.createElement(StackedCardResizeHandleGlyph, null)) : null);
171
+ onPointerUp: endGesture,
172
+ onLostPointerCapture: endGesture,
173
+ onKeyDown: handleKeyDown,
174
+ onKeyUp: handleKeyUp
175
+ }, resizeHandleProps), /*#__PURE__*/React.createElement(StackedCardResizeHandleGlyph, null)) : null);
93
176
  });
94
177
  StackedCard.displayName = "StackedCard";
95
178
  //# sourceMappingURL=StackedCard.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"StackedCard.js","names":["React","useCallback","useRef","classnames","STACKED_CARD_CONTROL_CLASS","StackedCardResizeHandleGlyph","StyledStackedCard","StyledStackedCardResizeHandle","StackedCard","forwardRef","_ref","ref","selected","disabled","pending","isDragSource","isDragPreview","entered","forceHover","resizable","priorityColor","onResizeDelta","className","children","rest","_objectWithoutPropertiesLoose","_excluded","dragOrigin","handlePointerDown","e","current","x","clientX","y","clientY","target","setPointerCapture","pointerId","preventDefault","handlePointerMove","handlePointerUp","createElement","_extends","$selected","$disabled","$pending","$isDragSource","$isDragPreview","$entered","$forceHover","$priorityColor","onPointerDown","onPointerMove","onPointerUp","displayName"],"sources":["../../../../src/components/StackedCard/StackedCard.tsx"],"sourcesContent":["import React, { ReactElement, ReactNode, useCallback, useRef } from \"react\";\n\nimport classnames from \"classnames\";\n\nimport { STACKED_CARD_CONTROL_CLASS } from \"./constants\";\nimport { StackedCardResizeHandleGlyph } from \"./Glyphs\";\nimport { StyledStackedCard, StyledStackedCardResizeHandle } from \"./Styles\";\n\n/**\n * StackedCard — the hollow shell for cards on drag-and-drop surfaces.\n *\n * This is NOT the base for cards in lists. It is the card for surfaces where\n * dragging is a primary interaction: column boards and canvases. Content is\n * laid out top to bottom in `StackedCardRow`s, which makes every card a\n * portrait presentation of its data.\n *\n * ── The rule the whole subsystem hangs on ──────────────────────────────────\n * THE SHELL STAYS HOLLOW. There is no `contentType` enum here, no per-type\n * prop soup, no `if task …`. The shell owns only VISUAL STATES (selected,\n * disabled, pending, priority, drag source/preview, entered) and one intent\n * callback (`onResizeDelta`). Content is passed as `children` and composes the\n * layout primitives. Typed cards — an ImageCard, a LinkCard, a TaskCard — are\n * facades built on top of it in the consuming app, and adding one requires\n * ZERO changes in this file.\n *\n * ── What the shell does NOT do ────────────────────────────────────────────\n * It implements no drag-and-drop, no selection bookkeeping, no resize policy\n * and no keyboard navigation. The card reports; the host decides. Drag\n * choreography (the drag layer, the landing indicator, the drop) belongs to\n * the host surface, which then feeds the result back as `isDragSource` /\n * `isDragPreview`. The shell forwards its ref and spreads DOM props, so a host\n * can attach `tabIndex`, ARIA, pointer and keyboard handlers to it.\n *\n * ── Theming ───────────────────────────────────────────────────────────────\n * Colours resolve through `--sc-*` custom properties with built-in fallbacks:\n * `--sc-selection-ring` (selection / focus / entered) and the cover scrim\n * family `--sc-scrim`, `--sc-scrim-strong`, `--sc-scrim-fg`. Declare any of\n * them on an ancestor to retint a whole surface.\n */\n\nexport interface IStackedCardProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, \"onResize\"> {\n /** Host-owned selection state — a ring around the card. */\n selected?: boolean;\n /** Policy state: the card cannot be acted on. Dimmed, inert. */\n disabled?: boolean;\n /**\n * Optimistic in-flight state — created or moved, not yet confirmed. Dimmed,\n * non-interactive and not draggable, but distinct from `disabled`: it is\n * transient, not a policy.\n */\n pending?: boolean;\n /**\n * The full-size outline placeholder left behind in the source position while\n * a drag is in flight. Content is hidden but keeps its box, so neighbouring\n * cards never move.\n */\n isDragSource?: boolean;\n /**\n * The 1:1 copy the host floats in its drag layer. Elevated shadow only — no\n * tilt, no scale, no translate.\n */\n isDragPreview?: boolean;\n /** Focus model: the card has been entered and focus is on an inner control. */\n entered?: boolean;\n /** Pin the hover treatment on, including revealed controls. For docs and specs. */\n forceHover?: boolean;\n /** Show the bottom-right resize grip. Opt-in, off by default. */\n resizable?: boolean;\n /**\n * Draws the emphasis border down the left edge. A data colour, passed in by\n * the caller (high priority, a label colour) — never baked into the shell.\n */\n priorityColor?: string;\n /**\n * Fired while the resize grip is dragged, with the pointer delta since the\n * last event. The card reports the deltas; the host decides what they mean.\n */\n onResizeDelta?: (dx: number, dy: number) => void;\n children: ReactNode;\n}\n\nexport const StackedCard = React.forwardRef<HTMLDivElement, IStackedCardProps>(\n (\n {\n selected,\n disabled,\n pending,\n isDragSource,\n isDragPreview,\n entered,\n forceHover,\n resizable,\n priorityColor,\n onResizeDelta,\n className,\n children,\n ...rest\n },\n ref\n ): ReactElement => {\n const dragOrigin = useRef<{ x: number; y: number } | null>(null);\n\n const handlePointerDown = useCallback((e: React.PointerEvent) => {\n dragOrigin.current = { x: e.clientX, y: e.clientY };\n (e.target as HTMLElement).setPointerCapture(e.pointerId);\n e.preventDefault();\n }, []);\n\n const handlePointerMove = useCallback(\n (e: React.PointerEvent) => {\n if (!dragOrigin.current || !onResizeDelta) return;\n onResizeDelta(\n e.clientX - dragOrigin.current.x,\n e.clientY - dragOrigin.current.y\n );\n dragOrigin.current = { x: e.clientX, y: e.clientY };\n },\n [onResizeDelta]\n );\n\n const handlePointerUp = useCallback(() => {\n dragOrigin.current = null;\n }, []);\n\n return (\n <StyledStackedCard\n ref={ref}\n $selected={selected}\n $disabled={disabled}\n $pending={pending}\n $isDragSource={isDragSource}\n $isDragPreview={isDragPreview}\n $entered={entered}\n $forceHover={forceHover}\n $priorityColor={priorityColor}\n className={classnames(\"c-stacked-card\", className)}\n {...rest}\n >\n {children}\n {resizable ? (\n <StyledStackedCardResizeHandle\n className={classnames(\n \"c-stacked-card__resize-handle\",\n STACKED_CARD_CONTROL_CLASS\n )}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n >\n <StackedCardResizeHandleGlyph />\n </StyledStackedCardResizeHandle>\n ) : null}\n </StyledStackedCard>\n );\n }\n);\n\nStackedCard.displayName = \"StackedCard\";\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"StackedCard.js","names":["React","useCallback","useRef","classnames","STACKED_CARD_CONTROL_CLASS","StackedCardResizeHandleGlyph","DEFAULT_KEYBOARD_STEP","SHIFT_STEP_MULTIPLIER","isResizeKey","StyledStackedCard","StyledStackedCardResizeHandle","StackedCard","forwardRef","_ref","ref","selected","disabled","pending","isDragSource","isDragPreview","entered","forceHover","resizable","_ref$resizeAxis","resizeAxis","_ref$resizeLabel","resizeLabel","priorityColor","onResizeStart","onResizeDelta","onResizeCommit","resizeHandleProps","className","children","rest","_objectWithoutPropertiesLoose","_excluded","gesture","emitDelta","dx","dy","g","current","moved","source","endGesture","handlePointerDown","e","x","clientX","y","clientY","target","setPointerCapture","pointerId","preventDefault","handlePointerMove","handleKeyDown","step","shiftKey","key","handleKeyUp","createElement","_extends","$selected","$disabled","$pending","$isDragSource","$isDragPreview","$entered","$forceHover","$priorityColor","$axis","role","tabIndex","onPointerDown","onPointerMove","onPointerUp","onLostPointerCapture","onKeyDown","onKeyUp","displayName"],"sources":["../../../../src/components/StackedCard/StackedCard.tsx"],"sourcesContent":["import React, { ReactElement, ReactNode, useCallback, useRef } from \"react\";\n\nimport classnames from \"classnames\";\n\nimport { STACKED_CARD_CONTROL_CLASS } from \"./constants\";\nimport { StackedCardResizeHandleGlyph } from \"./Glyphs\";\nimport {\n DEFAULT_KEYBOARD_STEP,\n SHIFT_STEP_MULTIPLIER,\n StackedCardResizeAxis,\n StackedCardResizeSource,\n isResizeKey,\n} from \"./resizePolicy\";\nimport { StyledStackedCard, StyledStackedCardResizeHandle } from \"./Styles\";\n\n/**\n * StackedCard — the hollow shell for cards on drag-and-drop surfaces.\n *\n * This is NOT the base for cards in lists. It is the card for surfaces where\n * dragging is a primary interaction: column boards and canvases. Content is\n * laid out top to bottom in `StackedCardRow`s, which makes every card a\n * portrait presentation of its data.\n *\n * ── The rule the whole subsystem hangs on ──────────────────────────────────\n * THE SHELL STAYS HOLLOW. There is no `contentType` enum here, no per-type\n * prop soup, no `if task …`. The shell owns only VISUAL STATES (selected,\n * disabled, pending, priority, drag source/preview, entered) and one intent\n * callback (`onResizeDelta`). Content is passed as `children` and composes the\n * layout primitives. Typed cards — an ImageCard, a LinkCard, a TaskCard — are\n * facades built on top of it in the consuming app, and adding one requires\n * ZERO changes in this file.\n *\n * ── What the shell does NOT do ────────────────────────────────────────────\n * It implements no drag-and-drop, no selection bookkeeping, no resize policy\n * and no keyboard navigation. The card reports; the host decides. Drag\n * choreography (the drag layer, the landing indicator, the drop) belongs to\n * the host surface, which then feeds the result back as `isDragSource` /\n * `isDragPreview`. The shell forwards its ref and spreads DOM props, so a host\n * can attach `tabIndex`, ARIA, pointer and keyboard handlers to it.\n *\n * ── Resize ────────────────────────────────────────────────────────────────\n * The grip is opt-in (`resizable`) and reports intent as a gesture: one\n * `onResizeStart`, a stream of `onResizeDelta` previews measured FROM THE\n * GESTURE START, and one `onResizeCommit` at the end — and only if the gesture\n * moved anything. A host applies previews for live feedback and records an undo\n * entry on the commit alone (spec §7e).\n *\n * Because the deltas are gesture-relative rather than incremental, a host can\n * resolve every event against the size it snapshotted on start, and never has\n * to keep a running accumulator. That is what makes a slow, few-pixels-at-a-time\n * drag keep growing instead of stalling under a snap step.\n *\n * The grip itself is a focusable `role=\"separator\"` and handles arrow keys\n * (Shift for a coarse nudge). For the full policy — bounds, proportional mode,\n * step snapping, content minimums, Home/End and the live `aria-valuenow` — use\n * `useStackedCardResize` and spread its result through `resizeHandleProps`;\n * those handlers then own the grip and the three callbacks above stay quiet.\n *\n * ── Theming ───────────────────────────────────────────────────────────────\n * Colours resolve through `--sc-*` custom properties with built-in fallbacks:\n * `--sc-selection-ring` (selection / focus / entered) and the cover scrim\n * family `--sc-scrim`, `--sc-scrim-strong`, `--sc-scrim-fg`. Declare any of\n * them on an ancestor to retint a whole surface.\n */\n\nexport interface IStackedCardProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, \"onResize\"> {\n /** Host-owned selection state — a ring around the card. */\n selected?: boolean;\n /** Policy state: the card cannot be acted on. Dimmed, inert. */\n disabled?: boolean;\n /**\n * Optimistic in-flight state — created or moved, not yet confirmed. Dimmed,\n * non-interactive and not draggable, but distinct from `disabled`: it is\n * transient, not a policy.\n */\n pending?: boolean;\n /**\n * The full-size outline placeholder left behind in the source position while\n * a drag is in flight. Content is hidden but keeps its box, so neighbouring\n * cards never move.\n */\n isDragSource?: boolean;\n /**\n * The 1:1 copy the host floats in its drag layer. Elevated shadow only — no\n * tilt, no scale, no translate.\n */\n isDragPreview?: boolean;\n /** Focus model: the card has been entered and focus is on an inner control. */\n entered?: boolean;\n /** Pin the hover treatment on, including revealed controls. For docs and specs. */\n forceHover?: boolean;\n /** Show the bottom-right resize grip. Opt-in, off by default. */\n resizable?: boolean;\n /**\n * Which axes the grip offers, as a cursor: `width` reads as a horizontal\n * handle for an auto-height card. Purely the affordance — what a delta means\n * is still the host's call. Defaults to `both`.\n */\n resizeAxis?: StackedCardResizeAxis;\n /** Accessible name for the resize grip. Defaults to \"Resize card\". */\n resizeLabel?: string;\n /**\n * Draws the emphasis border down the left edge. A data colour, passed in by\n * the caller (high priority, a label colour) — never baked into the shell.\n */\n priorityColor?: string;\n /** Fired once when a resize gesture begins, before the first delta. */\n onResizeStart?: (source: StackedCardResizeSource) => void;\n /**\n * Fired throughout a resize gesture with the delta measured FROM THE GESTURE\n * START — not from the previous event. The card reports; the host decides what\n * a delta means. Previews are live feedback, never an undoable change.\n */\n onResizeDelta?: (\n dx: number,\n dy: number,\n source: StackedCardResizeSource\n ) => void;\n /**\n * Fired once when the gesture ends (pointer up, lost pointer capture, key up),\n * and only if it moved the card. A bare click on the grip is not a change.\n */\n onResizeCommit?: (source: StackedCardResizeSource) => void;\n /**\n * Props spread onto the grip, overriding the built-in behaviour entirely —\n * this is where `useStackedCardResize`'s return value goes when a host wants\n * the full policy instead of raw deltas.\n */\n resizeHandleProps?: React.HTMLAttributes<HTMLSpanElement>;\n children: ReactNode;\n}\n\nexport const StackedCard = React.forwardRef<HTMLDivElement, IStackedCardProps>(\n (\n {\n selected,\n disabled,\n pending,\n isDragSource,\n isDragPreview,\n entered,\n forceHover,\n resizable,\n resizeAxis = \"both\",\n resizeLabel = \"Resize card\",\n priorityColor,\n onResizeStart,\n onResizeDelta,\n onResizeCommit,\n resizeHandleProps,\n className,\n children,\n ...rest\n },\n ref\n ): ReactElement => {\n /**\n * One live gesture. `x`/`y` anchor a pointer drag; `dx`/`dy` carry the\n * running total a keyboard gesture has nudged. `moved` gates the commit, so\n * a click that never travelled is not a change.\n */\n const gesture = useRef<{\n source: StackedCardResizeSource;\n x: number;\n y: number;\n dx: number;\n dy: number;\n moved: boolean;\n } | null>(null);\n\n const emitDelta = useCallback(\n (dx: number, dy: number) => {\n const g = gesture.current;\n if (!g) return;\n if (dx !== 0 || dy !== 0) g.moved = true;\n onResizeDelta?.(dx, dy, g.source);\n },\n [onResizeDelta]\n );\n\n const endGesture = useCallback(() => {\n const g = gesture.current;\n if (!g) return;\n gesture.current = null;\n if (g.moved) onResizeCommit?.(g.source);\n }, [onResizeCommit]);\n\n const handlePointerDown = useCallback(\n (e: React.PointerEvent) => {\n gesture.current = {\n source: \"pointer\",\n x: e.clientX,\n y: e.clientY,\n dx: 0,\n dy: 0,\n moved: false,\n };\n (e.target as HTMLElement).setPointerCapture?.(e.pointerId);\n e.preventDefault();\n onResizeStart?.(\"pointer\");\n },\n [onResizeStart]\n );\n\n const handlePointerMove = useCallback(\n (e: React.PointerEvent) => {\n const g = gesture.current;\n if (!g || g.source !== \"pointer\") return;\n // Measured from the gesture start, so the host resolves every event\n // against one snapshot instead of accumulating.\n emitDelta(e.clientX - g.x, e.clientY - g.y);\n },\n [emitDelta]\n );\n\n /**\n * Arrows nudge the running total; Shift makes it coarse. Home and End need\n * bounds to resolve, which the bare shell does not have — they fall through\n * to `useStackedCardResize`, or to the browser.\n */\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n const step =\n DEFAULT_KEYBOARD_STEP * (e.shiftKey ? SHIFT_STEP_MULTIPLIER : 1);\n let dx = 0;\n let dy = 0;\n\n if (e.key === \"ArrowRight\") dx = step;\n else if (e.key === \"ArrowLeft\") dx = -step;\n else if (e.key === \"ArrowDown\") dy = step;\n else if (e.key === \"ArrowUp\") dy = -step;\n else return;\n\n e.preventDefault();\n if (!gesture.current || gesture.current.source !== \"keyboard\") {\n gesture.current = {\n source: \"keyboard\",\n x: 0,\n y: 0,\n dx: 0,\n dy: 0,\n moved: false,\n };\n onResizeStart?.(\"keyboard\");\n }\n const g = gesture.current;\n g.dx += dx;\n g.dy += dy;\n emitDelta(g.dx, g.dy);\n },\n [emitDelta, onResizeStart]\n );\n\n const handleKeyUp = useCallback(\n (e: React.KeyboardEvent) => {\n // One commit per hold, mirroring pointer-up after a stream of moves.\n if (isResizeKey(e.key)) endGesture();\n },\n [endGesture]\n );\n\n return (\n <StyledStackedCard\n ref={ref}\n $selected={selected}\n $disabled={disabled}\n $pending={pending}\n $isDragSource={isDragSource}\n $isDragPreview={isDragPreview}\n $entered={entered}\n $forceHover={forceHover}\n $priorityColor={priorityColor}\n className={classnames(\"c-stacked-card\", className)}\n {...rest}\n >\n {children}\n {resizable ? (\n <StyledStackedCardResizeHandle\n $axis={resizeAxis}\n className={classnames(\n \"c-stacked-card__resize-handle\",\n STACKED_CARD_CONTROL_CLASS\n )}\n role=\"separator\"\n tabIndex={0}\n aria-label={resizeLabel}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={endGesture}\n onLostPointerCapture={endGesture}\n onKeyDown={handleKeyDown}\n onKeyUp={handleKeyUp}\n {...resizeHandleProps}\n >\n <StackedCardResizeHandleGlyph />\n </StyledStackedCardResizeHandle>\n ) : null}\n </StyledStackedCard>\n );\n }\n);\n\nStackedCard.displayName = \"StackedCard\";\n"],"mappings":"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","ignoreList":[]}
@@ -1,4 +1,5 @@
1
1
  import { StackedCardRowDirection, StackedCardRowRole } from "./constants";
2
+ import { StackedCardResizeAxis } from "./resizePolicy";
2
3
  export declare const StyledStackedCardStack: import("styled-components").StyledComponent<"div", any, {}, never>;
3
4
  interface IStyledRowProps {
4
5
  $role: StackedCardRowRole;
@@ -30,7 +31,9 @@ export declare const StyledStackedCardStripExpand: import("styled-components").S
30
31
  export declare const StyledStackedCardPlayBadge: import("styled-components").StyledComponent<"span", any, {}, never>;
31
32
  /** Top-right cover-management button (collapse, remove …). */
32
33
  export declare const StyledStackedCardCoverButton: import("styled-components").StyledComponent<"button", any, {}, never>;
33
- export declare const StyledStackedCardResizeHandle: import("styled-components").StyledComponent<"span", any, {}, never>;
34
+ export declare const StyledStackedCardResizeHandle: import("styled-components").StyledComponent<"span", any, {
35
+ $axis: StackedCardResizeAxis;
36
+ }, never>;
34
37
  export interface IStyledStackedCardProps {
35
38
  $selected?: boolean;
36
39
  $disabled?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"Styles.d.ts","sourceRoot":"","sources":["../../../../src/components/StackedCard/Styles.ts"],"names":[],"mappings":"AAEA,OAAO,EAML,uBAAuB,EACvB,kBAAkB,EACnB,MAAM,aAAa,CAAC;AAwCrB,eAAO,MAAM,sBAAsB,oEAMlC,CAAC;AAOF,UAAU,eAAe;IACvB,KAAK,EAAE,kBAAkB,CAAC;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,uBAAuB,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,oBAAoB,iFAkChC,CAAC;AAOF;;;GAGG;AACH,eAAO,MAAM,2BAA2B;kBAA8B,MAAM;SAO3E,CAAC;AAKF,eAAO,MAAM,0BAA0B,oEAyBtC,CAAC;AAGF,eAAO,MAAM,4BAA4B,oEAMxC,CAAC;AAGF,eAAO,MAAM,8BAA8B,oEAM1C,CAAC;AAGF;;;;;;GAMG;AACH,eAAO,MAAM,+BAA+B,uEA2B3C,CAAC;AAKF,eAAO,MAAM,4BAA4B,qEAcxC,CAAC;AAOF,iFAAiF;AACjF,eAAO,MAAM,0BAA0B,qEAgBtC,CAAC;AAGF,8DAA8D;AAC9D,eAAO,MAAM,4BAA4B,uEAwBxC,CAAC;AAOF,eAAO,MAAM,6BAA6B,qEAazC,CAAC;AAOF,MAAM,WAAW,uBAAuB;IACtC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAOD,eAAO,MAAM,iBAAiB,yFA2H7B,CAAC"}
1
+ {"version":3,"file":"Styles.d.ts","sourceRoot":"","sources":["../../../../src/components/StackedCard/Styles.ts"],"names":[],"mappings":"AAEA,OAAO,EAML,uBAAuB,EACvB,kBAAkB,EACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAwCvD,eAAO,MAAM,sBAAsB,oEAMlC,CAAC;AAOF,UAAU,eAAe;IACvB,KAAK,EAAE,kBAAkB,CAAC;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,uBAAuB,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,oBAAoB,iFAkChC,CAAC;AAOF;;;GAGG;AACH,eAAO,MAAM,2BAA2B;kBAA8B,MAAM;SAO3E,CAAC;AAKF,eAAO,MAAM,0BAA0B,oEAyBtC,CAAC;AAGF,eAAO,MAAM,4BAA4B,oEAMxC,CAAC;AAGF,eAAO,MAAM,8BAA8B,oEAM1C,CAAC;AAGF;;;;;;GAMG;AACH,eAAO,MAAM,+BAA+B,uEA2B3C,CAAC;AAKF,eAAO,MAAM,4BAA4B,qEAcxC,CAAC;AAOF,iFAAiF;AACjF,eAAO,MAAM,0BAA0B,qEAgBtC,CAAC;AAGF,8DAA8D;AAC9D,eAAO,MAAM,4BAA4B,uEAwBxC,CAAC;AASF,eAAO,MAAM,6BAA6B;WACjC,qBAAqB;SA4B7B,CAAC;AAOF,MAAM,WAAW,uBAAuB;IACtC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAOD,eAAO,MAAM,iBAAiB,yFA2H7B,CAAC"}
@@ -143,10 +143,15 @@ StyledStackedCardCoverButton.displayName = "StyledStackedCardCoverButton";
143
143
  /* Resize (opt-in): handle on hover, the card only reports deltas */
144
144
  /* ------------------------------------------------------------------ */
145
145
 
146
+ /* The grip is a focusable separator, so it needs a focus ring of its own — a
147
+ keyboard user has no pointer to tell them where they are. */
146
148
  export const StyledStackedCardResizeHandle = styled.span.withConfig({
147
149
  displayName: "Styles__StyledStackedCardResizeHandle",
148
150
  componentId: "sc-vnqm9x-10"
149
- })(["position:absolute;right:2px;bottom:2px;width:14px;height:14px;cursor:nwse-resize;color:var(--color-theme-600);z-index:2;svg{display:block;}"]);
151
+ })(["position:absolute;right:2px;bottom:2px;display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;border-radius:4px;cursor:", ";color:var(--color-theme-600);z-index:2;&:hover{color:var(--color-theme-900);}&:focus-visible{outline:2px solid ", ";outline-offset:1px;color:var(--color-theme-900);}svg{display:block;}"], _ref8 => {
152
+ let $axis = _ref8.$axis;
153
+ return $axis === "width" ? "ew-resize" : "nwse-resize";
154
+ }, SELECTION_RING);
150
155
  StyledStackedCardResizeHandle.displayName = "StyledStackedCardResizeHandle";
151
156
 
152
157
  /* ------------------------------------------------------------------ */
@@ -157,29 +162,29 @@ const hoverStyle = css(["box-shadow:0 4px 12px rgba(0,0,0,0.12);border-color:var
157
162
  export const StyledStackedCard = styled.div.withConfig({
158
163
  displayName: "Styles__StyledStackedCard",
159
164
  componentId: "sc-vnqm9x-11"
160
- })(["", " position:relative;display:flex;flex-direction:column;width:", "px;border-radius:", "px;background-color:var(--page-paper-main);border:1px solid var(--border-primary);box-shadow:0 1px 3px rgba(0,0,0,0.08);overflow:hidden;transition:box-shadow 150ms ease,border-color 150ms ease;", " &:hover{", "}&:focus-visible{outline:none;", " box-shadow:0 0 0 2px ", ";}", " ", " ", " ", " ", " ", " ", " ", ""], BoxSizingStyle, STACKED_CARD_WIDTH, STACKED_CARD_RADIUS, revealControls, hoverStyle, hoverStyle, SELECTION_RING, _ref8 => {
161
- let $forceHover = _ref8.$forceHover;
165
+ })(["", " position:relative;display:flex;flex-direction:column;width:", "px;border-radius:", "px;background-color:var(--page-paper-main);border:1px solid var(--border-primary);box-shadow:0 1px 3px rgba(0,0,0,0.08);overflow:hidden;transition:box-shadow 150ms ease,border-color 150ms ease;", " &:hover{", "}&:focus-visible{outline:none;", " box-shadow:0 0 0 2px ", ";}", " ", " ", " ", " ", " ", " ", " ", ""], BoxSizingStyle, STACKED_CARD_WIDTH, STACKED_CARD_RADIUS, revealControls, hoverStyle, hoverStyle, SELECTION_RING, _ref9 => {
166
+ let $forceHover = _ref9.$forceHover;
162
167
  return $forceHover && css(["", " && ", "{opacity:1;}"], hoverStyle, CONTROL);
163
- }, _ref9 => {
164
- let $priorityColor = _ref9.$priorityColor;
165
- return $priorityColor && css(["&::before{content:\"\";position:absolute;top:0;bottom:0;left:0;width:4px;background:", ";z-index:2;}"], $priorityColor);
166
168
  }, _ref0 => {
167
- let $selected = _ref0.$selected;
168
- return $selected && css(["&&{border-color:", ";box-shadow:0 0 0 2px ", ";}"], SELECTION_RING, SELECTION_RING);
169
+ let $priorityColor = _ref0.$priorityColor;
170
+ return $priorityColor && css(["&::before{content:\"\";position:absolute;top:0;bottom:0;left:0;width:4px;background:", ";z-index:2;}"], $priorityColor);
169
171
  }, _ref1 => {
170
- let $disabled = _ref1.$disabled;
171
- return $disabled && css(["opacity:0.5;pointer-events:none;"]);
172
+ let $selected = _ref1.$selected;
173
+ return $selected && css(["&&{border-color:", ";box-shadow:0 0 0 2px ", ";}"], SELECTION_RING, SELECTION_RING);
172
174
  }, _ref10 => {
173
- let $pending = _ref10.$pending;
174
- return $pending && css(["opacity:0.6;pointer-events:none;cursor:progress;"]);
175
+ let $disabled = _ref10.$disabled;
176
+ return $disabled && css(["opacity:0.5;pointer-events:none;"]);
175
177
  }, _ref11 => {
176
- let $isDragSource = _ref11.$isDragSource;
177
- return $isDragSource && css(["background:transparent;border:1px dashed var(--color-theme-500);box-shadow:none;&:hover{box-shadow:none;border-color:var(--color-theme-500);}> *{visibility:hidden;}"]);
178
+ let $pending = _ref11.$pending;
179
+ return $pending && css(["opacity:0.6;pointer-events:none;cursor:progress;"]);
178
180
  }, _ref12 => {
179
- let $isDragPreview = _ref12.$isDragPreview;
180
- return $isDragPreview && css(["box-shadow:0 12px 28px rgba(0,0,0,0.24);cursor:grabbing;"]);
181
+ let $isDragSource = _ref12.$isDragSource;
182
+ return $isDragSource && css(["background:transparent;border:1px dashed var(--color-theme-500);box-shadow:none;&:hover{box-shadow:none;border-color:var(--color-theme-500);}> *{visibility:hidden;}"]);
181
183
  }, _ref13 => {
182
- let $entered = _ref13.$entered;
184
+ let $isDragPreview = _ref13.$isDragPreview;
185
+ return $isDragPreview && css(["box-shadow:0 12px 28px rgba(0,0,0,0.24);cursor:grabbing;"]);
186
+ }, _ref14 => {
187
+ let $entered = _ref14.$entered;
183
188
  return $entered && css(["&&{border-color:", ";box-shadow:inset 0 0 0 2px ", ",0 0 0 2px ", ";}"], SELECTION_RING, SELECTION_RING, SELECTION_RING);
184
189
  });
185
190
  StyledStackedCard.displayName = "StyledStackedCard";
@@ -1 +1 @@
1
- {"version":3,"file":"Styles.js","names":["styled","css","STACKED_CARD_CONTROL_CLASS","STACKED_CARD_FIXED_ATTR","STACKED_CARD_RADIUS","STACKED_CARD_ROLE_PADDING","STACKED_CARD_WIDTH","BoxSizingStyle","SELECTION_RING","SCRIM","SCRIM_STRONG","SCRIM_FG","CONTROL","revealControls","StyledStackedCardStack","div","withConfig","displayName","componentId","StyledStackedCardRow","_ref","$direction","_ref2","_ref3","_ref4","$role","$bleed","_ref5","$background","_ref6","StyledStackedCardCoverMedia","_ref7","$aspectRatio","StyledStackedCardCoverFill","StyledStackedCardCoverCenter","StyledStackedCardCoverTopRight","StyledStackedCardCollapsedStrip","button","StyledStackedCardStripExpand","span","StyledStackedCardPlayBadge","StyledStackedCardCoverButton","StyledStackedCardResizeHandle","hoverStyle","StyledStackedCard","_ref8","$forceHover","_ref9","$priorityColor","_ref0","$selected","_ref1","$disabled","_ref10","$pending","_ref11","$isDragSource","_ref12","$isDragPreview","_ref13","$entered"],"sources":["../../../../src/components/StackedCard/Styles.ts"],"sourcesContent":["import styled, { css } from \"styled-components\";\n\nimport {\n STACKED_CARD_CONTROL_CLASS,\n STACKED_CARD_FIXED_ATTR,\n STACKED_CARD_RADIUS,\n STACKED_CARD_ROLE_PADDING,\n STACKED_CARD_WIDTH,\n StackedCardRowDirection,\n StackedCardRowRole,\n} from \"./constants\";\nimport { BoxSizingStyle } from \"../BoxSizingStyle\";\n\n/**\n * Theming hooks.\n *\n * Every colour a StackedCard part needs is read through a `--sc-*` custom\n * property with a built-in fallback, so the component looks right standing on\n * its own and a host surface can still retint it by declaring the variable on\n * any ancestor. No rgba/hex is baked into a rule; data colours (a swatch value,\n * a priority colour) are always passed in by the caller.\n */\nconst SELECTION_RING = \"var(--sc-selection-ring, var(--color-primary-500))\";\nconst SCRIM = \"var(--sc-scrim, rgba(0, 0, 0, 0.55))\";\nconst SCRIM_STRONG = \"var(--sc-scrim-strong, rgba(0, 0, 0, 0.72))\";\nconst SCRIM_FG = \"var(--sc-scrim-fg, #ffffff)\";\n\n/** Selector for anything carrying the control class. */\nconst CONTROL = `.${STACKED_CARD_CONTROL_CLASS}`;\n\n/**\n * The one reveal rule the whole subsystem shares: controls are hidden until the\n * card (or the cover) is hovered OR holds focus. The focus path is what keeps\n * them reachable by keyboard instead of mouse-only.\n */\nconst revealControls = css`\n ${CONTROL} {\n opacity: 0;\n transition: opacity 120ms ease;\n }\n\n &:hover ${CONTROL}, &:focus-within ${CONTROL} {\n opacity: 1;\n }\n`;\n\n/* ------------------------------------------------------------------ */\n/* Stack — the vertical column. A card is a Stack of rows. */\n/* ------------------------------------------------------------------ */\n\nexport const StyledStackedCardStack = styled.div`\n ${BoxSizingStyle}\n\n position: relative;\n display: flex;\n flex-direction: column;\n`;\nStyledStackedCardStack.displayName = \"StyledStackedCardStack\";\n\n/* ------------------------------------------------------------------ */\n/* Row — the only layout primitive, differentiated by `role`. */\n/* ------------------------------------------------------------------ */\n\ninterface IStyledRowProps {\n $role: StackedCardRowRole;\n $bleed?: boolean;\n $direction: StackedCardRowDirection;\n $background?: string;\n}\n\nexport const StyledStackedCardRow = styled.div<IStyledRowProps>`\n ${BoxSizingStyle}\n\n position: relative;\n display: flex;\n flex-direction: ${({ $direction }) => $direction};\n align-items: ${({ $direction }) =>\n $direction === \"column\" ? \"stretch\" : \"center\"};\n gap: ${({ $direction }) => ($direction === \"column\" ? \"4px\" : \"8px\")};\n\n /* bleed overrides any role and runs the row edge to edge. */\n padding: ${({ $role, $bleed }) =>\n $bleed ? \"0\" : STACKED_CARD_ROLE_PADDING[$role]};\n\n ${({ $background }) =>\n $background &&\n css`\n background: ${$background};\n `}\n\n /* Distribution (row direction only): fixed-width children keep their width,\n the rest share what remains evenly; drop an empty spacer to push items. */\n ${({ $direction }) =>\n $direction === \"row\" &&\n css`\n > * {\n flex: 1 1 0;\n min-width: 0;\n }\n\n > [${STACKED_CARD_FIXED_ATTR}] {\n flex: 0 0 auto;\n }\n `}\n`;\nStyledStackedCardRow.displayName = \"StyledStackedCardRow\";\n\n/* ------------------------------------------------------------------ */\n/* Cover — a bleed row that holds media. */\n/* ------------------------------------------------------------------ */\n\n/**\n * The media box reserves its height with `aspect-ratio` so the image (or the\n * skeleton standing in for it) never reflows the card when it arrives.\n */\nexport const StyledStackedCardCoverMedia = styled.div<{ $aspectRatio: string }>`\n position: relative;\n width: 100%;\n aspect-ratio: ${({ $aspectRatio }) => $aspectRatio};\n overflow: hidden;\n\n ${revealControls}\n`;\nStyledStackedCardCoverMedia.displayName = \"StyledStackedCardCoverMedia\";\n\n/* The fill (an <img>, an inline <svg> wrapper, or a solid-colour box) is laid\n over the reserved box and made to cover it. */\nexport const StyledStackedCardCoverFill = styled.div`\n position: absolute;\n inset: 0;\n\n > * {\n width: 100%;\n height: 100%;\n }\n\n > img {\n display: block;\n object-fit: cover;\n }\n\n /* Media must never be natively draggable. An <img> is a browser drag source\n by default, so grabbing the cover would start an image drag and swallow the\n mousemove/mouseup the HOST's drag depends on — the card would stay put and\n then jump on the next pointer move. The host owns dragging; the cover must\n not compete with it. */\n > img,\n > svg {\n -webkit-user-drag: none;\n user-select: none;\n pointer-events: none;\n }\n`;\nStyledStackedCardCoverFill.displayName = \"StyledStackedCardCoverFill\";\n\nexport const StyledStackedCardCoverCenter = styled.div`\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n`;\nStyledStackedCardCoverCenter.displayName = \"StyledStackedCardCoverCenter\";\n\nexport const StyledStackedCardCoverTopRight = styled.div`\n position: absolute;\n top: 8px;\n right: 8px;\n display: flex;\n gap: 6px;\n`;\nStyledStackedCardCoverTopRight.displayName = \"StyledStackedCardCoverTopRight\";\n\n/**\n * Collapsed cover — the media box gives way to a thin strip. The strip IS the\n * expand affordance: the whole bar is a button and a chevron hint is revealed\n * on hover or focus. It reserves no height of its own; the caller's\n * `collapsedStrip` (an ~8px colour bar, a favicon + domain row) sets how tall\n * it reads.\n */\nexport const StyledStackedCardCollapsedStrip = styled.button`\n ${BoxSizingStyle}\n\n position: relative;\n display: flex;\n align-items: center;\n width: 100%;\n min-height: 16px;\n padding: 0;\n border: 0;\n background: transparent;\n cursor: pointer;\n text-align: left;\n\n ${CONTROL} {\n opacity: 0;\n transition: opacity 120ms ease;\n }\n\n &:hover ${CONTROL}, &:focus-visible ${CONTROL} {\n opacity: 1;\n }\n\n &:focus-visible {\n outline: 2px solid ${SELECTION_RING};\n outline-offset: -2px;\n }\n`;\nStyledStackedCardCollapsedStrip.displayName = \"StyledStackedCardCollapsedStrip\";\n\n/* The expand chevron sits at the right, vertically centred, so it reads the\n same whether the strip is a hairline colour bar or a taller favicon row. */\nexport const StyledStackedCardStripExpand = styled.span`\n position: absolute;\n top: 50%;\n right: 8px;\n transform: translateY(-50%);\n display: inline-flex;\n width: 16px;\n height: 16px;\n color: var(--color-theme-600);\n\n svg {\n width: 14px;\n height: 14px;\n }\n`;\nStyledStackedCardStripExpand.displayName = \"StyledStackedCardStripExpand\";\n\n/* ------------------------------------------------------------------ */\n/* Cover chrome — scrim-backed controls that sit over media */\n/* ------------------------------------------------------------------ */\n\n/** Centered media control (a play button). The caller drops the glyph inside. */\nexport const StyledStackedCardPlayBadge = styled.span`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n border-radius: 12px;\n background: ${SCRIM};\n color: ${SCRIM_FG};\n\n svg {\n fill: currentColor;\n width: 20px;\n height: 20px;\n margin-left: 2px;\n }\n`;\nStyledStackedCardPlayBadge.displayName = \"StyledStackedCardPlayBadge\";\n\n/** Top-right cover-management button (collapse, remove …). */\nexport const StyledStackedCardCoverButton = styled.button`\n ${BoxSizingStyle}\n\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 30px;\n height: 30px;\n padding: 0;\n border: 0;\n border-radius: 8px;\n cursor: pointer;\n color: ${SCRIM_FG};\n background: ${SCRIM};\n\n svg {\n width: 16px;\n height: 16px;\n display: block;\n }\n\n &:hover {\n background: ${SCRIM_STRONG};\n }\n`;\nStyledStackedCardCoverButton.displayName = \"StyledStackedCardCoverButton\";\n\n/* ------------------------------------------------------------------ */\n/* Resize (opt-in): handle on hover, the card only reports deltas */\n/* ------------------------------------------------------------------ */\n\nexport const StyledStackedCardResizeHandle = styled.span`\n position: absolute;\n right: 2px;\n bottom: 2px;\n width: 14px;\n height: 14px;\n cursor: nwse-resize;\n color: var(--color-theme-600);\n z-index: 2;\n\n svg {\n display: block;\n }\n`;\nStyledStackedCardResizeHandle.displayName = \"StyledStackedCardResizeHandle\";\n\n/* ------------------------------------------------------------------ */\n/* The shell */\n/* ------------------------------------------------------------------ */\n\nexport interface IStyledStackedCardProps {\n $selected?: boolean;\n $disabled?: boolean;\n $pending?: boolean;\n $isDragSource?: boolean;\n $isDragPreview?: boolean;\n $entered?: boolean;\n $forceHover?: boolean;\n $priorityColor?: string;\n}\n\nconst hoverStyle = css`\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);\n border-color: var(--color-theme-500);\n`;\n\nexport const StyledStackedCard = styled.div<IStyledStackedCardProps>`\n ${BoxSizingStyle}\n\n position: relative;\n display: flex;\n flex-direction: column;\n width: ${STACKED_CARD_WIDTH}px;\n border-radius: ${STACKED_CARD_RADIUS}px;\n background-color: var(--page-paper-main);\n border: 1px solid var(--border-primary);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n transition: box-shadow 150ms ease, border-color 150ms ease;\n\n ${revealControls}\n\n &:hover {\n ${hoverStyle}\n }\n\n &:focus-visible {\n outline: none;\n ${hoverStyle}\n box-shadow: 0 0 0 2px ${SELECTION_RING};\n }\n\n /* Forced hover — for docs, snapshots and \"this is what hover looks like\"\n demos. The doubled ampersand gives it the specificity to beat the cover's\n own reveal rule. */\n ${({ $forceHover }) =>\n $forceHover &&\n css`\n ${hoverStyle}\n && ${CONTROL} {\n opacity: 1;\n }\n `}\n\n ${({ $priorityColor }) =>\n $priorityColor &&\n css`\n &::before {\n content: \"\";\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 4px;\n background: ${$priorityColor};\n z-index: 2;\n }\n `}\n\n /* Selection outranks hover: a selected card must keep its ring while the\n pointer is over it — which, right after the click that selected it, is\n always. The doubled ampersand buys the specificity to beat the hover rule\n above (same reason the entered state below does it). */\n ${({ $selected }) =>\n $selected &&\n css`\n && {\n border-color: ${SELECTION_RING};\n box-shadow: 0 0 0 2px ${SELECTION_RING};\n }\n `}\n\n ${({ $disabled }) =>\n $disabled &&\n css`\n opacity: 0.5;\n pointer-events: none;\n `}\n\n /* Pending / optimistic — created or moved, not yet confirmed by the server.\n Dimmed, non-interactive and NOT draggable, but distinct from disabled: a\n transient in-flight state, not a policy. */\n ${({ $pending }) =>\n $pending &&\n css`\n opacity: 0.6;\n pointer-events: none;\n cursor: progress;\n `}\n\n /* Drag SOURCE — full-size outline placeholder. Content is hidden but keeps\n its box (visibility, not display) so the card holds identical dimensions\n and the surrounding cards never move. */\n ${({ $isDragSource }) =>\n $isDragSource &&\n css`\n background: transparent;\n border: 1px dashed var(--color-theme-500);\n box-shadow: none;\n\n &:hover {\n box-shadow: none;\n border-color: var(--color-theme-500);\n }\n\n > * {\n visibility: hidden;\n }\n `}\n\n /* Drag PREVIEW — the 1:1 copy the host floats in its drag layer. Elevated\n shadow ONLY: no rotate, no scale, no translate. */\n ${({ $isDragPreview }) =>\n $isDragPreview &&\n css`\n box-shadow: 0 12px 28px rgba(0, 0, 0, 0.24);\n cursor: grabbing;\n `}\n\n /* Entered (focus model) — focus has moved inside, onto an inner control. */\n ${({ $entered }) =>\n $entered &&\n css`\n && {\n border-color: ${SELECTION_RING};\n box-shadow: inset 0 0 0 2px ${SELECTION_RING},\n 0 0 0 2px ${SELECTION_RING};\n }\n `}\n`;\nStyledStackedCard.displayName = \"StyledStackedCard\";\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"Styles.js","names":["styled","css","STACKED_CARD_CONTROL_CLASS","STACKED_CARD_FIXED_ATTR","STACKED_CARD_RADIUS","STACKED_CARD_ROLE_PADDING","STACKED_CARD_WIDTH","BoxSizingStyle","SELECTION_RING","SCRIM","SCRIM_STRONG","SCRIM_FG","CONTROL","revealControls","StyledStackedCardStack","div","withConfig","displayName","componentId","StyledStackedCardRow","_ref","$direction","_ref2","_ref3","_ref4","$role","$bleed","_ref5","$background","_ref6","StyledStackedCardCoverMedia","_ref7","$aspectRatio","StyledStackedCardCoverFill","StyledStackedCardCoverCenter","StyledStackedCardCoverTopRight","StyledStackedCardCollapsedStrip","button","StyledStackedCardStripExpand","span","StyledStackedCardPlayBadge","StyledStackedCardCoverButton","StyledStackedCardResizeHandle","_ref8","$axis","hoverStyle","StyledStackedCard","_ref9","$forceHover","_ref0","$priorityColor","_ref1","$selected","_ref10","$disabled","_ref11","$pending","_ref12","$isDragSource","_ref13","$isDragPreview","_ref14","$entered"],"sources":["../../../../src/components/StackedCard/Styles.ts"],"sourcesContent":["import styled, { css } from \"styled-components\";\n\nimport {\n STACKED_CARD_CONTROL_CLASS,\n STACKED_CARD_FIXED_ATTR,\n STACKED_CARD_RADIUS,\n STACKED_CARD_ROLE_PADDING,\n STACKED_CARD_WIDTH,\n StackedCardRowDirection,\n StackedCardRowRole,\n} from \"./constants\";\nimport { StackedCardResizeAxis } from \"./resizePolicy\";\nimport { BoxSizingStyle } from \"../BoxSizingStyle\";\n\n/**\n * Theming hooks.\n *\n * Every colour a StackedCard part needs is read through a `--sc-*` custom\n * property with a built-in fallback, so the component looks right standing on\n * its own and a host surface can still retint it by declaring the variable on\n * any ancestor. No rgba/hex is baked into a rule; data colours (a swatch value,\n * a priority colour) are always passed in by the caller.\n */\nconst SELECTION_RING = \"var(--sc-selection-ring, var(--color-primary-500))\";\nconst SCRIM = \"var(--sc-scrim, rgba(0, 0, 0, 0.55))\";\nconst SCRIM_STRONG = \"var(--sc-scrim-strong, rgba(0, 0, 0, 0.72))\";\nconst SCRIM_FG = \"var(--sc-scrim-fg, #ffffff)\";\n\n/** Selector for anything carrying the control class. */\nconst CONTROL = `.${STACKED_CARD_CONTROL_CLASS}`;\n\n/**\n * The one reveal rule the whole subsystem shares: controls are hidden until the\n * card (or the cover) is hovered OR holds focus. The focus path is what keeps\n * them reachable by keyboard instead of mouse-only.\n */\nconst revealControls = css`\n ${CONTROL} {\n opacity: 0;\n transition: opacity 120ms ease;\n }\n\n &:hover ${CONTROL}, &:focus-within ${CONTROL} {\n opacity: 1;\n }\n`;\n\n/* ------------------------------------------------------------------ */\n/* Stack — the vertical column. A card is a Stack of rows. */\n/* ------------------------------------------------------------------ */\n\nexport const StyledStackedCardStack = styled.div`\n ${BoxSizingStyle}\n\n position: relative;\n display: flex;\n flex-direction: column;\n`;\nStyledStackedCardStack.displayName = \"StyledStackedCardStack\";\n\n/* ------------------------------------------------------------------ */\n/* Row — the only layout primitive, differentiated by `role`. */\n/* ------------------------------------------------------------------ */\n\ninterface IStyledRowProps {\n $role: StackedCardRowRole;\n $bleed?: boolean;\n $direction: StackedCardRowDirection;\n $background?: string;\n}\n\nexport const StyledStackedCardRow = styled.div<IStyledRowProps>`\n ${BoxSizingStyle}\n\n position: relative;\n display: flex;\n flex-direction: ${({ $direction }) => $direction};\n align-items: ${({ $direction }) =>\n $direction === \"column\" ? \"stretch\" : \"center\"};\n gap: ${({ $direction }) => ($direction === \"column\" ? \"4px\" : \"8px\")};\n\n /* bleed overrides any role and runs the row edge to edge. */\n padding: ${({ $role, $bleed }) =>\n $bleed ? \"0\" : STACKED_CARD_ROLE_PADDING[$role]};\n\n ${({ $background }) =>\n $background &&\n css`\n background: ${$background};\n `}\n\n /* Distribution (row direction only): fixed-width children keep their width,\n the rest share what remains evenly; drop an empty spacer to push items. */\n ${({ $direction }) =>\n $direction === \"row\" &&\n css`\n > * {\n flex: 1 1 0;\n min-width: 0;\n }\n\n > [${STACKED_CARD_FIXED_ATTR}] {\n flex: 0 0 auto;\n }\n `}\n`;\nStyledStackedCardRow.displayName = \"StyledStackedCardRow\";\n\n/* ------------------------------------------------------------------ */\n/* Cover — a bleed row that holds media. */\n/* ------------------------------------------------------------------ */\n\n/**\n * The media box reserves its height with `aspect-ratio` so the image (or the\n * skeleton standing in for it) never reflows the card when it arrives.\n */\nexport const StyledStackedCardCoverMedia = styled.div<{ $aspectRatio: string }>`\n position: relative;\n width: 100%;\n aspect-ratio: ${({ $aspectRatio }) => $aspectRatio};\n overflow: hidden;\n\n ${revealControls}\n`;\nStyledStackedCardCoverMedia.displayName = \"StyledStackedCardCoverMedia\";\n\n/* The fill (an <img>, an inline <svg> wrapper, or a solid-colour box) is laid\n over the reserved box and made to cover it. */\nexport const StyledStackedCardCoverFill = styled.div`\n position: absolute;\n inset: 0;\n\n > * {\n width: 100%;\n height: 100%;\n }\n\n > img {\n display: block;\n object-fit: cover;\n }\n\n /* Media must never be natively draggable. An <img> is a browser drag source\n by default, so grabbing the cover would start an image drag and swallow the\n mousemove/mouseup the HOST's drag depends on — the card would stay put and\n then jump on the next pointer move. The host owns dragging; the cover must\n not compete with it. */\n > img,\n > svg {\n -webkit-user-drag: none;\n user-select: none;\n pointer-events: none;\n }\n`;\nStyledStackedCardCoverFill.displayName = \"StyledStackedCardCoverFill\";\n\nexport const StyledStackedCardCoverCenter = styled.div`\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n`;\nStyledStackedCardCoverCenter.displayName = \"StyledStackedCardCoverCenter\";\n\nexport const StyledStackedCardCoverTopRight = styled.div`\n position: absolute;\n top: 8px;\n right: 8px;\n display: flex;\n gap: 6px;\n`;\nStyledStackedCardCoverTopRight.displayName = \"StyledStackedCardCoverTopRight\";\n\n/**\n * Collapsed cover — the media box gives way to a thin strip. The strip IS the\n * expand affordance: the whole bar is a button and a chevron hint is revealed\n * on hover or focus. It reserves no height of its own; the caller's\n * `collapsedStrip` (an ~8px colour bar, a favicon + domain row) sets how tall\n * it reads.\n */\nexport const StyledStackedCardCollapsedStrip = styled.button`\n ${BoxSizingStyle}\n\n position: relative;\n display: flex;\n align-items: center;\n width: 100%;\n min-height: 16px;\n padding: 0;\n border: 0;\n background: transparent;\n cursor: pointer;\n text-align: left;\n\n ${CONTROL} {\n opacity: 0;\n transition: opacity 120ms ease;\n }\n\n &:hover ${CONTROL}, &:focus-visible ${CONTROL} {\n opacity: 1;\n }\n\n &:focus-visible {\n outline: 2px solid ${SELECTION_RING};\n outline-offset: -2px;\n }\n`;\nStyledStackedCardCollapsedStrip.displayName = \"StyledStackedCardCollapsedStrip\";\n\n/* The expand chevron sits at the right, vertically centred, so it reads the\n same whether the strip is a hairline colour bar or a taller favicon row. */\nexport const StyledStackedCardStripExpand = styled.span`\n position: absolute;\n top: 50%;\n right: 8px;\n transform: translateY(-50%);\n display: inline-flex;\n width: 16px;\n height: 16px;\n color: var(--color-theme-600);\n\n svg {\n width: 14px;\n height: 14px;\n }\n`;\nStyledStackedCardStripExpand.displayName = \"StyledStackedCardStripExpand\";\n\n/* ------------------------------------------------------------------ */\n/* Cover chrome — scrim-backed controls that sit over media */\n/* ------------------------------------------------------------------ */\n\n/** Centered media control (a play button). The caller drops the glyph inside. */\nexport const StyledStackedCardPlayBadge = styled.span`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n border-radius: 12px;\n background: ${SCRIM};\n color: ${SCRIM_FG};\n\n svg {\n fill: currentColor;\n width: 20px;\n height: 20px;\n margin-left: 2px;\n }\n`;\nStyledStackedCardPlayBadge.displayName = \"StyledStackedCardPlayBadge\";\n\n/** Top-right cover-management button (collapse, remove …). */\nexport const StyledStackedCardCoverButton = styled.button`\n ${BoxSizingStyle}\n\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 30px;\n height: 30px;\n padding: 0;\n border: 0;\n border-radius: 8px;\n cursor: pointer;\n color: ${SCRIM_FG};\n background: ${SCRIM};\n\n svg {\n width: 16px;\n height: 16px;\n display: block;\n }\n\n &:hover {\n background: ${SCRIM_STRONG};\n }\n`;\nStyledStackedCardCoverButton.displayName = \"StyledStackedCardCoverButton\";\n\n/* ------------------------------------------------------------------ */\n/* Resize (opt-in): handle on hover, the card only reports deltas */\n/* ------------------------------------------------------------------ */\n\n/* The grip is a focusable separator, so it needs a focus ring of its own — a\n keyboard user has no pointer to tell them where they are. */\nexport const StyledStackedCardResizeHandle = styled.span<{\n $axis: StackedCardResizeAxis;\n}>`\n position: absolute;\n right: 2px;\n bottom: 2px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n border-radius: 4px;\n cursor: ${({ $axis }) => ($axis === \"width\" ? \"ew-resize\" : \"nwse-resize\")};\n color: var(--color-theme-600);\n z-index: 2;\n\n &:hover {\n color: var(--color-theme-900);\n }\n\n &:focus-visible {\n outline: 2px solid ${SELECTION_RING};\n outline-offset: 1px;\n color: var(--color-theme-900);\n }\n\n svg {\n display: block;\n }\n`;\nStyledStackedCardResizeHandle.displayName = \"StyledStackedCardResizeHandle\";\n\n/* ------------------------------------------------------------------ */\n/* The shell */\n/* ------------------------------------------------------------------ */\n\nexport interface IStyledStackedCardProps {\n $selected?: boolean;\n $disabled?: boolean;\n $pending?: boolean;\n $isDragSource?: boolean;\n $isDragPreview?: boolean;\n $entered?: boolean;\n $forceHover?: boolean;\n $priorityColor?: string;\n}\n\nconst hoverStyle = css`\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);\n border-color: var(--color-theme-500);\n`;\n\nexport const StyledStackedCard = styled.div<IStyledStackedCardProps>`\n ${BoxSizingStyle}\n\n position: relative;\n display: flex;\n flex-direction: column;\n width: ${STACKED_CARD_WIDTH}px;\n border-radius: ${STACKED_CARD_RADIUS}px;\n background-color: var(--page-paper-main);\n border: 1px solid var(--border-primary);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n transition: box-shadow 150ms ease, border-color 150ms ease;\n\n ${revealControls}\n\n &:hover {\n ${hoverStyle}\n }\n\n &:focus-visible {\n outline: none;\n ${hoverStyle}\n box-shadow: 0 0 0 2px ${SELECTION_RING};\n }\n\n /* Forced hover — for docs, snapshots and \"this is what hover looks like\"\n demos. The doubled ampersand gives it the specificity to beat the cover's\n own reveal rule. */\n ${({ $forceHover }) =>\n $forceHover &&\n css`\n ${hoverStyle}\n && ${CONTROL} {\n opacity: 1;\n }\n `}\n\n ${({ $priorityColor }) =>\n $priorityColor &&\n css`\n &::before {\n content: \"\";\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 4px;\n background: ${$priorityColor};\n z-index: 2;\n }\n `}\n\n /* Selection outranks hover: a selected card must keep its ring while the\n pointer is over it — which, right after the click that selected it, is\n always. The doubled ampersand buys the specificity to beat the hover rule\n above (same reason the entered state below does it). */\n ${({ $selected }) =>\n $selected &&\n css`\n && {\n border-color: ${SELECTION_RING};\n box-shadow: 0 0 0 2px ${SELECTION_RING};\n }\n `}\n\n ${({ $disabled }) =>\n $disabled &&\n css`\n opacity: 0.5;\n pointer-events: none;\n `}\n\n /* Pending / optimistic — created or moved, not yet confirmed by the server.\n Dimmed, non-interactive and NOT draggable, but distinct from disabled: a\n transient in-flight state, not a policy. */\n ${({ $pending }) =>\n $pending &&\n css`\n opacity: 0.6;\n pointer-events: none;\n cursor: progress;\n `}\n\n /* Drag SOURCE — full-size outline placeholder. Content is hidden but keeps\n its box (visibility, not display) so the card holds identical dimensions\n and the surrounding cards never move. */\n ${({ $isDragSource }) =>\n $isDragSource &&\n css`\n background: transparent;\n border: 1px dashed var(--color-theme-500);\n box-shadow: none;\n\n &:hover {\n box-shadow: none;\n border-color: var(--color-theme-500);\n }\n\n > * {\n visibility: hidden;\n }\n `}\n\n /* Drag PREVIEW — the 1:1 copy the host floats in its drag layer. Elevated\n shadow ONLY: no rotate, no scale, no translate. */\n ${({ $isDragPreview }) =>\n $isDragPreview &&\n css`\n box-shadow: 0 12px 28px rgba(0, 0, 0, 0.24);\n cursor: grabbing;\n `}\n\n /* Entered (focus model) — focus has moved inside, onto an inner control. */\n ${({ $entered }) =>\n $entered &&\n css`\n && {\n border-color: ${SELECTION_RING};\n box-shadow: inset 0 0 0 2px ${SELECTION_RING},\n 0 0 0 2px ${SELECTION_RING};\n }\n `}\n`;\nStyledStackedCard.displayName = \"StyledStackedCard\";\n"],"mappings":"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","ignoreList":[]}
@@ -2,4 +2,6 @@ export * from "./StackedCard";
2
2
  export * from "./Primitives";
3
3
  export * from "./Glyphs";
4
4
  export * from "./constants";
5
+ export * from "./resizePolicy";
6
+ export * from "./useStackedCardResize";
5
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/StackedCard/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/StackedCard/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC"}
@@ -2,4 +2,6 @@ export * from "./StackedCard";
2
2
  export * from "./Primitives";
3
3
  export * from "./Glyphs";
4
4
  export * from "./constants";
5
+ export * from "./resizePolicy";
6
+ export * from "./useStackedCardResize";
5
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/StackedCard/index.ts"],"sourcesContent":["export * from \"./StackedCard\";\nexport * from \"./Primitives\";\nexport * from \"./Glyphs\";\nexport * from \"./constants\";\n"],"mappings":"AAAA,cAAc,eAAe;AAC7B,cAAc,cAAc;AAC5B,cAAc,UAAU;AACxB,cAAc,aAAa","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/StackedCard/index.ts"],"sourcesContent":["export * from \"./StackedCard\";\nexport * from \"./Primitives\";\nexport * from \"./Glyphs\";\nexport * from \"./constants\";\nexport * from \"./resizePolicy\";\nexport * from \"./useStackedCardResize\";\n"],"mappings":"AAAA,cAAc,eAAe;AAC7B,cAAc,cAAc;AAC5B,cAAc,UAAU;AACxB,cAAc,aAAa;AAC3B,cAAc,gBAAgB;AAC9B,cAAc,wBAAwB","ignoreList":[]}