@activecollab/components 2.0.371 → 2.0.373

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/dist/cjs/components/Icons/collection/ConnectionIcon.js +9 -17
  2. package/dist/cjs/components/Icons/collection/ConnectionIcon.js.map +1 -1
  3. package/dist/cjs/components/Icons/collection/ShapesIcon.js +61 -0
  4. package/dist/cjs/components/Icons/collection/ShapesIcon.js.map +1 -0
  5. package/dist/cjs/components/Icons/collection/index.js +7 -0
  6. package/dist/cjs/components/Icons/collection/index.js.map +1 -1
  7. package/dist/cjs/components/StackedCard/StackedCard.js +103 -19
  8. package/dist/cjs/components/StackedCard/StackedCard.js.map +1 -1
  9. package/dist/cjs/components/StackedCard/Styles.js +23 -18
  10. package/dist/cjs/components/StackedCard/Styles.js.map +1 -1
  11. package/dist/cjs/components/StackedCard/index.js +22 -0
  12. package/dist/cjs/components/StackedCard/index.js.map +1 -1
  13. package/dist/cjs/components/StackedCard/resizePolicy.js +238 -0
  14. package/dist/cjs/components/StackedCard/resizePolicy.js.map +1 -0
  15. package/dist/cjs/components/StackedCard/resizePolicy.test.js +474 -0
  16. package/dist/cjs/components/StackedCard/resizePolicy.test.js.map +1 -0
  17. package/dist/cjs/components/StackedCard/useStackedCardResize.js +145 -0
  18. package/dist/cjs/components/StackedCard/useStackedCardResize.js.map +1 -0
  19. package/dist/cjs/presentation/stackedCard/content/LinkCard.js +35 -22
  20. package/dist/cjs/presentation/stackedCard/content/LinkCard.js.map +1 -1
  21. package/dist/esm/components/Icons/collection/ConnectionIcon.d.ts.map +1 -1
  22. package/dist/esm/components/Icons/collection/ConnectionIcon.js +9 -17
  23. package/dist/esm/components/Icons/collection/ConnectionIcon.js.map +1 -1
  24. package/dist/esm/components/Icons/collection/ShapesIcon.d.ts +32 -0
  25. package/dist/esm/components/Icons/collection/ShapesIcon.d.ts.map +1 -0
  26. package/dist/esm/components/Icons/collection/ShapesIcon.js +54 -0
  27. package/dist/esm/components/Icons/collection/ShapesIcon.js.map +1 -0
  28. package/dist/esm/components/Icons/collection/index.d.ts +1 -0
  29. package/dist/esm/components/Icons/collection/index.d.ts.map +1 -1
  30. package/dist/esm/components/Icons/collection/index.js +1 -0
  31. package/dist/esm/components/Icons/collection/index.js.map +1 -1
  32. package/dist/esm/components/StackedCard/StackedCard.d.ts +44 -3
  33. package/dist/esm/components/StackedCard/StackedCard.d.ts.map +1 -1
  34. package/dist/esm/components/StackedCard/StackedCard.js +102 -19
  35. package/dist/esm/components/StackedCard/StackedCard.js.map +1 -1
  36. package/dist/esm/components/StackedCard/Styles.d.ts +4 -1
  37. package/dist/esm/components/StackedCard/Styles.d.ts.map +1 -1
  38. package/dist/esm/components/StackedCard/Styles.js +23 -18
  39. package/dist/esm/components/StackedCard/Styles.js.map +1 -1
  40. package/dist/esm/components/StackedCard/index.d.ts +2 -0
  41. package/dist/esm/components/StackedCard/index.d.ts.map +1 -1
  42. package/dist/esm/components/StackedCard/index.js +2 -0
  43. package/dist/esm/components/StackedCard/index.js.map +1 -1
  44. package/dist/esm/components/StackedCard/resizePolicy.d.ts +111 -0
  45. package/dist/esm/components/StackedCard/resizePolicy.d.ts.map +1 -0
  46. package/dist/esm/{presentation/stackedCard → components/StackedCard}/resizePolicy.js +93 -48
  47. package/dist/esm/components/StackedCard/resizePolicy.js.map +1 -0
  48. package/dist/esm/components/StackedCard/resizePolicy.test.d.ts +2 -0
  49. package/dist/esm/components/StackedCard/resizePolicy.test.d.ts.map +1 -0
  50. package/dist/esm/components/StackedCard/resizePolicy.test.js +470 -0
  51. package/dist/esm/components/StackedCard/resizePolicy.test.js.map +1 -0
  52. package/dist/esm/components/StackedCard/useStackedCardResize.d.ts +62 -0
  53. package/dist/esm/components/StackedCard/useStackedCardResize.d.ts.map +1 -0
  54. package/dist/esm/components/StackedCard/useStackedCardResize.js +137 -0
  55. package/dist/esm/components/StackedCard/useStackedCardResize.js.map +1 -0
  56. package/dist/esm/presentation/stackedCard/content/LinkCard.d.ts.map +1 -1
  57. package/dist/esm/presentation/stackedCard/content/LinkCard.js +35 -20
  58. package/dist/esm/presentation/stackedCard/content/LinkCard.js.map +1 -1
  59. package/dist/index.js +989 -482
  60. package/dist/index.js.map +1 -1
  61. package/dist/index.min.js +1 -1
  62. package/dist/index.min.js.map +1 -1
  63. package/package.json +1 -1
  64. package/dist/cjs/presentation/stackedCard/resizePolicy.js +0 -183
  65. package/dist/cjs/presentation/stackedCard/resizePolicy.js.map +0 -1
  66. package/dist/esm/presentation/stackedCard/resizePolicy.d.ts +0 -97
  67. package/dist/esm/presentation/stackedCard/resizePolicy.d.ts.map +0 -1
  68. package/dist/esm/presentation/stackedCard/resizePolicy.js.map +0 -1
@@ -0,0 +1,137 @@
1
+ import { useCallback, useRef } from "react";
2
+ import { applyResize, isResizeKey, keyboardResize, makeStart, measurePercent } from "./resizePolicy";
3
+
4
+ /**
5
+ * The one place pointer and keyboard input meet the resize policy.
6
+ *
7
+ * `StackedCard`'s built-in grip reports raw deltas and knows no policy — enough
8
+ * for a host that just tracks a width. This hook is the full contract: it
9
+ * captures the gesture start, funnels both inputs through the pure policy in
10
+ * `resizePolicy.ts`, streams preview events and fires exactly ONE commit per
11
+ * gesture. It returns the props to spread on the grip, including the live
12
+ * separator ARIA.
13
+ *
14
+ * Preview versus commit (spec §7e): the continuous stream is live feedback
15
+ * only. A host creates an undo entry on the COMMIT, never on a preview — and a
16
+ * gesture that never changed the size commits nothing at all, so a bare click
17
+ * on the grip is not a change.
18
+ *
19
+ * The hook never touches the card's content: the intrinsic minimum is read
20
+ * through `contentMin`, which may be a getter so a card that measures its own
21
+ * footer can answer at the moment it is asked.
22
+ */
23
+
24
+ /** The props to spread on the grip — `StackedCard`'s `resizeHandleProps`. */
25
+
26
+ const sameSize = (a, b) => a.w === b.w && a.h === b.h;
27
+ export const useStackedCardResize = _ref => {
28
+ let size = _ref.size,
29
+ policy = _ref.policy,
30
+ cardId = _ref.cardId,
31
+ contentMin = _ref.contentMin,
32
+ _ref$axis = _ref.axis,
33
+ axis = _ref$axis === void 0 ? "both" : _ref$axis,
34
+ _ref$scale = _ref.scale,
35
+ scale = _ref$scale === void 0 ? 1 : _ref$scale,
36
+ _ref$label = _ref.label,
37
+ label = _ref$label === void 0 ? "Resize card" : _ref$label,
38
+ onResize = _ref.onResize,
39
+ onResizeCommit = _ref.onResizeCommit;
40
+ // The pointer gesture's anchor: the size + content-min captured on pointer
41
+ // down, plus the pointer origin the delta is measured from.
42
+ const pointerStart = useRef(null);
43
+ // Mirrors the latest emitted size so pointer-up / key-up can commit exactly
44
+ // what preview last showed, without a stale closure.
45
+ const latest = useRef(size);
46
+ latest.current = size;
47
+ // Whether this gesture actually moved the card. A bare click, or a Home on an
48
+ // axis with no floor, leaves it false and commits nothing.
49
+ const dirty = useRef(false);
50
+
51
+ // Read through refs so the handlers below can stay stable across renders
52
+ // while still seeing the current policy, axis and zoom.
53
+ const policyRef = useRef(policy);
54
+ policyRef.current = policy;
55
+ const axisRef = useRef(axis);
56
+ axisRef.current = axis;
57
+ const scaleRef = useRef(scale);
58
+ scaleRef.current = scale;
59
+ const contentMinRef = useRef(contentMin);
60
+ contentMinRef.current = contentMin;
61
+ const readContentMin = useCallback(() => {
62
+ const source = contentMinRef.current;
63
+ return typeof source === "function" ? source() : source;
64
+ }, []);
65
+ const emitPreview = useCallback((next, source) => {
66
+ // Nothing changed — not a preview, and not something to commit later.
67
+ if (sameSize(next, latest.current)) return;
68
+ latest.current = next;
69
+ dirty.current = true;
70
+ onResize(next, source);
71
+ }, [onResize]);
72
+ const handlePointerDown = useCallback(e => {
73
+ pointerStart.current = {
74
+ start: makeStart(latest.current, readContentMin()),
75
+ x: e.clientX,
76
+ y: e.clientY
77
+ };
78
+ dirty.current = false;
79
+ e.target.setPointerCapture == null || e.target.setPointerCapture(e.pointerId);
80
+ e.preventDefault();
81
+ }, [readContentMin]);
82
+ const handlePointerMove = useCallback(e => {
83
+ const ps = pointerStart.current;
84
+ if (!ps) return;
85
+ const z = scaleRef.current || 1;
86
+ const next = applyResize(ps.start, {
87
+ dx: (e.clientX - ps.x) / z,
88
+ dy: (e.clientY - ps.y) / z
89
+ }, policyRef.current,
90
+ // Shift held during a free-form drag = temporary proportional lock.
91
+ {
92
+ constrain: e.shiftKey,
93
+ axis: axisRef.current
94
+ });
95
+ emitPreview(next, "pointer");
96
+ }, [emitPreview]);
97
+ const endPointer = useCallback(() => {
98
+ if (!pointerStart.current) return;
99
+ pointerStart.current = null;
100
+ if (dirty.current) onResizeCommit(latest.current, "pointer");
101
+ dirty.current = false;
102
+ }, [onResizeCommit]);
103
+ const handleKeyDown = useCallback(e => {
104
+ const next = keyboardResize(e.key, latest.current, policyRef.current, readContentMin(), {
105
+ shiftKey: e.shiftKey,
106
+ axis: axisRef.current
107
+ });
108
+ if (!next) return;
109
+ // The key is ours even when it resolves to no movement (already pinned at
110
+ // a bound), so the browser must not also scroll the surface.
111
+ e.preventDefault();
112
+ emitPreview(next, "keyboard");
113
+ }, [emitPreview, readContentMin]);
114
+ const handleKeyUp = useCallback(e => {
115
+ if (!isResizeKey(e.key)) return;
116
+ // The gesture end for the keyboard is the key release: one commit per
117
+ // hold, mirroring pointer-up after a stream of moves.
118
+ if (dirty.current) onResizeCommit(latest.current, "keyboard");
119
+ dirty.current = false;
120
+ }, [onResizeCommit]);
121
+ return {
122
+ role: "separator",
123
+ tabIndex: 0,
124
+ "aria-label": label,
125
+ "aria-controls": cardId,
126
+ "aria-valuemin": 0,
127
+ "aria-valuemax": 100,
128
+ "aria-valuenow": measurePercent(size, policy, readContentMin()),
129
+ onPointerDown: handlePointerDown,
130
+ onPointerMove: handlePointerMove,
131
+ onPointerUp: endPointer,
132
+ onLostPointerCapture: endPointer,
133
+ onKeyDown: handleKeyDown,
134
+ onKeyUp: handleKeyUp
135
+ };
136
+ };
137
+ //# sourceMappingURL=useStackedCardResize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStackedCardResize.js","names":["useCallback","useRef","applyResize","isResizeKey","keyboardResize","makeStart","measurePercent","sameSize","a","b","w","h","useStackedCardResize","_ref","size","policy","cardId","contentMin","_ref$axis","axis","_ref$scale","scale","_ref$label","label","onResize","onResizeCommit","pointerStart","latest","current","dirty","policyRef","axisRef","scaleRef","contentMinRef","readContentMin","source","emitPreview","next","handlePointerDown","e","start","x","clientX","y","clientY","target","setPointerCapture","pointerId","preventDefault","handlePointerMove","ps","z","dx","dy","constrain","shiftKey","endPointer","handleKeyDown","key","handleKeyUp","role","tabIndex","onPointerDown","onPointerMove","onPointerUp","onLostPointerCapture","onKeyDown","onKeyUp"],"sources":["../../../../src/components/StackedCard/useStackedCardResize.ts"],"sourcesContent":["import React, { useCallback, useRef } from \"react\";\n\nimport {\n StackedCardContentMin,\n StackedCardResizeAxis,\n StackedCardResizePolicy,\n StackedCardResizeSource,\n StackedCardResizeStart,\n StackedCardSize,\n applyResize,\n isResizeKey,\n keyboardResize,\n makeStart,\n measurePercent,\n} from \"./resizePolicy\";\n\n/**\n * The one place pointer and keyboard input meet the resize policy.\n *\n * `StackedCard`'s built-in grip reports raw deltas and knows no policy — enough\n * for a host that just tracks a width. This hook is the full contract: it\n * captures the gesture start, funnels both inputs through the pure policy in\n * `resizePolicy.ts`, streams preview events and fires exactly ONE commit per\n * gesture. It returns the props to spread on the grip, including the live\n * separator ARIA.\n *\n * Preview versus commit (spec §7e): the continuous stream is live feedback\n * only. A host creates an undo entry on the COMMIT, never on a preview — and a\n * gesture that never changed the size commits nothing at all, so a bare click\n * on the grip is not a change.\n *\n * The hook never touches the card's content: the intrinsic minimum is read\n * through `contentMin`, which may be a getter so a card that measures its own\n * footer can answer at the moment it is asked.\n */\n\nexport interface UseStackedCardResizeArgs {\n /** The card's current size, owned by the host. */\n size: StackedCardSize;\n policy: StackedCardResizePolicy;\n /** Id of the element the grip resizes — becomes `aria-controls`. */\n cardId: string;\n /** The card's intrinsic minimum; a getter is read at the moment it is needed. */\n contentMin: StackedCardContentMin | (() => StackedCardContentMin);\n /** `width` locks the vertical axis (auto-height cards). Defaults to `both`. */\n axis?: StackedCardResizeAxis;\n /**\n * Pointer deltas are divided by this before they reach the policy, so a grip\n * inside a zoomed canvas tracks the cursor exactly. Keyboard nudges are\n * already in the host's units and pass straight through. Defaults to 1.\n */\n scale?: number;\n /** Accessible name for the grip. Defaults to \"Resize card\". */\n label?: string;\n /** Live feedback during the gesture. Never an undoable change. */\n onResize: (next: StackedCardSize, source: StackedCardResizeSource) => void;\n /** Fires once per gesture, and only if the size actually changed. */\n onResizeCommit: (\n final: StackedCardSize,\n source: StackedCardResizeSource\n ) => void;\n}\n\n/** The props to spread on the grip — `StackedCard`'s `resizeHandleProps`. */\nexport interface StackedCardResizeHandleProps {\n role: \"separator\";\n tabIndex: 0;\n \"aria-label\": string;\n \"aria-controls\": string;\n \"aria-valuemin\": number;\n \"aria-valuemax\": number;\n \"aria-valuenow\": number;\n onPointerDown: (e: React.PointerEvent) => void;\n onPointerMove: (e: React.PointerEvent) => void;\n onPointerUp: (e: React.PointerEvent) => void;\n onLostPointerCapture: (e: React.PointerEvent) => void;\n onKeyDown: (e: React.KeyboardEvent) => void;\n onKeyUp: (e: React.KeyboardEvent) => void;\n}\n\nconst sameSize = (a: StackedCardSize, b: StackedCardSize): boolean =>\n a.w === b.w && a.h === b.h;\n\nexport const useStackedCardResize = ({\n size,\n policy,\n cardId,\n contentMin,\n axis = \"both\",\n scale = 1,\n label = \"Resize card\",\n onResize,\n onResizeCommit,\n}: UseStackedCardResizeArgs): StackedCardResizeHandleProps => {\n // The pointer gesture's anchor: the size + content-min captured on pointer\n // down, plus the pointer origin the delta is measured from.\n const pointerStart = useRef<{\n start: StackedCardResizeStart;\n x: number;\n y: number;\n } | null>(null);\n // Mirrors the latest emitted size so pointer-up / key-up can commit exactly\n // what preview last showed, without a stale closure.\n const latest = useRef<StackedCardSize>(size);\n latest.current = size;\n // Whether this gesture actually moved the card. A bare click, or a Home on an\n // axis with no floor, leaves it false and commits nothing.\n const dirty = useRef(false);\n\n // Read through refs so the handlers below can stay stable across renders\n // while still seeing the current policy, axis and zoom.\n const policyRef = useRef(policy);\n policyRef.current = policy;\n const axisRef = useRef(axis);\n axisRef.current = axis;\n const scaleRef = useRef(scale);\n scaleRef.current = scale;\n const contentMinRef = useRef(contentMin);\n contentMinRef.current = contentMin;\n\n const readContentMin = useCallback((): StackedCardContentMin => {\n const source = contentMinRef.current;\n return typeof source === \"function\" ? source() : source;\n }, []);\n\n const emitPreview = useCallback(\n (next: StackedCardSize, source: StackedCardResizeSource) => {\n // Nothing changed — not a preview, and not something to commit later.\n if (sameSize(next, latest.current)) return;\n latest.current = next;\n dirty.current = true;\n onResize(next, source);\n },\n [onResize]\n );\n\n const handlePointerDown = useCallback(\n (e: React.PointerEvent) => {\n pointerStart.current = {\n start: makeStart(latest.current, readContentMin()),\n x: e.clientX,\n y: e.clientY,\n };\n dirty.current = false;\n (e.target as HTMLElement).setPointerCapture?.(e.pointerId);\n e.preventDefault();\n },\n [readContentMin]\n );\n\n const handlePointerMove = useCallback(\n (e: React.PointerEvent) => {\n const ps = pointerStart.current;\n if (!ps) return;\n const z = scaleRef.current || 1;\n const next = applyResize(\n ps.start,\n { dx: (e.clientX - ps.x) / z, dy: (e.clientY - ps.y) / z },\n policyRef.current,\n // Shift held during a free-form drag = temporary proportional lock.\n { constrain: e.shiftKey, axis: axisRef.current }\n );\n emitPreview(next, \"pointer\");\n },\n [emitPreview]\n );\n\n const endPointer = useCallback(() => {\n if (!pointerStart.current) return;\n pointerStart.current = null;\n if (dirty.current) onResizeCommit(latest.current, \"pointer\");\n dirty.current = false;\n }, [onResizeCommit]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n const next = keyboardResize(\n e.key,\n latest.current,\n policyRef.current,\n readContentMin(),\n { shiftKey: e.shiftKey, axis: axisRef.current }\n );\n if (!next) return;\n // The key is ours even when it resolves to no movement (already pinned at\n // a bound), so the browser must not also scroll the surface.\n e.preventDefault();\n emitPreview(next, \"keyboard\");\n },\n [emitPreview, readContentMin]\n );\n\n const handleKeyUp = useCallback(\n (e: React.KeyboardEvent) => {\n if (!isResizeKey(e.key)) return;\n // The gesture end for the keyboard is the key release: one commit per\n // hold, mirroring pointer-up after a stream of moves.\n if (dirty.current) onResizeCommit(latest.current, \"keyboard\");\n dirty.current = false;\n },\n [onResizeCommit]\n );\n\n return {\n role: \"separator\",\n tabIndex: 0,\n \"aria-label\": label,\n \"aria-controls\": cardId,\n \"aria-valuemin\": 0,\n \"aria-valuemax\": 100,\n \"aria-valuenow\": measurePercent(size, policy, readContentMin()),\n onPointerDown: handlePointerDown,\n onPointerMove: handlePointerMove,\n onPointerUp: endPointer,\n onLostPointerCapture: endPointer,\n onKeyDown: handleKeyDown,\n onKeyUp: handleKeyUp,\n };\n};\n"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"LinkCard.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/stackedCard/content/LinkCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAc5C,OAAO,EAAE,gBAAgB,EAAmB,MAAM,UAAU,CAAC;AAgB7D;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,UAAU,CAAC;AA+JjD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,gBAAgB,CAAC;IACzB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED,eAAO,MAAM,QAAQ,GAAI,uCAItB,aAAa,KAAG,YAiKlB,CAAC;AAyBF,eAAO,MAAM,YAAY,QAAO,YA0B/B,CAAC;AAIF,eAAO,MAAM,eAAe,GAC1B,OAAO,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,KACnD,YAEF,CAAC"}
1
+ {"version":3,"file":"LinkCard.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/stackedCard/content/LinkCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAc5C,OAAO,EAAE,gBAAgB,EAA+B,MAAM,UAAU,CAAC;AAsBzE;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,UAAU,CAAC;AA6KjD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,gBAAgB,CAAC;IACzB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED,eAAO,MAAM,QAAQ,GAAI,uCAItB,aAAa,KAAG,YAsKlB,CAAC;AAyBF,eAAO,MAAM,YAAY,QAAO,YA0B/B,CAAC;AAIF,eAAO,MAAM,eAAe,GAC1B,OAAO,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,KACnD,YAEF,CAAC"}
@@ -9,6 +9,11 @@ import { STACKED_CARD_COVER_RATIO as COVER_RATIO, STACKED_CARD_CONTROL_CLASS, St
9
9
  import { Body2, Caption1 } from "../../../components/Typography";
10
10
  import { Typography } from "../../../components/Typography/Typography";
11
11
 
12
+ /* There is no global CSS reset in this Storybook, so a raw <button> falls back
13
+ to the UA font (Arial) instead of the DS stack. Every button below is text, so
14
+ they all need it. */
15
+ const CONTROL_FONT = "-apple-system, BlinkMacSystemFont, \"Roboto\",\n \"Helvetica Neue\", Arial, sans-serif";
16
+
12
17
  /**
13
18
  * LinkCard — a link preview as a LIFECYCLE, not two static layouts.
14
19
  *
@@ -47,7 +52,7 @@ const StyledStaleStrip = styled.div.withConfig({
47
52
  const StyledReunfurl = styled.button.withConfig({
48
53
  displayName: "LinkCard__StyledReunfurl",
49
54
  componentId: "sc-qyea73-3"
50
- })(["display:inline-flex;align-items:center;gap:4px;flex:0 0 auto;padding:3px 8px;border:1px solid var(--border-primary);border-radius:6px;background:var(--page-paper-main);color:var(--color-theme-800);font-size:11px;cursor:pointer;svg{width:12px;height:12px;}&:hover{background:var(--color-theme-200);border-color:var(--sc-selection-ring);}"]);
55
+ })(["display:inline-flex;align-items:center;gap:4px;flex:0 0 auto;padding:3px 8px;border:1px solid var(--border-primary);border-radius:6px;background:var(--page-paper-main);color:var(--color-theme-800);font-family:", ";font-size:11px;cursor:pointer;svg{width:12px;height:12px;}&:hover{background:var(--color-theme-200);border-color:var(--sc-selection-ring);}"], CONTROL_FONT);
51
56
 
52
57
  /* The error body — favicon + raw URL + retry, no media (per spec §5). It is a
53
58
  column row like any other: the padding comes from the role, so the error
@@ -60,7 +65,21 @@ const StyledErrorRow = styled(StackRow).withConfig({
60
65
  const StyledRetry = styled.button.withConfig({
61
66
  displayName: "LinkCard__StyledRetry",
62
67
  componentId: "sc-qyea73-5"
63
- })(["align-self:flex-start;display:inline-flex;align-items:center;gap:6px;padding:5px 10px;border:1px solid var(--border-primary);border-radius:6px;background:var(--page-paper-main);color:var(--color-theme-800);cursor:pointer;svg{width:14px;height:14px;}&:hover{background:var(--color-theme-200);border-color:var(--sc-selection-ring);}"]);
68
+ })(["align-self:flex-start;display:inline-flex;align-items:center;gap:6px;padding:5px 10px;border:1px solid var(--border-primary);border-radius:6px;background:var(--page-paper-main);color:var(--color-theme-800);font-family:", ";cursor:pointer;svg{width:14px;height:14px;}&:hover{background:var(--color-theme-200);border-color:var(--sc-selection-ring);}"], CONTROL_FONT);
69
+
70
+ /* The resolved cover. A production unfurl stores the OpenGraph image, so when
71
+ the ladder returns one we render a real <img> (the Cover fill already gives
72
+ it `object-fit: cover`); the fill colour is the fallback for links that carry
73
+ no image at all. */
74
+ const resolvedCover = data => {
75
+ var _data$heroColor;
76
+ return data.heroSrc ? /*#__PURE__*/React.createElement("img", {
77
+ src: data.heroSrc,
78
+ alt: ""
79
+ }) : /*#__PURE__*/React.createElement(StyledColorCover, {
80
+ $color: (_data$heroColor = data.heroColor) != null ? _data$heroColor : "#1D9E75"
81
+ });
82
+ };
64
83
 
65
84
  /* The expanded footer band — tinted, holds the title + domain under the hero. */
66
85
  const StyledFooterTitle = styled(Body2).withConfig({
@@ -75,7 +94,7 @@ const StyledFooterTitle = styled(Body2).withConfig({
75
94
  const StyledDisplayToggle = styled.button.withConfig({
76
95
  displayName: "LinkCard__StyledDisplayToggle",
77
96
  componentId: "sc-qyea73-7"
78
- })(["display:inline-flex;align-items:center;padding:2px 8px;border:1px solid var(--border-primary);border-radius:10px;background:var(--color-theme-200);color:var(--color-theme-700);font-size:11px;cursor:pointer;white-space:nowrap;&:hover{background:var(--color-theme-300);}"]);
97
+ })(["display:inline-flex;align-items:center;padding:2px 8px;border:1px solid var(--border-primary);border-radius:10px;background:var(--color-theme-200);color:var(--color-theme-700);font-family:", ";font-size:11px;cursor:pointer;white-space:nowrap;&:hover{background:var(--color-theme-300);}"], CONTROL_FONT);
79
98
  const DisplayToggle = _ref => {
80
99
  let display = _ref.display,
81
100
  onToggle = _ref.onToggle;
@@ -93,7 +112,7 @@ const DisplayToggle = _ref => {
93
112
  /* ------------------------------------------------------------------ */
94
113
 
95
114
  export const LinkCard = _ref2 => {
96
- var _data$heroColor2, _data$faviconColor2;
115
+ var _data$faviconColor2;
97
116
  let unfurl = _ref2.unfurl,
98
117
  _ref2$display = _ref2.display,
99
118
  display = _ref2$display === void 0 ? "compact" : _ref2$display,
@@ -132,18 +151,22 @@ export const LinkCard = _ref2 => {
132
151
  }
133
152
  const hasBasic = tier === "basic" || tier === "full";
134
153
  const hasFull = tier === "full";
135
- const toggle = onToggleDisplay != null ? onToggleDisplay : () => undefined;
154
+ /* The display level belongs to the host, so the switch only appears when a
155
+ host actually owns one. A surface that fixes the card at one level (the
156
+ whiteboard pins it to expanded) gets no dead control. */
157
+ const toggle = onToggleDisplay ? /*#__PURE__*/React.createElement(DisplayToggle, {
158
+ display: display,
159
+ onToggle: onToggleDisplay
160
+ }) : null;
136
161
 
137
162
  // ── Expanded: hero + tinted footer band (title + domain) ────────
138
163
  if (display === "expanded") {
139
- var _data$heroColor, _data$faviconColor;
164
+ var _data$faviconColor;
140
165
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Cover, {
141
166
  aspectRatio: COVER_RATIO_HERO,
142
167
  centerSlot: hasFull && data.playable ? playControl : undefined,
143
168
  topRightSlot: coverManagement()
144
- }, hasFull ? /*#__PURE__*/React.createElement(StyledColorCover, {
145
- $color: (_data$heroColor = data.heroColor) != null ? _data$heroColor : "#1D9E75"
146
- }) : /*#__PURE__*/React.createElement(SkeletonLoader, {
169
+ }, hasFull ? resolvedCover(data) : /*#__PURE__*/React.createElement(SkeletonLoader, {
147
170
  style: {
148
171
  width: "100%",
149
172
  height: "100%"
@@ -170,10 +193,7 @@ export const LinkCard = _ref2 => {
170
193
  style: {
171
194
  flex: "1 1 auto"
172
195
  }
173
- }), /*#__PURE__*/React.createElement(DisplayToggle, {
174
- display: display,
175
- onToggle: toggle
176
- })), hasBasic ? /*#__PURE__*/React.createElement(StyledFooterTitle, {
196
+ }), toggle), hasBasic ? /*#__PURE__*/React.createElement(StyledFooterTitle, {
177
197
  weight: "bold"
178
198
  }, data.title) : /*#__PURE__*/React.createElement(SkeletonLoader, {
179
199
  style: {
@@ -199,9 +219,7 @@ export const LinkCard = _ref2 => {
199
219
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Cover, {
200
220
  aspectRatio: COVER_RATIO,
201
221
  centerSlot: hasFull && data.playable ? playControl : undefined
202
- }, hasFull ? /*#__PURE__*/React.createElement(StyledColorCover, {
203
- $color: (_data$heroColor2 = data.heroColor) != null ? _data$heroColor2 : "#1D9E75"
204
- }) : /*#__PURE__*/React.createElement(SkeletonLoader, {
222
+ }, hasFull ? resolvedCover(data) : /*#__PURE__*/React.createElement(SkeletonLoader, {
205
223
  style: {
206
224
  width: "100%",
207
225
  height: "100%"
@@ -226,10 +244,7 @@ export const LinkCard = _ref2 => {
226
244
  style: {
227
245
  flex: "1 1 auto"
228
246
  }
229
- }), /*#__PURE__*/React.createElement(DisplayToggle, {
230
- display: display,
231
- onToggle: toggle
232
- }))), /*#__PURE__*/React.createElement(StackRow, {
247
+ }), toggle)), /*#__PURE__*/React.createElement(StackRow, {
233
248
  role: "title"
234
249
  }, hasBasic ? /*#__PURE__*/React.createElement(StyledClamp, null, data.title) : /*#__PURE__*/React.createElement("div", {
235
250
  style: {
@@ -1 +1 @@
1
- {"version":3,"file":"LinkCard.js","names":["React","styled","COVER_RATIO_HERO","StyledChip","StyledClamp","StyledColorCover","StyledFavicon","coverManagement","playControl","Placeholder","formatFetchedAt","ArrowRefreshIcon","InsertLinkIcon","WarningTriangleIcon","SkeletonLoader","STACKED_CARD_COVER_RATIO","COVER_RATIO","STACKED_CARD_CONTROL_CLASS","StackedCardCover","Cover","StackedCardRow","StackRow","Body2","Caption1","Typography","StyledDomainRow","div","withConfig","displayName","componentId","StyledChips","StyledStaleStrip","StyledReunfurl","button","StyledErrorRow","StyledRetry","StyledFooterTitle","StyledDisplayToggle","DisplayToggle","_ref","display","onToggle","createElement","type","className","onClick","LinkCard","_ref2","_data$heroColor2","_data$faviconColor2","unfurl","_ref2$display","onToggleDisplay","status","tier","data","fetchedAt","retry","reunfurl","role","direction","weight","color","$bg","url","as","variant","hasBasic","hasFull","toggle","undefined","_data$heroColor","_data$faviconColor","Fragment","aspectRatio","centerSlot","playable","topRightSlot","$color","heroColor","style","width","height","background","faviconColor","borderRadius","domain","flex","title","description","StaleStrip","onReunfurl","marginTop","kind","duration","_ref3","LinkSkeleton","LinkPlaceholder","props","_extends","icon","label"],"sources":["../../../../../src/presentation/stackedCard/content/LinkCard.tsx"],"sourcesContent":["import React, { ReactElement } from \"react\";\n\nimport styled from \"styled-components\";\n\nimport {\n COVER_RATIO_HERO,\n StyledChip,\n StyledClamp,\n StyledColorCover,\n StyledFavicon,\n coverManagement,\n playControl,\n Placeholder,\n} from \"./shared\";\nimport { UnfurlController, formatFetchedAt } from \"./unfurl\";\nimport {\n ArrowRefreshIcon,\n InsertLinkIcon,\n WarningTriangleIcon,\n} from \"../../../components/Icons\";\nimport { SkeletonLoader } from \"../../../components/Loaders\";\nimport {\n STACKED_CARD_COVER_RATIO as COVER_RATIO,\n STACKED_CARD_CONTROL_CLASS,\n StackedCardCover as Cover,\n StackedCardRow as StackRow,\n} from \"../../../components/StackedCard\";\nimport { Body2, Caption1 } from \"../../../components/Typography\";\nimport { Typography } from \"../../../components/Typography/Typography\";\n\n/**\n * LinkCard — a link preview as a LIFECYCLE, not two static layouts.\n *\n * Data climbs a progressive ladder (url → basic → full); the anatomy is\n * CONSTANT at every tier, so each slot swaps a skeleton for real content in\n * place and the card never reflows on upgrade. Four statuses layer on top:\n * resolving — climbing the ladder, aspect + rows reserved by skeletons\n * resolved — the full card\n * stale — resolved, but past its cache window: shows `fetchedAt` and a\n * re-unfurl affordance\n * error — the unfurl failed: favicon + raw URL + retry, NO media\n *\n * Compact ↔ expanded is a user-switchable DISPLAY LEVEL on the same link\n * entity (the data lives in the controller, so switching never refetches or\n * loses it) — not two separate card types.\n */\n\nexport type LinkDisplay = \"compact\" | \"expanded\";\n\n/* ------------------------------------------------------------------ */\n/* Small building blocks */\n/* ------------------------------------------------------------------ */\n\nconst StyledDomainRow = styled.div`\n display: flex;\n align-items: center;\n gap: 8px;\n min-height: 16px;\n`;\n\nconst StyledChips = styled.div`\n display: flex;\n align-items: center;\n gap: 6px;\n min-height: 18px;\n`;\n\n/* The stale strip — a re-unfurl affordance with the fetch time. */\nconst StyledStaleStrip = styled.div`\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--color-theme-600);\n\n > span {\n flex: 1 1 auto;\n min-width: 0;\n }\n`;\n\nconst StyledReunfurl = styled.button`\n display: inline-flex;\n align-items: center;\n gap: 4px;\n flex: 0 0 auto;\n padding: 3px 8px;\n border: 1px solid var(--border-primary);\n border-radius: 6px;\n background: var(--page-paper-main);\n color: var(--color-theme-800);\n font-size: 11px;\n cursor: pointer;\n\n svg {\n width: 12px;\n height: 12px;\n }\n\n &:hover {\n background: var(--color-theme-200);\n border-color: var(--sc-selection-ring);\n }\n`;\n\n/* The error body — favicon + raw URL + retry, no media (per spec §5). It is a\n column row like any other: the padding comes from the role, so the error\n state lines up with the states it replaces instead of setting its own inset.\n Only the gap is widened — three stacked blocks, not four text lines. */\nconst StyledErrorRow = styled(StackRow)`\n gap: 10px;\n\n .err-head {\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--red-alert);\n }\n\n .err-head svg {\n width: 16px;\n height: 16px;\n flex: 0 0 auto;\n }\n\n .err-url {\n display: flex;\n align-items: center;\n gap: 8px;\n word-break: break-all;\n }\n`;\n\nconst StyledRetry = styled.button`\n align-self: flex-start;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 5px 10px;\n border: 1px solid var(--border-primary);\n border-radius: 6px;\n background: var(--page-paper-main);\n color: var(--color-theme-800);\n cursor: pointer;\n\n svg {\n width: 14px;\n height: 14px;\n }\n\n &:hover {\n background: var(--color-theme-200);\n border-color: var(--sc-selection-ring);\n }\n`;\n\n/* The expanded footer band — tinted, holds the title + domain under the hero. */\nconst StyledFooterTitle = styled(Body2)`\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n`;\n\n/* ------------------------------------------------------------------ */\n/* The display-level switch — lives in the entity \"…\" slot */\n/* ------------------------------------------------------------------ */\n\nconst StyledDisplayToggle = styled.button`\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n border: 1px solid var(--border-primary);\n border-radius: 10px;\n background: var(--color-theme-200);\n color: var(--color-theme-700);\n font-size: 11px;\n cursor: pointer;\n white-space: nowrap;\n\n &:hover {\n background: var(--color-theme-300);\n }\n`;\n\nconst DisplayToggle = ({\n display,\n onToggle,\n}: {\n display: LinkDisplay;\n onToggle: () => void;\n}): ReactElement => (\n <StyledDisplayToggle\n type=\"button\"\n data-fixed\n className={STACKED_CARD_CONTROL_CLASS}\n aria-label=\"Switch display level\"\n onClick={onToggle}\n >\n {display === \"compact\" ? \"Expand ▾\" : \"Compact ▴\"}\n </StyledDisplayToggle>\n);\n\n/* ------------------------------------------------------------------ */\n/* LinkCard */\n/* ------------------------------------------------------------------ */\n\nexport interface LinkCardProps {\n unfurl: UnfurlController;\n display?: LinkDisplay;\n onToggleDisplay?: () => void;\n}\n\nexport const LinkCard = ({\n unfurl,\n display = \"compact\",\n onToggleDisplay,\n}: LinkCardProps): ReactElement => {\n const { status, tier, data, fetchedAt, retry, reunfurl } = unfurl;\n\n // ── Error: favicon + raw URL + retry, no media ──────────────────\n if (status === \"error\") {\n return (\n <StyledErrorRow role=\"custom\" direction=\"column\">\n <div className=\"err-head\">\n <WarningTriangleIcon />\n <Caption1 weight=\"bold\" color=\"tertiary\">\n Couldn’t load a preview\n </Caption1>\n </div>\n <div className=\"err-url\">\n <StyledFavicon $bg=\"var(--color-theme-400)\" data-fixed />\n <Caption1 color=\"secondary\">{data.url}</Caption1>\n </div>\n <StyledRetry type=\"button\" onClick={retry}>\n <ArrowRefreshIcon />\n <Typography as=\"span\" variant=\"Caption 1\">\n Retry\n </Typography>\n </StyledRetry>\n </StyledErrorRow>\n );\n }\n\n const hasBasic = tier === \"basic\" || tier === \"full\";\n const hasFull = tier === \"full\";\n const toggle = onToggleDisplay ?? (() => undefined);\n\n // ── Expanded: hero + tinted footer band (title + domain) ────────\n if (display === \"expanded\") {\n return (\n <>\n <Cover\n aspectRatio={COVER_RATIO_HERO}\n centerSlot={hasFull && data.playable ? playControl : undefined}\n topRightSlot={coverManagement()}\n >\n {hasFull ? (\n <StyledColorCover $color={data.heroColor ?? \"#1D9E75\"} />\n ) : (\n <SkeletonLoader style={{ width: \"100%\", height: \"100%\" }} />\n )}\n </Cover>\n <StackRow\n role=\"footer\"\n direction=\"column\"\n background=\"var(--color-theme-200)\"\n >\n <StyledDomainRow>\n {hasBasic ? (\n <StyledFavicon $bg={data.faviconColor ?? \"#0F6E56\"} data-fixed />\n ) : (\n <SkeletonLoader\n data-fixed\n style={{ width: 16, height: 16, borderRadius: 4 }}\n />\n )}\n {hasBasic ? (\n <Caption1 color=\"tertiary\">{data.domain}</Caption1>\n ) : (\n <Caption1 color=\"tertiary\">{data.url}</Caption1>\n )}\n <span style={{ flex: \"1 1 auto\" }} />\n <DisplayToggle display={display} onToggle={toggle} />\n </StyledDomainRow>\n {hasBasic ? (\n <StyledFooterTitle weight=\"bold\">{data.title}</StyledFooterTitle>\n ) : (\n <SkeletonLoader style={{ height: 14, width: \"90%\" }} />\n )}\n {hasFull ? (\n <Caption1 color=\"tertiary\">{data.description}</Caption1>\n ) : (\n <SkeletonLoader style={{ height: 10, width: \"70%\" }} />\n )}\n </StackRow>\n {status === \"stale\" ? (\n <StackRow role=\"meta\">\n <StaleStrip fetchedAt={fetchedAt} onReunfurl={reunfurl} />\n </StackRow>\n ) : null}\n </>\n );\n }\n\n // ── Compact: cover + favicon/domain + title + chips ─────────────\n return (\n <>\n <Cover\n aspectRatio={COVER_RATIO}\n centerSlot={hasFull && data.playable ? playControl : undefined}\n >\n {hasFull ? (\n <StyledColorCover $color={data.heroColor ?? \"#1D9E75\"} />\n ) : (\n <SkeletonLoader style={{ width: \"100%\", height: \"100%\" }} />\n )}\n </Cover>\n\n <StackRow role=\"custom\">\n <StyledDomainRow>\n {hasBasic ? (\n <StyledFavicon $bg={data.faviconColor ?? \"#0F6E56\"} data-fixed />\n ) : (\n <SkeletonLoader\n data-fixed\n style={{ width: 16, height: 16, borderRadius: 4 }}\n />\n )}\n {hasBasic ? (\n <Caption1 color=\"tertiary\">{data.domain}</Caption1>\n ) : (\n <Caption1 color=\"tertiary\">{data.url}</Caption1>\n )}\n <span style={{ flex: \"1 1 auto\" }} />\n <DisplayToggle display={display} onToggle={toggle} />\n </StyledDomainRow>\n </StackRow>\n\n <StackRow role=\"title\">\n {hasBasic ? (\n <StyledClamp>{data.title}</StyledClamp>\n ) : (\n <div style={{ width: \"100%\" }}>\n <SkeletonLoader style={{ height: 14, width: \"92%\" }} />\n <SkeletonLoader\n style={{ height: 14, width: \"60%\", marginTop: 6 }}\n />\n </div>\n )}\n </StackRow>\n\n <StackRow role=\"custom\">\n <StyledChips>\n {hasFull ? (\n <>\n {data.kind ? (\n <StyledChip data-fixed>{data.kind}</StyledChip>\n ) : null}\n {data.duration ? (\n <StyledChip data-fixed>{data.duration}</StyledChip>\n ) : null}\n </>\n ) : (\n <SkeletonLoader\n style={{ height: 18, width: 96, borderRadius: 10 }}\n />\n )}\n </StyledChips>\n </StackRow>\n\n {status === \"stale\" ? (\n <StackRow role=\"meta\">\n <StaleStrip fetchedAt={fetchedAt} onReunfurl={reunfurl} />\n </StackRow>\n ) : null}\n </>\n );\n};\n\n/* The stale affordance — fetch time + a manual re-unfurl button. */\nconst StaleStrip = ({\n fetchedAt,\n onReunfurl,\n}: {\n fetchedAt: number | null;\n onReunfurl: () => void;\n}): ReactElement => (\n <StyledStaleStrip>\n <Typography as=\"span\" variant=\"Caption 1\" color=\"tertiary\">\n Preview may be out of date · fetched {formatFetchedAt(fetchedAt)}\n </Typography>\n <StyledReunfurl type=\"button\" onClick={onReunfurl}>\n <ArrowRefreshIcon />\n Re-unfurl\n </StyledReunfurl>\n </StyledStaleStrip>\n);\n\n/* ---- skeleton ---- */\n\n/* Mirrors the compact anatomy row for row (this is the `resolving` render at\n tier `url`), so a resolving link never reflows as it climbs the ladder. */\nexport const LinkSkeleton = (): ReactElement => (\n <>\n <Cover aspectRatio={COVER_RATIO}>\n <SkeletonLoader style={{ width: \"100%\", height: \"100%\" }} />\n </Cover>\n <StackRow role=\"custom\">\n <StyledDomainRow>\n <SkeletonLoader\n data-fixed\n style={{ width: 16, height: 16, borderRadius: 4 }}\n />\n <SkeletonLoader style={{ height: 10, width: \"40%\" }} />\n </StyledDomainRow>\n </StackRow>\n <StackRow role=\"title\">\n <div style={{ width: \"100%\" }}>\n <SkeletonLoader style={{ height: 14, width: \"92%\" }} />\n <SkeletonLoader style={{ height: 14, width: \"60%\", marginTop: 6 }} />\n </div>\n </StackRow>\n <StackRow role=\"custom\">\n <StyledChips>\n <SkeletonLoader style={{ height: 18, width: 96, borderRadius: 10 }} />\n </StyledChips>\n </StackRow>\n </>\n);\n\n/* ---- placeholder ---- */\n\nexport const LinkPlaceholder = (\n props: React.ButtonHTMLAttributes<HTMLButtonElement>\n): ReactElement => (\n <Placeholder icon={<InsertLinkIcon />} label=\"Add a link\" {...props} />\n);\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"LinkCard.js","names":["React","styled","COVER_RATIO_HERO","StyledChip","StyledClamp","StyledColorCover","StyledFavicon","coverManagement","playControl","Placeholder","formatFetchedAt","ArrowRefreshIcon","InsertLinkIcon","WarningTriangleIcon","SkeletonLoader","STACKED_CARD_COVER_RATIO","COVER_RATIO","STACKED_CARD_CONTROL_CLASS","StackedCardCover","Cover","StackedCardRow","StackRow","Body2","Caption1","Typography","CONTROL_FONT","StyledDomainRow","div","withConfig","displayName","componentId","StyledChips","StyledStaleStrip","StyledReunfurl","button","StyledErrorRow","StyledRetry","resolvedCover","data","_data$heroColor","heroSrc","createElement","src","alt","$color","heroColor","StyledFooterTitle","StyledDisplayToggle","DisplayToggle","_ref","display","onToggle","type","className","onClick","LinkCard","_ref2","_data$faviconColor2","unfurl","_ref2$display","onToggleDisplay","status","tier","fetchedAt","retry","reunfurl","role","direction","weight","color","$bg","url","as","variant","hasBasic","hasFull","toggle","_data$faviconColor","Fragment","aspectRatio","centerSlot","playable","undefined","topRightSlot","style","width","height","background","faviconColor","borderRadius","domain","flex","title","description","StaleStrip","onReunfurl","marginTop","kind","duration","_ref3","LinkSkeleton","LinkPlaceholder","props","_extends","icon","label"],"sources":["../../../../../src/presentation/stackedCard/content/LinkCard.tsx"],"sourcesContent":["import React, { ReactElement } from \"react\";\n\nimport styled from \"styled-components\";\n\nimport {\n COVER_RATIO_HERO,\n StyledChip,\n StyledClamp,\n StyledColorCover,\n StyledFavicon,\n coverManagement,\n playControl,\n Placeholder,\n} from \"./shared\";\nimport { UnfurlController, UnfurlData, formatFetchedAt } from \"./unfurl\";\nimport {\n ArrowRefreshIcon,\n InsertLinkIcon,\n WarningTriangleIcon,\n} from \"../../../components/Icons\";\nimport { SkeletonLoader } from \"../../../components/Loaders\";\nimport {\n STACKED_CARD_COVER_RATIO as COVER_RATIO,\n STACKED_CARD_CONTROL_CLASS,\n StackedCardCover as Cover,\n StackedCardRow as StackRow,\n} from \"../../../components/StackedCard\";\nimport { Body2, Caption1 } from \"../../../components/Typography\";\nimport { Typography } from \"../../../components/Typography/Typography\";\n\n/* There is no global CSS reset in this Storybook, so a raw <button> falls back\n to the UA font (Arial) instead of the DS stack. Every button below is text, so\n they all need it. */\nconst CONTROL_FONT = `-apple-system, BlinkMacSystemFont, \"Roboto\",\n \"Helvetica Neue\", Arial, sans-serif`;\n\n/**\n * LinkCard — a link preview as a LIFECYCLE, not two static layouts.\n *\n * Data climbs a progressive ladder (url → basic → full); the anatomy is\n * CONSTANT at every tier, so each slot swaps a skeleton for real content in\n * place and the card never reflows on upgrade. Four statuses layer on top:\n * resolving — climbing the ladder, aspect + rows reserved by skeletons\n * resolved — the full card\n * stale — resolved, but past its cache window: shows `fetchedAt` and a\n * re-unfurl affordance\n * error — the unfurl failed: favicon + raw URL + retry, NO media\n *\n * Compact ↔ expanded is a user-switchable DISPLAY LEVEL on the same link\n * entity (the data lives in the controller, so switching never refetches or\n * loses it) — not two separate card types.\n */\n\nexport type LinkDisplay = \"compact\" | \"expanded\";\n\n/* ------------------------------------------------------------------ */\n/* Small building blocks */\n/* ------------------------------------------------------------------ */\n\nconst StyledDomainRow = styled.div`\n display: flex;\n align-items: center;\n gap: 8px;\n min-height: 16px;\n`;\n\nconst StyledChips = styled.div`\n display: flex;\n align-items: center;\n gap: 6px;\n min-height: 18px;\n`;\n\n/* The stale strip — a re-unfurl affordance with the fetch time. */\nconst StyledStaleStrip = styled.div`\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--color-theme-600);\n\n > span {\n flex: 1 1 auto;\n min-width: 0;\n }\n`;\n\nconst StyledReunfurl = styled.button`\n display: inline-flex;\n align-items: center;\n gap: 4px;\n flex: 0 0 auto;\n padding: 3px 8px;\n border: 1px solid var(--border-primary);\n border-radius: 6px;\n background: var(--page-paper-main);\n color: var(--color-theme-800);\n font-family: ${CONTROL_FONT};\n font-size: 11px;\n cursor: pointer;\n\n svg {\n width: 12px;\n height: 12px;\n }\n\n &:hover {\n background: var(--color-theme-200);\n border-color: var(--sc-selection-ring);\n }\n`;\n\n/* The error body — favicon + raw URL + retry, no media (per spec §5). It is a\n column row like any other: the padding comes from the role, so the error\n state lines up with the states it replaces instead of setting its own inset.\n Only the gap is widened — three stacked blocks, not four text lines. */\nconst StyledErrorRow = styled(StackRow)`\n gap: 10px;\n\n .err-head {\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--red-alert);\n }\n\n .err-head svg {\n width: 16px;\n height: 16px;\n flex: 0 0 auto;\n }\n\n .err-url {\n display: flex;\n align-items: center;\n gap: 8px;\n word-break: break-all;\n }\n`;\n\nconst StyledRetry = styled.button`\n align-self: flex-start;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 5px 10px;\n border: 1px solid var(--border-primary);\n border-radius: 6px;\n background: var(--page-paper-main);\n color: var(--color-theme-800);\n font-family: ${CONTROL_FONT};\n cursor: pointer;\n\n svg {\n width: 14px;\n height: 14px;\n }\n\n &:hover {\n background: var(--color-theme-200);\n border-color: var(--sc-selection-ring);\n }\n`;\n\n/* The resolved cover. A production unfurl stores the OpenGraph image, so when\n the ladder returns one we render a real <img> (the Cover fill already gives\n it `object-fit: cover`); the fill colour is the fallback for links that carry\n no image at all. */\nconst resolvedCover = (data: UnfurlData): ReactElement =>\n data.heroSrc ? (\n <img src={data.heroSrc} alt=\"\" />\n ) : (\n <StyledColorCover $color={data.heroColor ?? \"#1D9E75\"} />\n );\n\n/* The expanded footer band — tinted, holds the title + domain under the hero. */\nconst StyledFooterTitle = styled(Body2)`\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n`;\n\n/* ------------------------------------------------------------------ */\n/* The display-level switch — lives in the entity \"…\" slot */\n/* ------------------------------------------------------------------ */\n\nconst StyledDisplayToggle = styled.button`\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n border: 1px solid var(--border-primary);\n border-radius: 10px;\n background: var(--color-theme-200);\n color: var(--color-theme-700);\n font-family: ${CONTROL_FONT};\n font-size: 11px;\n cursor: pointer;\n white-space: nowrap;\n\n &:hover {\n background: var(--color-theme-300);\n }\n`;\n\nconst DisplayToggle = ({\n display,\n onToggle,\n}: {\n display: LinkDisplay;\n onToggle: () => void;\n}): ReactElement => (\n <StyledDisplayToggle\n type=\"button\"\n data-fixed\n className={STACKED_CARD_CONTROL_CLASS}\n aria-label=\"Switch display level\"\n onClick={onToggle}\n >\n {display === \"compact\" ? \"Expand ▾\" : \"Compact ▴\"}\n </StyledDisplayToggle>\n);\n\n/* ------------------------------------------------------------------ */\n/* LinkCard */\n/* ------------------------------------------------------------------ */\n\nexport interface LinkCardProps {\n unfurl: UnfurlController;\n display?: LinkDisplay;\n onToggleDisplay?: () => void;\n}\n\nexport const LinkCard = ({\n unfurl,\n display = \"compact\",\n onToggleDisplay,\n}: LinkCardProps): ReactElement => {\n const { status, tier, data, fetchedAt, retry, reunfurl } = unfurl;\n\n // ── Error: favicon + raw URL + retry, no media ──────────────────\n if (status === \"error\") {\n return (\n <StyledErrorRow role=\"custom\" direction=\"column\">\n <div className=\"err-head\">\n <WarningTriangleIcon />\n <Caption1 weight=\"bold\" color=\"tertiary\">\n Couldn’t load a preview\n </Caption1>\n </div>\n <div className=\"err-url\">\n <StyledFavicon $bg=\"var(--color-theme-400)\" data-fixed />\n <Caption1 color=\"secondary\">{data.url}</Caption1>\n </div>\n <StyledRetry type=\"button\" onClick={retry}>\n <ArrowRefreshIcon />\n <Typography as=\"span\" variant=\"Caption 1\">\n Retry\n </Typography>\n </StyledRetry>\n </StyledErrorRow>\n );\n }\n\n const hasBasic = tier === \"basic\" || tier === \"full\";\n const hasFull = tier === \"full\";\n /* The display level belongs to the host, so the switch only appears when a\n host actually owns one. A surface that fixes the card at one level (the\n whiteboard pins it to expanded) gets no dead control. */\n const toggle = onToggleDisplay ? (\n <DisplayToggle display={display} onToggle={onToggleDisplay} />\n ) : null;\n\n // ── Expanded: hero + tinted footer band (title + domain) ────────\n if (display === \"expanded\") {\n return (\n <>\n <Cover\n aspectRatio={COVER_RATIO_HERO}\n centerSlot={hasFull && data.playable ? playControl : undefined}\n topRightSlot={coverManagement()}\n >\n {hasFull ? (\n resolvedCover(data)\n ) : (\n <SkeletonLoader style={{ width: \"100%\", height: \"100%\" }} />\n )}\n </Cover>\n <StackRow\n role=\"footer\"\n direction=\"column\"\n background=\"var(--color-theme-200)\"\n >\n <StyledDomainRow>\n {hasBasic ? (\n <StyledFavicon $bg={data.faviconColor ?? \"#0F6E56\"} data-fixed />\n ) : (\n <SkeletonLoader\n data-fixed\n style={{ width: 16, height: 16, borderRadius: 4 }}\n />\n )}\n {hasBasic ? (\n <Caption1 color=\"tertiary\">{data.domain}</Caption1>\n ) : (\n <Caption1 color=\"tertiary\">{data.url}</Caption1>\n )}\n <span style={{ flex: \"1 1 auto\" }} />\n {toggle}\n </StyledDomainRow>\n {hasBasic ? (\n <StyledFooterTitle weight=\"bold\">{data.title}</StyledFooterTitle>\n ) : (\n <SkeletonLoader style={{ height: 14, width: \"90%\" }} />\n )}\n {hasFull ? (\n <Caption1 color=\"tertiary\">{data.description}</Caption1>\n ) : (\n <SkeletonLoader style={{ height: 10, width: \"70%\" }} />\n )}\n </StackRow>\n {status === \"stale\" ? (\n <StackRow role=\"meta\">\n <StaleStrip fetchedAt={fetchedAt} onReunfurl={reunfurl} />\n </StackRow>\n ) : null}\n </>\n );\n }\n\n // ── Compact: cover + favicon/domain + title + chips ─────────────\n return (\n <>\n <Cover\n aspectRatio={COVER_RATIO}\n centerSlot={hasFull && data.playable ? playControl : undefined}\n >\n {hasFull ? (\n resolvedCover(data)\n ) : (\n <SkeletonLoader style={{ width: \"100%\", height: \"100%\" }} />\n )}\n </Cover>\n\n <StackRow role=\"custom\">\n <StyledDomainRow>\n {hasBasic ? (\n <StyledFavicon $bg={data.faviconColor ?? \"#0F6E56\"} data-fixed />\n ) : (\n <SkeletonLoader\n data-fixed\n style={{ width: 16, height: 16, borderRadius: 4 }}\n />\n )}\n {hasBasic ? (\n <Caption1 color=\"tertiary\">{data.domain}</Caption1>\n ) : (\n <Caption1 color=\"tertiary\">{data.url}</Caption1>\n )}\n <span style={{ flex: \"1 1 auto\" }} />\n {toggle}\n </StyledDomainRow>\n </StackRow>\n\n <StackRow role=\"title\">\n {hasBasic ? (\n <StyledClamp>{data.title}</StyledClamp>\n ) : (\n <div style={{ width: \"100%\" }}>\n <SkeletonLoader style={{ height: 14, width: \"92%\" }} />\n <SkeletonLoader\n style={{ height: 14, width: \"60%\", marginTop: 6 }}\n />\n </div>\n )}\n </StackRow>\n\n <StackRow role=\"custom\">\n <StyledChips>\n {hasFull ? (\n <>\n {data.kind ? (\n <StyledChip data-fixed>{data.kind}</StyledChip>\n ) : null}\n {data.duration ? (\n <StyledChip data-fixed>{data.duration}</StyledChip>\n ) : null}\n </>\n ) : (\n <SkeletonLoader\n style={{ height: 18, width: 96, borderRadius: 10 }}\n />\n )}\n </StyledChips>\n </StackRow>\n\n {status === \"stale\" ? (\n <StackRow role=\"meta\">\n <StaleStrip fetchedAt={fetchedAt} onReunfurl={reunfurl} />\n </StackRow>\n ) : null}\n </>\n );\n};\n\n/* The stale affordance — fetch time + a manual re-unfurl button. */\nconst StaleStrip = ({\n fetchedAt,\n onReunfurl,\n}: {\n fetchedAt: number | null;\n onReunfurl: () => void;\n}): ReactElement => (\n <StyledStaleStrip>\n <Typography as=\"span\" variant=\"Caption 1\" color=\"tertiary\">\n Preview may be out of date · fetched {formatFetchedAt(fetchedAt)}\n </Typography>\n <StyledReunfurl type=\"button\" onClick={onReunfurl}>\n <ArrowRefreshIcon />\n Re-unfurl\n </StyledReunfurl>\n </StyledStaleStrip>\n);\n\n/* ---- skeleton ---- */\n\n/* Mirrors the compact anatomy row for row (this is the `resolving` render at\n tier `url`), so a resolving link never reflows as it climbs the ladder. */\nexport const LinkSkeleton = (): ReactElement => (\n <>\n <Cover aspectRatio={COVER_RATIO}>\n <SkeletonLoader style={{ width: \"100%\", height: \"100%\" }} />\n </Cover>\n <StackRow role=\"custom\">\n <StyledDomainRow>\n <SkeletonLoader\n data-fixed\n style={{ width: 16, height: 16, borderRadius: 4 }}\n />\n <SkeletonLoader style={{ height: 10, width: \"40%\" }} />\n </StyledDomainRow>\n </StackRow>\n <StackRow role=\"title\">\n <div style={{ width: \"100%\" }}>\n <SkeletonLoader style={{ height: 14, width: \"92%\" }} />\n <SkeletonLoader style={{ height: 14, width: \"60%\", marginTop: 6 }} />\n </div>\n </StackRow>\n <StackRow role=\"custom\">\n <StyledChips>\n <SkeletonLoader style={{ height: 18, width: 96, borderRadius: 10 }} />\n </StyledChips>\n </StackRow>\n </>\n);\n\n/* ---- placeholder ---- */\n\nexport const LinkPlaceholder = (\n props: React.ButtonHTMLAttributes<HTMLButtonElement>\n): ReactElement => (\n <Placeholder icon={<InsertLinkIcon />} label=\"Add a link\" {...props} />\n);\n"],"mappings":"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","ignoreList":[]}