@_linked/primitives 1.1.0 → 1.2.0

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 (64) hide show
  1. package/.github/workflows/publish.yml +74 -7
  2. package/CHANGELOG.md +55 -0
  3. package/README.md +62 -0
  4. package/lib/cjs/components/ConfirmDialog.d.ts +37 -0
  5. package/lib/cjs/components/ConfirmDialog.js +68 -0
  6. package/lib/cjs/components/ConfirmDialog.js.map +1 -0
  7. package/lib/cjs/components/ConfirmDialog.module.css +22 -0
  8. package/lib/cjs/components/ImageThumb.d.ts +17 -0
  9. package/lib/cjs/components/ImageThumb.js +90 -0
  10. package/lib/cjs/components/ImageThumb.js.map +1 -0
  11. package/lib/cjs/components/ImageThumb.module.css +134 -0
  12. package/lib/cjs/components/SkeletonLoader.d.ts +14 -0
  13. package/lib/cjs/components/SkeletonLoader.js +71 -0
  14. package/lib/cjs/components/SkeletonLoader.js.map +1 -0
  15. package/lib/cjs/components/SkeletonLoader.module.css +83 -0
  16. package/lib/cjs/components/Spinner.d.ts +22 -3
  17. package/lib/cjs/components/Spinner.js +55 -3
  18. package/lib/cjs/components/Spinner.js.map +1 -1
  19. package/lib/cjs/components/Spinner.module.css +57 -10
  20. package/lib/cjs/components/TruncatedText.d.ts +16 -0
  21. package/lib/cjs/components/TruncatedText.js +130 -0
  22. package/lib/cjs/components/TruncatedText.js.map +1 -0
  23. package/lib/cjs/components/TruncatedText.module.css +162 -0
  24. package/lib/cjs/hooks/useReducedMotion.d.ts +12 -0
  25. package/lib/cjs/hooks/useReducedMotion.js +35 -0
  26. package/lib/cjs/hooks/useReducedMotion.js.map +1 -0
  27. package/lib/cjs/index.d.ts +5 -0
  28. package/lib/cjs/index.js +21 -0
  29. package/lib/cjs/index.js.map +1 -1
  30. package/lib/cjs/motion.d.ts +219 -0
  31. package/lib/cjs/motion.js +154 -0
  32. package/lib/cjs/motion.js.map +1 -0
  33. package/lib/cjs/package.json +6 -6
  34. package/lib/esm/components/ConfirmDialog.d.ts +37 -0
  35. package/lib/esm/components/ConfirmDialog.js +29 -0
  36. package/lib/esm/components/ConfirmDialog.js.map +1 -0
  37. package/lib/esm/components/ConfirmDialog.module.css +22 -0
  38. package/lib/esm/components/ImageThumb.d.ts +17 -0
  39. package/lib/esm/components/ImageThumb.js +50 -0
  40. package/lib/esm/components/ImageThumb.js.map +1 -0
  41. package/lib/esm/components/ImageThumb.module.css +134 -0
  42. package/lib/esm/components/SkeletonLoader.d.ts +14 -0
  43. package/lib/esm/components/SkeletonLoader.js +31 -0
  44. package/lib/esm/components/SkeletonLoader.js.map +1 -0
  45. package/lib/esm/components/SkeletonLoader.module.css +83 -0
  46. package/lib/esm/components/Spinner.d.ts +22 -3
  47. package/lib/esm/components/Spinner.js +22 -3
  48. package/lib/esm/components/Spinner.js.map +1 -1
  49. package/lib/esm/components/Spinner.module.css +57 -10
  50. package/lib/esm/components/TruncatedText.d.ts +16 -0
  51. package/lib/esm/components/TruncatedText.js +83 -0
  52. package/lib/esm/components/TruncatedText.js.map +1 -0
  53. package/lib/esm/components/TruncatedText.module.css +162 -0
  54. package/lib/esm/hooks/useReducedMotion.d.ts +12 -0
  55. package/lib/esm/hooks/useReducedMotion.js +32 -0
  56. package/lib/esm/hooks/useReducedMotion.js.map +1 -0
  57. package/lib/esm/index.d.ts +5 -0
  58. package/lib/esm/index.js +7 -0
  59. package/lib/esm/index.js.map +1 -1
  60. package/lib/esm/motion.d.ts +219 -0
  61. package/lib/esm/motion.js +154 -0
  62. package/lib/esm/motion.js.map +1 -0
  63. package/lib/esm/package.json +6 -6
  64. package/package.json +6 -6
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Whether the viewer has asked for reduced motion.
3
+ *
4
+ * Plain `matchMedia`, deliberately: this is the one piece of the motion story that every
5
+ * component needs and that carries no dependency, so it lives here rather than travelling
6
+ * with an animation library.
7
+ *
8
+ * Starts `false` and corrects on mount. Server-rendered markup cannot know the preference,
9
+ * and rendering the still version first would flash into motion for everyone else; erring
10
+ * toward motion and stopping it is the less disruptive order.
11
+ */
12
+ export declare function useReducedMotion(): boolean;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useReducedMotion = useReducedMotion;
4
+ const react_1 = require("react");
5
+ /**
6
+ * Whether the viewer has asked for reduced motion.
7
+ *
8
+ * Plain `matchMedia`, deliberately: this is the one piece of the motion story that every
9
+ * component needs and that carries no dependency, so it lives here rather than travelling
10
+ * with an animation library.
11
+ *
12
+ * Starts `false` and corrects on mount. Server-rendered markup cannot know the preference,
13
+ * and rendering the still version first would flash into motion for everyone else; erring
14
+ * toward motion and stopping it is the less disruptive order.
15
+ */
16
+ function useReducedMotion() {
17
+ const [reduced, setReduced] = (0, react_1.useState)(false);
18
+ (0, react_1.useEffect)(() => {
19
+ if (typeof window === 'undefined' || !window.matchMedia)
20
+ return;
21
+ const query = window.matchMedia('(prefers-reduced-motion: reduce)');
22
+ setReduced(query.matches);
23
+ const onChange = (event) => setReduced(event.matches);
24
+ // `addEventListener` on MediaQueryList is not in older Safari; both are kept because a
25
+ // component library cannot choose its host browser.
26
+ if (query.addEventListener) {
27
+ query.addEventListener('change', onChange);
28
+ return () => query.removeEventListener('change', onChange);
29
+ }
30
+ query.addListener(onChange);
31
+ return () => query.removeListener(onChange);
32
+ }, []);
33
+ return reduced;
34
+ }
35
+ //# sourceMappingURL=useReducedMotion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useReducedMotion.js","sourceRoot":"","sources":["../../../src/hooks/useReducedMotion.ts"],"names":[],"mappings":";;AAaA,4CAmBC;AAhCD,iCAA0C;AAE1C;;;;;;;;;;GAUG;AACH,SAAgB,gBAAgB;IAC9B,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IAE9C,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,CAAC,MAAM,CAAC,UAAU;YAAE,OAAO;QAChE,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,kCAAkC,CAAC,CAAC;QACpE,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC1B,MAAM,QAAQ,GAAG,CAAC,KAA0B,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3E,uFAAuF;QACvF,oDAAoD;QACpD,IAAI,KAAK,CAAC,gBAAgB,EAAE,CAAC;YAC3B,KAAK,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAC3C,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC7D,CAAC;QACD,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QAC5B,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -35,6 +35,10 @@ import './components/NavigationMenu.js';
35
35
  import './components/Menubar.js';
36
36
  import './components/MultiSelect.js';
37
37
  import './components/Spinner.js';
38
+ import './components/ConfirmDialog.js';
39
+ import './components/SkeletonLoader.js';
40
+ import './components/ImageThumb.js';
41
+ import './components/TruncatedText.js';
38
42
  import './components/Breadcrumb.js';
39
43
  import './components/Drawer.js';
40
44
  import './components/IconButton.js';
@@ -44,3 +48,4 @@ import './components/Form.js';
44
48
  import './components/Toolbar.js';
45
49
  import './components/VisuallyHidden.js';
46
50
  import './hooks/use-toast.js';
51
+ export * from './motion.js';
package/lib/cjs/index.js CHANGED
@@ -1,4 +1,18 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
2
16
  Object.defineProperty(exports, "__esModule", { value: true });
3
17
  require("./theme.css");
4
18
  require("./types.js");
@@ -40,6 +54,10 @@ require("./components/NavigationMenu.js");
40
54
  require("./components/Menubar.js");
41
55
  require("./components/MultiSelect.js");
42
56
  require("./components/Spinner.js");
57
+ require("./components/ConfirmDialog.js");
58
+ require("./components/SkeletonLoader.js");
59
+ require("./components/ImageThumb.js");
60
+ require("./components/TruncatedText.js");
43
61
  require("./components/Breadcrumb.js");
44
62
  require("./components/Drawer.js");
45
63
  require("./components/IconButton.js");
@@ -49,4 +67,7 @@ require("./components/Form.js");
49
67
  require("./components/Toolbar.js");
50
68
  require("./components/VisuallyHidden.js");
51
69
  require("./hooks/use-toast.js");
70
+ // The motion presets. Reachable from the entry point so tsc emits them: this package's
71
+ // tsconfig compiles what `index.ts` reaches, not the whole src tree.
72
+ __exportStar(require("./motion.js"), exports);
52
73
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;AAAA,uBAAqB;AACrB,sBAAoB;AACpB,sCAAoC;AAEpC,cAAc;AACd,kCAAkC;AAElC,iBAAiB;AACjB,iCAA+B;AAC/B,kCAAgC;AAChC,iCAA+B;AAC/B,gCAA8B;AAC9B,kCAAgC;AAChC,oCAAkC;AAClC,sCAAoC;AACpC,kCAAgC;AAChC,iCAA+B;AAC/B,qCAAmC;AACnC,kCAAgC;AAChC,uCAAqC;AACrC,oCAAkC;AAClC,qCAAmC;AACnC,qCAAmC;AACnC,uCAAqC;AACrC,sCAAoC;AACpC,gCAA8B;AAC9B,mCAAiC;AACjC,uCAAqC;AACrC,kCAAgC;AAChC,sCAAoC;AACpC,mCAAiC;AACjC,mCAAiC;AACjC,kCAAgC;AAChC,uCAAqC;AACrC,kCAAgC;AAChC,iCAA+B;AAC/B,mCAAiC;AACjC,oCAAkC;AAClC,0CAAwC;AACxC,mCAAiC;AACjC,uCAAqC;AACrC,mCAAiC;AACjC,sCAAoC;AACpC,kCAAgC;AAChC,sCAAoC;AACpC,wCAAsC;AACtC,uCAAqC;AACrC,gCAA8B;AAC9B,mCAAiC;AACjC,0CAAwC;AAExC,gCAA8B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,uBAAqB;AACrB,sBAAoB;AACpB,sCAAoC;AAEpC,cAAc;AACd,kCAAkC;AAElC,iBAAiB;AACjB,iCAA+B;AAC/B,kCAAgC;AAChC,iCAA+B;AAC/B,gCAA8B;AAC9B,kCAAgC;AAChC,oCAAkC;AAClC,sCAAoC;AACpC,kCAAgC;AAChC,iCAA+B;AAC/B,qCAAmC;AACnC,kCAAgC;AAChC,uCAAqC;AACrC,oCAAkC;AAClC,qCAAmC;AACnC,qCAAmC;AACnC,uCAAqC;AACrC,sCAAoC;AACpC,gCAA8B;AAC9B,mCAAiC;AACjC,uCAAqC;AACrC,kCAAgC;AAChC,sCAAoC;AACpC,mCAAiC;AACjC,mCAAiC;AACjC,kCAAgC;AAChC,uCAAqC;AACrC,kCAAgC;AAChC,iCAA+B;AAC/B,mCAAiC;AACjC,oCAAkC;AAClC,0CAAwC;AACxC,mCAAiC;AACjC,uCAAqC;AACrC,mCAAiC;AACjC,yCAAuC;AACvC,0CAAwC;AACxC,sCAAoC;AACpC,yCAAuC;AACvC,sCAAoC;AACpC,kCAAgC;AAChC,sCAAoC;AACpC,wCAAsC;AACtC,uCAAqC;AACrC,gCAA8B;AAC9B,mCAAiC;AACjC,0CAAwC;AAExC,gCAA8B;AAE9B,uFAAuF;AACvF,qEAAqE;AACrE,8CAA4B"}
@@ -0,0 +1,219 @@
1
+ /**
2
+ * Motion presets.
3
+ *
4
+ * Design tokens that happen to be objects rather than CSS custom properties, because that is
5
+ * the shape an animation library consumes. Same purpose as a colour token: one definition of
6
+ * "how a list staggers in", so two surfaces cannot disagree about it.
7
+ *
8
+ * This module imports **nothing**, not even types. Every export is a plain object whose type
9
+ * is inferred, and an inferred object literal is structurally assignable to `framer-motion`'s
10
+ * `Variants` and `Transition` at the point of use — so a consumer gets full checking without
11
+ * this package depending on the animation library at all.
12
+ *
13
+ * That matters more than it looks. Naming the types here would mean a devDependency to build
14
+ * and a peer to consume, which is how the workspace ended up with two copies of
15
+ * `framer-motion` and presets from one that were not assignable to the other. A library that
16
+ * animates with CSS should not carry an animation library so it can describe some constants.
17
+ */
18
+ import { useReducedMotion } from './hooks/useReducedMotion.js';
19
+ /**
20
+ * Shared animation variants for consistent motion across the app
21
+ */
22
+ export declare const fadeInUp: {
23
+ initial: {
24
+ opacity: number;
25
+ y: number;
26
+ };
27
+ animate: {
28
+ opacity: number;
29
+ y: number;
30
+ };
31
+ exit: {
32
+ opacity: number;
33
+ y: number;
34
+ };
35
+ };
36
+ export declare const fadeIn: {
37
+ initial: {
38
+ opacity: number;
39
+ };
40
+ animate: {
41
+ opacity: number;
42
+ };
43
+ exit: {
44
+ opacity: number;
45
+ };
46
+ };
47
+ export declare const scaleIn: {
48
+ initial: {
49
+ opacity: number;
50
+ scale: number;
51
+ };
52
+ animate: {
53
+ opacity: number;
54
+ scale: number;
55
+ };
56
+ exit: {
57
+ opacity: number;
58
+ scale: number;
59
+ };
60
+ };
61
+ export declare const slideInRight: {
62
+ initial: {
63
+ x: number;
64
+ opacity: number;
65
+ };
66
+ animate: {
67
+ x: number;
68
+ opacity: number;
69
+ };
70
+ exit: {
71
+ x: number;
72
+ opacity: number;
73
+ };
74
+ };
75
+ /**
76
+ * Easing and transition configurations
77
+ */
78
+ /**
79
+ * A cubic-bezier easing: the four control points, as a tuple.
80
+ *
81
+ * The tuple type is load-bearing. Written inline, `[0.16, 1, 0.3, 1]` infers as `number[]`,
82
+ * which is not assignable to an animation library's easing type — it wants exactly four
83
+ * numbers. Naming it once fixes that and stops the curve being retyped at each use.
84
+ */
85
+ export type Easing = [number, number, number, number];
86
+ /** The shared ease-out curve. Decelerates hard at the end, so motion settles rather than stops. */
87
+ export declare const EASE_OUT_CURVE: Easing;
88
+ export declare const spring: {
89
+ type: string;
90
+ stiffness: number;
91
+ damping: number;
92
+ };
93
+ export declare const easeOut: {
94
+ duration: number;
95
+ ease: Easing;
96
+ };
97
+ export declare const easeSlow: {
98
+ duration: number;
99
+ ease: Easing;
100
+ };
101
+ /**
102
+ * Stagger animation configurations
103
+ */
104
+ export declare const staggerContainer: {
105
+ animate: {
106
+ transition: {
107
+ staggerChildren: number;
108
+ };
109
+ };
110
+ };
111
+ export declare const staggerItem: {
112
+ initial: {
113
+ opacity: number;
114
+ y: number;
115
+ };
116
+ animate: {
117
+ opacity: number;
118
+ y: number;
119
+ };
120
+ };
121
+ /**
122
+ * Slower stagger for table rows - more subtle and elegant
123
+ */
124
+ export declare const tableStaggerContainer: {
125
+ animate: {
126
+ transition: {
127
+ staggerChildren: number;
128
+ delayChildren: number;
129
+ };
130
+ };
131
+ };
132
+ export declare const tableRowItem: {
133
+ initial: {
134
+ opacity: number;
135
+ y: number;
136
+ };
137
+ animate: {
138
+ opacity: number;
139
+ y: number;
140
+ transition: {
141
+ duration: number;
142
+ ease: Easing;
143
+ };
144
+ };
145
+ };
146
+ /**
147
+ * Stagger for card grids - elegant cascade effect
148
+ */
149
+ export declare const cardGridContainer: {
150
+ hidden: {
151
+ opacity: number;
152
+ };
153
+ visible: {
154
+ opacity: number;
155
+ transition: {
156
+ staggerChildren: number;
157
+ delayChildren: number;
158
+ };
159
+ };
160
+ };
161
+ export declare const cardGridItem: {
162
+ hidden: {
163
+ opacity: number;
164
+ y: number;
165
+ scale: number;
166
+ };
167
+ visible: {
168
+ opacity: number;
169
+ y: number;
170
+ scale: number;
171
+ transition: {
172
+ duration: number;
173
+ ease: Easing;
174
+ };
175
+ };
176
+ };
177
+ /**
178
+ * Stagger for list items - subtle slide-in effect
179
+ */
180
+ export declare const listContainer: {
181
+ hidden: {
182
+ opacity: number;
183
+ };
184
+ visible: {
185
+ opacity: number;
186
+ transition: {
187
+ staggerChildren: number;
188
+ delayChildren: number;
189
+ };
190
+ };
191
+ };
192
+ export declare const listItem: {
193
+ hidden: {
194
+ opacity: number;
195
+ x: number;
196
+ };
197
+ visible: {
198
+ opacity: number;
199
+ x: number;
200
+ transition: {
201
+ duration: number;
202
+ ease: Easing;
203
+ };
204
+ };
205
+ };
206
+ /**
207
+ * Re-exported so a component reaching for the motion presets does not have to know that the
208
+ * preference hook lives elsewhere. It carries no animation dependency of its own.
209
+ */
210
+ export { useReducedMotion };
211
+ /**
212
+ * Get appropriate transition based on reduced motion preference
213
+ */
214
+ export declare const getTransition: (reducedMotion: boolean) => {
215
+ duration: number;
216
+ ease: Easing;
217
+ } | {
218
+ duration: number;
219
+ };
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getTransition = exports.useReducedMotion = exports.listItem = exports.listContainer = exports.cardGridItem = exports.cardGridContainer = exports.tableRowItem = exports.tableStaggerContainer = exports.staggerItem = exports.staggerContainer = exports.easeSlow = exports.easeOut = exports.spring = exports.EASE_OUT_CURVE = exports.slideInRight = exports.scaleIn = exports.fadeIn = exports.fadeInUp = void 0;
4
+ /**
5
+ * Motion presets.
6
+ *
7
+ * Design tokens that happen to be objects rather than CSS custom properties, because that is
8
+ * the shape an animation library consumes. Same purpose as a colour token: one definition of
9
+ * "how a list staggers in", so two surfaces cannot disagree about it.
10
+ *
11
+ * This module imports **nothing**, not even types. Every export is a plain object whose type
12
+ * is inferred, and an inferred object literal is structurally assignable to `framer-motion`'s
13
+ * `Variants` and `Transition` at the point of use — so a consumer gets full checking without
14
+ * this package depending on the animation library at all.
15
+ *
16
+ * That matters more than it looks. Naming the types here would mean a devDependency to build
17
+ * and a peer to consume, which is how the workspace ended up with two copies of
18
+ * `framer-motion` and presets from one that were not assignable to the other. A library that
19
+ * animates with CSS should not carry an animation library so it can describe some constants.
20
+ */
21
+ const useReducedMotion_js_1 = require("./hooks/useReducedMotion.js");
22
+ Object.defineProperty(exports, "useReducedMotion", { enumerable: true, get: function () { return useReducedMotion_js_1.useReducedMotion; } });
23
+ /**
24
+ * Shared animation variants for consistent motion across the app
25
+ */
26
+ // Fade animations
27
+ exports.fadeInUp = {
28
+ initial: { opacity: 0, y: 20 },
29
+ animate: { opacity: 1, y: 0 },
30
+ exit: { opacity: 0, y: -20 },
31
+ };
32
+ exports.fadeIn = {
33
+ initial: { opacity: 0 },
34
+ animate: { opacity: 1 },
35
+ exit: { opacity: 0 },
36
+ };
37
+ exports.scaleIn = {
38
+ initial: { opacity: 0, scale: 0.95 },
39
+ animate: { opacity: 1, scale: 1 },
40
+ exit: { opacity: 0, scale: 0.95 },
41
+ };
42
+ exports.slideInRight = {
43
+ initial: { x: -20, opacity: 0 },
44
+ animate: { x: 0, opacity: 1 },
45
+ exit: { x: -20, opacity: 0 },
46
+ };
47
+ /** The shared ease-out curve. Decelerates hard at the end, so motion settles rather than stops. */
48
+ exports.EASE_OUT_CURVE = [0.16, 1, 0.3, 1];
49
+ exports.spring = {
50
+ type: 'spring',
51
+ stiffness: 300,
52
+ damping: 30,
53
+ };
54
+ exports.easeOut = {
55
+ duration: 0.2,
56
+ ease: exports.EASE_OUT_CURVE,
57
+ };
58
+ exports.easeSlow = {
59
+ duration: 0.3,
60
+ ease: exports.EASE_OUT_CURVE,
61
+ };
62
+ /**
63
+ * Stagger animation configurations
64
+ */
65
+ exports.staggerContainer = {
66
+ animate: {
67
+ transition: {
68
+ staggerChildren: 0.05,
69
+ },
70
+ },
71
+ };
72
+ exports.staggerItem = {
73
+ initial: { opacity: 0, y: 10 },
74
+ animate: { opacity: 1, y: 0 },
75
+ };
76
+ /**
77
+ * Slower stagger for table rows - more subtle and elegant
78
+ */
79
+ exports.tableStaggerContainer = {
80
+ animate: {
81
+ transition: {
82
+ staggerChildren: 0.08,
83
+ delayChildren: 0.1,
84
+ },
85
+ },
86
+ };
87
+ exports.tableRowItem = {
88
+ initial: { opacity: 0, y: 8 },
89
+ animate: {
90
+ opacity: 1,
91
+ y: 0,
92
+ transition: {
93
+ duration: 0.35,
94
+ ease: exports.EASE_OUT_CURVE,
95
+ },
96
+ },
97
+ };
98
+ /**
99
+ * Stagger for card grids - elegant cascade effect
100
+ */
101
+ exports.cardGridContainer = {
102
+ hidden: { opacity: 0 },
103
+ visible: {
104
+ opacity: 1,
105
+ transition: {
106
+ staggerChildren: 0.04,
107
+ delayChildren: 0.05,
108
+ },
109
+ },
110
+ };
111
+ exports.cardGridItem = {
112
+ hidden: { opacity: 0, y: 12, scale: 0.98 },
113
+ visible: {
114
+ opacity: 1,
115
+ y: 0,
116
+ scale: 1,
117
+ transition: {
118
+ duration: 0.3,
119
+ ease: exports.EASE_OUT_CURVE,
120
+ },
121
+ },
122
+ };
123
+ /**
124
+ * Stagger for list items - subtle slide-in effect
125
+ */
126
+ exports.listContainer = {
127
+ hidden: { opacity: 0 },
128
+ visible: {
129
+ opacity: 1,
130
+ transition: {
131
+ staggerChildren: 0.03,
132
+ delayChildren: 0.02,
133
+ },
134
+ },
135
+ };
136
+ exports.listItem = {
137
+ hidden: { opacity: 0, x: -8 },
138
+ visible: {
139
+ opacity: 1,
140
+ x: 0,
141
+ transition: {
142
+ duration: 0.25,
143
+ ease: exports.EASE_OUT_CURVE,
144
+ },
145
+ },
146
+ };
147
+ /**
148
+ * Get appropriate transition based on reduced motion preference
149
+ */
150
+ const getTransition = (reducedMotion) => {
151
+ return reducedMotion ? { duration: 0 } : exports.easeOut;
152
+ };
153
+ exports.getTransition = getTransition;
154
+ //# sourceMappingURL=motion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motion.js","sourceRoot":"","sources":["../../src/motion.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@_linked/primitives",
3
- "description": "lincd-primitives is a UI library based on Radix UI",
3
+ "description": "A UI component library: a headless behaviour source (Radix UI, cmdk, vaul, or hand-written) plus a CSS module reading @_linked/css design tokens — and no knowledge of data, of shapes, or of any particular application.",
4
4
  "author": {
5
5
  "name": "",
6
6
  "email": "",
@@ -8,9 +8,9 @@
8
8
  },
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": ""
11
+ "url": "git+https://github.com/linked-cm/primitives.git"
12
12
  },
13
- "version": "1.1.0",
13
+ "version": "1.2.0",
14
14
  "linkedPackage": true,
15
15
  "license": "ISC",
16
16
  "scripts": {
@@ -70,11 +70,11 @@
70
70
  "@_linked/cli": "^1.2",
71
71
  "@changesets/changelog-github": "^0.5.2",
72
72
  "@changesets/cli": "^2.29.8",
73
+ "copyfiles": "^2.4.1",
74
+ "rimraf": "^5.0.7",
73
75
  "tsconfig-to-dual-package": "^1.2.0",
74
76
  "typescript": "^5.7.3",
75
- "typescript-plugin-css-modules": "^5.1.0",
76
- "rimraf": "^5.0.7",
77
- "copyfiles": "^2.4.1"
77
+ "typescript-plugin-css-modules": "^5.1.0"
78
78
  },
79
79
  "typesVersions": {
80
80
  "*": {
@@ -0,0 +1,37 @@
1
+ import * as React from 'react';
2
+ export interface ConfirmDialogProps {
3
+ open: boolean;
4
+ onOpenChange: (open: boolean) => void;
5
+ onConfirm: () => void;
6
+ title: string;
7
+ message: React.ReactNode;
8
+ confirmText?: string;
9
+ cancelText?: string;
10
+ /**
11
+ * `danger` for a destructive action. Not a colour — a statement about consequence, which
12
+ * is what `--intent-danger-*` exists to express.
13
+ */
14
+ tone?: 'default' | 'danger';
15
+ /** The confirm action is in flight: both buttons lock. */
16
+ isLoading?: boolean;
17
+ /** Withhold confirmation until the caller has something complete to confirm. */
18
+ confirmDisabled?: boolean;
19
+ /** Replaces the confirm label while loading. */
20
+ loadingContent?: React.ReactNode;
21
+ /** Wider layout, for multi-column content such as an impact preview. */
22
+ wide?: boolean;
23
+ className?: string;
24
+ }
25
+ /**
26
+ * "Are you sure?" — a title, a message, and two buttons.
27
+ *
28
+ * A composition over `AlertDialog` rather than its own dialog. The hand-rolled version this
29
+ * replaces built its own portal and its own backdrop, and in doing so had no focus trap, no
30
+ * escape handling, no `aria-modal` and no restoration of focus on close — a confirmation
31
+ * step that a keyboard or screen-reader user could not reliably complete, which is the worst
32
+ * possible component to get wrong, since the whole point is guarding a destructive action.
33
+ *
34
+ * `alertdialog` semantics are the right ones here, not `dialog`: it interrupts, and it must
35
+ * not be dismissed by clicking away.
36
+ */
37
+ export declare function ConfirmDialog({ open, onOpenChange, onConfirm, title, message, confirmText, cancelText, tone, isLoading, confirmDisabled, loadingContent, wide, className, }: ConfirmDialogProps): React.JSX.Element;
@@ -0,0 +1,29 @@
1
+ import * as React from 'react';
2
+ import { cl } from '@_linked/react/utils/ClassNames';
3
+ import { AlertDialog } from './AlertDialog.js';
4
+ import { Button } from './Button.js';
5
+ import style from './ConfirmDialog.module.css';
6
+ /**
7
+ * "Are you sure?" — a title, a message, and two buttons.
8
+ *
9
+ * A composition over `AlertDialog` rather than its own dialog. The hand-rolled version this
10
+ * replaces built its own portal and its own backdrop, and in doing so had no focus trap, no
11
+ * escape handling, no `aria-modal` and no restoration of focus on close — a confirmation
12
+ * step that a keyboard or screen-reader user could not reliably complete, which is the worst
13
+ * possible component to get wrong, since the whole point is guarding a destructive action.
14
+ *
15
+ * `alertdialog` semantics are the right ones here, not `dialog`: it interrupts, and it must
16
+ * not be dismissed by clicking away.
17
+ */
18
+ export function ConfirmDialog({ open, onOpenChange, onConfirm, title, message, confirmText = 'Confirm', cancelText = 'Cancel', tone = 'default', isLoading = false, confirmDisabled = false, loadingContent, wide = false, className, }) {
19
+ return (React.createElement(AlertDialog.Root, { open: open, onOpenChange: onOpenChange },
20
+ React.createElement(AlertDialog.Content, { className: cl(style.Content, wide && style.wide, className) },
21
+ React.createElement(AlertDialog.Header, null,
22
+ React.createElement(AlertDialog.Title, null, title),
23
+ React.createElement(AlertDialog.Description, { asChild: typeof message !== 'string' }, typeof message === 'string' ? message : React.createElement("div", null, message))),
24
+ React.createElement(AlertDialog.Footer, null,
25
+ React.createElement(AlertDialog.Cancel, { asChild: true },
26
+ React.createElement(Button, { variant: "ghost", disabled: isLoading }, cancelText)),
27
+ React.createElement(Button, { className: cl(tone === 'danger' && style.danger), onClick: onConfirm, disabled: isLoading || confirmDisabled }, isLoading && loadingContent ? loadingContent : confirmText)))));
28
+ }
29
+ //# sourceMappingURL=ConfirmDialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfirmDialog.js","sourceRoot":"","sources":["../../../src/components/ConfirmDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAC,EAAE,EAAC,MAAM,iCAAiC,CAAC;AACnD,OAAO,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACnC,OAAO,KAAK,MAAM,4BAA4B,CAAC;AA0B/C;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAAC,EAC5B,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,KAAK,EACL,OAAO,EACP,WAAW,GAAG,SAAS,EACvB,UAAU,GAAG,QAAQ,EACrB,IAAI,GAAG,SAAS,EAChB,SAAS,GAAG,KAAK,EACjB,eAAe,GAAG,KAAK,EACvB,cAAc,EACd,IAAI,GAAG,KAAK,EACZ,SAAS,GACU;IACnB,OAAO,CACL,oBAAC,WAAW,CAAC,IAAI,IAAC,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,YAAY;QACtD,oBAAC,WAAW,CAAC,OAAO,IAClB,SAAS,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC;YAE3D,oBAAC,WAAW,CAAC,MAAM;gBACjB,oBAAC,WAAW,CAAC,KAAK,QAAE,KAAK,CAAqB;gBAI9C,oBAAC,WAAW,CAAC,WAAW,IAAC,OAAO,EAAE,OAAO,OAAO,KAAK,QAAQ,IAC1D,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,iCAAM,OAAO,CAAO,CACrC,CACP;YACrB,oBAAC,WAAW,CAAC,MAAM;gBACjB,oBAAC,WAAW,CAAC,MAAM,IAAC,OAAO;oBACzB,oBAAC,MAAM,IAAC,OAAO,EAAC,OAAO,EAAC,QAAQ,EAAE,SAAS,IACxC,UAAU,CACJ,CACU;gBAIrB,oBAAC,MAAM,IACL,SAAS,EAAE,EAAE,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC,EAChD,OAAO,EAAE,SAAS,EAClB,QAAQ,EAAE,SAAS,IAAI,eAAe,IAErC,SAAS,IAAI,cAAc,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,WAAW,CACpD,CACU,CACD,CACL,CACpB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,22 @@
1
+ @import './helpers/mixins.css';
2
+ @import '@_linked/css/package.css';
3
+
4
+ .Content {
5
+ max-width: var(--confirm-dialog-width, 32rem);
6
+ }
7
+
8
+ .wide {
9
+ max-width: var(--confirm-dialog-width-wide, 56rem);
10
+ }
11
+
12
+ /* Destructive confirmation. Reads the intent family rather than a red primitive, so an app
13
+ that restyles what "danger" looks like restyles this too. */
14
+ .danger {
15
+ background: var(--confirm-dialog-danger-bg, var(--intent-danger-icon));
16
+ border-color: var(--confirm-dialog-danger-border, var(--intent-danger-border));
17
+ color: var(--confirm-dialog-danger-text, var(--color-white));
18
+ }
19
+
20
+ .danger:hover:not(:disabled) {
21
+ background: var(--confirm-dialog-danger-bg-hover, var(--intent-danger-text));
22
+ }
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ interface ImageThumbProps {
3
+ src: string;
4
+ size?: number;
5
+ hoverSize?: number;
6
+ alt?: string;
7
+ className?: string;
8
+ /** If true, clicking opens a full-screen lightbox preview */
9
+ clickToEnlarge?: boolean;
10
+ }
11
+ declare const ImageThumb: React.FC<ImageThumbProps>;
12
+ /** Small inline thumbnail for use inside chips, badges, and dropdown options */
13
+ export declare const InlineImageThumb: React.FC<{
14
+ src: string;
15
+ alt?: string;
16
+ }>;
17
+ export default ImageThumb;