@activecollab/components
Version:
ActiveCollab Components
187 lines (184 loc) • 10.6 kB
JavaScript
"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