@mt-gloss/ui 0.0.47 → 0.0.49

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 (35) hide show
  1. package/{BaseAsyncButton-nFOdhiBv.js → BaseAsyncButton-usdApZUY.js} +8 -8
  2. package/{Expandable-BdC9RXOI.js → Expandable-CsLVYNv3.js} +4769 -4877
  3. package/catalog.js +39 -40
  4. package/index.d.ts +2 -0
  5. package/index.js +1639 -1326
  6. package/internals.js +1 -1
  7. package/lib/composites/dashboard/BottomToolbar/BottomToolbar.d.ts +19 -0
  8. package/lib/composites/dashboard/BottomToolbar/SectionDots.d.ts +14 -0
  9. package/lib/composites/dashboard/BottomToolbar/index.d.ts +4 -0
  10. package/lib/composites/dashboard/index.d.ts +1 -0
  11. package/lib/facade/data-display.d.ts +0 -2
  12. package/lib/primitives/dashboard/DropAnchorCell/DropAnchorCell.d.ts +29 -0
  13. package/lib/primitives/dashboard/DropAnchorCell/index.d.ts +2 -0
  14. package/lib/primitives/dashboard/EmptyCellPackAffordance/EmptyCellPackAffordance.d.ts +17 -0
  15. package/lib/primitives/dashboard/EmptyCellPackAffordance/index.d.ts +2 -0
  16. package/lib/primitives/dashboard/MetricCard/CardShell.d.ts +1 -1
  17. package/lib/primitives/dashboard/MetricCard/__tests__/_testSupport/gridHoverListeners.d.ts +29 -0
  18. package/lib/primitives/dashboard/MetricCard/__tests__/nyquist-10.fixture.d.ts +93 -0
  19. package/lib/primitives/dashboard/MetricCard/gridInteractionPhysics.d.ts +29 -0
  20. package/lib/primitives/dashboard/MetricCard/index.d.ts +2 -2
  21. package/lib/primitives/dashboard/MetricCard/types.d.ts +15 -0
  22. package/lib/primitives/dashboard/MetricCard/useEdgeHoverResize.d.ts +26 -11
  23. package/lib/primitives/dashboard/ResizeEnvelope/ResizeEnvelope.d.ts +41 -0
  24. package/lib/primitives/dashboard/ResizeEnvelope/index.d.ts +2 -0
  25. package/lib/primitives/dashboard/SectionDivider/SectionDivider.d.ts +29 -0
  26. package/lib/primitives/dashboard/SectionDivider/index.d.ts +2 -0
  27. package/lib/primitives/dashboard/SpilloverArc/SpilloverArc.d.ts +30 -0
  28. package/lib/primitives/dashboard/SpilloverArc/index.d.ts +2 -0
  29. package/lib/primitives/dashboard/index.d.ts +5 -0
  30. package/lib/primitives/overlays/ActionStrip/index.d.ts +0 -2
  31. package/lib/primitives/overlays/ActionStrip/types.d.ts +5 -1
  32. package/package.json +1 -1
  33. package/ui.css +1 -1
  34. package/lib/primitives/dashboard/MetricCard/useSlideOutReveal.d.ts +0 -1
  35. package/lib/primitives/overlays/ActionStrip/useSlideOutReveal.d.ts +0 -47
package/internals.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { b as B } from "./UIContext-C3E-k7HI.js";
2
2
  import { F as A, I, G as H, H as M, af as $, ah as R, c as E, h as F, t as O, D as U, w as z, x as W, v as L, y as j, A as G, z as V, k as X, ai as Z, a7 as q, aa as J, a9 as K, a8 as Q, ab as Y, Q as aa, W as sa, X as ea, V as oa, a0 as ta, a1 as la, e as ra, a4 as ia, a6 as da, a5 as na, g as ca, i as Ba, aj as ga, a3 as ba, J as ma, M as ua, K as pa, L as ya, a2 as ha, B as _a, ag as fa, l as va, ac as Ca, O as ka, P as Da, n as Ta, p as wa, r as xa, q as Sa, o as Na, s as Pa, d as Aa, ad as Ia, j as Ha, Y as Ma, $ as $a, _ as Ra, ae as Ea, m as Fa, N as Oa, f as Ua, C as za, E as Wa, R as La, S as ja, T as Ga, a as Va, U as Xa, Z as Za, u as qa } from "./UIContext-C3E-k7HI.js";
3
3
  import { jsx as d, jsxs as g, Fragment as b } from "react/jsx-runtime";
4
- import { c as Ka, e as Qa, d as Ya, B as as, b as ss, a as es } from "./BaseAsyncButton-nFOdhiBv.js";
4
+ import { c as Ka, e as Qa, d as Ya, B as as, b as ss, a as es } from "./BaseAsyncButton-usdApZUY.js";
5
5
  const T = {
6
6
  DurationFast: "var(--gloss-motion-duration-fast)",
7
7
  DurationNormal: "var(--gloss-motion-duration-normal)",
@@ -0,0 +1,19 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * Phase 23 — TOOLBAR-01 — persistent ~36px strip per D-23 / D-24.
4
+ *
5
+ * Always visible (not tied to edit-session state). Three named slots — left, center,
6
+ * right — composed by the consumer. Reptime supplies a `<PageDropdown>` in `slotLeft`
7
+ * and `<SectionDots>` in `slotCenter`; `slotRight` is reserved for future controls.
8
+ */
9
+ export interface BottomToolbarProps {
10
+ slotLeft?: React.ReactNode;
11
+ slotCenter?: React.ReactNode;
12
+ slotRight?: React.ReactNode;
13
+ /** Override D-23 default 36px height. */
14
+ height?: number;
15
+ className?: string;
16
+ style?: React.CSSProperties;
17
+ 'aria-label'?: string;
18
+ }
19
+ export declare function BottomToolbar({ slotLeft, slotCenter, slotRight, height, className, style, 'aria-label': ariaLabel, }: BottomToolbarProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Phase 23 — TOOLBAR-01 — N-button section navigator per D-24 / D-25.
3
+ *
4
+ * Renders `count` buttons inside a `role="tablist"`. Click dispatches
5
+ * `onSelect(index)`. Keyboard ← → loop forward/backward with wrap semantics
6
+ * (D-25). Hollow default, filled for the current section.
7
+ */
8
+ export interface SectionDotsProps {
9
+ count: number;
10
+ currentIndex: number;
11
+ onSelect: (index: number) => void;
12
+ 'aria-label'?: string;
13
+ }
14
+ export declare function SectionDots({ count, currentIndex, onSelect, 'aria-label': ariaLabel, }: SectionDotsProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,4 @@
1
+ export { BottomToolbar } from './BottomToolbar';
2
+ export type { BottomToolbarProps } from './BottomToolbar';
3
+ export { SectionDots } from './SectionDots';
4
+ export type { SectionDotsProps } from './SectionDots';
@@ -0,0 +1 @@
1
+ export * from './BottomToolbar';
@@ -19,8 +19,6 @@ export { SparklineBg } from '../primitives/dashboard/MetricCard';
19
19
  export { BarsBg } from '../primitives/dashboard/MetricCard';
20
20
  export { DonutChart } from '../primitives/dashboard/MetricCard';
21
21
  export { ObjectArrow } from '../primitives/dashboard/MetricCard';
22
- export { useSlideOutReveal } from '../primitives/dashboard/MetricCard';
23
- export type { SlideOutRevealConfig, SlideOutRevealReturn } from '../primitives/dashboard/MetricCard/useSlideOutReveal';
24
22
  export { TimeFrame, HybridDatePicker } from '../primitives/dashboard/TimeFrame';
25
23
  export type { TimeFrameProps, HybridDatePickerProps } from '../primitives/dashboard/TimeFrame';
26
24
  export { resolvePreset, resolveEvent, smartDateFormat, formatDateRange as formatDateRangeInterpretation } from '@mt-gloss/utils/dateInterpretation';
@@ -0,0 +1,29 @@
1
+ import * as React from 'react';
2
+ export type DropAnchorDensity = 'near' | 'adjacent' | 'far' | 'distant' | 'none';
3
+ export interface DropAnchorCellProps extends React.HTMLAttributes<HTMLDivElement> {
4
+ density: DropAnchorDensity;
5
+ /** D-13 / DRAG-AN-02 — occupied cells never highlight. Pass false for occupied cells. */
6
+ canAccept: boolean;
7
+ /** Brief not-allowed pulse when user attempts drop on occupied. */
8
+ blocked?: boolean;
9
+ /** Stable cell id for test selectors + future instrumentation. */
10
+ ['data-cell-id']?: string;
11
+ children?: React.ReactNode;
12
+ }
13
+ /**
14
+ * DropAnchorCell — DRAG-AN-01/02/03 (Phase 23 D-13/D-14).
15
+ *
16
+ * Presentational cell wrapper that drives drop-anchor tint via `data-density`
17
+ * + `data-can-accept` attrs. Consumers (Plan 23-06) compute density bucket per
18
+ * cell relative to the cursor; this primitive owns the visual contract only.
19
+ *
20
+ * Visual contract (see drop-anchor-cell.scss):
21
+ * - data-density ∈ {near|adjacent|far|distant} drives ::after opacity per
22
+ * D-14 array [0.80, 0.50, 0.30, 0.15].
23
+ * - data-can-accept="false" suppresses highlight unconditionally (D-13 —
24
+ * occupied cells never light up).
25
+ * - data-blocked="true" + className modifier triggers brief not-allowed pulse.
26
+ *
27
+ * Respects prefers-reduced-motion.
28
+ */
29
+ export declare function DropAnchorCell({ density, canAccept, blocked, className, children, ...rest }: DropAnchorCellProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ export { DropAnchorCell } from './DropAnchorCell';
2
+ export type { DropAnchorCellProps, DropAnchorDensity } from './DropAnchorCell';
@@ -0,0 +1,17 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * Phase 23 — EMPTY-PACK-01 — `[×]` empty-cell pack affordance per D-19 / D-20.
4
+ *
5
+ * Renders a small top-right button on an empty cell that, when clicked, requests
6
+ * right-neighbor left-shift via `onPack()`. When `enabled=false` (all cells to
7
+ * the right are also empty), the affordance is fully hidden (returns `null`).
8
+ */
9
+ export interface EmptyCellPackAffordanceProps {
10
+ /** D-19 — hide when all cells to the right are also empty. Consumer decides. */
11
+ enabled: boolean;
12
+ onPack: () => void;
13
+ ariaLabel?: string;
14
+ className?: string;
15
+ style?: React.CSSProperties;
16
+ }
17
+ export declare function EmptyCellPackAffordance({ enabled, onPack, ariaLabel, className, style, }: EmptyCellPackAffordanceProps): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,2 @@
1
+ export { EmptyCellPackAffordance } from './EmptyCellPackAffordance';
2
+ export type { EmptyCellPackAffordanceProps } from './EmptyCellPackAffordance';
@@ -17,6 +17,6 @@ import { CardShellProps } from './types';
17
17
  * ```
18
18
  */
19
19
  export declare const CardShell: {
20
- ({ contentSlot, children, colSpan, isStale, isRetrying, beta, disabled, style, accentRing, onGraph, onDetails, onCustomize, onRemove, onWhatsThis, onExpand, onShrink, onMove, onReplace, onNavigate, onRetry, onRefresh, enableQuickSettings, onUpdateTimeframe, instanceTimeframe, cardTitle, quickConfigSlot, onViewAsStack, onUnstack, isStackedGroup, onUpdateStackedTimeframes, instanceStackedTimeframes, isGraphActive, isTableActive, isGraphCard, canExpand, anchorX, extensionOverflow, cardRef: externalCardRef, }: CardShellProps): import("react/jsx-runtime").JSX.Element;
20
+ ({ contentSlot, children, colSpan, isStale, isRetrying, beta, disabled, style, accentRing, onGraph, onDetails, onCustomize, onRemove, onWhatsThis, onExpand, onShrink, onMove, onReplace, onNavigate, onRetry, onRefresh, enableQuickSettings, onUpdateTimeframe, instanceTimeframe, cardTitle, quickConfigSlot, onViewAsStack, onUnstack, isStackedGroup, onUpdateStackedTimeframes, instanceStackedTimeframes, isGraphActive, isTableActive, isGraphCard, canExpand, anchorX, extensionOverflow, cardRef: externalCardRef, hovered, }: CardShellProps): import("react/jsx-runtime").JSX.Element;
21
21
  displayName: string;
22
22
  };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Test-only duplicate of
3
+ * reptime-cloud/react-dashboard/app/components/MetricCards/gridHoverListeners.ts
4
+ *
5
+ * Phase 19.2 Plan 19.2-03 Task 3 — the production helper lives in the reptime
6
+ * consumer repo because the grid-level pointerover listener wiring is reptime-
7
+ * scoped (MetricCardGrid is not part of @mt-gloss/ui). For the NYQUIST-10
8
+ * invariant runner to mount + exercise the listener inside gloss-ui's jsdom
9
+ * test environment, we mirror the helper here.
10
+ *
11
+ * RULE: This file MUST stay byte-for-byte equivalent in behavior to the reptime
12
+ * source. When the reptime helper changes (debounce semantics, drag freeze,
13
+ * disabled filter), update this copy as well. The file exists ONLY to support
14
+ * the `hoveredCardId.invariant.test.tsx` harness — do NOT import it from any
15
+ * production gloss file.
16
+ *
17
+ * If gloss-ui ever ships a MetricCardGrid primitive of its own, promote the
18
+ * helper to a shared location and retire both copies.
19
+ */
20
+ export declare const HOVER_IDLE_DEBOUNCE_MS = 100;
21
+ export interface InstallGridHoverListenersOptions {
22
+ onHoveredCardIdChange: (nextId: string | null) => void;
23
+ draggedCardIdRef: {
24
+ current: string | null;
25
+ };
26
+ debounceMs?: number;
27
+ isDisabledCard?: (el: Element) => boolean;
28
+ }
29
+ export declare function installGridHoverListeners(root: HTMLElement, options: InstallGridHoverListenersOptions): () => void;
@@ -0,0 +1,93 @@
1
+ /**
2
+ * NYQUIST-10 — Phase 19.2 Cross-Card Hover-State Unification behavior matrix fixture.
3
+ *
4
+ * Parametrized behavior definitions that the NYQUIST-10 runner iterates over
5
+ * via `it.each(BEHAVIOR_MATRIX)`. Each row pins one contract-level invariant
6
+ * asserted by Phase 19.2 plans 19.2-01 / 19.2-02 / 19.2-03. The matrix acts as a
7
+ * high-level regression net: if a future wave regresses ANY of the 10 rows,
8
+ * the runner fails with a specific row label even if the underlying test
9
+ * file lives elsewhere.
10
+ *
11
+ * Orthogonal axes (per VALIDATION.md §Orthogonal Sampling Matrix):
12
+ * - gridSize: 3 | 6 | 9 cards (leak-rate scaling)
13
+ * - intervalMs: 8 | 16 | 32 ms (event interval vs frame boundary)
14
+ * - eventCount: 10 | 20 | 40 (min signal / debug baseline / worst case)
15
+ * - cardType: standard | stackable | mixed (StackedGroupCard hover unit)
16
+ * - dndActive: boolean (dnd-kit drag suppression, RESEARCH Pitfall 4)
17
+ * - reducedMotion: boolean (prefers-reduced-motion parity)
18
+ *
19
+ * Row-count pin: the runner asserts exactly 10 rows so that accidentally
20
+ * dropping or silently renaming a behavior fails fast.
21
+ *
22
+ * Invariant each row asserts (after 200ms settle — D-16):
23
+ * 1. ≤1 card has `[data-visible="true"]` on its ActionStrip
24
+ * 2. Every non-hovered card's `useEdgeHoverResize` state === 'idle'
25
+ * 3. `hoveredCardId === expectedFinalCardId || null`
26
+ * 4. `vi.getTimerCount() === 0`
27
+ *
28
+ * @see .planning/phases/19.2-cross-card-hover-state-unification/19.2-CONTEXT.md (D-16, D-17, D-18)
29
+ * @see .planning/phases/19.2-cross-card-hover-state-unification/19.2-VALIDATION.md §Orthogonal Sampling Matrix
30
+ * @see .planning/phases/19.2-cross-card-hover-state-unification/19.2-PATTERNS.md Analog 8 (nyquist-11-fixtures.ts)
31
+ */
32
+ export interface NyquistHarness {
33
+ /** Root grid container element (for dispatchEvent). */
34
+ gridRoot: HTMLElement;
35
+ /** Ordered list of card root elements (each has data-instance-id). */
36
+ cards: HTMLElement[];
37
+ /**
38
+ * Returns current hoveredCardId value from the grid (reads from
39
+ * data-hovered-card-id attribute on root, or a test-only prop hook).
40
+ */
41
+ getHoveredCardId: () => string | null;
42
+ /**
43
+ * Returns the useEdgeHoverResize state for a given card id — reads
44
+ * data-resize-state attribute from slot root.
45
+ */
46
+ getEdgeHoverStateFor: (cardId: string) => string;
47
+ /** Cleanup harness-mounted DOM. */
48
+ unmount: () => void;
49
+ }
50
+ export interface BehaviorParams {
51
+ gridSize: 3 | 6 | 9;
52
+ intervalMs: 8 | 16 | 32;
53
+ eventCount: 10 | 20 | 40;
54
+ cardType: 'standard' | 'stackable' | 'mixed';
55
+ dndActive: boolean;
56
+ reducedMotion: boolean;
57
+ }
58
+ export interface BehaviorDef {
59
+ /** 1-indexed for human readability in test output. */
60
+ id: number;
61
+ /** Short, greppable label. */
62
+ label: string;
63
+ /** Orthogonal axis values for this row. */
64
+ params: BehaviorParams;
65
+ /**
66
+ * The contract invariant this row pins. Either an assert-lambda that the
67
+ * runner invokes inside `it.each`, or `null` when the row is documented as
68
+ * covered by a sibling test file (runner skips but keeps the row in the
69
+ * matrix count pin). Wave 0 ships with `null` assert bodies; Task 2 wires
70
+ * the invariant body via it.each + harness mount, NOT via these callbacks.
71
+ */
72
+ assert: ((harness: NyquistHarness) => Promise<void>) | null;
73
+ /**
74
+ * When present, the runner skips the row with the returned reason string
75
+ * instead of calling `assert`. Used to document rows whose contract is
76
+ * pinned by a dedicated sibling test file (cross-reference maintained in
77
+ * 19.2-VALIDATION.md).
78
+ */
79
+ skipFor?: () => string | undefined;
80
+ }
81
+ /**
82
+ * The 10 NYQUIST-10 behaviors. Each row's `assert` is `null` in Wave 0; the
83
+ * invariant body lives in hoveredCardId.invariant.test.tsx driven by
84
+ * `it.each(BEHAVIOR_MATRIX)`. Rows remain in the matrix so the row-count pin
85
+ * (10) catches silent drops or reorder.
86
+ */
87
+ export declare const BEHAVIOR_MATRIX: BehaviorDef[];
88
+ /**
89
+ * Row-count pin — NYQUIST-10 runner asserts exactly this number of rows.
90
+ * Changing the behavior set requires updating this constant and adding a
91
+ * line in 19.2-VALIDATION.md §Orthogonal Sampling Matrix.
92
+ */
93
+ export declare const BEHAVIOR_ROW_COUNT = 10;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * gridInteractionPhysics — D-26 Phase 23 config tokens.
3
+ *
4
+ * STRICT SEPARATION from resizePhysics.ts (D-27): this module contains
5
+ * ONLY grid-interaction timings not already in resizePhysics.ts. Spring +
6
+ * hysteresis + blueprint constants continue to live in resizePhysics.ts
7
+ * and are imported from there by consumers. Forking resizePhysics.ts is
8
+ * AP-16 equivalent and forbidden.
9
+ *
10
+ * Keys sourced from 23-CONTEXT.md D-26 + 23-RESEARCH.md Pattern 13.
11
+ */
12
+ export declare const DEFAULT_GRID_INTERACTION_PHYSICS: {
13
+ readonly staggerMs: 50;
14
+ readonly reverseStaggerMs: 30;
15
+ readonly envelopeEnterMs: 180;
16
+ readonly envelopeExitMs: 140;
17
+ readonly rubberBandRatio: 0.33;
18
+ readonly dragEdgeHoldMs: 400;
19
+ readonly spilloverArcDurationMs: 600;
20
+ readonly spilloverStaggerMs: 50;
21
+ readonly anchorProximityOpacities: readonly [0.8, 0.5, 0.3, 0.15];
22
+ readonly anchorFadeStaggerMs: 30;
23
+ readonly editStandbyMs: 4000;
24
+ readonly editFadeOutMs: 600;
25
+ readonly sectionDividerFadeInMs: 120;
26
+ readonly sectionDividerFadeOutMs: 80;
27
+ readonly sectionDividerStaggerMs: 40;
28
+ };
29
+ export type GridInteractionPhysicsConfig = typeof DEFAULT_GRID_INTERACTION_PHYSICS;
@@ -8,17 +8,17 @@ export { StatusSlotChipMenu } from './StatusSlotChipMenu';
8
8
  export type { StatusSlotChipMenuProps, ChipMenuAction } from './StatusSlotChipMenu';
9
9
  export { EdgeHoverHandle } from './EdgeHoverHandle';
10
10
  export { GhostPreview } from './GhostPreview';
11
- export { useSlideOutReveal } from './useSlideOutReveal';
12
11
  export { useEdgeHoverResize } from './useEdgeHoverResize';
13
12
  export { DEFAULT_RESIZE_PHYSICS } from './resizePhysics';
14
13
  export type { ResizePhysicsConfig } from './resizePhysics';
15
14
  export { VelocityBuffer } from './velocityBuffer';
16
15
  export type { VelocitySample } from './velocityBuffer';
16
+ export { DEFAULT_GRID_INTERACTION_PHYSICS } from './gridInteractionPhysics';
17
+ export type { GridInteractionPhysicsConfig } from './gridInteractionPhysics';
17
18
  export * from './flipAndStage';
18
19
  export * from './types';
19
20
  export type { CardBackProps } from './CardBack';
20
21
  export type { StackedGroupCardProps, StackedValueEntry, SlotActionStripConfig, SlotToActionStripConfig, } from './StackedGroupCard';
21
- export type { SlideOutRevealConfig, SlideOutRevealReturn } from './useSlideOutReveal';
22
22
  export type { ResizeState, ResizeDirection, ResizeMode, ResizeCommit, UseEdgeHoverResizeArgs, UseEdgeHoverResizeReturn, } from './useEdgeHoverResize';
23
23
  export type { EdgeHoverHandleProps } from './EdgeHoverHandle';
24
24
  export type { GhostPreviewProps } from './GhostPreview';
@@ -136,6 +136,21 @@ export interface CardShellProps {
136
136
  beta?: boolean;
137
137
  disabled?: boolean;
138
138
  style?: CSSProperties;
139
+ /**
140
+ * Optional controlled hover state (Phase 19.2 D-02 / D-03 / D-08).
141
+ *
142
+ * When provided, CardShell DOES NOT track hover internally. Grid-authoritative
143
+ * consumers (e.g. `MetricCardGrid` in reptime-cloud) derive hover from a
144
+ * single container-level `pointerover`/`pointerleave` listener and thread
145
+ * `hovered={id === hoveredCardId}` to each slot (D-15).
146
+ *
147
+ * When undefined (default; backward-compat), falls back to internal
148
+ * `useState` driven by `onMouseEnter`/`onMouseLeave`, with the legacy 180ms
149
+ * leave-delay REMOVED (D-08 — CSS animation handles the fade).
150
+ *
151
+ * @default undefined (uncontrolled)
152
+ */
153
+ hovered?: boolean;
139
154
  /**
140
155
  * When true, renders a 2px accent ring around the card shell using box-shadow
141
156
  * (NOT border, to avoid reflow). Used to indicate config mode is active (D-09).
@@ -38,20 +38,35 @@ export interface UseEdgeHoverResizeArgs {
38
38
  */
39
39
  maxColSpan?: 1 | 2 | 3;
40
40
  /**
41
- * Polish Fix #7 (0.0.46 UAT) optional slot-scoped container element.
42
- * When provided, the hook installs a window-level pointermove listener
43
- * during 'dwelling' and 'handle-visible' states. If the cursor's target
44
- * is NOT within `containerRef.current`, the hook force-calls
45
- * `leaveEdgeZone()` — self-heal that fires when a consumer's own
46
- * pointerleave guard (e.g. MetricCardSlot's `closest('.edge-hover-sentinel')`)
47
- * incorrectly matches a SIBLING card's sentinel during a rapid sweep,
48
- * leaving this card stuck at 'handle-visible' while the pointer has
49
- * already moved on. Drag/settling are exempt (pointer capture owns the
50
- * gesture); the self-heal only resets pre-gesture hover state.
41
+ * @deprecated since Phase 19.2superseded by `forceIdle`; retained for
42
+ * consumer-side compat until Phase 19.2 cutover ships. The window-level
43
+ * pointermove self-heal ("Polish Fix #7") that used this ref has been
44
+ * removed (D-04 ¶2). New code should pass `forceIdle` instead.
45
+ *
46
+ * Historical note: When provided, the hook installed a window-level
47
+ * pointermove listener during 'dwelling' and 'handle-visible' states to
48
+ * detect the cursor leaving `containerRef.current`. This was fragile under
49
+ * cross-card sweeps grid-driven `forceIdle` is the correct pattern.
51
50
  */
52
51
  containerRef?: React.RefObject<Element | null> | {
53
52
  current: Element | null;
54
53
  };
54
+ /**
55
+ * Phase 19.2 D-04 — grid-driven synchronous idle reset.
56
+ *
57
+ * When `true`, the hook synchronously clears pending dwell/touch-idle
58
+ * timers and transitions state to `'idle'`. Protects the drag grip:
59
+ * no-op during `'dragging'` or `'settling'` states (pointer-captured;
60
+ * spring owns settle; see D-05 + D-11 + debug/260419-hover-state-stuck-multi-card.md).
61
+ *
62
+ * Replaces the legacy "Polish Fix #7" window-pointermove self-heal
63
+ * (now deleted — grid-driven beats window-driven; D-04 ¶2).
64
+ *
65
+ * Prop-driven only. DO NOT add a ref-based imperative path (D-05).
66
+ *
67
+ * @default undefined (treated as false — hook runs normally)
68
+ */
69
+ forceIdle?: boolean;
55
70
  }
56
71
  export interface UseEdgeHoverResizeReturn {
57
72
  state: ResizeState;
@@ -113,4 +128,4 @@ export interface UseEdgeHoverResizeReturn {
113
128
  * - Bug E handle pointerenter keeps zone alive on sentinel→handle crossover
114
129
  * - Dwell timer cleanup on unmount
115
130
  */
116
- export declare function useEdgeHoverResize({ currentColSpan, stackable, onResize, onCancel, step, gap, tuning, dwellMs, enterMs, exitMs, maxColSpan, containerRef, }: UseEdgeHoverResizeArgs): UseEdgeHoverResizeReturn;
131
+ export declare function useEdgeHoverResize({ currentColSpan, stackable, onResize, onCancel, step, gap, tuning, dwellMs, enterMs, exitMs, maxColSpan, containerRef, forceIdle, }: UseEdgeHoverResizeArgs): UseEdgeHoverResizeReturn;
@@ -0,0 +1,41 @@
1
+ import * as React from 'react';
2
+ export type ResizeEnvelopeState = 'hidden' | 'entering' | 'entered' | 'exiting';
3
+ export interface ResizeEnvelopeProps {
4
+ state: ResizeEnvelopeState;
5
+ originX: number;
6
+ originY: number;
7
+ leftEdgeX: number;
8
+ rightEdgeX: number;
9
+ minBoundaryX: number;
10
+ /** Intermediate permeable snap positions between min and max; rendered as dotted lines. */
11
+ snapBoundariesX: number[];
12
+ topY: number;
13
+ bottomY: number;
14
+ /** Override D-07 enter duration (default: DEFAULT_GRID_INTERACTION_PHYSICS.envelopeEnterMs = 180ms). */
15
+ enterMs?: number;
16
+ /** Override D-07 exit duration (default: DEFAULT_GRID_INTERACTION_PHYSICS.envelopeExitMs = 140ms). */
17
+ exitMs?: number;
18
+ className?: string;
19
+ style?: React.CSSProperties;
20
+ }
21
+ /**
22
+ * Phase 23 — RESIZE-ENV-01 — D-05/D-06/D-07
23
+ *
24
+ * Pure presentational overlay drawn on pointerdown of a resize handle. Shows
25
+ * the full resize option space:
26
+ * - Solid LEFT edge (card's fixed anchor)
27
+ * - Solid RIGHT edge (max colSpan extent)
28
+ * - Solid MIN-BOUNDARY interior line (the wall — impermeable)
29
+ * - Dotted INTERMEDIATE snap lines (permeable snap points)
30
+ *
31
+ * Asymmetric D-07 timings:
32
+ * - Enter 180ms: 120ms solid edges fade-in + 60ms dotted fade-in (offset by 120ms)
33
+ * - Exit 140ms: 40ms dotted fade-out + 100ms solid collapse (offset by 40ms)
34
+ *
35
+ * Defaults pull from `DEFAULT_GRID_INTERACTION_PHYSICS` (CONFIG-01); never
36
+ * hardcode duration strings in consumers. Respects `prefers-reduced-motion`.
37
+ *
38
+ * Aria-hidden — purely decorative overlay; the underlying resize gesture
39
+ * carries the semantic meaning.
40
+ */
41
+ export declare function ResizeEnvelope({ state, originX, originY, leftEdgeX, rightEdgeX, minBoundaryX, snapBoundariesX, topY, bottomY, enterMs, exitMs, className, style, }: ResizeEnvelopeProps): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,2 @@
1
+ export { ResizeEnvelope } from './ResizeEnvelope';
2
+ export type { ResizeEnvelopeProps, ResizeEnvelopeState } from './ResizeEnvelope';
@@ -0,0 +1,29 @@
1
+ import * as React from 'react';
2
+ export type SectionDividerState = 'hidden' | 'revealed' | 'emphasized';
3
+ export interface SectionDividerProps extends React.HTMLAttributes<HTMLDivElement> {
4
+ state: SectionDividerState;
5
+ /** Left-to-right cascade position (0, 1, 2, ...) multiplied by staggerMs for animation-delay. */
6
+ staggerIndex?: number;
7
+ fadeInMs?: number;
8
+ fadeOutMs?: number;
9
+ staggerMs?: number;
10
+ }
11
+ /**
12
+ * SectionDivider — SECTION-DIV-01 (Phase 23 D-22).
13
+ *
14
+ * Dashed vertical divider revealed only during grid manipulation. Three-state
15
+ * machine (hidden|revealed|emphasized) drives opacity + color via CSS class
16
+ * modifiers. Each instance accepts a `staggerIndex` so consumers (Plan 23-06)
17
+ * can render N dividers with a left-to-right cascade — index threads through
18
+ * a CSS custom property as `staggerIndex × staggerMs` ms.
19
+ *
20
+ * Visual contract (see section-divider.scss):
21
+ * - state='hidden': opacity 0, no chrome
22
+ * - state='revealed': opacity 0.4, neutral border color, fade-in over fadeInMs
23
+ * - state='emphasized': opacity 0.85, accent color (current section), fade-in
24
+ * over fadeInMs
25
+ *
26
+ * Defaults bind to DEFAULT_GRID_INTERACTION_PHYSICS (CONFIG-01).
27
+ * Respects prefers-reduced-motion.
28
+ */
29
+ export declare function SectionDivider({ state, staggerIndex, fadeInMs, fadeOutMs, staggerMs, className, style, ...rest }: SectionDividerProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ export { SectionDivider } from './SectionDivider';
2
+ export type { SectionDividerProps, SectionDividerState } from './SectionDivider';
@@ -0,0 +1,30 @@
1
+ import * as React from 'react';
2
+ export interface ArcSegment {
3
+ id: string;
4
+ fromX: number;
5
+ fromY: number;
6
+ toX: number;
7
+ toY: number;
8
+ }
9
+ export interface SpilloverArcProps {
10
+ segments: ArcSegment[];
11
+ /** D-18 — full arc lifetime (default spilloverArcDurationMs = 600). */
12
+ durationMs?: number;
13
+ /** D-18 — per-segment stagger (default spilloverStaggerMs = 50). */
14
+ staggerMs?: number;
15
+ className?: string;
16
+ style?: React.CSSProperties;
17
+ }
18
+ /**
19
+ * SpilloverArc — DRAG-SPILL-01 (Phase 23 D-17/D-18).
20
+ *
21
+ * Single `<svg>` overlay rendering N quadratic Bezier `<path>` arcs from a
22
+ * drop origin to each spilled card's final position. Each path fades over
23
+ * `durationMs` (default 600) with `staggerMs` (default 50) per-arc offset.
24
+ *
25
+ * Single-SVG strategy (vs. one SVG per segment) chosen for paint perf and to
26
+ * eliminate cross-arc clipping concerns. See 23-RESEARCH.md §Pattern 9.
27
+ *
28
+ * Respects prefers-reduced-motion.
29
+ */
30
+ export declare function SpilloverArc({ segments, durationMs, staggerMs, className, style, }: SpilloverArcProps): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,2 @@
1
+ export { SpilloverArc } from './SpilloverArc';
2
+ export type { SpilloverArcProps, ArcSegment } from './SpilloverArc';
@@ -12,3 +12,8 @@ export * from './MetricCardGrid';
12
12
  export * from './TabbedDataView';
13
13
  export * from './MetricGroupContainer';
14
14
  export * from './DevTuningPanel';
15
+ export * from './ResizeEnvelope';
16
+ export * from './DropAnchorCell';
17
+ export * from './SpilloverArc';
18
+ export * from './SectionDivider';
19
+ export * from './EmptyCellPackAffordance';
@@ -1,7 +1,5 @@
1
1
  export { ActionStrip } from './ActionStrip';
2
2
  export type { PrimaryAction, OverflowAction, ActionStripProps, ActionStripContext, ActionStripMenuDirection, } from './types';
3
3
  export { subscribe, getActive, setActive, resetForTests, } from './overflowMenuRegistry';
4
- export { useSlideOutReveal } from './useSlideOutReveal';
5
- export type { SlideOutRevealConfig, SlideOutRevealReturn, SlideOutRevealStyle, } from './useSlideOutReveal';
6
4
  export { DEFAULT_OVERFLOW_IDS, DEFAULT_FOOTER_IDS, buildDefaultOverflow, } from './defaultActions';
7
5
  export type { DefaultHandlers } from './defaultActions';
@@ -90,7 +90,11 @@ export interface ActionStripProps {
90
90
  primary: PrimaryAction[];
91
91
  /** Overflow entries (Settings, Remove, Replace, Refresh, What's this?). */
92
92
  overflow: OverflowAction[];
93
- /** From `useSlideOutReveal` — true when the consumer card is hovered/focused. */
93
+ /**
94
+ * True when the consumer card is hovered/focused. Drives the CSS-owned
95
+ * slide-reveal animation via the root motion.div's `data-visible` attribute
96
+ * (Phase 19.2 D-07 / D-07a — see ActionStrip.scss @keyframes).
97
+ */
94
98
  visible: boolean;
95
99
  /** Sticky-on-click expansion state. */
96
100
  expanded: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mt-gloss/ui",
3
- "version": "0.0.47",
3
+ "version": "0.0.49",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "restricted"