UNPKG

@activecollab/components

Version:

ActiveCollab Components

187 lines (184 loc) 10.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.StackedCard = void 0; var _react = _interopRequireWildcard(require("react")); var _classnames = _interopRequireDefault(require("classnames")); var _constants = require("./constants"); var _Glyphs = require("./Glyphs"); var _resizePolicy = require("./resizePolicy"); var _Styles = require("./Styles"); var _excluded = ["selected", "disabled", "pending", "isDragSource", "isDragPreview", "entered", "forceHover", "resizable", "resizeAxis", "resizeLabel", "priorityColor", "onResizeStart", "onResizeDelta", "onResizeCommit", "resizeHandleProps", "className", "children"]; function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); } function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; } function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; } /** * StackedCard — the hollow shell for cards on drag-and-drop surfaces. * * This is NOT the base for cards in lists. It is the card for surfaces where * dragging is a primary interaction: column boards and canvases. Content is * laid out top to bottom in `StackedCardRow`s, which makes every card a * portrait presentation of its data. * * ── The rule the whole subsystem hangs on ────────────────────────────────── * THE SHELL STAYS HOLLOW. There is no `contentType` enum here, no per-type * prop soup, no `if task …`. The shell owns only VISUAL STATES (selected, * disabled, pending, priority, drag source/preview, entered) and one intent * callback (`onResizeDelta`). Content is passed as `children` and composes the * layout primitives. Typed cards — an ImageCard, a LinkCard, a TaskCard — are * facades built on top of it in the consuming app, and adding one requires * ZERO changes in this file. * * ── What the shell does NOT do ──────────────────────────────────────────── * It implements no drag-and-drop, no selection bookkeeping, no resize policy * and no keyboard navigation. The card reports; the host decides. Drag * choreography (the drag layer, the landing indicator, the drop) belongs to * the host surface, which then feeds the result back as `isDragSource` / * `isDragPreview`. The shell forwards its ref and spreads DOM props, so a host * can attach `tabIndex`, ARIA, pointer and keyboard handlers to it. * * ── Resize ──────────────────────────────────────────────────────────────── * The grip is opt-in (`resizable`) and reports intent as a gesture: one * `onResizeStart`, a stream of `onResizeDelta` previews measured FROM THE * GESTURE START, and one `onResizeCommit` at the end — and only if the gesture * moved anything. A host applies previews for live feedback and records an undo * entry on the commit alone (spec §7e). * * Because the deltas are gesture-relative rather than incremental, a host can * resolve every event against the size it snapshotted on start, and never has * to keep a running accumulator. That is what makes a slow, few-pixels-at-a-time * drag keep growing instead of stalling under a snap step. * * The grip itself is a focusable `role="separator"` and handles arrow keys * (Shift for a coarse nudge). For the full policy — bounds, proportional mode, * step snapping, content minimums, Home/End and the live `aria-valuenow` — use * `useStackedCardResize` and spread its result through `resizeHandleProps`; * those handlers then own the grip and the three callbacks above stay quiet. * * ── Theming ─────────────────────────────────────────────────────────────── * Colours resolve through `--sc-*` custom properties with built-in fallbacks: * `--sc-selection-ring` (selection / focus / entered) and the cover scrim * family `--sc-scrim`, `--sc-scrim-strong`, `--sc-scrim-fg`. Declare any of * them on an ancestor to retint a whole surface. */ var StackedCard = exports.StackedCard = /*#__PURE__*/_react.default.forwardRef(function (_ref, ref) { var selected = _ref.selected, disabled = _ref.disabled, pending = _ref.pending, isDragSource = _ref.isDragSource, isDragPreview = _ref.isDragPreview, entered = _ref.entered, forceHover = _ref.forceHover, resizable = _ref.resizable, _ref$resizeAxis = _ref.resizeAxis, resizeAxis = _ref$resizeAxis === void 0 ? "both" : _ref$resizeAxis, _ref$resizeLabel = _ref.resizeLabel, resizeLabel = _ref$resizeLabel === void 0 ? "Resize card" : _ref$resizeLabel, priorityColor = _ref.priorityColor, onResizeStart = _ref.onResizeStart, onResizeDelta = _ref.onResizeDelta, onResizeCommit = _ref.onResizeCommit, resizeHandleProps = _ref.resizeHandleProps, className = _ref.className, children = _ref.children, rest = _objectWithoutProperties(_ref, _excluded); /** * One live gesture. `x`/`y` anchor a pointer drag; `dx`/`dy` carry the * running total a keyboard gesture has nudged. `moved` gates the commit, so * a click that never travelled is not a change. */ var gesture = (0, _react.useRef)(null); var emitDelta = (0, _react.useCallback)(function (dx, dy) { var g = gesture.current; if (!g) return; if (dx !== 0 || dy !== 0) g.moved = true; onResizeDelta === null || onResizeDelta === void 0 || onResizeDelta(dx, dy, g.source); }, [onResizeDelta]); var endGesture = (0, _react.useCallback)(function () { var g = gesture.current; if (!g) return; gesture.current = null; if (g.moved) onResizeCommit === null || onResizeCommit === void 0 || onResizeCommit(g.source); }, [onResizeCommit]); var handlePointerDown = (0, _react.useCallback)(function (e) { var _setPointerCapture, _ref2; gesture.current = { source: "pointer", x: e.clientX, y: e.clientY, dx: 0, dy: 0, moved: false }; (_setPointerCapture = (_ref2 = e.target).setPointerCapture) === null || _setPointerCapture === void 0 || _setPointerCapture.call(_ref2, e.pointerId); e.preventDefault(); onResizeStart === null || onResizeStart === void 0 || onResizeStart("pointer"); }, [onResizeStart]); var handlePointerMove = (0, _react.useCallback)(function (e) { var g = gesture.current; if (!g || g.source !== "pointer") return; // Measured from the gesture start, so the host resolves every event // against one snapshot instead of accumulating. emitDelta(e.clientX - g.x, e.clientY - g.y); }, [emitDelta]); /** * Arrows nudge the running total; Shift makes it coarse. Home and End need * bounds to resolve, which the bare shell does not have — they fall through * to `useStackedCardResize`, or to the browser. */ var handleKeyDown = (0, _react.useCallback)(function (e) { var step = _resizePolicy.DEFAULT_KEYBOARD_STEP * (e.shiftKey ? _resizePolicy.SHIFT_STEP_MULTIPLIER : 1); var dx = 0; var dy = 0; 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; e.preventDefault(); if (!gesture.current || gesture.current.source !== "keyboard") { gesture.current = { source: "keyboard", x: 0, y: 0, dx: 0, dy: 0, moved: false }; onResizeStart === null || onResizeStart === void 0 || onResizeStart("keyboard"); } var g = gesture.current; g.dx += dx; g.dy += dy; emitDelta(g.dx, g.dy); }, [emitDelta, onResizeStart]); var handleKeyUp = (0, _react.useCallback)(function (e) { // One commit per hold, mirroring pointer-up after a stream of moves. if ((0, _resizePolicy.isResizeKey)(e.key)) endGesture(); }, [endGesture]); return /*#__PURE__*/_react.default.createElement(_Styles.StyledStackedCard, _extends({ ref: ref, $selected: selected, $disabled: disabled, $pending: pending, $isDragSource: isDragSource, $isDragPreview: isDragPreview, $entered: entered, $forceHover: forceHover, $priorityColor: priorityColor, className: (0, _classnames.default)("c-stacked-card", className) }, rest), children, resizable ? /*#__PURE__*/_react.default.createElement(_Styles.StyledStackedCardResizeHandle, _extends({ $axis: resizeAxis, className: (0, _classnames.default)("c-stacked-card__resize-handle", _constants.STACKED_CARD_CONTROL_CLASS), role: "separator", tabIndex: 0, "aria-label": resizeLabel, onPointerDown: handlePointerDown, onPointerMove: handlePointerMove, onPointerUp: endGesture, onLostPointerCapture: endGesture, onKeyDown: handleKeyDown, onKeyUp: handleKeyUp }, resizeHandleProps), /*#__PURE__*/_react.default.createElement(_Glyphs.StackedCardResizeHandleGlyph, null)) : null); }); StackedCard.displayName = "StackedCard"; //# sourceMappingURL=StackedCard.js.map