@choice-ui/radio 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +9 -17
- package/dist/index.js +52 -11
- package/package.json +10 -12
- package/dist/index.cjs +0 -341
- package/dist/index.d.cts +0 -69
- package/src/context.ts +0 -38
- package/src/index.ts +0 -8
- package/src/radio-group.tsx +0 -137
- package/src/radio-label.tsx +0 -33
- package/src/radio.tsx +0 -109
- package/src/tv.ts +0 -128
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { HTMLProps, ReactNode } from 'react';
|
|
3
3
|
|
|
4
|
+
interface RadioIconProps extends Omit<HTMLProps<HTMLDivElement>, "children"> {
|
|
5
|
+
children?: ReactNode | ((props: {
|
|
6
|
+
value?: boolean;
|
|
7
|
+
}) => ReactNode);
|
|
8
|
+
}
|
|
9
|
+
declare const RadioIcon: react.MemoExoticComponent<react.ForwardRefExoticComponent<Omit<RadioIconProps, "ref"> & react.RefAttributes<HTMLDivElement>>>;
|
|
10
|
+
|
|
4
11
|
interface RadioLabelProps extends Omit<HTMLProps<HTMLLabelElement>, "htmlFor" | "id" | "disabled"> {
|
|
5
12
|
children: ReactNode;
|
|
6
13
|
}
|
|
@@ -19,6 +26,7 @@ interface RadioType {
|
|
|
19
26
|
(props: RadioProps & {
|
|
20
27
|
ref?: React.Ref<HTMLInputElement>;
|
|
21
28
|
}): JSX.Element;
|
|
29
|
+
Icon: typeof RadioIcon;
|
|
22
30
|
Label: typeof RadioLabel;
|
|
23
31
|
displayName?: string;
|
|
24
32
|
}
|
|
@@ -50,20 +58,4 @@ interface RadioGroupType {
|
|
|
50
58
|
}
|
|
51
59
|
declare const RadioGroup: RadioGroupType;
|
|
52
60
|
|
|
53
|
-
|
|
54
|
-
descriptionId: string;
|
|
55
|
-
disabled?: boolean;
|
|
56
|
-
id: string;
|
|
57
|
-
}
|
|
58
|
-
declare function useRadioContext(): RadioContextType;
|
|
59
|
-
interface RadioGroupContextType {
|
|
60
|
-
disabled?: boolean;
|
|
61
|
-
name: string;
|
|
62
|
-
onChange: (value: string) => void;
|
|
63
|
-
readOnly?: boolean;
|
|
64
|
-
value: string;
|
|
65
|
-
variant?: "default" | "accent" | "outline";
|
|
66
|
-
}
|
|
67
|
-
declare function useRadioGroupContext(): RadioGroupContextType;
|
|
68
|
-
|
|
69
|
-
export { Radio, type RadioContextType, RadioGroup, type RadioGroupContextType, type RadioGroupProps, RadioLabel, type RadioLabelProps, type RadioProps, useRadioContext, useRadioGroupContext };
|
|
61
|
+
export { Radio, RadioGroup, type RadioGroupProps, type RadioIconProps, type RadioLabelProps, type RadioProps };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { tcv, tcx } from '@choice-ui/shared';
|
|
2
2
|
import { Dot } from '@choiceform/icons-react';
|
|
3
|
-
import { createContext, memo, forwardRef, useId, useMemo, useContext } from 'react';
|
|
3
|
+
import { createContext, memo, forwardRef, useId, Children, isValidElement, useMemo, useContext } from 'react';
|
|
4
4
|
import { useEventCallback } from 'usehooks-ts';
|
|
5
5
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
6
6
|
|
|
@@ -147,18 +147,50 @@ var radioTv = tcv({
|
|
|
147
147
|
focused: false
|
|
148
148
|
}
|
|
149
149
|
});
|
|
150
|
+
var RadioIcon = memo(
|
|
151
|
+
forwardRef(function RadioIcon2(props, ref) {
|
|
152
|
+
const { className, children, ...rest } = props;
|
|
153
|
+
const { value, disabled, variant } = useRadioContext();
|
|
154
|
+
const tv = radioTv({
|
|
155
|
+
type: "radio",
|
|
156
|
+
variant,
|
|
157
|
+
disabled,
|
|
158
|
+
checked: value
|
|
159
|
+
});
|
|
160
|
+
const renderIcon = () => {
|
|
161
|
+
if (typeof children === "function") {
|
|
162
|
+
return children({ value });
|
|
163
|
+
}
|
|
164
|
+
if (children !== void 0) {
|
|
165
|
+
return children;
|
|
166
|
+
}
|
|
167
|
+
return value ? /* @__PURE__ */ jsx(Dot, {}) : null;
|
|
168
|
+
};
|
|
169
|
+
return /* @__PURE__ */ jsx(
|
|
170
|
+
"div",
|
|
171
|
+
{
|
|
172
|
+
ref,
|
|
173
|
+
className: tcx(tv.box(), className),
|
|
174
|
+
"data-active": value,
|
|
175
|
+
...rest,
|
|
176
|
+
children: renderIcon()
|
|
177
|
+
}
|
|
178
|
+
);
|
|
179
|
+
})
|
|
180
|
+
);
|
|
181
|
+
RadioIcon.displayName = "Radio.Icon";
|
|
150
182
|
var RadioLabel = memo(
|
|
151
183
|
forwardRef(function RadioLabel2(props, ref) {
|
|
152
184
|
const { children, className, ...rest } = props;
|
|
153
185
|
const { id, descriptionId, disabled } = useRadioContext();
|
|
154
|
-
const
|
|
186
|
+
const tv = radioTv({ disabled });
|
|
155
187
|
return /* @__PURE__ */ jsx(
|
|
156
188
|
"label",
|
|
157
189
|
{
|
|
158
190
|
ref,
|
|
159
191
|
id: descriptionId,
|
|
160
192
|
htmlFor: id,
|
|
161
|
-
className: tcx(
|
|
193
|
+
className: tcx(tv.label(), className),
|
|
162
194
|
...rest,
|
|
163
195
|
children
|
|
164
196
|
}
|
|
@@ -184,7 +216,7 @@ var RadioBase = forwardRef(function Radio(props, ref) {
|
|
|
184
216
|
} = props;
|
|
185
217
|
const id = useId();
|
|
186
218
|
const descriptionId = useId();
|
|
187
|
-
const
|
|
219
|
+
const tv = radioTv({
|
|
188
220
|
type: "radio",
|
|
189
221
|
variant,
|
|
190
222
|
disabled,
|
|
@@ -203,19 +235,27 @@ var RadioBase = forwardRef(function Radio(props, ref) {
|
|
|
203
235
|
}
|
|
204
236
|
onKeyDown?.(e);
|
|
205
237
|
});
|
|
238
|
+
const isIconElement = (child) => isValidElement(child) && (child.type === RadioIcon || child.type?.displayName === "Radio.Icon");
|
|
239
|
+
const childArray = Children.toArray(children);
|
|
240
|
+
const iconChild = childArray.find(isIconElement);
|
|
241
|
+
const otherChildren = childArray.filter((child) => !isIconElement(child));
|
|
206
242
|
const renderChildren = () => {
|
|
207
|
-
if (
|
|
208
|
-
|
|
243
|
+
if (otherChildren.length === 1) {
|
|
244
|
+
const child = otherChildren[0];
|
|
245
|
+
if (typeof child === "string" || typeof child === "number") {
|
|
246
|
+
return /* @__PURE__ */ jsx(RadioLabel, { children: child });
|
|
247
|
+
}
|
|
209
248
|
}
|
|
210
|
-
return
|
|
249
|
+
return otherChildren;
|
|
211
250
|
};
|
|
212
|
-
|
|
251
|
+
const renderDefaultIcon = () => /* @__PURE__ */ jsx("div", { className: tv.box(), children: value && /* @__PURE__ */ jsx(Dot, {}) });
|
|
252
|
+
return /* @__PURE__ */ jsx(RadioContext.Provider, { value: { id, descriptionId, disabled, value, variant }, children: /* @__PURE__ */ jsxs("div", { className: tcx(tv.root(), className), children: [
|
|
213
253
|
/* @__PURE__ */ jsxs("div", { className: "pointer-events-none relative", children: [
|
|
214
254
|
/* @__PURE__ */ jsx(
|
|
215
255
|
"input",
|
|
216
256
|
{
|
|
217
257
|
ref,
|
|
218
|
-
className:
|
|
258
|
+
className: tv.input(),
|
|
219
259
|
type: "radio",
|
|
220
260
|
id,
|
|
221
261
|
name,
|
|
@@ -231,13 +271,14 @@ var RadioBase = forwardRef(function Radio(props, ref) {
|
|
|
231
271
|
...rest
|
|
232
272
|
}
|
|
233
273
|
),
|
|
234
|
-
|
|
274
|
+
iconChild ?? renderDefaultIcon()
|
|
235
275
|
] }),
|
|
236
276
|
renderChildren()
|
|
237
277
|
] }) });
|
|
238
278
|
});
|
|
239
279
|
var MemoizedRadio = memo(RadioBase);
|
|
240
280
|
var Radio2 = MemoizedRadio;
|
|
281
|
+
Radio2.Icon = RadioIcon;
|
|
241
282
|
Radio2.Label = RadioLabel;
|
|
242
283
|
Radio2.displayName = "Radio";
|
|
243
284
|
var RadioGroupItem = memo(
|
|
@@ -332,4 +373,4 @@ var RadioGroup2 = MemoizedRadioGroup;
|
|
|
332
373
|
RadioGroup2.Item = RadioGroupItem;
|
|
333
374
|
RadioGroup2.displayName = "RadioGroup";
|
|
334
375
|
|
|
335
|
-
export { Radio2 as Radio, RadioGroup2 as RadioGroup
|
|
376
|
+
export { Radio2 as Radio, RadioGroup2 as RadioGroup };
|
package/package.json
CHANGED
|
@@ -1,21 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@choice-ui/radio",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.0.6",
|
|
4
|
+
"description": "A radio button component for single selection from a group of mutually exclusive options",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"type": "module",
|
|
7
|
-
"main": "./dist/index.
|
|
8
|
-
"
|
|
9
|
-
"types": "./src/index.ts",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
10
9
|
"files": [
|
|
11
|
-
"dist"
|
|
12
|
-
"src"
|
|
10
|
+
"dist"
|
|
13
11
|
],
|
|
14
12
|
"exports": {
|
|
15
13
|
".": {
|
|
16
|
-
"types": "./
|
|
17
|
-
"import": "./dist/index.js"
|
|
18
|
-
"require": "./dist/index.cjs"
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js"
|
|
19
16
|
}
|
|
20
17
|
},
|
|
21
18
|
"publishConfig": {
|
|
@@ -23,8 +20,8 @@
|
|
|
23
20
|
},
|
|
24
21
|
"dependencies": {
|
|
25
22
|
"usehooks-ts": "^3.1.0",
|
|
26
|
-
"@
|
|
27
|
-
"@
|
|
23
|
+
"@choice-ui/shared": "^0.0.1",
|
|
24
|
+
"@choiceform/icons-react": "^1.3.8"
|
|
28
25
|
},
|
|
29
26
|
"devDependencies": {
|
|
30
27
|
"@types/react": "^18.3.12",
|
|
@@ -39,6 +36,7 @@
|
|
|
39
36
|
"react": ">=18.0.0",
|
|
40
37
|
"react-dom": ">=18.0.0"
|
|
41
38
|
},
|
|
39
|
+
"source": "./src/index.ts",
|
|
42
40
|
"scripts": {
|
|
43
41
|
"build": "tsup",
|
|
44
42
|
"build:watch": "tsup --watch",
|
package/dist/index.cjs
DELETED
|
@@ -1,341 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var shared = require('@choice-ui/shared');
|
|
4
|
-
var iconsReact = require('@choiceform/icons-react');
|
|
5
|
-
var react = require('react');
|
|
6
|
-
var usehooksTs = require('usehooks-ts');
|
|
7
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
8
|
-
|
|
9
|
-
// src/radio.tsx
|
|
10
|
-
var RadioContext = react.createContext(null);
|
|
11
|
-
function useRadioContext() {
|
|
12
|
-
const context = react.useContext(RadioContext);
|
|
13
|
-
if (!context) {
|
|
14
|
-
throw new Error("Radio.Label must be used within a Radio component");
|
|
15
|
-
}
|
|
16
|
-
return context;
|
|
17
|
-
}
|
|
18
|
-
var RadioGroupContext = react.createContext(null);
|
|
19
|
-
function useRadioGroupContext() {
|
|
20
|
-
const context = react.useContext(RadioGroupContext);
|
|
21
|
-
if (!context) {
|
|
22
|
-
throw new Error("RadioGroupItem must be used within a RadioGroup");
|
|
23
|
-
}
|
|
24
|
-
return context;
|
|
25
|
-
}
|
|
26
|
-
var radioTv = shared.tcv({
|
|
27
|
-
slots: {
|
|
28
|
-
root: "flex items-center select-none",
|
|
29
|
-
box: ["relative flex size-4 items-center justify-center", "border border-solid"],
|
|
30
|
-
input: "peer pointer-events-auto absolute inset-0 appearance-none opacity-0",
|
|
31
|
-
label: "pl-2"
|
|
32
|
-
},
|
|
33
|
-
variants: {
|
|
34
|
-
type: {
|
|
35
|
-
checkbox: {
|
|
36
|
-
box: "rounded-md"
|
|
37
|
-
},
|
|
38
|
-
radio: {
|
|
39
|
-
box: "rounded-full"
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
|
-
variant: {
|
|
43
|
-
default: {},
|
|
44
|
-
accent: {},
|
|
45
|
-
outline: {}
|
|
46
|
-
},
|
|
47
|
-
checked: {
|
|
48
|
-
true: {},
|
|
49
|
-
false: {}
|
|
50
|
-
},
|
|
51
|
-
disabled: {
|
|
52
|
-
true: {},
|
|
53
|
-
false: {}
|
|
54
|
-
},
|
|
55
|
-
focused: {
|
|
56
|
-
true: {},
|
|
57
|
-
false: {}
|
|
58
|
-
}
|
|
59
|
-
},
|
|
60
|
-
compoundVariants: [
|
|
61
|
-
// 未选中状态
|
|
62
|
-
{
|
|
63
|
-
variant: ["default", "accent"],
|
|
64
|
-
checked: false,
|
|
65
|
-
disabled: false,
|
|
66
|
-
focused: false,
|
|
67
|
-
class: {
|
|
68
|
-
box: "bg-secondary-background border-default-boundary"
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
variant: "outline",
|
|
73
|
-
checked: false,
|
|
74
|
-
disabled: false,
|
|
75
|
-
focused: false,
|
|
76
|
-
class: {
|
|
77
|
-
box: ["border-default-foreground", "peer-focus-visible:border-selected-boundary"]
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
// 选中状态 - default
|
|
81
|
-
{
|
|
82
|
-
variant: "default",
|
|
83
|
-
checked: true,
|
|
84
|
-
disabled: false,
|
|
85
|
-
focused: false,
|
|
86
|
-
class: {
|
|
87
|
-
box: [
|
|
88
|
-
"bg-secondary-background border-default-boundary",
|
|
89
|
-
"peer-focus-visible:border-selected-strong-boundary"
|
|
90
|
-
]
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
// 选中状态 - accent & outline
|
|
94
|
-
{
|
|
95
|
-
variant: ["accent", "outline"],
|
|
96
|
-
checked: true,
|
|
97
|
-
disabled: false,
|
|
98
|
-
focused: false,
|
|
99
|
-
class: {
|
|
100
|
-
box: [
|
|
101
|
-
"bg-accent-background border-selected-strong-boundary text-on-accent-foreground",
|
|
102
|
-
"peer-focus-visible:border-selected-strong-boundary",
|
|
103
|
-
"peer-focus-visible:text-on-accent-foreground",
|
|
104
|
-
"peer-focus-visible:shadow-checked-focused"
|
|
105
|
-
]
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
variant: ["default", "accent", "outline"],
|
|
110
|
-
checked: false,
|
|
111
|
-
disabled: false,
|
|
112
|
-
focused: true,
|
|
113
|
-
class: {
|
|
114
|
-
box: "border-selected-boundary"
|
|
115
|
-
}
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
variant: "default",
|
|
119
|
-
checked: true,
|
|
120
|
-
disabled: false,
|
|
121
|
-
focused: true,
|
|
122
|
-
class: {
|
|
123
|
-
box: "border-selected-strong-boundary"
|
|
124
|
-
}
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
variant: ["accent", "outline"],
|
|
128
|
-
checked: true,
|
|
129
|
-
disabled: false,
|
|
130
|
-
focused: true,
|
|
131
|
-
class: {
|
|
132
|
-
box: "text-on-accent-foreground border-selected-strong-boundary shadow-checked-focused"
|
|
133
|
-
}
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
variant: ["accent", "outline", "default"],
|
|
137
|
-
disabled: true,
|
|
138
|
-
class: {
|
|
139
|
-
root: "text-default-background",
|
|
140
|
-
box: "border-disabled-background bg-disabled-background",
|
|
141
|
-
label: "text-disabled-foreground"
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
],
|
|
145
|
-
defaultVariants: {
|
|
146
|
-
variant: "default",
|
|
147
|
-
checked: false,
|
|
148
|
-
disabled: false,
|
|
149
|
-
focused: false
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
var RadioLabel = react.memo(
|
|
153
|
-
react.forwardRef(function RadioLabel2(props, ref) {
|
|
154
|
-
const { children, className, ...rest } = props;
|
|
155
|
-
const { id, descriptionId, disabled } = useRadioContext();
|
|
156
|
-
const styles = radioTv({ disabled });
|
|
157
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
158
|
-
"label",
|
|
159
|
-
{
|
|
160
|
-
ref,
|
|
161
|
-
id: descriptionId,
|
|
162
|
-
htmlFor: id,
|
|
163
|
-
className: shared.tcx(styles.label(), className),
|
|
164
|
-
...rest,
|
|
165
|
-
children
|
|
166
|
-
}
|
|
167
|
-
);
|
|
168
|
-
})
|
|
169
|
-
);
|
|
170
|
-
RadioLabel.displayName = "Radio.Label";
|
|
171
|
-
var RadioBase = react.forwardRef(function Radio(props, ref) {
|
|
172
|
-
const {
|
|
173
|
-
value,
|
|
174
|
-
onChange,
|
|
175
|
-
disabled,
|
|
176
|
-
readOnly = false,
|
|
177
|
-
name,
|
|
178
|
-
variant = "default",
|
|
179
|
-
className,
|
|
180
|
-
focused,
|
|
181
|
-
children,
|
|
182
|
-
"aria-label": ariaLabel,
|
|
183
|
-
"aria-describedby": ariaDescribedby,
|
|
184
|
-
onKeyDown,
|
|
185
|
-
...rest
|
|
186
|
-
} = props;
|
|
187
|
-
const id = react.useId();
|
|
188
|
-
const descriptionId = react.useId();
|
|
189
|
-
const styles = radioTv({
|
|
190
|
-
type: "radio",
|
|
191
|
-
variant,
|
|
192
|
-
disabled,
|
|
193
|
-
checked: value,
|
|
194
|
-
focused
|
|
195
|
-
});
|
|
196
|
-
const handleChange = usehooksTs.useEventCallback((e) => {
|
|
197
|
-
if (readOnly) return;
|
|
198
|
-
onChange(e.target.checked);
|
|
199
|
-
});
|
|
200
|
-
const handleKeyDown = usehooksTs.useEventCallback((e) => {
|
|
201
|
-
if (readOnly) return;
|
|
202
|
-
if (e.key === " " || e.key === "Enter") {
|
|
203
|
-
e.preventDefault();
|
|
204
|
-
onChange(!value);
|
|
205
|
-
}
|
|
206
|
-
onKeyDown?.(e);
|
|
207
|
-
});
|
|
208
|
-
const renderChildren = () => {
|
|
209
|
-
if (typeof children === "string" || typeof children === "number") {
|
|
210
|
-
return /* @__PURE__ */ jsxRuntime.jsx(RadioLabel, { children });
|
|
211
|
-
}
|
|
212
|
-
return children;
|
|
213
|
-
};
|
|
214
|
-
return /* @__PURE__ */ jsxRuntime.jsx(RadioContext.Provider, { value: { id, descriptionId, disabled }, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: shared.tcx(styles.root(), className), children: [
|
|
215
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pointer-events-none relative", children: [
|
|
216
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
217
|
-
"input",
|
|
218
|
-
{
|
|
219
|
-
ref,
|
|
220
|
-
className: styles.input(),
|
|
221
|
-
type: "radio",
|
|
222
|
-
id,
|
|
223
|
-
name,
|
|
224
|
-
checked: value,
|
|
225
|
-
disabled: disabled || readOnly,
|
|
226
|
-
onChange: handleChange,
|
|
227
|
-
"aria-label": ariaLabel,
|
|
228
|
-
"aria-describedby": ariaDescribedby || descriptionId,
|
|
229
|
-
"aria-checked": value,
|
|
230
|
-
"aria-disabled": disabled || readOnly,
|
|
231
|
-
role: "radio",
|
|
232
|
-
onKeyDown: handleKeyDown,
|
|
233
|
-
...rest
|
|
234
|
-
}
|
|
235
|
-
),
|
|
236
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.box(), children: value && /* @__PURE__ */ jsxRuntime.jsx(iconsReact.Dot, {}) })
|
|
237
|
-
] }),
|
|
238
|
-
renderChildren()
|
|
239
|
-
] }) });
|
|
240
|
-
});
|
|
241
|
-
var MemoizedRadio = react.memo(RadioBase);
|
|
242
|
-
var Radio2 = MemoizedRadio;
|
|
243
|
-
Radio2.Label = RadioLabel;
|
|
244
|
-
Radio2.displayName = "Radio";
|
|
245
|
-
var RadioGroupItem = react.memo(
|
|
246
|
-
react.forwardRef(function RadioGroupItem2(props, ref) {
|
|
247
|
-
const { value, children, className, disabled, ...rest } = props;
|
|
248
|
-
const {
|
|
249
|
-
name,
|
|
250
|
-
value: selectedValue,
|
|
251
|
-
onChange,
|
|
252
|
-
variant,
|
|
253
|
-
readOnly: contextReadonly
|
|
254
|
-
} = useRadioGroupContext();
|
|
255
|
-
const isChecked = selectedValue === value;
|
|
256
|
-
const handleChange = usehooksTs.useEventCallback(() => {
|
|
257
|
-
if (contextReadonly) return;
|
|
258
|
-
onChange(value);
|
|
259
|
-
});
|
|
260
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
261
|
-
Radio2,
|
|
262
|
-
{
|
|
263
|
-
name,
|
|
264
|
-
value: isChecked,
|
|
265
|
-
disabled,
|
|
266
|
-
readOnly: contextReadonly,
|
|
267
|
-
variant,
|
|
268
|
-
onChange: handleChange,
|
|
269
|
-
className,
|
|
270
|
-
...rest,
|
|
271
|
-
ref,
|
|
272
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(Radio2.Label, { children })
|
|
273
|
-
}
|
|
274
|
-
);
|
|
275
|
-
})
|
|
276
|
-
);
|
|
277
|
-
RadioGroupItem.displayName = "RadioGroup.Item";
|
|
278
|
-
var RadioGroupBase = react.forwardRef(function RadioGroup(props, ref) {
|
|
279
|
-
const {
|
|
280
|
-
className,
|
|
281
|
-
options,
|
|
282
|
-
value,
|
|
283
|
-
onChange,
|
|
284
|
-
disabled,
|
|
285
|
-
readOnly = false,
|
|
286
|
-
variant = "default",
|
|
287
|
-
children,
|
|
288
|
-
...rest
|
|
289
|
-
} = props;
|
|
290
|
-
const id = react.useId();
|
|
291
|
-
const handleChange = usehooksTs.useEventCallback((newValue) => {
|
|
292
|
-
if (readOnly) return;
|
|
293
|
-
onChange(newValue);
|
|
294
|
-
});
|
|
295
|
-
const contextValue = react.useMemo(
|
|
296
|
-
() => ({
|
|
297
|
-
name: id,
|
|
298
|
-
value,
|
|
299
|
-
onChange: handleChange,
|
|
300
|
-
disabled,
|
|
301
|
-
readOnly,
|
|
302
|
-
variant
|
|
303
|
-
}),
|
|
304
|
-
[id, value, handleChange, disabled, readOnly, variant]
|
|
305
|
-
);
|
|
306
|
-
const renderOptionsRadios = react.useMemo(() => {
|
|
307
|
-
if (!options) return null;
|
|
308
|
-
return options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
309
|
-
RadioGroupItem,
|
|
310
|
-
{
|
|
311
|
-
value: option.value,
|
|
312
|
-
disabled: option.disabled || disabled,
|
|
313
|
-
variant,
|
|
314
|
-
children: option.label
|
|
315
|
-
},
|
|
316
|
-
option.value
|
|
317
|
-
));
|
|
318
|
-
}, [disabled, options, variant]);
|
|
319
|
-
return /* @__PURE__ */ jsxRuntime.jsx(RadioGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
320
|
-
"div",
|
|
321
|
-
{
|
|
322
|
-
className: shared.tcx("flex flex-col gap-2", className),
|
|
323
|
-
ref,
|
|
324
|
-
role: "radiogroup",
|
|
325
|
-
"aria-labelledby": props["aria-labelledby"],
|
|
326
|
-
"aria-label": props["aria-label"],
|
|
327
|
-
...rest,
|
|
328
|
-
children: options ? renderOptionsRadios : children
|
|
329
|
-
}
|
|
330
|
-
) });
|
|
331
|
-
});
|
|
332
|
-
var MemoizedRadioGroup = react.memo(RadioGroupBase);
|
|
333
|
-
var RadioGroup2 = MemoizedRadioGroup;
|
|
334
|
-
RadioGroup2.Item = RadioGroupItem;
|
|
335
|
-
RadioGroup2.displayName = "RadioGroup";
|
|
336
|
-
|
|
337
|
-
exports.Radio = Radio2;
|
|
338
|
-
exports.RadioGroup = RadioGroup2;
|
|
339
|
-
exports.RadioLabel = RadioLabel;
|
|
340
|
-
exports.useRadioContext = useRadioContext;
|
|
341
|
-
exports.useRadioGroupContext = useRadioGroupContext;
|
package/dist/index.d.cts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import * as react from 'react';
|
|
2
|
-
import { HTMLProps, ReactNode } from 'react';
|
|
3
|
-
|
|
4
|
-
interface RadioLabelProps extends Omit<HTMLProps<HTMLLabelElement>, "htmlFor" | "id" | "disabled"> {
|
|
5
|
-
children: ReactNode;
|
|
6
|
-
}
|
|
7
|
-
declare const RadioLabel: react.MemoExoticComponent<react.ForwardRefExoticComponent<Omit<RadioLabelProps, "ref"> & react.RefAttributes<HTMLLabelElement>>>;
|
|
8
|
-
|
|
9
|
-
interface RadioProps extends Omit<HTMLProps<HTMLInputElement>, "value" | "onChange"> {
|
|
10
|
-
children?: ReactNode;
|
|
11
|
-
className?: string;
|
|
12
|
-
focused?: boolean;
|
|
13
|
-
onChange: (value: boolean) => void;
|
|
14
|
-
readOnly?: boolean;
|
|
15
|
-
value: boolean;
|
|
16
|
-
variant?: "default" | "accent" | "outline";
|
|
17
|
-
}
|
|
18
|
-
interface RadioType {
|
|
19
|
-
(props: RadioProps & {
|
|
20
|
-
ref?: React.Ref<HTMLInputElement>;
|
|
21
|
-
}): JSX.Element;
|
|
22
|
-
Label: typeof RadioLabel;
|
|
23
|
-
displayName?: string;
|
|
24
|
-
}
|
|
25
|
-
declare const Radio: RadioType;
|
|
26
|
-
|
|
27
|
-
interface RadioGroupProps extends Omit<HTMLProps<HTMLDivElement>, "value" | "onChange"> {
|
|
28
|
-
children?: ReactNode;
|
|
29
|
-
onChange: (value: string) => void;
|
|
30
|
-
options?: {
|
|
31
|
-
disabled?: boolean;
|
|
32
|
-
label: string;
|
|
33
|
-
value: string;
|
|
34
|
-
}[];
|
|
35
|
-
readOnly?: boolean;
|
|
36
|
-
value: string;
|
|
37
|
-
variant?: "default" | "accent" | "outline";
|
|
38
|
-
}
|
|
39
|
-
type RadioGroupItemProps = Omit<RadioProps, "value" | "onChange"> & {
|
|
40
|
-
children: ReactNode;
|
|
41
|
-
value: string;
|
|
42
|
-
};
|
|
43
|
-
declare const RadioGroupItem: react.MemoExoticComponent<react.ForwardRefExoticComponent<Omit<RadioGroupItemProps, "ref"> & react.RefAttributes<HTMLInputElement>>>;
|
|
44
|
-
interface RadioGroupType {
|
|
45
|
-
(props: RadioGroupProps & {
|
|
46
|
-
ref?: React.Ref<HTMLDivElement>;
|
|
47
|
-
}): JSX.Element;
|
|
48
|
-
Item: typeof RadioGroupItem;
|
|
49
|
-
displayName?: string;
|
|
50
|
-
}
|
|
51
|
-
declare const RadioGroup: RadioGroupType;
|
|
52
|
-
|
|
53
|
-
interface RadioContextType {
|
|
54
|
-
descriptionId: string;
|
|
55
|
-
disabled?: boolean;
|
|
56
|
-
id: string;
|
|
57
|
-
}
|
|
58
|
-
declare function useRadioContext(): RadioContextType;
|
|
59
|
-
interface RadioGroupContextType {
|
|
60
|
-
disabled?: boolean;
|
|
61
|
-
name: string;
|
|
62
|
-
onChange: (value: string) => void;
|
|
63
|
-
readOnly?: boolean;
|
|
64
|
-
value: string;
|
|
65
|
-
variant?: "default" | "accent" | "outline";
|
|
66
|
-
}
|
|
67
|
-
declare function useRadioGroupContext(): RadioGroupContextType;
|
|
68
|
-
|
|
69
|
-
export { Radio, type RadioContextType, RadioGroup, type RadioGroupContextType, type RadioGroupProps, RadioLabel, type RadioLabelProps, type RadioProps, useRadioContext, useRadioGroupContext };
|
package/src/context.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { createContext, useContext } from "react"
|
|
2
|
-
|
|
3
|
-
// Radio 组件的 Context
|
|
4
|
-
export interface RadioContextType {
|
|
5
|
-
descriptionId: string
|
|
6
|
-
disabled?: boolean
|
|
7
|
-
id: string
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const RadioContext = createContext<RadioContextType | null>(null)
|
|
11
|
-
|
|
12
|
-
export function useRadioContext() {
|
|
13
|
-
const context = useContext(RadioContext)
|
|
14
|
-
if (!context) {
|
|
15
|
-
throw new Error("Radio.Label must be used within a Radio component")
|
|
16
|
-
}
|
|
17
|
-
return context
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// RadioGroup 组件的 Context
|
|
21
|
-
export interface RadioGroupContextType {
|
|
22
|
-
disabled?: boolean
|
|
23
|
-
name: string
|
|
24
|
-
onChange: (value: string) => void
|
|
25
|
-
readOnly?: boolean
|
|
26
|
-
value: string
|
|
27
|
-
variant?: "default" | "accent" | "outline"
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export const RadioGroupContext = createContext<RadioGroupContextType | null>(null)
|
|
31
|
-
|
|
32
|
-
export function useRadioGroupContext() {
|
|
33
|
-
const context = useContext(RadioGroupContext)
|
|
34
|
-
if (!context) {
|
|
35
|
-
throw new Error("RadioGroupItem must be used within a RadioGroup")
|
|
36
|
-
}
|
|
37
|
-
return context
|
|
38
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export { Radio } from "./radio"
|
|
2
|
-
export { RadioGroup } from "./radio-group"
|
|
3
|
-
export { RadioLabel } from "./radio-label"
|
|
4
|
-
export { useRadioContext, useRadioGroupContext } from "./context"
|
|
5
|
-
export type { RadioProps } from "./radio"
|
|
6
|
-
export type { RadioGroupProps } from "./radio-group"
|
|
7
|
-
export type { RadioLabelProps } from "./radio-label"
|
|
8
|
-
export type { RadioContextType, RadioGroupContextType } from "./context"
|
package/src/radio-group.tsx
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import { tcx } from "@choice-ui/shared"
|
|
2
|
-
import { forwardRef, HTMLProps, memo, ReactNode, useId, useMemo } from "react"
|
|
3
|
-
import { useEventCallback } from "usehooks-ts"
|
|
4
|
-
import { RadioGroupContext, useRadioGroupContext } from "./context"
|
|
5
|
-
import { Radio, RadioProps } from "./radio"
|
|
6
|
-
|
|
7
|
-
export interface RadioGroupProps extends Omit<HTMLProps<HTMLDivElement>, "value" | "onChange"> {
|
|
8
|
-
children?: ReactNode
|
|
9
|
-
onChange: (value: string) => void
|
|
10
|
-
options?: {
|
|
11
|
-
disabled?: boolean
|
|
12
|
-
label: string
|
|
13
|
-
value: string
|
|
14
|
-
}[]
|
|
15
|
-
readOnly?: boolean
|
|
16
|
-
value: string
|
|
17
|
-
variant?: "default" | "accent" | "outline"
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
type RadioGroupItemProps = Omit<RadioProps, "value" | "onChange"> & {
|
|
21
|
-
children: ReactNode
|
|
22
|
-
value: string
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const RadioGroupItem = memo(
|
|
26
|
-
forwardRef<HTMLInputElement, RadioGroupItemProps>(function RadioGroupItem(props, ref) {
|
|
27
|
-
const { value, children, className, disabled, ...rest } = props
|
|
28
|
-
const {
|
|
29
|
-
name,
|
|
30
|
-
value: selectedValue,
|
|
31
|
-
onChange,
|
|
32
|
-
variant,
|
|
33
|
-
readOnly: contextReadonly,
|
|
34
|
-
} = useRadioGroupContext()
|
|
35
|
-
const isChecked = selectedValue === value
|
|
36
|
-
|
|
37
|
-
const handleChange = useEventCallback(() => {
|
|
38
|
-
if (contextReadonly) return
|
|
39
|
-
onChange(value)
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
return (
|
|
43
|
-
<Radio
|
|
44
|
-
name={name}
|
|
45
|
-
value={isChecked}
|
|
46
|
-
disabled={disabled}
|
|
47
|
-
readOnly={contextReadonly}
|
|
48
|
-
variant={variant}
|
|
49
|
-
onChange={handleChange}
|
|
50
|
-
className={className}
|
|
51
|
-
{...rest}
|
|
52
|
-
ref={ref}
|
|
53
|
-
>
|
|
54
|
-
<Radio.Label>{children}</Radio.Label>
|
|
55
|
-
</Radio>
|
|
56
|
-
)
|
|
57
|
-
}),
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
RadioGroupItem.displayName = "RadioGroup.Item"
|
|
61
|
-
|
|
62
|
-
const RadioGroupBase = forwardRef<HTMLDivElement, RadioGroupProps>(function RadioGroup(props, ref) {
|
|
63
|
-
const {
|
|
64
|
-
className,
|
|
65
|
-
options,
|
|
66
|
-
value,
|
|
67
|
-
onChange,
|
|
68
|
-
disabled,
|
|
69
|
-
readOnly = false,
|
|
70
|
-
variant = "default",
|
|
71
|
-
children,
|
|
72
|
-
...rest
|
|
73
|
-
} = props
|
|
74
|
-
const id = useId()
|
|
75
|
-
|
|
76
|
-
const handleChange = useEventCallback((newValue: string) => {
|
|
77
|
-
if (readOnly) return
|
|
78
|
-
onChange(newValue)
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
const contextValue = useMemo(
|
|
82
|
-
() => ({
|
|
83
|
-
name: id,
|
|
84
|
-
value,
|
|
85
|
-
onChange: handleChange,
|
|
86
|
-
disabled,
|
|
87
|
-
readOnly,
|
|
88
|
-
variant,
|
|
89
|
-
}),
|
|
90
|
-
[id, value, handleChange, disabled, readOnly, variant],
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
// 渲染基于选项的单选按钮
|
|
94
|
-
const renderOptionsRadios = useMemo(() => {
|
|
95
|
-
if (!options) return null
|
|
96
|
-
|
|
97
|
-
return options.map((option) => (
|
|
98
|
-
<RadioGroupItem
|
|
99
|
-
key={option.value}
|
|
100
|
-
value={option.value}
|
|
101
|
-
disabled={option.disabled || disabled}
|
|
102
|
-
variant={variant}
|
|
103
|
-
>
|
|
104
|
-
{option.label}
|
|
105
|
-
</RadioGroupItem>
|
|
106
|
-
))
|
|
107
|
-
}, [disabled, options, variant])
|
|
108
|
-
|
|
109
|
-
return (
|
|
110
|
-
<RadioGroupContext.Provider value={contextValue}>
|
|
111
|
-
<div
|
|
112
|
-
className={tcx("flex flex-col gap-2", className)}
|
|
113
|
-
ref={ref}
|
|
114
|
-
role="radiogroup"
|
|
115
|
-
aria-labelledby={props["aria-labelledby"]}
|
|
116
|
-
aria-label={props["aria-label"]}
|
|
117
|
-
{...rest}
|
|
118
|
-
>
|
|
119
|
-
{options ? renderOptionsRadios : children}
|
|
120
|
-
</div>
|
|
121
|
-
</RadioGroupContext.Provider>
|
|
122
|
-
)
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
// 使用 memo 包装组件以避免不必要的重渲染
|
|
126
|
-
const MemoizedRadioGroup = memo(RadioGroupBase) as unknown as RadioGroupType
|
|
127
|
-
|
|
128
|
-
interface RadioGroupType {
|
|
129
|
-
(props: RadioGroupProps & { ref?: React.Ref<HTMLDivElement> }): JSX.Element
|
|
130
|
-
Item: typeof RadioGroupItem
|
|
131
|
-
displayName?: string
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
export const RadioGroup = MemoizedRadioGroup
|
|
135
|
-
|
|
136
|
-
RadioGroup.Item = RadioGroupItem
|
|
137
|
-
RadioGroup.displayName = "RadioGroup"
|
package/src/radio-label.tsx
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { tcx } from "@choice-ui/shared"
|
|
2
|
-
import { forwardRef, HTMLProps, memo, ReactNode } from "react"
|
|
3
|
-
import { useRadioContext } from "./context"
|
|
4
|
-
import { radioTv } from "./tv"
|
|
5
|
-
|
|
6
|
-
export interface RadioLabelProps extends Omit<
|
|
7
|
-
HTMLProps<HTMLLabelElement>,
|
|
8
|
-
"htmlFor" | "id" | "disabled"
|
|
9
|
-
> {
|
|
10
|
-
children: ReactNode
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const RadioLabel = memo(
|
|
14
|
-
forwardRef<HTMLLabelElement, RadioLabelProps>(function RadioLabel(props, ref) {
|
|
15
|
-
const { children, className, ...rest } = props
|
|
16
|
-
const { id, descriptionId, disabled } = useRadioContext()
|
|
17
|
-
const styles = radioTv({ disabled })
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<label
|
|
21
|
-
ref={ref}
|
|
22
|
-
id={descriptionId}
|
|
23
|
-
htmlFor={id}
|
|
24
|
-
className={tcx(styles.label(), className)}
|
|
25
|
-
{...rest}
|
|
26
|
-
>
|
|
27
|
-
{children}
|
|
28
|
-
</label>
|
|
29
|
-
)
|
|
30
|
-
}),
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
RadioLabel.displayName = "Radio.Label"
|
package/src/radio.tsx
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { tcx } from "@choice-ui/shared"
|
|
2
|
-
import { Dot } from "@choiceform/icons-react"
|
|
3
|
-
import { forwardRef, HTMLProps, memo, ReactNode, useId } from "react"
|
|
4
|
-
import { useEventCallback } from "usehooks-ts"
|
|
5
|
-
import { RadioContext } from "./context"
|
|
6
|
-
import { RadioLabel } from "./radio-label"
|
|
7
|
-
import { radioTv } from "./tv"
|
|
8
|
-
|
|
9
|
-
export interface RadioProps extends Omit<HTMLProps<HTMLInputElement>, "value" | "onChange"> {
|
|
10
|
-
children?: ReactNode
|
|
11
|
-
className?: string
|
|
12
|
-
focused?: boolean
|
|
13
|
-
onChange: (value: boolean) => void
|
|
14
|
-
readOnly?: boolean
|
|
15
|
-
value: boolean
|
|
16
|
-
variant?: "default" | "accent" | "outline"
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const RadioBase = forwardRef<HTMLInputElement, RadioProps>(function Radio(props, ref) {
|
|
20
|
-
const {
|
|
21
|
-
value,
|
|
22
|
-
onChange,
|
|
23
|
-
disabled,
|
|
24
|
-
readOnly = false,
|
|
25
|
-
name,
|
|
26
|
-
variant = "default",
|
|
27
|
-
className,
|
|
28
|
-
focused,
|
|
29
|
-
children,
|
|
30
|
-
"aria-label": ariaLabel,
|
|
31
|
-
"aria-describedby": ariaDescribedby,
|
|
32
|
-
onKeyDown,
|
|
33
|
-
...rest
|
|
34
|
-
} = props
|
|
35
|
-
const id = useId()
|
|
36
|
-
const descriptionId = useId()
|
|
37
|
-
|
|
38
|
-
const styles = radioTv({
|
|
39
|
-
type: "radio",
|
|
40
|
-
variant,
|
|
41
|
-
disabled,
|
|
42
|
-
checked: value,
|
|
43
|
-
focused,
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
const handleChange = useEventCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
|
47
|
-
if (readOnly) return
|
|
48
|
-
onChange(e.target.checked)
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
const handleKeyDown = useEventCallback((e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
52
|
-
if (readOnly) return
|
|
53
|
-
if (e.key === " " || e.key === "Enter") {
|
|
54
|
-
e.preventDefault()
|
|
55
|
-
onChange(!value)
|
|
56
|
-
}
|
|
57
|
-
onKeyDown?.(e)
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
// 自动将字符串类型的 children 包装成 RadioLabel
|
|
61
|
-
const renderChildren = () => {
|
|
62
|
-
if (typeof children === "string" || typeof children === "number") {
|
|
63
|
-
return <RadioLabel>{children}</RadioLabel>
|
|
64
|
-
}
|
|
65
|
-
return children
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return (
|
|
69
|
-
<RadioContext.Provider value={{ id, descriptionId, disabled }}>
|
|
70
|
-
<div className={tcx(styles.root(), className)}>
|
|
71
|
-
<div className="pointer-events-none relative">
|
|
72
|
-
<input
|
|
73
|
-
ref={ref}
|
|
74
|
-
className={styles.input()}
|
|
75
|
-
type="radio"
|
|
76
|
-
id={id}
|
|
77
|
-
name={name}
|
|
78
|
-
checked={value}
|
|
79
|
-
disabled={disabled || readOnly}
|
|
80
|
-
onChange={handleChange}
|
|
81
|
-
aria-label={ariaLabel}
|
|
82
|
-
aria-describedby={ariaDescribedby || descriptionId}
|
|
83
|
-
aria-checked={value}
|
|
84
|
-
aria-disabled={disabled || readOnly}
|
|
85
|
-
role="radio"
|
|
86
|
-
onKeyDown={handleKeyDown}
|
|
87
|
-
{...rest}
|
|
88
|
-
/>
|
|
89
|
-
<div className={styles.box()}>{value && <Dot />}</div>
|
|
90
|
-
</div>
|
|
91
|
-
|
|
92
|
-
{renderChildren()}
|
|
93
|
-
</div>
|
|
94
|
-
</RadioContext.Provider>
|
|
95
|
-
)
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
const MemoizedRadio = memo(RadioBase) as unknown as RadioType
|
|
99
|
-
|
|
100
|
-
interface RadioType {
|
|
101
|
-
(props: RadioProps & { ref?: React.Ref<HTMLInputElement> }): JSX.Element
|
|
102
|
-
Label: typeof RadioLabel
|
|
103
|
-
displayName?: string
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export const Radio = MemoizedRadio as RadioType
|
|
107
|
-
|
|
108
|
-
Radio.Label = RadioLabel
|
|
109
|
-
Radio.displayName = "Radio"
|
package/src/tv.ts
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { tcv } from "@choice-ui/shared"
|
|
2
|
-
|
|
3
|
-
export const radioTv = tcv({
|
|
4
|
-
slots: {
|
|
5
|
-
root: "flex items-center select-none",
|
|
6
|
-
box: ["relative flex size-4 items-center justify-center", "border border-solid"],
|
|
7
|
-
input: "peer pointer-events-auto absolute inset-0 appearance-none opacity-0",
|
|
8
|
-
label: "pl-2",
|
|
9
|
-
},
|
|
10
|
-
variants: {
|
|
11
|
-
type: {
|
|
12
|
-
checkbox: {
|
|
13
|
-
box: "rounded-md",
|
|
14
|
-
},
|
|
15
|
-
radio: {
|
|
16
|
-
box: "rounded-full",
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
variant: {
|
|
20
|
-
default: {},
|
|
21
|
-
accent: {},
|
|
22
|
-
outline: {},
|
|
23
|
-
},
|
|
24
|
-
checked: {
|
|
25
|
-
true: {},
|
|
26
|
-
false: {},
|
|
27
|
-
},
|
|
28
|
-
disabled: {
|
|
29
|
-
true: {},
|
|
30
|
-
false: {},
|
|
31
|
-
},
|
|
32
|
-
focused: {
|
|
33
|
-
true: {},
|
|
34
|
-
false: {},
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
compoundVariants: [
|
|
38
|
-
// 未选中状态
|
|
39
|
-
{
|
|
40
|
-
variant: ["default", "accent"],
|
|
41
|
-
checked: false,
|
|
42
|
-
disabled: false,
|
|
43
|
-
focused: false,
|
|
44
|
-
class: {
|
|
45
|
-
box: "bg-secondary-background border-default-boundary",
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
variant: "outline",
|
|
50
|
-
checked: false,
|
|
51
|
-
disabled: false,
|
|
52
|
-
focused: false,
|
|
53
|
-
class: {
|
|
54
|
-
box: ["border-default-foreground", "peer-focus-visible:border-selected-boundary"],
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
// 选中状态 - default
|
|
58
|
-
{
|
|
59
|
-
variant: "default",
|
|
60
|
-
checked: true,
|
|
61
|
-
disabled: false,
|
|
62
|
-
focused: false,
|
|
63
|
-
class: {
|
|
64
|
-
box: [
|
|
65
|
-
"bg-secondary-background border-default-boundary",
|
|
66
|
-
"peer-focus-visible:border-selected-strong-boundary",
|
|
67
|
-
],
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
// 选中状态 - accent & outline
|
|
71
|
-
{
|
|
72
|
-
variant: ["accent", "outline"],
|
|
73
|
-
checked: true,
|
|
74
|
-
disabled: false,
|
|
75
|
-
focused: false,
|
|
76
|
-
class: {
|
|
77
|
-
box: [
|
|
78
|
-
"bg-accent-background border-selected-strong-boundary text-on-accent-foreground",
|
|
79
|
-
"peer-focus-visible:border-selected-strong-boundary",
|
|
80
|
-
"peer-focus-visible:text-on-accent-foreground",
|
|
81
|
-
"peer-focus-visible:shadow-checked-focused",
|
|
82
|
-
],
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
variant: ["default", "accent", "outline"],
|
|
87
|
-
checked: false,
|
|
88
|
-
disabled: false,
|
|
89
|
-
focused: true,
|
|
90
|
-
class: {
|
|
91
|
-
box: "border-selected-boundary",
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
variant: "default",
|
|
96
|
-
checked: true,
|
|
97
|
-
disabled: false,
|
|
98
|
-
focused: true,
|
|
99
|
-
class: {
|
|
100
|
-
box: "border-selected-strong-boundary",
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
variant: ["accent", "outline"],
|
|
105
|
-
checked: true,
|
|
106
|
-
disabled: false,
|
|
107
|
-
focused: true,
|
|
108
|
-
class: {
|
|
109
|
-
box: "text-on-accent-foreground border-selected-strong-boundary shadow-checked-focused",
|
|
110
|
-
},
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
variant: ["accent", "outline", "default"],
|
|
114
|
-
disabled: true,
|
|
115
|
-
class: {
|
|
116
|
-
root: "text-default-background",
|
|
117
|
-
box: "border-disabled-background bg-disabled-background",
|
|
118
|
-
label: "text-disabled-foreground",
|
|
119
|
-
},
|
|
120
|
-
},
|
|
121
|
-
],
|
|
122
|
-
defaultVariants: {
|
|
123
|
-
variant: "default",
|
|
124
|
-
checked: false,
|
|
125
|
-
disabled: false,
|
|
126
|
-
focused: false,
|
|
127
|
-
},
|
|
128
|
-
})
|