@_linked/primitives 1.0.9 → 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.
- package/.github/workflows/publish.yml +74 -7
- package/CHANGELOG.md +65 -0
- package/README.md +62 -0
- package/lib/cjs/components/Badge.d.ts +30 -0
- package/lib/cjs/components/Badge.js +64 -0
- package/lib/cjs/components/Badge.js.map +1 -0
- package/lib/cjs/components/Badge.module.css +89 -0
- package/lib/cjs/components/Command.d.ts +6 -6
- package/lib/cjs/components/ConfirmDialog.d.ts +37 -0
- package/lib/cjs/components/ConfirmDialog.js +68 -0
- package/lib/cjs/components/ConfirmDialog.js.map +1 -0
- package/lib/cjs/components/ConfirmDialog.module.css +22 -0
- package/lib/cjs/components/ImageThumb.d.ts +17 -0
- package/lib/cjs/components/ImageThumb.js +90 -0
- package/lib/cjs/components/ImageThumb.js.map +1 -0
- package/lib/cjs/components/ImageThumb.module.css +134 -0
- package/lib/cjs/components/MultiSelect.d.ts +4 -4
- package/lib/cjs/components/SkeletonLoader.d.ts +14 -0
- package/lib/cjs/components/SkeletonLoader.js +71 -0
- package/lib/cjs/components/SkeletonLoader.js.map +1 -0
- package/lib/cjs/components/SkeletonLoader.module.css +83 -0
- package/lib/cjs/components/Slider.js +7 -3
- package/lib/cjs/components/Slider.js.map +1 -1
- package/lib/cjs/components/Spinner.d.ts +22 -3
- package/lib/cjs/components/Spinner.js +55 -3
- package/lib/cjs/components/Spinner.js.map +1 -1
- package/lib/cjs/components/Spinner.module.css +57 -10
- package/lib/cjs/components/TruncatedText.d.ts +16 -0
- package/lib/cjs/components/TruncatedText.js +130 -0
- package/lib/cjs/components/TruncatedText.js.map +1 -0
- package/lib/cjs/components/TruncatedText.module.css +162 -0
- package/lib/cjs/hooks/useReducedMotion.d.ts +12 -0
- package/lib/cjs/hooks/useReducedMotion.js +35 -0
- package/lib/cjs/hooks/useReducedMotion.js.map +1 -0
- package/lib/cjs/index.d.ts +6 -0
- package/lib/cjs/index.js +22 -0
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/motion.d.ts +219 -0
- package/lib/cjs/motion.js +154 -0
- package/lib/cjs/motion.js.map +1 -0
- package/lib/cjs/package.json +6 -6
- package/lib/esm/components/Badge.d.ts +30 -0
- package/lib/esm/components/Badge.js +13 -0
- package/lib/esm/components/Badge.js.map +1 -0
- package/lib/esm/components/Badge.module.css +89 -0
- package/lib/esm/components/Command.d.ts +6 -6
- package/lib/esm/components/ConfirmDialog.d.ts +37 -0
- package/lib/esm/components/ConfirmDialog.js +29 -0
- package/lib/esm/components/ConfirmDialog.js.map +1 -0
- package/lib/esm/components/ConfirmDialog.module.css +22 -0
- package/lib/esm/components/ImageThumb.d.ts +17 -0
- package/lib/esm/components/ImageThumb.js +50 -0
- package/lib/esm/components/ImageThumb.js.map +1 -0
- package/lib/esm/components/ImageThumb.module.css +134 -0
- package/lib/esm/components/MultiSelect.d.ts +4 -4
- package/lib/esm/components/SkeletonLoader.d.ts +14 -0
- package/lib/esm/components/SkeletonLoader.js +31 -0
- package/lib/esm/components/SkeletonLoader.js.map +1 -0
- package/lib/esm/components/SkeletonLoader.module.css +83 -0
- package/lib/esm/components/Slider.js +6 -2
- package/lib/esm/components/Slider.js.map +1 -1
- package/lib/esm/components/Spinner.d.ts +22 -3
- package/lib/esm/components/Spinner.js +22 -3
- package/lib/esm/components/Spinner.js.map +1 -1
- package/lib/esm/components/Spinner.module.css +57 -10
- package/lib/esm/components/TruncatedText.d.ts +16 -0
- package/lib/esm/components/TruncatedText.js +83 -0
- package/lib/esm/components/TruncatedText.js.map +1 -0
- package/lib/esm/components/TruncatedText.module.css +162 -0
- package/lib/esm/hooks/useReducedMotion.d.ts +12 -0
- package/lib/esm/hooks/useReducedMotion.js +32 -0
- package/lib/esm/hooks/useReducedMotion.js.map +1 -0
- package/lib/esm/index.d.ts +6 -0
- package/lib/esm/index.js +8 -0
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/motion.d.ts +219 -0
- package/lib/esm/motion.js +154 -0
- package/lib/esm/motion.js.map +1 -0
- package/lib/esm/package.json +6 -6
- package/package.json +6 -6
|
@@ -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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"}
|
package/lib/cjs/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@_linked/primitives",
|
|
3
|
-
"description": "
|
|
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.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,30 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Badge — a small status/metadata label (badge, tag, chip, pill).
|
|
4
|
+
*
|
|
5
|
+
* One primitive, many looks: every axis is an independent prop so surfaces can
|
|
6
|
+
* swap variation without new components —
|
|
7
|
+
*
|
|
8
|
+
* variant solid | soft | outline | ghost fill strength
|
|
9
|
+
* color neutral | primary | success | warning | danger | info
|
|
10
|
+
* size small | medium | large
|
|
11
|
+
* shape pill | rounded
|
|
12
|
+
* dot leading status dot in the badge color
|
|
13
|
+
* asChild render as the child element (a link, a button) via Radix Slot,
|
|
14
|
+
* so an interactive badge keeps real semantics and focus behavior
|
|
15
|
+
*
|
|
16
|
+
* Theming follows the library contract: the component consumes `--badge-*`
|
|
17
|
+
* variables with working fallbacks, so it renders sensibly out of the box and
|
|
18
|
+
* apps re-skin it from their theme without touching the component.
|
|
19
|
+
*/
|
|
20
|
+
export interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
|
|
21
|
+
asChild?: boolean;
|
|
22
|
+
variant?: 'solid' | 'soft' | 'outline' | 'ghost';
|
|
23
|
+
color?: 'neutral' | 'primary' | 'success' | 'warning' | 'danger' | 'info';
|
|
24
|
+
size?: 'small' | 'medium' | 'large';
|
|
25
|
+
shape?: 'pill' | 'rounded';
|
|
26
|
+
/** Leading status dot in the badge color. */
|
|
27
|
+
dot?: boolean;
|
|
28
|
+
}
|
|
29
|
+
declare const Badge: React.ForwardRefExoticComponent<BadgeProps & React.RefAttributes<HTMLSpanElement>>;
|
|
30
|
+
export { Badge };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import style from './Badge.module.css';
|
|
3
|
+
import { cl } from '@_linked/react/utils/ClassNames';
|
|
4
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
5
|
+
const Badge = React.forwardRef(({ className, variant = 'soft', color = 'neutral', size = 'medium', shape = 'pill', dot = false, asChild = false, children, ...props }, ref) => {
|
|
6
|
+
const Comp = asChild ? Slot : 'span';
|
|
7
|
+
return (React.createElement(Comp, { className: cl(style.Root, style[variant], style[color], style[size], style[shape], className), ref: ref, ...props }, asChild ? (children) : (React.createElement(React.Fragment, null,
|
|
8
|
+
dot && React.createElement("span", { className: style.dot, "aria-hidden": true }),
|
|
9
|
+
children))));
|
|
10
|
+
});
|
|
11
|
+
Badge.displayName = 'Badge';
|
|
12
|
+
export { Badge };
|
|
13
|
+
//# sourceMappingURL=Badge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Badge.js","sourceRoot":"","sources":["../../../src/components/Badge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,MAAM,oBAAoB,CAAC;AACvC,OAAO,EAAE,EAAE,EAAE,MAAM,iCAAiC,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AA8B5C,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,CAC5B,CACE,EACE,SAAS,EACT,OAAO,GAAG,MAAM,EAChB,KAAK,GAAG,SAAS,EACjB,IAAI,GAAG,QAAQ,EACf,KAAK,GAAG,MAAM,EACd,GAAG,GAAG,KAAK,EACX,OAAO,GAAG,KAAK,EACf,QAAQ,EACR,GAAG,KAAK,EACT,EACD,GAAG,EACH,EAAE;IACF,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;IAErC,OAAO,CACL,oBAAC,IAAI,IACH,SAAS,EAAE,EAAE,CACX,KAAK,CAAC,IAAI,EACV,KAAK,CAAC,OAAO,CAAC,EACd,KAAK,CAAC,KAAK,CAAC,EACZ,KAAK,CAAC,IAAI,CAAC,EACX,KAAK,CAAC,KAAK,CAAC,EACZ,SAAS,CACV,EACD,GAAG,EAAE,GAAG,KACJ,KAAK,IAER,OAAO,CAAC,CAAC,CAAC,CACT,QAAQ,CACT,CAAC,CAAC,CAAC,CACF;QACG,GAAG,IAAI,8BAAM,SAAS,EAAE,KAAK,CAAC,GAAG,wBAAgB;QACjD,QAAQ,CACR,CACJ,CACI,CACR,CAAC;AACJ,CAAC,CACF,CAAC;AACF,KAAK,CAAC,WAAW,GAAG,OAAO,CAAC;AAE5B,OAAO,EAAE,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/* Badge — consumes `--badge-*` semantic variables with working fallbacks, so it
|
|
2
|
+
renders out of the box and apps re-skin it from their theme (same contract as
|
|
3
|
+
Button/Input: the component names the tokens, the app supplies them). */
|
|
4
|
+
|
|
5
|
+
.Root {
|
|
6
|
+
display: inline-flex;
|
|
7
|
+
align-items: center;
|
|
8
|
+
white-space: nowrap;
|
|
9
|
+
vertical-align: middle;
|
|
10
|
+
border: solid 1px transparent;
|
|
11
|
+
gap: var(--badge-gap, 0.3em);
|
|
12
|
+
font-family: var(--badge-font-family, inherit);
|
|
13
|
+
font-weight: var(--badge-font-weight, 500);
|
|
14
|
+
line-height: var(--badge-line-height, 1.2);
|
|
15
|
+
|
|
16
|
+
/* Per-color base; every visual below derives from this one custom property,
|
|
17
|
+
which is what keeps the variant × color matrix to two small class sets. */
|
|
18
|
+
--_badge-color: var(--badge-color-neutral, #64748b);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/* ── color ─────────────────────────────────────────────────────────────── */
|
|
22
|
+
.neutral { --_badge-color: var(--badge-color-neutral, #64748b); }
|
|
23
|
+
.primary { --_badge-color: var(--badge-color-primary, var(--primary, #4f46e5)); }
|
|
24
|
+
.success { --_badge-color: var(--badge-color-success, #15803d); }
|
|
25
|
+
.warning { --_badge-color: var(--badge-color-warning, #b45309); }
|
|
26
|
+
.danger { --_badge-color: var(--badge-color-danger, #b91c1c); }
|
|
27
|
+
.info { --_badge-color: var(--badge-color-info, #0369a1); }
|
|
28
|
+
|
|
29
|
+
/* ── variant ───────────────────────────────────────────────────────────── */
|
|
30
|
+
.solid {
|
|
31
|
+
background: var(--_badge-color);
|
|
32
|
+
color: var(--badge-solid-foreground, #fff);
|
|
33
|
+
}
|
|
34
|
+
.soft {
|
|
35
|
+
background: color-mix(in oklch, var(--_badge-color) 12%, transparent);
|
|
36
|
+
color: var(--_badge-color);
|
|
37
|
+
}
|
|
38
|
+
.outline {
|
|
39
|
+
border-color: color-mix(in oklch, var(--_badge-color) 45%, transparent);
|
|
40
|
+
color: var(--_badge-color);
|
|
41
|
+
}
|
|
42
|
+
.ghost {
|
|
43
|
+
color: var(--_badge-color);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* ── size ──────────────────────────────────────────────────────────────── */
|
|
47
|
+
.small {
|
|
48
|
+
font-size: var(--badge-font-size-sm, 0.6875rem);
|
|
49
|
+
padding: var(--badge-padding-y-sm, 0.0625rem) var(--badge-padding-x-sm, 0.375rem);
|
|
50
|
+
}
|
|
51
|
+
.medium {
|
|
52
|
+
font-size: var(--badge-font-size, 0.75rem);
|
|
53
|
+
padding: var(--badge-padding-y, 0.125rem) var(--badge-padding-x, 0.5rem);
|
|
54
|
+
}
|
|
55
|
+
.large {
|
|
56
|
+
font-size: var(--badge-font-size-lg, 0.8125rem);
|
|
57
|
+
padding: var(--badge-padding-y-lg, 0.1875rem) var(--badge-padding-x-lg, 0.625rem);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* ── shape ─────────────────────────────────────────────────────────────── */
|
|
61
|
+
.pill { border-radius: var(--badge-radius-pill, 999px); }
|
|
62
|
+
.rounded { border-radius: var(--badge-radius, var(--control-radius, 0.375rem)); }
|
|
63
|
+
|
|
64
|
+
/* ── dot ───────────────────────────────────────────────────────────────── */
|
|
65
|
+
.dot {
|
|
66
|
+
width: 0.375em;
|
|
67
|
+
height: 0.375em;
|
|
68
|
+
border-radius: 999px;
|
|
69
|
+
background: currentColor;
|
|
70
|
+
flex: none;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* Interactive badges (asChild over a link/button) get hover/focus affordance
|
|
74
|
+
without imposing it on static ones. */
|
|
75
|
+
a.Root,
|
|
76
|
+
button.Root {
|
|
77
|
+
cursor: pointer;
|
|
78
|
+
transition: var(--transition-fast, background-color 120ms ease);
|
|
79
|
+
text-decoration: none;
|
|
80
|
+
}
|
|
81
|
+
a.Root:hover,
|
|
82
|
+
button.Root:hover {
|
|
83
|
+
filter: brightness(0.95);
|
|
84
|
+
}
|
|
85
|
+
a.Root:focus-visible,
|
|
86
|
+
button.Root:focus-visible {
|
|
87
|
+
outline: 2px solid color-mix(in oklch, var(--_badge-color) 45%, transparent);
|
|
88
|
+
outline-offset: 1px;
|
|
89
|
+
}
|
|
@@ -27,7 +27,7 @@ declare const Input: React.ForwardRefExoticComponent<Omit<Omit<Pick<Pick<React.D
|
|
|
27
27
|
ref?: React.Ref<HTMLInputElement>;
|
|
28
28
|
} & {
|
|
29
29
|
asChild?: boolean;
|
|
30
|
-
}, "asChild" | "key" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "type" | "
|
|
30
|
+
}, "asChild" | "key" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "type" | "onChange" | "value"> & {
|
|
31
31
|
value?: string;
|
|
32
32
|
onValueChange?: (search: string) => void;
|
|
33
33
|
} & React.RefAttributes<HTMLInputElement>, "ref"> & React.RefAttributes<HTMLInputElement>>;
|
|
@@ -53,7 +53,7 @@ declare const Group: React.ForwardRefExoticComponent<Omit<{
|
|
|
53
53
|
ref?: React.Ref<HTMLDivElement>;
|
|
54
54
|
} & {
|
|
55
55
|
asChild?: boolean;
|
|
56
|
-
}, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>>, "
|
|
56
|
+
}, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>>, "heading" | "value"> & {
|
|
57
57
|
heading?: React.ReactNode;
|
|
58
58
|
value?: string;
|
|
59
59
|
forceMount?: boolean;
|
|
@@ -71,7 +71,7 @@ declare const Item: React.ForwardRefExoticComponent<Omit<{
|
|
|
71
71
|
ref?: React.Ref<HTMLDivElement>;
|
|
72
72
|
} & {
|
|
73
73
|
asChild?: boolean;
|
|
74
|
-
}, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>>, "
|
|
74
|
+
}, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>>, "onSelect" | "disabled" | "value"> & {
|
|
75
75
|
disabled?: boolean;
|
|
76
76
|
onSelect?: (value: string) => void;
|
|
77
77
|
value?: string;
|
|
@@ -108,7 +108,7 @@ export declare const Command: {
|
|
|
108
108
|
ref?: React.Ref<HTMLInputElement>;
|
|
109
109
|
} & {
|
|
110
110
|
asChild?: boolean;
|
|
111
|
-
}, "asChild" | "key" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "type" | "
|
|
111
|
+
}, "asChild" | "key" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "type" | "onChange" | "value"> & {
|
|
112
112
|
value?: string;
|
|
113
113
|
onValueChange?: (search: string) => void;
|
|
114
114
|
} & React.RefAttributes<HTMLInputElement>, "ref"> & React.RefAttributes<HTMLInputElement>>;
|
|
@@ -134,7 +134,7 @@ export declare const Command: {
|
|
|
134
134
|
ref?: React.Ref<HTMLDivElement>;
|
|
135
135
|
} & {
|
|
136
136
|
asChild?: boolean;
|
|
137
|
-
}, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>>, "
|
|
137
|
+
}, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>>, "heading" | "value"> & {
|
|
138
138
|
heading?: React.ReactNode;
|
|
139
139
|
value?: string;
|
|
140
140
|
forceMount?: boolean;
|
|
@@ -145,7 +145,7 @@ export declare const Command: {
|
|
|
145
145
|
ref?: React.Ref<HTMLDivElement>;
|
|
146
146
|
} & {
|
|
147
147
|
asChild?: boolean;
|
|
148
|
-
}, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>>, "
|
|
148
|
+
}, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>>, "onSelect" | "disabled" | "value"> & {
|
|
149
149
|
disabled?: boolean;
|
|
150
150
|
onSelect?: (value: string) => void;
|
|
151
151
|
value?: string;
|
|
@@ -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;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React, { useCallback, useRef, useState } from 'react';
|
|
2
|
+
import { cl } from '@_linked/react/utils/ClassNames';
|
|
3
|
+
import style from './ImageThumb.module.css';
|
|
4
|
+
const ImageThumb = ({ src, size = 36, hoverSize = 280, alt = '', className = '', clickToEnlarge = true, }) => {
|
|
5
|
+
const [hover, setHover] = useState(false);
|
|
6
|
+
const [lightbox, setLightbox] = useState(false);
|
|
7
|
+
const [hoverPos, setHoverPos] = useState({
|
|
8
|
+
top: 0,
|
|
9
|
+
left: 0,
|
|
10
|
+
});
|
|
11
|
+
const thumbRef = useRef(null);
|
|
12
|
+
const handleMouseEnter = useCallback(() => {
|
|
13
|
+
if (thumbRef.current) {
|
|
14
|
+
const rect = thumbRef.current.getBoundingClientRect();
|
|
15
|
+
// Position the hover preview to the right of the thumbnail,
|
|
16
|
+
// but clamp so it doesn't overflow the viewport
|
|
17
|
+
const left = Math.min(rect.right + 8, window.innerWidth - hoverSize - 16);
|
|
18
|
+
const top = Math.max(8, Math.min(rect.top - hoverSize / 2 + size / 2, window.innerHeight - hoverSize - 16));
|
|
19
|
+
setHoverPos({ top, left });
|
|
20
|
+
}
|
|
21
|
+
setHover(true);
|
|
22
|
+
}, [hoverSize, size]);
|
|
23
|
+
const handleClick = useCallback((e) => {
|
|
24
|
+
if (clickToEnlarge) {
|
|
25
|
+
e.stopPropagation();
|
|
26
|
+
setHover(false);
|
|
27
|
+
setLightbox(true);
|
|
28
|
+
}
|
|
29
|
+
}, [clickToEnlarge]);
|
|
30
|
+
const closeLightbox = useCallback(() => {
|
|
31
|
+
setLightbox(false);
|
|
32
|
+
}, []);
|
|
33
|
+
return (React.createElement(React.Fragment, null,
|
|
34
|
+
React.createElement("span", { className: cl(style.root, className), onMouseEnter: handleMouseEnter, onMouseLeave: () => setHover(false) },
|
|
35
|
+
React.createElement("img", { ref: thumbRef, src: src, alt: alt, className: style.thumb, style: { width: size, height: size }, onClick: handleClick, loading: "lazy" }),
|
|
36
|
+
hover && !lightbox && (React.createElement("div", { className: cl(style.hoverPreview, hover && style.visible), style: {
|
|
37
|
+
top: hoverPos.top,
|
|
38
|
+
left: hoverPos.left,
|
|
39
|
+
width: hoverSize,
|
|
40
|
+
height: hoverSize,
|
|
41
|
+
} },
|
|
42
|
+
React.createElement("img", { src: src, alt: alt, className: style.hoverPreviewImage, style: { width: hoverSize, height: hoverSize } })))),
|
|
43
|
+
lightbox && (React.createElement("div", { className: style.previewOverlay, onClick: closeLightbox },
|
|
44
|
+
React.createElement("div", { className: cl(style.previewBackdrop, style.visible) }),
|
|
45
|
+
React.createElement("img", { src: src, alt: alt, className: cl(style.previewImage, style.visible) })))));
|
|
46
|
+
};
|
|
47
|
+
/** Small inline thumbnail for use inside chips, badges, and dropdown options */
|
|
48
|
+
export const InlineImageThumb = ({ src, alt = '', }) => (React.createElement("img", { src: src, alt: alt, className: style.inlineThumb, loading: "lazy" }));
|
|
49
|
+
export default ImageThumb;
|
|
50
|
+
//# sourceMappingURL=ImageThumb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImageThumb.js","sourceRoot":"","sources":["../../../src/components/ImageThumb.tsx"],"names":[],"mappings":"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"}
|