@activecollab/components 2.0.363 → 2.0.364
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.
- package/dist/cjs/presentation/stackedCard/content/ImageCard.js +60 -0
- package/dist/cjs/presentation/stackedCard/content/ImageCard.js.map +1 -0
- package/dist/cjs/presentation/stackedCard/content/LinkCard.js +348 -0
- package/dist/cjs/presentation/stackedCard/content/LinkCard.js.map +1 -0
- package/dist/cjs/presentation/stackedCard/content/NoteCard.js +92 -0
- package/dist/cjs/presentation/stackedCard/content/NoteCard.js.map +1 -0
- package/dist/cjs/presentation/stackedCard/content/SwatchCard.js +74 -0
- package/dist/cjs/presentation/stackedCard/content/SwatchCard.js.map +1 -0
- package/dist/cjs/presentation/stackedCard/content/TaskCard.js +231 -0
- package/dist/cjs/presentation/stackedCard/content/TaskCard.js.map +1 -0
- package/dist/cjs/presentation/stackedCard/content/index.js +83 -0
- package/dist/cjs/presentation/stackedCard/content/index.js.map +1 -0
- package/dist/cjs/presentation/stackedCard/content/shared.js +144 -0
- package/dist/cjs/presentation/stackedCard/content/shared.js.map +1 -0
- package/dist/cjs/presentation/stackedCard/content/unfurl.js +172 -0
- package/dist/cjs/presentation/stackedCard/content/unfurl.js.map +1 -0
- package/dist/cjs/presentation/stackedCard/primitives.js +254 -0
- package/dist/cjs/presentation/stackedCard/primitives.js.map +1 -0
- package/dist/cjs/presentation/stackedCard/resizePolicy.js +183 -0
- package/dist/cjs/presentation/stackedCard/resizePolicy.js.map +1 -0
- package/dist/cjs/presentation/stackedCard/shell.js +165 -0
- package/dist/cjs/presentation/stackedCard/shell.js.map +1 -0
- package/dist/cjs/presentation/stackedCard/storyScaffold.js +72 -0
- package/dist/cjs/presentation/stackedCard/storyScaffold.js.map +1 -0
- package/dist/cjs/presentation/stackedCard/useInlineEdit.js +208 -0
- package/dist/cjs/presentation/stackedCard/useInlineEdit.js.map +1 -0
- package/dist/esm/presentation/stackedCard/content/ImageCard.d.ts +15 -0
- package/dist/esm/presentation/stackedCard/content/ImageCard.d.ts.map +1 -0
- package/dist/esm/presentation/stackedCard/content/ImageCard.js +50 -0
- package/dist/esm/presentation/stackedCard/content/ImageCard.js.map +1 -0
- package/dist/esm/presentation/stackedCard/content/LinkCard.d.ts +28 -0
- package/dist/esm/presentation/stackedCard/content/LinkCard.d.ts.map +1 -0
- package/dist/esm/presentation/stackedCard/content/LinkCard.js +336 -0
- package/dist/esm/presentation/stackedCard/content/LinkCard.js.map +1 -0
- package/dist/esm/presentation/stackedCard/content/NoteCard.d.ts +10 -0
- package/dist/esm/presentation/stackedCard/content/NoteCard.d.ts.map +1 -0
- package/dist/esm/presentation/stackedCard/content/NoteCard.js +82 -0
- package/dist/esm/presentation/stackedCard/content/NoteCard.js.map +1 -0
- package/dist/esm/presentation/stackedCard/content/SwatchCard.d.ts +14 -0
- package/dist/esm/presentation/stackedCard/content/SwatchCard.d.ts.map +1 -0
- package/dist/esm/presentation/stackedCard/content/SwatchCard.js +64 -0
- package/dist/esm/presentation/stackedCard/content/SwatchCard.js.map +1 -0
- package/dist/esm/presentation/stackedCard/content/TaskCard.d.ts +29 -0
- package/dist/esm/presentation/stackedCard/content/TaskCard.d.ts.map +1 -0
- package/dist/esm/presentation/stackedCard/content/TaskCard.js +218 -0
- package/dist/esm/presentation/stackedCard/content/TaskCard.js.map +1 -0
- package/dist/esm/presentation/stackedCard/content/index.d.ts +8 -0
- package/dist/esm/presentation/stackedCard/content/index.d.ts.map +1 -0
- package/dist/esm/presentation/stackedCard/content/index.js +8 -0
- package/dist/esm/presentation/stackedCard/content/index.js.map +1 -0
- package/dist/esm/presentation/stackedCard/content/shared.d.ts +46 -0
- package/dist/esm/presentation/stackedCard/content/shared.d.ts.map +1 -0
- package/dist/esm/presentation/stackedCard/content/shared.js +134 -0
- package/dist/esm/presentation/stackedCard/content/shared.js.map +1 -0
- package/dist/esm/presentation/stackedCard/content/unfurl.d.ts +89 -0
- package/dist/esm/presentation/stackedCard/content/unfurl.d.ts.map +1 -0
- package/dist/esm/presentation/stackedCard/content/unfurl.js +147 -0
- package/dist/esm/presentation/stackedCard/content/unfurl.js.map +1 -0
- package/dist/esm/presentation/stackedCard/primitives.d.ts +84 -0
- package/dist/esm/presentation/stackedCard/primitives.d.ts.map +1 -0
- package/dist/esm/presentation/stackedCard/primitives.js +241 -0
- package/dist/esm/presentation/stackedCard/primitives.js.map +1 -0
- package/dist/esm/presentation/stackedCard/resizePolicy.d.ts +97 -0
- package/dist/esm/presentation/stackedCard/resizePolicy.d.ts.map +1 -0
- package/dist/esm/presentation/stackedCard/resizePolicy.js +173 -0
- package/dist/esm/presentation/stackedCard/resizePolicy.js.map +1 -0
- package/dist/esm/presentation/stackedCard/shell.d.ts +46 -0
- package/dist/esm/presentation/stackedCard/shell.d.ts.map +1 -0
- package/dist/esm/presentation/stackedCard/shell.js +156 -0
- package/dist/esm/presentation/stackedCard/shell.js.map +1 -0
- package/dist/esm/presentation/stackedCard/storyScaffold.d.ts +28 -0
- package/dist/esm/presentation/stackedCard/storyScaffold.d.ts.map +1 -0
- package/dist/esm/presentation/stackedCard/storyScaffold.js +66 -0
- package/dist/esm/presentation/stackedCard/storyScaffold.js.map +1 -0
- package/dist/esm/presentation/stackedCard/useInlineEdit.d.ts +68 -0
- package/dist/esm/presentation/stackedCard/useInlineEdit.d.ts.map +1 -0
- package/dist/esm/presentation/stackedCard/useInlineEdit.js +192 -0
- package/dist/esm/presentation/stackedCard/useInlineEdit.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StackedCard resize policy — pure math (story-local, presentation-only).
|
|
3
|
+
*
|
|
4
|
+
* The card only reports deltas; the HOST applies a resize policy (note 52097
|
|
5
|
+
* §7). This module is that policy, packaged as pure functions so the SAME code
|
|
6
|
+
* path serves both the pointer drag and the keyboard resize (task 5/8). Nothing
|
|
7
|
+
* here touches the DOM, React, or the content — it takes a start size, a delta,
|
|
8
|
+
* and a policy, and returns a clamped size. The story wires events to it; the
|
|
9
|
+
* card's intrinsic content minimum is measured story-side and passed in as
|
|
10
|
+
* `contentMin`, so this module knows nothing about heroes or footers.
|
|
11
|
+
*
|
|
12
|
+
* The policy has four parts, all preserved from the concept:
|
|
13
|
+
* - bounds — optional min/max per axis; unset means unbounded.
|
|
14
|
+
* - proportional — lock the aspect ratio captured at the start of the gesture;
|
|
15
|
+
* the scale is clamped by the BINDING axis so the ratio never
|
|
16
|
+
* distorts at a bound.
|
|
17
|
+
* - step — optional grid snap; proportion wins over the grid.
|
|
18
|
+
* - content min — the effective min is max(policyMin, contentMin) per axis,
|
|
19
|
+
* so the card can never be crushed below what its content needs.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/** The card's intrinsic minimum, measured from its real content. */
|
|
23
|
+
|
|
24
|
+
/** The size captured at the start of a gesture (pointer down or a key press). */
|
|
25
|
+
|
|
26
|
+
/** Keyboard resize nudges by the policy step, or this when no step is set. */
|
|
27
|
+
export const DEFAULT_KEYBOARD_STEP = 8;
|
|
28
|
+
|
|
29
|
+
/** Shift + arrow resizes by a larger increment (the familiar coarse nudge). */
|
|
30
|
+
export const SHIFT_STEP_MULTIPLIER = 4;
|
|
31
|
+
|
|
32
|
+
/** Keys the separator handles; everything else falls through to the browser. */
|
|
33
|
+
export const RESIZE_KEYS = ["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "Home", "End"];
|
|
34
|
+
export const isResizeKey = key => RESIZE_KEYS.includes(key);
|
|
35
|
+
export const clamp = (v, lo, hi) => Math.min(hi != null ? hi : Number.POSITIVE_INFINITY, Math.max(lo, v));
|
|
36
|
+
export const snap = (v, step) => step && step > 0 ? Math.round(v / step) * step : v;
|
|
37
|
+
export const makeStart = (size, contentMin) => ({
|
|
38
|
+
w: size.w,
|
|
39
|
+
h: size.h,
|
|
40
|
+
contentMin
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The effective bounds a size is clamped to: the policy min floored by the
|
|
45
|
+
* content min, and the policy max (unbounded when unset). Independent of any
|
|
46
|
+
* live gesture, so the story can also use it for the aria value and Home/End.
|
|
47
|
+
*/
|
|
48
|
+
export const effectiveBounds = (policy, contentMin) => {
|
|
49
|
+
var _policy$minW, _policy$minH, _policy$maxW, _policy$maxH;
|
|
50
|
+
return {
|
|
51
|
+
wMin: Math.max((_policy$minW = policy.minW) != null ? _policy$minW : 0, contentMin.w),
|
|
52
|
+
hMin: Math.max((_policy$minH = policy.minH) != null ? _policy$minH : 0, contentMin.h),
|
|
53
|
+
wMax: (_policy$maxW = policy.maxW) != null ? _policy$maxW : Number.POSITIVE_INFINITY,
|
|
54
|
+
hMax: (_policy$maxH = policy.maxH) != null ? _policy$maxH : Number.POSITIVE_INFINITY
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Apply a delta to the start size under the policy — the single path for both
|
|
60
|
+
* inputs. `constrain` is the transient Shift-to-constrain lock: a free-form
|
|
61
|
+
* policy behaves proportionally for that one gesture; a proportional policy is
|
|
62
|
+
* already locked and ignores it.
|
|
63
|
+
*/
|
|
64
|
+
export const applyResize = function (start, delta, policy, opts) {
|
|
65
|
+
if (opts === void 0) {
|
|
66
|
+
opts = {};
|
|
67
|
+
}
|
|
68
|
+
const _effectiveBounds = effectiveBounds(policy, start.contentMin),
|
|
69
|
+
wMin = _effectiveBounds.wMin,
|
|
70
|
+
hMin = _effectiveBounds.hMin,
|
|
71
|
+
wMax = _effectiveBounds.wMax,
|
|
72
|
+
hMax = _effectiveBounds.hMax;
|
|
73
|
+
const proportional = policy.proportional || opts.constrain === true;
|
|
74
|
+
let w;
|
|
75
|
+
let h;
|
|
76
|
+
if (proportional) {
|
|
77
|
+
// one scale drives both axes; the corner's dominant direction wins, so a
|
|
78
|
+
// vertical drag is as effective as a horizontal one
|
|
79
|
+
const sW = (start.w + delta.dx) / start.w;
|
|
80
|
+
const sH = (start.h + delta.dy) / start.h;
|
|
81
|
+
let scale = Math.abs(sW - 1) >= Math.abs(sH - 1) ? sW : sH;
|
|
82
|
+
|
|
83
|
+
// clamp the SCALE so both axes stay in bounds (binding constraint): the
|
|
84
|
+
// ratio can never break at a bound — whichever edge is limiting stops both
|
|
85
|
+
const scaleMin = Math.max(wMin / start.w, hMin / start.h);
|
|
86
|
+
const scaleMax = Math.min(wMax / start.w, hMax / start.h);
|
|
87
|
+
scale = clamp(scale, scaleMin, Math.max(scaleMin, scaleMax));
|
|
88
|
+
|
|
89
|
+
// step: proportion wins. Snap via the scale (driven off the width edge) and
|
|
90
|
+
// re-clamp, so ratio and bounds always hold; the grid yields when honoring
|
|
91
|
+
// it would cost the ratio
|
|
92
|
+
if (policy.step) {
|
|
93
|
+
const snappedScale = snap(start.w * scale, policy.step) / start.w;
|
|
94
|
+
scale = clamp(snappedScale, scaleMin, Math.max(scaleMin, scaleMax));
|
|
95
|
+
}
|
|
96
|
+
w = start.w * scale;
|
|
97
|
+
h = start.h * scale;
|
|
98
|
+
} else {
|
|
99
|
+
w = clamp(snap(start.w + delta.dx, policy.step), wMin, wMax);
|
|
100
|
+
h = clamp(snap(start.h + delta.dy, policy.step), hMin, hMax);
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
w: Math.round(w),
|
|
104
|
+
h: Math.round(h)
|
|
105
|
+
};
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Translate a resize key into the next size, reusing `applyResize` so the
|
|
110
|
+
* keyboard clamps exactly like the pointer. Arrows nudge by the step (Shift ×4);
|
|
111
|
+
* Home/End jump to the min/max of the allowed range. Returns null for any key
|
|
112
|
+
* the handle does not own.
|
|
113
|
+
*/
|
|
114
|
+
export const keyboardResize = function (key, size, policy, contentMin, opts) {
|
|
115
|
+
if (opts === void 0) {
|
|
116
|
+
opts = {};
|
|
117
|
+
}
|
|
118
|
+
const base = policy.step && policy.step > 0 ? policy.step : DEFAULT_KEYBOARD_STEP;
|
|
119
|
+
const step = base * (opts.shiftKey ? SHIFT_STEP_MULTIPLIER : 1);
|
|
120
|
+
const start = makeStart(size, contentMin);
|
|
121
|
+
const b = effectiveBounds(policy, contentMin);
|
|
122
|
+
switch (key) {
|
|
123
|
+
case "ArrowRight":
|
|
124
|
+
return applyResize(start, {
|
|
125
|
+
dx: step,
|
|
126
|
+
dy: 0
|
|
127
|
+
}, policy);
|
|
128
|
+
case "ArrowLeft":
|
|
129
|
+
return applyResize(start, {
|
|
130
|
+
dx: -step,
|
|
131
|
+
dy: 0
|
|
132
|
+
}, policy);
|
|
133
|
+
case "ArrowDown":
|
|
134
|
+
return applyResize(start, {
|
|
135
|
+
dx: 0,
|
|
136
|
+
dy: step
|
|
137
|
+
}, policy);
|
|
138
|
+
case "ArrowUp":
|
|
139
|
+
return applyResize(start, {
|
|
140
|
+
dx: 0,
|
|
141
|
+
dy: -step
|
|
142
|
+
}, policy);
|
|
143
|
+
case "Home":
|
|
144
|
+
// jump to the min corner (a huge negative delta clamps to the floor)
|
|
145
|
+
return applyResize(start, {
|
|
146
|
+
dx: b.wMin - size.w,
|
|
147
|
+
dy: b.hMin - size.h
|
|
148
|
+
}, policy);
|
|
149
|
+
case "End":
|
|
150
|
+
// jump to the max corner; an unbounded axis simply doesn't move
|
|
151
|
+
return applyResize(start, {
|
|
152
|
+
dx: Number.isFinite(b.wMax) ? b.wMax - size.w : 0,
|
|
153
|
+
dy: Number.isFinite(b.hMax) ? b.hMax - size.h : 0
|
|
154
|
+
}, policy);
|
|
155
|
+
default:
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* The handle's `aria-valuenow`: the current size as a percent (0–100) of its
|
|
162
|
+
* allowed range. The corner resizes both axes, but the value must be a single
|
|
163
|
+
* number, so it reports the WIDTH axis — the one axis both the fixed-box and the
|
|
164
|
+
* width-only cards share. Returns 0 when the range isn't finite (no max bound).
|
|
165
|
+
*/
|
|
166
|
+
export const measurePercent = (size, policy, contentMin) => {
|
|
167
|
+
const _effectiveBounds2 = effectiveBounds(policy, contentMin),
|
|
168
|
+
wMin = _effectiveBounds2.wMin,
|
|
169
|
+
wMax = _effectiveBounds2.wMax;
|
|
170
|
+
if (!Number.isFinite(wMax) || wMax <= wMin) return 0;
|
|
171
|
+
return Math.round(clamp((size.w - wMin) / (wMax - wMin) * 100, 0, 100));
|
|
172
|
+
};
|
|
173
|
+
//# sourceMappingURL=resizePolicy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resizePolicy.js","names":["DEFAULT_KEYBOARD_STEP","SHIFT_STEP_MULTIPLIER","RESIZE_KEYS","isResizeKey","key","includes","clamp","v","lo","hi","Math","min","Number","POSITIVE_INFINITY","max","snap","step","round","makeStart","size","contentMin","w","h","effectiveBounds","policy","_policy$minW","_policy$minH","_policy$maxW","_policy$maxH","wMin","minW","hMin","minH","wMax","maxW","hMax","maxH","applyResize","start","delta","opts","_effectiveBounds","proportional","constrain","sW","dx","sH","dy","scale","abs","scaleMin","scaleMax","snappedScale","keyboardResize","base","shiftKey","b","isFinite","measurePercent","_effectiveBounds2"],"sources":["../../../../src/presentation/stackedCard/resizePolicy.ts"],"sourcesContent":["/**\n * StackedCard resize policy — pure math (story-local, presentation-only).\n *\n * The card only reports deltas; the HOST applies a resize policy (note 52097\n * §7). This module is that policy, packaged as pure functions so the SAME code\n * path serves both the pointer drag and the keyboard resize (task 5/8). Nothing\n * here touches the DOM, React, or the content — it takes a start size, a delta,\n * and a policy, and returns a clamped size. The story wires events to it; the\n * card's intrinsic content minimum is measured story-side and passed in as\n * `contentMin`, so this module knows nothing about heroes or footers.\n *\n * The policy has four parts, all preserved from the concept:\n * - bounds — optional min/max per axis; unset means unbounded.\n * - proportional — lock the aspect ratio captured at the start of the gesture;\n * the scale is clamped by the BINDING axis so the ratio never\n * distorts at a bound.\n * - step — optional grid snap; proportion wins over the grid.\n * - content min — the effective min is max(policyMin, contentMin) per axis,\n * so the card can never be crushed below what its content needs.\n */\n\nexport interface Size {\n w: number;\n h: number;\n}\n\n/** The card's intrinsic minimum, measured from its real content. */\nexport interface ContentMin {\n w: number;\n h: number;\n}\n\nexport interface Policy {\n minW?: number;\n maxW?: number;\n minH?: number;\n maxH?: number;\n /** Lock the aspect ratio for the whole gesture. */\n proportional: boolean;\n /** Grid snap increment in px; omitted / 0 means continuous. */\n step?: number;\n}\n\n/** The size captured at the start of a gesture (pointer down or a key press). */\nexport interface ResizeStart {\n w: number;\n h: number;\n contentMin: ContentMin;\n}\n\nexport interface ResizeDelta {\n dx: number;\n dy: number;\n}\n\nexport interface EffectiveBounds {\n wMin: number;\n wMax: number;\n hMin: number;\n hMax: number;\n}\n\n/** Keyboard resize nudges by the policy step, or this when no step is set. */\nexport const DEFAULT_KEYBOARD_STEP = 8;\n\n/** Shift + arrow resizes by a larger increment (the familiar coarse nudge). */\nexport const SHIFT_STEP_MULTIPLIER = 4;\n\n/** Keys the separator handles; everything else falls through to the browser. */\nexport const RESIZE_KEYS: ReadonlyArray<string> = [\n \"ArrowLeft\",\n \"ArrowRight\",\n \"ArrowUp\",\n \"ArrowDown\",\n \"Home\",\n \"End\",\n];\n\nexport const isResizeKey = (key: string): boolean => RESIZE_KEYS.includes(key);\n\nexport const clamp = (v: number, lo: number, hi?: number): number =>\n Math.min(hi ?? Number.POSITIVE_INFINITY, Math.max(lo, v));\n\nexport const snap = (v: number, step?: number): number =>\n step && step > 0 ? Math.round(v / step) * step : v;\n\nexport const makeStart = (size: Size, contentMin: ContentMin): ResizeStart => ({\n w: size.w,\n h: size.h,\n contentMin,\n});\n\n/**\n * The effective bounds a size is clamped to: the policy min floored by the\n * content min, and the policy max (unbounded when unset). Independent of any\n * live gesture, so the story can also use it for the aria value and Home/End.\n */\nexport const effectiveBounds = (\n policy: Policy,\n contentMin: ContentMin\n): EffectiveBounds => ({\n wMin: Math.max(policy.minW ?? 0, contentMin.w),\n hMin: Math.max(policy.minH ?? 0, contentMin.h),\n wMax: policy.maxW ?? Number.POSITIVE_INFINITY,\n hMax: policy.maxH ?? Number.POSITIVE_INFINITY,\n});\n\n/**\n * Apply a delta to the start size under the policy — the single path for both\n * inputs. `constrain` is the transient Shift-to-constrain lock: a free-form\n * policy behaves proportionally for that one gesture; a proportional policy is\n * already locked and ignores it.\n */\nexport const applyResize = (\n start: ResizeStart,\n delta: ResizeDelta,\n policy: Policy,\n opts: { constrain?: boolean } = {}\n): Size => {\n const { wMin, hMin, wMax, hMax } = effectiveBounds(policy, start.contentMin);\n const proportional = policy.proportional || opts.constrain === true;\n\n let w: number;\n let h: number;\n\n if (proportional) {\n // one scale drives both axes; the corner's dominant direction wins, so a\n // vertical drag is as effective as a horizontal one\n const sW = (start.w + delta.dx) / start.w;\n const sH = (start.h + delta.dy) / start.h;\n let scale = Math.abs(sW - 1) >= Math.abs(sH - 1) ? sW : sH;\n\n // clamp the SCALE so both axes stay in bounds (binding constraint): the\n // ratio can never break at a bound — whichever edge is limiting stops both\n const scaleMin = Math.max(wMin / start.w, hMin / start.h);\n const scaleMax = Math.min(wMax / start.w, hMax / start.h);\n scale = clamp(scale, scaleMin, Math.max(scaleMin, scaleMax));\n\n // step: proportion wins. Snap via the scale (driven off the width edge) and\n // re-clamp, so ratio and bounds always hold; the grid yields when honoring\n // it would cost the ratio\n if (policy.step) {\n const snappedScale = snap(start.w * scale, policy.step) / start.w;\n scale = clamp(snappedScale, scaleMin, Math.max(scaleMin, scaleMax));\n }\n\n w = start.w * scale;\n h = start.h * scale;\n } else {\n w = clamp(snap(start.w + delta.dx, policy.step), wMin, wMax);\n h = clamp(snap(start.h + delta.dy, policy.step), hMin, hMax);\n }\n\n return { w: Math.round(w), h: Math.round(h) };\n};\n\n/**\n * Translate a resize key into the next size, reusing `applyResize` so the\n * keyboard clamps exactly like the pointer. Arrows nudge by the step (Shift ×4);\n * Home/End jump to the min/max of the allowed range. Returns null for any key\n * the handle does not own.\n */\nexport const keyboardResize = (\n key: string,\n size: Size,\n policy: Policy,\n contentMin: ContentMin,\n opts: { shiftKey?: boolean } = {}\n): Size | null => {\n const base =\n policy.step && policy.step > 0 ? policy.step : DEFAULT_KEYBOARD_STEP;\n const step = base * (opts.shiftKey ? SHIFT_STEP_MULTIPLIER : 1);\n const start = makeStart(size, contentMin);\n const b = effectiveBounds(policy, contentMin);\n\n switch (key) {\n case \"ArrowRight\":\n return applyResize(start, { dx: step, dy: 0 }, policy);\n case \"ArrowLeft\":\n return applyResize(start, { dx: -step, dy: 0 }, policy);\n case \"ArrowDown\":\n return applyResize(start, { dx: 0, dy: step }, policy);\n case \"ArrowUp\":\n return applyResize(start, { dx: 0, dy: -step }, policy);\n case \"Home\":\n // jump to the min corner (a huge negative delta clamps to the floor)\n return applyResize(\n start,\n { dx: b.wMin - size.w, dy: b.hMin - size.h },\n policy\n );\n case \"End\":\n // jump to the max corner; an unbounded axis simply doesn't move\n return applyResize(\n start,\n {\n dx: Number.isFinite(b.wMax) ? b.wMax - size.w : 0,\n dy: Number.isFinite(b.hMax) ? b.hMax - size.h : 0,\n },\n policy\n );\n default:\n return null;\n }\n};\n\n/**\n * The handle's `aria-valuenow`: the current size as a percent (0–100) of its\n * allowed range. The corner resizes both axes, but the value must be a single\n * number, so it reports the WIDTH axis — the one axis both the fixed-box and the\n * width-only cards share. Returns 0 when the range isn't finite (no max bound).\n */\nexport const measurePercent = (\n size: Size,\n policy: Policy,\n contentMin: ContentMin\n): number => {\n const { wMin, wMax } = effectiveBounds(policy, contentMin);\n if (!Number.isFinite(wMax) || wMax <= wMin) return 0;\n return Math.round(clamp(((size.w - wMin) / (wMax - wMin)) * 100, 0, 100));\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React, { ReactElement, ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* StackedCard shell (story-local, presentation-only).
|
|
4
|
+
*
|
|
5
|
+
* The hollow frame every typed content component composes. Extracted from the
|
|
6
|
+
* concept spec story (task 2/8) so the StackedCard concept stories share one
|
|
7
|
+
* shell instead of re-declaring it. The rule the whole subsystem hangs on:
|
|
8
|
+
*
|
|
9
|
+
* THE SHELL STAYS HOLLOW.
|
|
10
|
+
*
|
|
11
|
+
* There is no `contentType` enum here, no per-type prop soup, no `if task …`.
|
|
12
|
+
* The shell owns only VISUAL STATES (selected, disabled, pending, priority,
|
|
13
|
+
* drag source/preview, entered) and the intent surface (`onResizeDelta`, the
|
|
14
|
+
* DOM props it forwards). Content — a task, a link, an image, a swatch, a note
|
|
15
|
+
* — is passed in as `children` and composes the layout primitives. A new
|
|
16
|
+
* content type later is a new wrapper, with ZERO changes in this file.
|
|
17
|
+
*
|
|
18
|
+
* Not exported from the design-system barrel; it lives here so the concept
|
|
19
|
+
* stories share one source of truth.
|
|
20
|
+
*/
|
|
21
|
+
export declare const CARD_WIDTH = 260;
|
|
22
|
+
export declare const CARD_RADIUS = 8;
|
|
23
|
+
export declare const COVER_RATIO = "260 / 132";
|
|
24
|
+
export declare const COVER_RATIO_HERO = "320 / 190";
|
|
25
|
+
export declare const COVER_RATIO_IMAGE = "260 / 168";
|
|
26
|
+
export declare const COVER_RATIO_SWATCH = "260 / 104";
|
|
27
|
+
export declare const ResizeHandleGlyph: () => ReactElement;
|
|
28
|
+
export interface StackedCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onResize"> {
|
|
29
|
+
selected?: boolean;
|
|
30
|
+
disabled?: boolean;
|
|
31
|
+
/** Optimistic in-flight state — dimmed, non-interactive, not draggable. */
|
|
32
|
+
pending?: boolean;
|
|
33
|
+
/** Full-size outline placeholder left in the source position while dragging. */
|
|
34
|
+
isDragSource?: boolean;
|
|
35
|
+
/** The 1:1 elevated copy the host floats in the drag layer. */
|
|
36
|
+
isDragPreview?: boolean;
|
|
37
|
+
/** Focus model: the card has been entered and focus is on an inner control. */
|
|
38
|
+
entered?: boolean;
|
|
39
|
+
forceHover?: boolean;
|
|
40
|
+
resizable?: boolean;
|
|
41
|
+
priorityColor?: string;
|
|
42
|
+
onResizeDelta?: (dx: number, dy: number) => void;
|
|
43
|
+
children: ReactNode;
|
|
44
|
+
}
|
|
45
|
+
export declare const StackedCard: React.ForwardRefExoticComponent<StackedCardProps & React.RefAttributes<HTMLDivElement>>;
|
|
46
|
+
//# sourceMappingURL=shell.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../../../src/presentation/stackedCard/shell.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,YAAY,EAAE,SAAS,EAAuB,MAAM,OAAO,CAAC;AAI5E;;;;;;;;;;;;;;;;;;GAkBG;AAMH,eAAO,MAAM,UAAU,MAAM,CAAC;AAC9B,eAAO,MAAM,WAAW,IAAI,CAAC;AAK7B,eAAO,MAAM,WAAW,cAAc,CAAC;AACvC,eAAO,MAAM,gBAAgB,cAAc,CAAC;AAC5C,eAAO,MAAM,iBAAiB,cAAc,CAAC;AAC7C,eAAO,MAAM,kBAAkB,cAAc,CAAC;AA2K9C,eAAO,MAAM,iBAAiB,QAAO,YAepC,CAAC;AAEF,MAAM,WAAW,gBACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC;IAC9D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gFAAgF;IAChF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,QAAQ,EAAE,SAAS,CAAC;CACrB;AAKD,eAAO,MAAM,WAAW,yFAqEvB,CAAC"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
|
+
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
|
3
|
+
const _excluded = ["selected", "disabled", "pending", "isDragSource", "isDragPreview", "entered", "forceHover", "resizable", "priorityColor", "onResizeDelta", "children"];
|
|
4
|
+
import React, { useCallback, useRef } from "react";
|
|
5
|
+
import styled, { css } from "styled-components";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* StackedCard shell (story-local, presentation-only).
|
|
9
|
+
*
|
|
10
|
+
* The hollow frame every typed content component composes. Extracted from the
|
|
11
|
+
* concept spec story (task 2/8) so the StackedCard concept stories share one
|
|
12
|
+
* shell instead of re-declaring it. The rule the whole subsystem hangs on:
|
|
13
|
+
*
|
|
14
|
+
* THE SHELL STAYS HOLLOW.
|
|
15
|
+
*
|
|
16
|
+
* There is no `contentType` enum here, no per-type prop soup, no `if task …`.
|
|
17
|
+
* The shell owns only VISUAL STATES (selected, disabled, pending, priority,
|
|
18
|
+
* drag source/preview, entered) and the intent surface (`onResizeDelta`, the
|
|
19
|
+
* DOM props it forwards). Content — a task, a link, an image, a swatch, a note
|
|
20
|
+
* — is passed in as `children` and composes the layout primitives. A new
|
|
21
|
+
* content type later is a new wrapper, with ZERO changes in this file.
|
|
22
|
+
*
|
|
23
|
+
* Not exported from the design-system barrel; it lives here so the concept
|
|
24
|
+
* stories share one source of truth.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/* ------------------------------------------------------------------ */
|
|
28
|
+
/* Reference dimensions (from the concept) */
|
|
29
|
+
/* ------------------------------------------------------------------ */
|
|
30
|
+
|
|
31
|
+
export const CARD_WIDTH = 260;
|
|
32
|
+
export const CARD_RADIUS = 8;
|
|
33
|
+
|
|
34
|
+
/* Cover heights are reserved with aspect-ratio (width / height) so a late image
|
|
35
|
+
never reflows the card. Per-type ratios live with the shell so every content
|
|
36
|
+
component reserves the same space its skeleton does. */
|
|
37
|
+
export const COVER_RATIO = "260 / 132";
|
|
38
|
+
export const COVER_RATIO_HERO = "320 / 190";
|
|
39
|
+
export const COVER_RATIO_IMAGE = "260 / 168";
|
|
40
|
+
export const COVER_RATIO_SWATCH = "260 / 104";
|
|
41
|
+
|
|
42
|
+
/* ------------------------------------------------------------------ */
|
|
43
|
+
/* Shell chrome */
|
|
44
|
+
/* ------------------------------------------------------------------ */
|
|
45
|
+
|
|
46
|
+
const hoverStyle = css(["box-shadow:0 4px 12px rgba(0,0,0,0.12);border-color:var(--color-theme-500);"]);
|
|
47
|
+
|
|
48
|
+
/* Controls (cover + entity) share one reveal rule: hidden until the card is
|
|
49
|
+
hovered OR holds focus, so they are reachable by keyboard, not mouse-only.
|
|
50
|
+
The cover also reveals its own controls; `&&` gives the forced-on state the
|
|
51
|
+
specificity to win over that resting rule. */
|
|
52
|
+
const revealControls = css([".sc-control{opacity:0;transition:opacity 120ms ease;}&:hover .sc-control,&:focus-within .sc-control{opacity:1;}"]);
|
|
53
|
+
const StyledCard = styled.div.withConfig({
|
|
54
|
+
displayName: "shell__StyledCard",
|
|
55
|
+
componentId: "sc-nmi1iu-0"
|
|
56
|
+
})(["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 var(--sc-selection-ring);}", " ", " ", " ", " ", " ", " ", " ", ""], CARD_WIDTH, CARD_RADIUS, revealControls, hoverStyle, hoverStyle, _ref => {
|
|
57
|
+
let $forceHover = _ref.$forceHover;
|
|
58
|
+
return $forceHover && css(["", " && .sc-control{opacity:1;}"], hoverStyle);
|
|
59
|
+
}, _ref2 => {
|
|
60
|
+
let $priorityColor = _ref2.$priorityColor;
|
|
61
|
+
return $priorityColor && css(["&::before{content:\"\";position:absolute;top:0;bottom:0;left:0;width:4px;background:", ";z-index:2;}"], $priorityColor);
|
|
62
|
+
}, _ref3 => {
|
|
63
|
+
let $selected = _ref3.$selected;
|
|
64
|
+
return $selected && css(["border-color:var(--sc-selection-ring);box-shadow:0 0 0 2px var(--sc-selection-ring);"]);
|
|
65
|
+
}, _ref4 => {
|
|
66
|
+
let $disabled = _ref4.$disabled;
|
|
67
|
+
return $disabled && css(["opacity:0.5;pointer-events:none;"]);
|
|
68
|
+
}, _ref5 => {
|
|
69
|
+
let $pending = _ref5.$pending;
|
|
70
|
+
return $pending && css(["opacity:0.6;pointer-events:none;cursor:progress;"]);
|
|
71
|
+
}, _ref6 => {
|
|
72
|
+
let $isDragSource = _ref6.$isDragSource;
|
|
73
|
+
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;}"]);
|
|
74
|
+
}, _ref7 => {
|
|
75
|
+
let $isDragPreview = _ref7.$isDragPreview;
|
|
76
|
+
return $isDragPreview && css(["box-shadow:0 12px 28px rgba(0,0,0,0.24);cursor:grabbing;"]);
|
|
77
|
+
}, _ref8 => {
|
|
78
|
+
let $entered = _ref8.$entered;
|
|
79
|
+
return $entered && css(["&&{border-color:var(--sc-selection-ring);box-shadow:inset 0 0 0 2px var(--sc-selection-ring),0 0 0 2px var(--sc-selection-ring);}"]);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
/* ------------------------------------------------------------------ */
|
|
83
|
+
/* Resize (opt-in): handle on hover, card reports deltas */
|
|
84
|
+
/* ------------------------------------------------------------------ */
|
|
85
|
+
|
|
86
|
+
const StyledResizeHandle = styled.span.withConfig({
|
|
87
|
+
displayName: "shell__StyledResizeHandle",
|
|
88
|
+
componentId: "sc-nmi1iu-1"
|
|
89
|
+
})(["position:absolute;right:2px;bottom:2px;width:14px;height:14px;cursor:nwse-resize;color:var(--color-theme-600);z-index:2;svg{display:block;}"]);
|
|
90
|
+
export const ResizeHandleGlyph = () => /*#__PURE__*/React.createElement("svg", {
|
|
91
|
+
width: "14",
|
|
92
|
+
height: "14",
|
|
93
|
+
viewBox: "0 0 14 14",
|
|
94
|
+
fill: "none",
|
|
95
|
+
"aria-hidden": "true"
|
|
96
|
+
}, /*#__PURE__*/React.createElement("path", {
|
|
97
|
+
d: "M12 6v6H6M12 9.5L9.5 12",
|
|
98
|
+
stroke: "currentColor",
|
|
99
|
+
strokeWidth: "1.5",
|
|
100
|
+
strokeLinecap: "round"
|
|
101
|
+
}));
|
|
102
|
+
/* The shell forwards its ref and spreads DOM props (tabIndex, role, aria-*, the
|
|
103
|
+
keyboard/click handlers) so the focus-model and open-vs-select demos can
|
|
104
|
+
drive it — but it owns NO drag, selection, or content logic itself. */
|
|
105
|
+
export const StackedCard = /*#__PURE__*/React.forwardRef((_ref9, ref) => {
|
|
106
|
+
let selected = _ref9.selected,
|
|
107
|
+
disabled = _ref9.disabled,
|
|
108
|
+
pending = _ref9.pending,
|
|
109
|
+
isDragSource = _ref9.isDragSource,
|
|
110
|
+
isDragPreview = _ref9.isDragPreview,
|
|
111
|
+
entered = _ref9.entered,
|
|
112
|
+
forceHover = _ref9.forceHover,
|
|
113
|
+
resizable = _ref9.resizable,
|
|
114
|
+
priorityColor = _ref9.priorityColor,
|
|
115
|
+
onResizeDelta = _ref9.onResizeDelta,
|
|
116
|
+
children = _ref9.children,
|
|
117
|
+
rest = _objectWithoutPropertiesLoose(_ref9, _excluded);
|
|
118
|
+
const dragOrigin = useRef(null);
|
|
119
|
+
const handlePointerDown = useCallback(e => {
|
|
120
|
+
dragOrigin.current = {
|
|
121
|
+
x: e.clientX,
|
|
122
|
+
y: e.clientY
|
|
123
|
+
};
|
|
124
|
+
e.target.setPointerCapture(e.pointerId);
|
|
125
|
+
e.preventDefault();
|
|
126
|
+
}, []);
|
|
127
|
+
const handlePointerMove = useCallback(e => {
|
|
128
|
+
if (!dragOrigin.current || !onResizeDelta) return;
|
|
129
|
+
onResizeDelta(e.clientX - dragOrigin.current.x, e.clientY - dragOrigin.current.y);
|
|
130
|
+
dragOrigin.current = {
|
|
131
|
+
x: e.clientX,
|
|
132
|
+
y: e.clientY
|
|
133
|
+
};
|
|
134
|
+
}, [onResizeDelta]);
|
|
135
|
+
const handlePointerUp = useCallback(() => {
|
|
136
|
+
dragOrigin.current = null;
|
|
137
|
+
}, []);
|
|
138
|
+
return /*#__PURE__*/React.createElement(StyledCard, _extends({
|
|
139
|
+
ref: ref,
|
|
140
|
+
$selected: selected,
|
|
141
|
+
$disabled: disabled,
|
|
142
|
+
$pending: pending,
|
|
143
|
+
$isDragSource: isDragSource,
|
|
144
|
+
$isDragPreview: isDragPreview,
|
|
145
|
+
$entered: entered,
|
|
146
|
+
$forceHover: forceHover,
|
|
147
|
+
$priorityColor: priorityColor
|
|
148
|
+
}, rest), children, resizable ? /*#__PURE__*/React.createElement(StyledResizeHandle, {
|
|
149
|
+
className: "sc-control",
|
|
150
|
+
onPointerDown: handlePointerDown,
|
|
151
|
+
onPointerMove: handlePointerMove,
|
|
152
|
+
onPointerUp: handlePointerUp
|
|
153
|
+
}, /*#__PURE__*/React.createElement(ResizeHandleGlyph, null)) : null);
|
|
154
|
+
});
|
|
155
|
+
StackedCard.displayName = "StackedCard";
|
|
156
|
+
//# sourceMappingURL=shell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell.js","names":["React","useCallback","useRef","styled","css","CARD_WIDTH","CARD_RADIUS","COVER_RATIO","COVER_RATIO_HERO","COVER_RATIO_IMAGE","COVER_RATIO_SWATCH","hoverStyle","revealControls","StyledCard","div","withConfig","displayName","componentId","_ref","$forceHover","_ref2","$priorityColor","_ref3","$selected","_ref4","$disabled","_ref5","$pending","_ref6","$isDragSource","_ref7","$isDragPreview","_ref8","$entered","StyledResizeHandle","span","ResizeHandleGlyph","createElement","width","height","viewBox","fill","d","stroke","strokeWidth","strokeLinecap","StackedCard","forwardRef","_ref9","ref","selected","disabled","pending","isDragSource","isDragPreview","entered","forceHover","resizable","priorityColor","onResizeDelta","children","rest","_objectWithoutPropertiesLoose","_excluded","dragOrigin","handlePointerDown","e","current","x","clientX","y","clientY","target","setPointerCapture","pointerId","preventDefault","handlePointerMove","handlePointerUp","_extends","className","onPointerDown","onPointerMove","onPointerUp"],"sources":["../../../../src/presentation/stackedCard/shell.tsx"],"sourcesContent":["import React, { ReactElement, ReactNode, useCallback, useRef } from \"react\";\n\nimport styled, { css } from \"styled-components\";\n\n/**\n * StackedCard shell (story-local, presentation-only).\n *\n * The hollow frame every typed content component composes. Extracted from the\n * concept spec story (task 2/8) so the StackedCard concept stories share one\n * shell instead of re-declaring it. The rule the whole subsystem hangs on:\n *\n * THE SHELL STAYS HOLLOW.\n *\n * There is no `contentType` enum here, no per-type prop soup, no `if task …`.\n * The shell owns only VISUAL STATES (selected, disabled, pending, priority,\n * drag source/preview, entered) and the intent surface (`onResizeDelta`, the\n * DOM props it forwards). Content — a task, a link, an image, a swatch, a note\n * — is passed in as `children` and composes the layout primitives. A new\n * content type later is a new wrapper, with ZERO changes in this file.\n *\n * Not exported from the design-system barrel; it lives here so the concept\n * stories share one source of truth.\n */\n\n/* ------------------------------------------------------------------ */\n/* Reference dimensions (from the concept) */\n/* ------------------------------------------------------------------ */\n\nexport const CARD_WIDTH = 260;\nexport const CARD_RADIUS = 8;\n\n/* Cover heights are reserved with aspect-ratio (width / height) so a late image\n never reflows the card. Per-type ratios live with the shell so every content\n component reserves the same space its skeleton does. */\nexport const COVER_RATIO = \"260 / 132\";\nexport const COVER_RATIO_HERO = \"320 / 190\";\nexport const COVER_RATIO_IMAGE = \"260 / 168\";\nexport const COVER_RATIO_SWATCH = \"260 / 104\";\n\n/* ------------------------------------------------------------------ */\n/* Shell chrome */\n/* ------------------------------------------------------------------ */\n\ninterface StyledCardProps {\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\n/* Controls (cover + entity) share one reveal rule: hidden until the card is\n hovered OR holds focus, so they are reachable by keyboard, not mouse-only.\n The cover also reveals its own controls; `&&` gives the forced-on state the\n specificity to win over that resting rule. */\nconst revealControls = css`\n .sc-control {\n opacity: 0;\n transition: opacity 120ms ease;\n }\n\n &:hover .sc-control,\n &:focus-within .sc-control {\n opacity: 1;\n }\n`;\n\nconst StyledCard = styled.div<StyledCardProps>`\n position: relative;\n display: flex;\n flex-direction: column;\n width: ${CARD_WIDTH}px;\n border-radius: ${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 var(--sc-selection-ring);\n }\n\n ${({ $forceHover }) =>\n $forceHover &&\n css`\n ${hoverStyle}\n && .sc-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 ${({ $selected }) =>\n $selected &&\n css`\n border-color: var(--sc-selection-ring);\n box-shadow: 0 0 0 2px var(--sc-selection-ring);\n `}\n\n ${({ $disabled }) =>\n $disabled &&\n css`\n opacity: 0.5;\n pointer-events: none;\n `}\n\n /* Pending / optimistic — the card was just created or moved and the server\n has not confirmed it yet. Dimmed, non-interactive and NOT draggable, but\n distinct from disabled (it is a 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 the 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 is on one of the card's inner controls. */\n ${({ $entered }) =>\n $entered &&\n css`\n && {\n border-color: var(--sc-selection-ring);\n box-shadow: inset 0 0 0 2px var(--sc-selection-ring),\n 0 0 0 2px var(--sc-selection-ring);\n }\n `}\n`;\n\n/* ------------------------------------------------------------------ */\n/* Resize (opt-in): handle on hover, card reports deltas */\n/* ------------------------------------------------------------------ */\n\nconst StyledResizeHandle = 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`;\n\nexport const ResizeHandleGlyph = (): ReactElement => (\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 14 14\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M12 6v6H6M12 9.5L9.5 12\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n);\n\nexport interface StackedCardProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, \"onResize\"> {\n selected?: boolean;\n disabled?: boolean;\n /** Optimistic in-flight state — dimmed, non-interactive, not draggable. */\n pending?: boolean;\n /** Full-size outline placeholder left in the source position while dragging. */\n isDragSource?: boolean;\n /** The 1:1 elevated copy the host floats in the drag layer. */\n isDragPreview?: boolean;\n /** Focus model: the card has been entered and focus is on an inner control. */\n entered?: boolean;\n forceHover?: boolean;\n resizable?: boolean;\n priorityColor?: string;\n onResizeDelta?: (dx: number, dy: number) => void;\n children: ReactNode;\n}\n\n/* The shell forwards its ref and spreads DOM props (tabIndex, role, aria-*, the\n keyboard/click handlers) so the focus-model and open-vs-select demos can\n drive it — but it owns NO drag, selection, or content logic itself. */\nexport const StackedCard = React.forwardRef<HTMLDivElement, StackedCardProps>(\n (\n {\n selected,\n disabled,\n pending,\n isDragSource,\n isDragPreview,\n entered,\n forceHover,\n resizable,\n priorityColor,\n onResizeDelta,\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 <StyledCard\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 {...rest}\n >\n {children}\n {resizable ? (\n <StyledResizeHandle\n className=\"sc-control\"\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n >\n <ResizeHandleGlyph />\n </StyledResizeHandle>\n ) : null}\n </StyledCard>\n );\n }\n);\n\nStackedCard.displayName = \"StackedCard\";\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ReactElement, ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Shared spec-sheet scaffolding for the StackedCard concept stories (Sheet,
|
|
4
|
+
* Section, Labeled, Grid, Column) plus the DS token candidates the subsystem
|
|
5
|
+
* needs. Presentation-only; keeps the three StackedCard stories laying out the
|
|
6
|
+
* same way instead of each re-declaring the sheet chrome.
|
|
7
|
+
*
|
|
8
|
+
* The `--sc-*` variables are declared here as design-system PROPOSALS (a
|
|
9
|
+
* selection ring + a dark scrim family). The shell and primitives reference
|
|
10
|
+
* these only, so no rgba/hex is baked into a reusable style.
|
|
11
|
+
*/
|
|
12
|
+
export declare const StyledSheet: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
13
|
+
export declare const StyledGrid: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
14
|
+
export declare const StyledColumn: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
15
|
+
export declare const Labeled: ({ label, children, }: {
|
|
16
|
+
label: ReactNode;
|
|
17
|
+
children: ReactNode;
|
|
18
|
+
}) => ReactElement;
|
|
19
|
+
export declare const Section: ({ caption, note, children, }: {
|
|
20
|
+
caption: string;
|
|
21
|
+
note?: ReactNode;
|
|
22
|
+
children: ReactNode;
|
|
23
|
+
}) => ReactElement;
|
|
24
|
+
export declare const SheetHeading: ({ title, children, }: {
|
|
25
|
+
title: string;
|
|
26
|
+
children: ReactNode;
|
|
27
|
+
}) => ReactElement;
|
|
28
|
+
//# sourceMappingURL=storyScaffold.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storyScaffold.d.ts","sourceRoot":"","sources":["../../../../src/presentation/stackedCard/storyScaffold.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvD;;;;;;;;;GASG;AAEH,eAAO,MAAM,WAAW,oEAoBvB,CAAC;AAmBF,eAAO,MAAM,UAAU,oEAKtB,CAAC;AAEF,eAAO,MAAM,YAAY,oEAIxB,CAAC;AAcF,eAAO,MAAM,OAAO,GAAI,sBAGrB;IACD,KAAK,EAAE,SAAS,CAAC;IACjB,QAAQ,EAAE,SAAS,CAAC;CACrB,KAAG,YAOH,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,8BAIrB;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,QAAQ,EAAE,SAAS,CAAC;CACrB,KAAG,YAYH,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,sBAG1B;IACD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;CACrB,KAAG,YAOH,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import styled from "styled-components";
|
|
3
|
+
import { Caption1, Title2 } from "../../components/Typography";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Shared spec-sheet scaffolding for the StackedCard concept stories (Sheet,
|
|
7
|
+
* Section, Labeled, Grid, Column) plus the DS token candidates the subsystem
|
|
8
|
+
* needs. Presentation-only; keeps the three StackedCard stories laying out the
|
|
9
|
+
* same way instead of each re-declaring the sheet chrome.
|
|
10
|
+
*
|
|
11
|
+
* The `--sc-*` variables are declared here as design-system PROPOSALS (a
|
|
12
|
+
* selection ring + a dark scrim family). The shell and primitives reference
|
|
13
|
+
* these only, so no rgba/hex is baked into a reusable style.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export const StyledSheet = styled.div.withConfig({
|
|
17
|
+
displayName: "storyScaffold__StyledSheet",
|
|
18
|
+
componentId: "sc-7oxew-0"
|
|
19
|
+
})(["--sc-selection-ring:var(--color-primary-500,#2f6bff);--sc-scrim:rgba(0,0,0,0.55);--sc-scrim-strong:rgba(0,0,0,0.72);--sc-scrim-fg:#ffffff;--sc-completed-tint:rgba(72,201,176,0.16);min-height:100vh;padding:32px 40px 64px;background:var(--page-paper-dimmed,var(--color-theme-200));.sheet-title{margin-bottom:8px;}.sheet-lede{display:block;margin-bottom:24px;max-width:760px;}"]);
|
|
20
|
+
const StyledSection = styled.section.withConfig({
|
|
21
|
+
displayName: "storyScaffold__StyledSection",
|
|
22
|
+
componentId: "sc-7oxew-1"
|
|
23
|
+
})(["margin-top:40px;> .section-caption{display:block;margin-bottom:4px;text-transform:uppercase;letter-spacing:0.06em;}> .section-note{display:block;margin-bottom:16px;max-width:720px;}"]);
|
|
24
|
+
export const StyledGrid = styled.div.withConfig({
|
|
25
|
+
displayName: "storyScaffold__StyledGrid",
|
|
26
|
+
componentId: "sc-7oxew-2"
|
|
27
|
+
})(["display:flex;flex-wrap:wrap;gap:24px;align-items:flex-start;"]);
|
|
28
|
+
export const StyledColumn = styled.div.withConfig({
|
|
29
|
+
displayName: "storyScaffold__StyledColumn",
|
|
30
|
+
componentId: "sc-7oxew-3"
|
|
31
|
+
})(["display:flex;flex-direction:column;gap:12px;"]);
|
|
32
|
+
const StyledLabeled = styled.figure.withConfig({
|
|
33
|
+
displayName: "storyScaffold__StyledLabeled",
|
|
34
|
+
componentId: "sc-7oxew-4"
|
|
35
|
+
})(["margin:0;display:flex;flex-direction:column;gap:8px;> figcaption{order:-1;max-width:320px;}"]);
|
|
36
|
+
export const Labeled = _ref => {
|
|
37
|
+
let label = _ref.label,
|
|
38
|
+
children = _ref.children;
|
|
39
|
+
return /*#__PURE__*/React.createElement(StyledLabeled, null, /*#__PURE__*/React.createElement("figcaption", null, /*#__PURE__*/React.createElement(Caption1, {
|
|
40
|
+
color: "secondary"
|
|
41
|
+
}, label)), children);
|
|
42
|
+
};
|
|
43
|
+
export const Section = _ref2 => {
|
|
44
|
+
let caption = _ref2.caption,
|
|
45
|
+
note = _ref2.note,
|
|
46
|
+
children = _ref2.children;
|
|
47
|
+
return /*#__PURE__*/React.createElement(StyledSection, null, /*#__PURE__*/React.createElement(Caption1, {
|
|
48
|
+
weight: "bold",
|
|
49
|
+
color: "tertiary",
|
|
50
|
+
className: "section-caption"
|
|
51
|
+
}, caption), note ? /*#__PURE__*/React.createElement(Caption1, {
|
|
52
|
+
color: "tertiary",
|
|
53
|
+
className: "section-note"
|
|
54
|
+
}, note) : null, /*#__PURE__*/React.createElement(StyledGrid, null, children));
|
|
55
|
+
};
|
|
56
|
+
export const SheetHeading = _ref3 => {
|
|
57
|
+
let title = _ref3.title,
|
|
58
|
+
children = _ref3.children;
|
|
59
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Title2, {
|
|
60
|
+
className: "sheet-title"
|
|
61
|
+
}, title), /*#__PURE__*/React.createElement(Caption1, {
|
|
62
|
+
color: "tertiary",
|
|
63
|
+
className: "sheet-lede"
|
|
64
|
+
}, children));
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=storyScaffold.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storyScaffold.js","names":["React","styled","Caption1","Title2","StyledSheet","div","withConfig","displayName","componentId","StyledSection","section","StyledGrid","StyledColumn","StyledLabeled","figure","Labeled","_ref","label","children","createElement","color","Section","_ref2","caption","note","weight","className","SheetHeading","_ref3","title","Fragment"],"sources":["../../../../src/presentation/stackedCard/storyScaffold.tsx"],"sourcesContent":["import React, { ReactElement, ReactNode } from \"react\";\n\nimport styled from \"styled-components\";\n\nimport { Caption1, Title2 } from \"../../components/Typography\";\n\n/**\n * Shared spec-sheet scaffolding for the StackedCard concept stories (Sheet,\n * Section, Labeled, Grid, Column) plus the DS token candidates the subsystem\n * needs. Presentation-only; keeps the three StackedCard stories laying out the\n * same way instead of each re-declaring the sheet chrome.\n *\n * The `--sc-*` variables are declared here as design-system PROPOSALS (a\n * selection ring + a dark scrim family). The shell and primitives reference\n * these only, so no rgba/hex is baked into a reusable style.\n */\n\nexport const StyledSheet = styled.div`\n --sc-selection-ring: var(--color-primary-500, #2f6bff);\n --sc-scrim: rgba(0, 0, 0, 0.55);\n --sc-scrim-strong: rgba(0, 0, 0, 0.72);\n --sc-scrim-fg: #ffffff;\n --sc-completed-tint: rgba(72, 201, 176, 0.16);\n\n min-height: 100vh;\n padding: 32px 40px 64px;\n background: var(--page-paper-dimmed, var(--color-theme-200));\n\n .sheet-title {\n margin-bottom: 8px;\n }\n\n .sheet-lede {\n display: block;\n margin-bottom: 24px;\n max-width: 760px;\n }\n`;\n\nconst StyledSection = styled.section`\n margin-top: 40px;\n\n > .section-caption {\n display: block;\n margin-bottom: 4px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n }\n\n > .section-note {\n display: block;\n margin-bottom: 16px;\n max-width: 720px;\n }\n`;\n\nexport const StyledGrid = styled.div`\n display: flex;\n flex-wrap: wrap;\n gap: 24px;\n align-items: flex-start;\n`;\n\nexport const StyledColumn = styled.div`\n display: flex;\n flex-direction: column;\n gap: 12px;\n`;\n\nconst StyledLabeled = styled.figure`\n margin: 0;\n display: flex;\n flex-direction: column;\n gap: 8px;\n\n > figcaption {\n order: -1;\n max-width: 320px;\n }\n`;\n\nexport const Labeled = ({\n label,\n children,\n}: {\n label: ReactNode;\n children: ReactNode;\n}): ReactElement => (\n <StyledLabeled>\n <figcaption>\n <Caption1 color=\"secondary\">{label}</Caption1>\n </figcaption>\n {children}\n </StyledLabeled>\n);\n\nexport const Section = ({\n caption,\n note,\n children,\n}: {\n caption: string;\n note?: ReactNode;\n children: ReactNode;\n}): ReactElement => (\n <StyledSection>\n <Caption1 weight=\"bold\" color=\"tertiary\" className=\"section-caption\">\n {caption}\n </Caption1>\n {note ? (\n <Caption1 color=\"tertiary\" className=\"section-note\">\n {note}\n </Caption1>\n ) : null}\n <StyledGrid>{children}</StyledGrid>\n </StyledSection>\n);\n\nexport const SheetHeading = ({\n title,\n children,\n}: {\n title: string;\n children: ReactNode;\n}): ReactElement => (\n <>\n <Title2 className=\"sheet-title\">{title}</Title2>\n <Caption1 color=\"tertiary\" className=\"sheet-lede\">\n {children}\n </Caption1>\n </>\n);\n"],"mappings":"AAAA,OAAOA,KAAK,MAAmC,OAAO;AAEtD,OAAOC,MAAM,MAAM,mBAAmB;AAEtC,SAASC,QAAQ,EAAEC,MAAM,QAAQ,6BAA6B;;AAE9D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,OAAO,MAAMC,WAAW,GAAGH,MAAM,CAACI,GAAG,CAAAC,UAAA;EAAAC,WAAA;EAAAC,WAAA;AAAA,6XAoBpC;AAED,MAAMC,aAAa,GAAGR,MAAM,CAACS,OAAO,CAAAJ,UAAA;EAAAC,WAAA;EAAAC,WAAA;AAAA,6LAenC;AAED,OAAO,MAAMG,UAAU,GAAGV,MAAM,CAACI,GAAG,CAAAC,UAAA;EAAAC,WAAA;EAAAC,WAAA;AAAA,oEAKnC;AAED,OAAO,MAAMI,YAAY,GAAGX,MAAM,CAACI,GAAG,CAAAC,UAAA;EAAAC,WAAA;EAAAC,WAAA;AAAA,oDAIrC;AAED,MAAMK,aAAa,GAAGZ,MAAM,CAACa,MAAM,CAAAR,UAAA;EAAAC,WAAA;EAAAC,WAAA;AAAA,mGAUlC;AAED,OAAO,MAAMO,OAAO,GAAGC,IAAA;EAAA,IACrBC,KAAK,GAAAD,IAAA,CAALC,KAAK;IACLC,QAAQ,GAAAF,IAAA,CAARE,QAAQ;EAAA,oBAKRlB,KAAA,CAAAmB,aAAA,CAACN,aAAa,qBACZb,KAAA,CAAAmB,aAAA,kCACEnB,KAAA,CAAAmB,aAAA,CAACjB,QAAQ;IAACkB,KAAK,EAAC;EAAW,GAAEH,KAAgB,CACnC,CAAC,EACZC,QACY,CAAC;AAAA,CACjB;AAED,OAAO,MAAMG,OAAO,GAAGC,KAAA;EAAA,IACrBC,OAAO,GAAAD,KAAA,CAAPC,OAAO;IACPC,IAAI,GAAAF,KAAA,CAAJE,IAAI;IACJN,QAAQ,GAAAI,KAAA,CAARJ,QAAQ;EAAA,oBAMRlB,KAAA,CAAAmB,aAAA,CAACV,aAAa,qBACZT,KAAA,CAAAmB,aAAA,CAACjB,QAAQ;IAACuB,MAAM,EAAC,MAAM;IAACL,KAAK,EAAC,UAAU;IAACM,SAAS,EAAC;EAAiB,GACjEH,OACO,CAAC,EACVC,IAAI,gBACHxB,KAAA,CAAAmB,aAAA,CAACjB,QAAQ;IAACkB,KAAK,EAAC,UAAU;IAACM,SAAS,EAAC;EAAc,GAChDF,IACO,CAAC,GACT,IAAI,eACRxB,KAAA,CAAAmB,aAAA,CAACR,UAAU,QAAEO,QAAqB,CACrB,CAAC;AAAA,CACjB;AAED,OAAO,MAAMS,YAAY,GAAGC,KAAA;EAAA,IAC1BC,KAAK,GAAAD,KAAA,CAALC,KAAK;IACLX,QAAQ,GAAAU,KAAA,CAARV,QAAQ;EAAA,oBAKRlB,KAAA,CAAAmB,aAAA,CAAAnB,KAAA,CAAA8B,QAAA,qBACE9B,KAAA,CAAAmB,aAAA,CAAChB,MAAM;IAACuB,SAAS,EAAC;EAAa,GAAEG,KAAc,CAAC,eAChD7B,KAAA,CAAAmB,aAAA,CAACjB,QAAQ;IAACkB,KAAK,EAAC,UAAU;IAACM,SAAS,EAAC;EAAY,GAC9CR,QACO,CACV,CAAC;AAAA,CACJ","ignoreList":[]}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { ChangeEvent, FocusEvent, KeyboardEvent } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* useInlineEdit — story-local click-to-edit state machine for StackedCard
|
|
4
|
+
* (task 4/8). Presentation-only; not exported from the design-system barrel.
|
|
5
|
+
*
|
|
6
|
+
* A card in preview/placeholder mode enters an EDITING state on click: a
|
|
7
|
+
* card-centered text field with confirm/cancel keyboard rules, an optional
|
|
8
|
+
* validator, and a single-line ↔ multi-line mode switch. The hook owns only the
|
|
9
|
+
* editing lifecycle (mode, working value, error, keyboard + outside-click); the
|
|
10
|
+
* card chrome and the async handoff after commit (e.g. the link unfurl ladder
|
|
11
|
+
* from task 3/8) live in the story that consumes it.
|
|
12
|
+
*
|
|
13
|
+
* ── The decided rules (AC task #454744) ──
|
|
14
|
+
* Single-line Enter confirms · click-outside confirms · Esc cancels + reverts
|
|
15
|
+
* Multi-line Enter = newline · Cmd/Ctrl+Enter saves · click-outside saves ·
|
|
16
|
+
* Esc cancels + reverts
|
|
17
|
+
* Validator validate(value) => true | errorMessage, run before every accept
|
|
18
|
+
* pass → commit + exit editing
|
|
19
|
+
* fail via a key → STAY editing, surface the message (retry)
|
|
20
|
+
* fail via outside → REVERT (acts as cancel) — user never trapped
|
|
21
|
+
*
|
|
22
|
+
* Keyboard is handled on the field's own keydown (never a global listener) and
|
|
23
|
+
* every keydown stops propagation, so the card focus model (task 2/8) can't
|
|
24
|
+
* swallow the Enter/Esc that belong to the editor.
|
|
25
|
+
*/
|
|
26
|
+
export type InlineEditValidator = (value: string) => true | string;
|
|
27
|
+
export interface UseInlineEditConfig {
|
|
28
|
+
/** Seed value for the first edit; also the revert target until first commit. */
|
|
29
|
+
initialValue?: string;
|
|
30
|
+
/** Multi-line mode: Enter inserts a newline, Cmd/Ctrl+Enter saves. */
|
|
31
|
+
multiline?: boolean;
|
|
32
|
+
/** Optional validator, run before every accept. `true` passes; a string fails. */
|
|
33
|
+
validate?: InlineEditValidator;
|
|
34
|
+
/** Called with the committed value when an accept passes validation. */
|
|
35
|
+
onCommit?: (value: string) => void;
|
|
36
|
+
}
|
|
37
|
+
/** Props to spread onto the `<input>` or `<textarea>` while editing. */
|
|
38
|
+
export interface InlineEditBind {
|
|
39
|
+
/** Callback ref — assignable to both an input and a textarea. */
|
|
40
|
+
ref: (el: HTMLInputElement | HTMLTextAreaElement | null) => void;
|
|
41
|
+
value: string;
|
|
42
|
+
onChange: (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
|
|
43
|
+
onKeyDown: (e: KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
|
|
44
|
+
onBlur: (e: FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
|
|
45
|
+
"aria-invalid": boolean;
|
|
46
|
+
}
|
|
47
|
+
export interface InlineEditController {
|
|
48
|
+
/** Whether the field is currently shown. */
|
|
49
|
+
editing: boolean;
|
|
50
|
+
/** The working value (the draft being typed). */
|
|
51
|
+
value: string;
|
|
52
|
+
/** The last committed value — what a revert restores. */
|
|
53
|
+
committed: string;
|
|
54
|
+
/** The current validation message, or null when valid / untouched. */
|
|
55
|
+
error: string | null;
|
|
56
|
+
/** Whether this editor is in multi-line mode. */
|
|
57
|
+
multiline: boolean;
|
|
58
|
+
/** Enter editing, loading the last committed value. */
|
|
59
|
+
begin: () => void;
|
|
60
|
+
/** Cancel + revert to the committed value (the Esc / invalid-outside path). */
|
|
61
|
+
cancel: () => void;
|
|
62
|
+
/** Force a committed value without going through the field (repeat demos). */
|
|
63
|
+
reset: (next?: string) => void;
|
|
64
|
+
/** Spread onto the field element while `editing`. */
|
|
65
|
+
bind: InlineEditBind;
|
|
66
|
+
}
|
|
67
|
+
export declare const useInlineEdit: ({ initialValue, multiline, validate, onCommit, }?: UseInlineEditConfig) => InlineEditController;
|
|
68
|
+
//# sourceMappingURL=useInlineEdit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useInlineEdit.d.ts","sourceRoot":"","sources":["../../../../src/presentation/stackedCard/useInlineEdit.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,UAAU,EACV,aAAa,EAKd,MAAM,OAAO,CAAC;AAEf;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,CAAC;AAEnE,MAAM,WAAW,mBAAmB;IAClC,gFAAgF;IAChF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,wEAAwE;IACxE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAED,wEAAwE;AACxE,MAAM,WAAW,cAAc;IAC7B,iEAAiE;IACjE,GAAG,EAAE,CAAC,EAAE,EAAE,gBAAgB,GAAG,mBAAmB,GAAG,IAAI,KAAK,IAAI,CAAC;IACjE,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,gBAAgB,GAAG,mBAAmB,CAAC,KAAK,IAAI,CAAC;IAC3E,SAAS,EAAE,CAAC,CAAC,EAAE,aAAa,CAAC,gBAAgB,GAAG,mBAAmB,CAAC,KAAK,IAAI,CAAC;IAC9E,MAAM,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,gBAAgB,GAAG,mBAAmB,CAAC,KAAK,IAAI,CAAC;IACxE,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,4CAA4C;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,iDAAiD;IACjD,SAAS,EAAE,OAAO,CAAC;IACnB,uDAAuD;IACvD,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,+EAA+E;IAC/E,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,8EAA8E;IAC9E,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,qDAAqD;IACrD,IAAI,EAAE,cAAc,CAAC;CACtB;AAED,eAAO,MAAM,aAAa,GAAI,mDAK3B,mBAAwB,KAAG,oBAgL7B,CAAC"}
|