myshell-react-lib 0.1.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/README.md +268 -0
- package/dist/assets/audio-playing.json +3657 -0
- package/dist/index.cjs +9654 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1431 -0
- package/dist/index.d.ts +1431 -0
- package/dist/index.js +8788 -0
- package/dist/index.js.map +1 -0
- package/package.json +140 -0
- package/src/common/assets/audio-playing.json +3657 -0
- package/src/common/constants/constants.ts +24 -0
- package/src/common/constants/types/common.ts +10 -0
- package/src/common/hooks/useAudioPlayer.tsx +198 -0
- package/src/common/hooks/useDevice.ts +26 -0
- package/src/common/hooks/useNativeBridge.ts +42 -0
- package/src/common/hooks/useNotification.tsx +179 -0
- package/src/common/hooks/useWindowWidth.ts +19 -0
- package/src/common/utils/common-helper.ts +81 -0
- package/src/components/ItemDemo.tsx +15 -0
- package/src/components/accordion.tsx +126 -0
- package/src/components/alert-dialog.tsx +148 -0
- package/src/components/alert.tsx +65 -0
- package/src/components/aspect-ratio.tsx +7 -0
- package/src/components/audio-player.tsx +58 -0
- package/src/components/avatar.tsx +133 -0
- package/src/components/badge.tsx +65 -0
- package/src/components/button/button.styles.ts +258 -0
- package/src/components/button/button.tsx +215 -0
- package/src/components/button/icon-button.styles.ts +101 -0
- package/src/components/button/icon-button.tsx +100 -0
- package/src/components/button/index.tsx +3 -0
- package/src/components/button/link-button.tsx +184 -0
- package/src/components/cascader.tsx +175 -0
- package/src/components/checkbox.tsx +135 -0
- package/src/components/command.tsx +155 -0
- package/src/components/context-menu.tsx +198 -0
- package/src/components/count-down.tsx +83 -0
- package/src/components/custom-notification.tsx +95 -0
- package/src/components/dialog.tsx +158 -0
- package/src/components/drawer.tsx +116 -0
- package/src/components/dropdown-menu.tsx +196 -0
- package/src/components/energy-progress.tsx +55 -0
- package/src/components/form.tsx +201 -0
- package/src/components/group.tsx +9 -0
- package/src/components/guide.tsx +243 -0
- package/src/components/icon.tsx +89 -0
- package/src/components/icons/outline/DownIcon.tsx +18 -0
- package/src/components/icons/outline/FilterIcon.tsx +21 -0
- package/src/components/icons/outline/arrow-left.tsx +16 -0
- package/src/components/icons/outline/arrow-up-tray.tsx +16 -0
- package/src/components/icons/outline/check-circle.tsx +17 -0
- package/src/components/icons/outline/config.tsx +42 -0
- package/src/components/icons/outline/pencil-square.tsx +16 -0
- package/src/components/icons/outline/trash.tsx +17 -0
- package/src/components/icons/outline/window.tsx +16 -0
- package/src/components/icons/outline/x-circle.tsx +17 -0
- package/src/components/icons/outline/x-mark.tsx +16 -0
- package/src/components/icons/solid/audio-playing.tsx +31 -0
- package/src/components/icons/solid/caret-down.tsx +14 -0
- package/src/components/icons/solid/code.tsx +18 -0
- package/src/components/icons/solid/drag.tsx +14 -0
- package/src/components/icons/solid/phone.tsx +23 -0
- package/src/components/icons/solid/rectangle-group.tsx +14 -0
- package/src/components/image.tsx +151 -0
- package/src/components/input.tsx +118 -0
- package/src/components/label.tsx +26 -0
- package/src/components/link.tsx +123 -0
- package/src/components/marquee/index.css +15 -0
- package/src/components/marquee/marquee.tsx +220 -0
- package/src/components/masonry.tsx +138 -0
- package/src/components/menubar.tsx +234 -0
- package/src/components/mobile/m-tooltip.tsx +34 -0
- package/src/components/modal.tsx +561 -0
- package/src/components/navigation-bar.tsx +100 -0
- package/src/components/number-input.tsx +143 -0
- package/src/components/page-content.tsx +16 -0
- package/src/components/popover.tsx +191 -0
- package/src/components/progress.tsx +80 -0
- package/src/components/radio-group.tsx +44 -0
- package/src/components/scroll-area.tsx +49 -0
- package/src/components/search-bar.tsx +140 -0
- package/src/components/secondary-navigation-bar.tsx +307 -0
- package/src/components/select.tsx +273 -0
- package/src/components/separator.tsx +31 -0
- package/src/components/sheet.tsx +143 -0
- package/src/components/skeleton.tsx +20 -0
- package/src/components/slider.tsx +160 -0
- package/src/components/spinner.tsx +48 -0
- package/src/components/swiper/index.module.scss +88 -0
- package/src/components/swiper/index.tsx +319 -0
- package/src/components/switch.tsx +67 -0
- package/src/components/tabs.tsx +325 -0
- package/src/components/textarea.tsx +71 -0
- package/src/components/toast/toast.tsx +182 -0
- package/src/components/toast/toaster.tsx +160 -0
- package/src/components/toast/use-toast.tsx +248 -0
- package/src/components/toggle-group.tsx +64 -0
- package/src/components/toggle.tsx +46 -0
- package/src/components/tooltip.tsx +283 -0
- package/src/components/typography.tsx +437 -0
- package/src/index.ts +66 -0
- package/src/lib/utils.ts +62 -0
- package/src/stories/Accordion.stories.tsx +64 -0
- package/src/stories/AccordionItem.stories.tsx +48 -0
- package/src/stories/Avatar.stories.ts +58 -0
- package/src/stories/Badge.stories.tsx +40 -0
- package/src/stories/BannerSwiper.stories.tsx +102 -0
- package/src/stories/Button.stories.tsx +543 -0
- package/src/stories/Checkbox.stories.tsx +161 -0
- package/src/stories/Configure.mdx +341 -0
- package/src/stories/CssProperties.mdx +30 -0
- package/src/stories/Description.stories.ts +70 -0
- package/src/stories/Display.stories.ts +64 -0
- package/src/stories/FeaturedSwiper.stories.tsx +6978 -0
- package/src/stories/GridSwiper.stories.tsx +1407 -0
- package/src/stories/Guide.stories.tsx +247 -0
- package/src/stories/Heading.stories.ts +89 -0
- package/src/stories/Icon.stories.ts +77 -0
- package/src/stories/IconButton.stories.tsx +301 -0
- package/src/stories/IconTextButton.stories.ts +59 -0
- package/src/stories/Image.stories.ts +55 -0
- package/src/stories/Input.stories.tsx +203 -0
- package/src/stories/Modal.stories.tsx +144 -0
- package/src/stories/NavigationBar.stories.tsx +81 -0
- package/src/stories/Notification.stories.tsx +276 -0
- package/src/stories/Popover.stories.tsx +100 -0
- package/src/stories/SearchBar.stories.ts +43 -0
- package/src/stories/SecondaryNavigationBar.stories.tsx +199 -0
- package/src/stories/Select.stories.tsx +107 -0
- package/src/stories/Separator.stories.tsx +49 -0
- package/src/stories/Spinner.stories.tsx +48 -0
- package/src/stories/SubHeading.stories.ts +64 -0
- package/src/stories/Swich.stories.tsx +69 -0
- package/src/stories/Tabs.stories.tsx +90 -0
- package/src/stories/Text.stories.ts +78 -0
- package/src/stories/Textarea.stories.tsx +155 -0
- package/src/stories/Toast.stories.tsx +424 -0
- package/src/stories/Tooltip.stories.tsx +244 -0
- package/src/stories/ViewAutoSwiper.stories.tsx +1408 -0
- package/src/styles/components-dark.scss +212 -0
- package/src/styles/components-light.scss +210 -0
- package/src/styles/design-dark.scss +330 -0
- package/src/styles/design-light.scss +345 -0
- package/src/styles/design2-dark.scss +319 -0
- package/src/styles/design2-light.scss +364 -0
- package/src/styles/font.css +19 -0
- package/src/styles/global.scss +251 -0
- package/src/styles/md-viewer.scss +155 -0
- package/src/styles/new-tokens.scss +255 -0
- package/src/styles/tokens.scss +401 -0
- package/src/types/scss.d.ts +24 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/* eslint-disable react/require-default-props */
|
|
2
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
3
|
+
import { Loader2 } from 'lucide-react';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
|
|
6
|
+
import { getAssetsUrl } from '../../common/utils/common-helper';
|
|
7
|
+
import { cn } from '@/lib/utils';
|
|
8
|
+
|
|
9
|
+
import { Icon } from '../icon';
|
|
10
|
+
import { Image } from '../image';
|
|
11
|
+
import { Separator } from '../separator';
|
|
12
|
+
import { Text } from '../typography';
|
|
13
|
+
import { buttonVariants, iconVariants } from './button.styles';
|
|
14
|
+
|
|
15
|
+
export interface LinkButtonProps
|
|
16
|
+
extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'variant'> {
|
|
17
|
+
asChild?: boolean;
|
|
18
|
+
loading?: boolean;
|
|
19
|
+
icon?: React.ElementType;
|
|
20
|
+
iconDirection?: 'left' | 'right';
|
|
21
|
+
color?: 'default' | 'brand' | 'error' | 'chat';
|
|
22
|
+
noStyle?: boolean;
|
|
23
|
+
iconClassName?: string;
|
|
24
|
+
iconOutBox?: boolean;
|
|
25
|
+
isBlock?: boolean;
|
|
26
|
+
asset?: 'energy' | 'coin' | 'point';
|
|
27
|
+
assetNumber?: number;
|
|
28
|
+
size?: 'lg' | 'md' | 'sm';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const LinkButton = React.forwardRef<HTMLButtonElement, LinkButtonProps>(
|
|
32
|
+
(
|
|
33
|
+
{
|
|
34
|
+
className = '',
|
|
35
|
+
iconClassName,
|
|
36
|
+
color = 'default',
|
|
37
|
+
icon,
|
|
38
|
+
iconDirection = 'left',
|
|
39
|
+
size = 'lg',
|
|
40
|
+
asChild = false,
|
|
41
|
+
loading = false,
|
|
42
|
+
noStyle = false,
|
|
43
|
+
iconOutBox = false,
|
|
44
|
+
isBlock = false,
|
|
45
|
+
disabled,
|
|
46
|
+
children,
|
|
47
|
+
autoFocus,
|
|
48
|
+
asset,
|
|
49
|
+
assetNumber = 0,
|
|
50
|
+
...props
|
|
51
|
+
},
|
|
52
|
+
ref
|
|
53
|
+
) => {
|
|
54
|
+
const Comp = asChild ? Slot : 'button';
|
|
55
|
+
const disable = disabled || loading;
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<Comp
|
|
59
|
+
className={
|
|
60
|
+
noStyle
|
|
61
|
+
? className
|
|
62
|
+
: cn(
|
|
63
|
+
buttonVariants({ variant: 'link', color, size, className }),
|
|
64
|
+
disable && '!pointer-events-auto cursor-not-allowed',
|
|
65
|
+
isBlock && 'w-full'
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
ref={ref}
|
|
69
|
+
disabled={disable}
|
|
70
|
+
autoFocus={autoFocus}
|
|
71
|
+
{...props}
|
|
72
|
+
>
|
|
73
|
+
{loading && (
|
|
74
|
+
<span className="absolute left-1/2 top-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center">
|
|
75
|
+
<Loader2
|
|
76
|
+
className={cn(
|
|
77
|
+
iconVariants({ variant: 'link', size }),
|
|
78
|
+
'animate-spin',
|
|
79
|
+
size === 'lg'
|
|
80
|
+
? 'h-6 w-6'
|
|
81
|
+
: size === 'md'
|
|
82
|
+
? 'h-5 w-5'
|
|
83
|
+
: 'h-4.5 w-4.5'
|
|
84
|
+
)}
|
|
85
|
+
/>
|
|
86
|
+
</span>
|
|
87
|
+
)}
|
|
88
|
+
{!asset &&
|
|
89
|
+
icon &&
|
|
90
|
+
iconOutBox &&
|
|
91
|
+
iconDirection === 'left' &&
|
|
92
|
+
renderIcon(icon, 'left', {
|
|
93
|
+
loading,
|
|
94
|
+
noStyle,
|
|
95
|
+
iconClassName,
|
|
96
|
+
size,
|
|
97
|
+
})}
|
|
98
|
+
<span
|
|
99
|
+
className={cn(
|
|
100
|
+
'inline-flex w-full items-center justify-center',
|
|
101
|
+
loading ? 'opacity-0' : 'opacity-100'
|
|
102
|
+
)}
|
|
103
|
+
>
|
|
104
|
+
{!asset &&
|
|
105
|
+
icon &&
|
|
106
|
+
!iconOutBox &&
|
|
107
|
+
iconDirection === 'left' &&
|
|
108
|
+
renderIcon(icon, 'left', {
|
|
109
|
+
loading,
|
|
110
|
+
noStyle,
|
|
111
|
+
iconClassName,
|
|
112
|
+
size,
|
|
113
|
+
})}
|
|
114
|
+
{children}
|
|
115
|
+
{asset ? (
|
|
116
|
+
<>
|
|
117
|
+
<Separator orientation="vertical" className={cn('mx-1.5 h-3')} />
|
|
118
|
+
<Image
|
|
119
|
+
src={
|
|
120
|
+
asset === 'energy'
|
|
121
|
+
? getAssetsUrl(
|
|
122
|
+
'image/bot/tag/20231214/1719340128612116720.png'
|
|
123
|
+
)
|
|
124
|
+
: ''
|
|
125
|
+
}
|
|
126
|
+
alt={asset}
|
|
127
|
+
width={16}
|
|
128
|
+
height={16}
|
|
129
|
+
className="flex-shrink-0"
|
|
130
|
+
/>
|
|
131
|
+
<Text size="xs" className={cn('ml-0.5 text-inherit')}>
|
|
132
|
+
{assetNumber}
|
|
133
|
+
</Text>
|
|
134
|
+
</>
|
|
135
|
+
) : null}
|
|
136
|
+
{!asset &&
|
|
137
|
+
icon &&
|
|
138
|
+
!iconOutBox &&
|
|
139
|
+
iconDirection === 'right' &&
|
|
140
|
+
renderIcon(icon, 'right', {
|
|
141
|
+
loading,
|
|
142
|
+
noStyle,
|
|
143
|
+
iconClassName,
|
|
144
|
+
size,
|
|
145
|
+
})}
|
|
146
|
+
</span>
|
|
147
|
+
{!asset &&
|
|
148
|
+
icon &&
|
|
149
|
+
iconOutBox &&
|
|
150
|
+
iconDirection === 'right' &&
|
|
151
|
+
renderIcon(icon, 'right', {
|
|
152
|
+
loading,
|
|
153
|
+
noStyle,
|
|
154
|
+
iconClassName,
|
|
155
|
+
size,
|
|
156
|
+
})}
|
|
157
|
+
</Comp>
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
const renderIcon = (
|
|
163
|
+
icon: React.ElementType,
|
|
164
|
+
direction: 'left' | 'right',
|
|
165
|
+
{ loading, noStyle, iconClassName, size = 'lg' }: LinkButtonProps
|
|
166
|
+
) => (
|
|
167
|
+
<Icon
|
|
168
|
+
component={icon}
|
|
169
|
+
className={
|
|
170
|
+
noStyle
|
|
171
|
+
? iconClassName
|
|
172
|
+
: cn(
|
|
173
|
+
iconVariants({ variant: 'link', size }),
|
|
174
|
+
direction === 'left' ? 'mr-0.5' : 'ml-0.5',
|
|
175
|
+
iconClassName,
|
|
176
|
+
loading ? 'opacity-0' : 'opacity-100'
|
|
177
|
+
)
|
|
178
|
+
}
|
|
179
|
+
/>
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
LinkButton.displayName = 'LinkButton';
|
|
183
|
+
|
|
184
|
+
export { LinkButton };
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
// todo 展开时默认选中 value 对应的选项
|
|
2
|
+
|
|
3
|
+
import clsx from 'clsx';
|
|
4
|
+
import { Check, ChevronDown } from 'lucide-react';
|
|
5
|
+
import { Fragment } from 'react';
|
|
6
|
+
import { useToggle } from 'react-use';
|
|
7
|
+
import { ClassNameValue } from 'tailwind-merge';
|
|
8
|
+
|
|
9
|
+
import { cn } from '@/lib/utils';
|
|
10
|
+
|
|
11
|
+
import { Button } from './button/button';
|
|
12
|
+
import {
|
|
13
|
+
DropdownMenu,
|
|
14
|
+
DropdownMenuContent,
|
|
15
|
+
DropdownMenuItem,
|
|
16
|
+
DropdownMenuPortal,
|
|
17
|
+
DropdownMenuSub,
|
|
18
|
+
DropdownMenuSubContent,
|
|
19
|
+
DropdownMenuSubTrigger,
|
|
20
|
+
DropdownMenuTrigger,
|
|
21
|
+
} from './dropdown-menu';
|
|
22
|
+
|
|
23
|
+
export interface CascaderOption {
|
|
24
|
+
label: string;
|
|
25
|
+
value: string;
|
|
26
|
+
children?: CascaderOption[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface CommonP {
|
|
30
|
+
value?: string;
|
|
31
|
+
onValueChange: (value: string) => void;
|
|
32
|
+
className?: ClassNameValue;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface P extends CommonP {
|
|
36
|
+
options: CascaderOption[];
|
|
37
|
+
showParentLabel?: boolean;
|
|
38
|
+
placeholder?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default function Cascader(props: P) {
|
|
42
|
+
const {
|
|
43
|
+
options,
|
|
44
|
+
className,
|
|
45
|
+
value,
|
|
46
|
+
onValueChange,
|
|
47
|
+
showParentLabel,
|
|
48
|
+
placeholder,
|
|
49
|
+
} = props;
|
|
50
|
+
const [open, setOpen] = useToggle(false);
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<DropdownMenu onOpenChange={setOpen}>
|
|
54
|
+
<DropdownMenuTrigger asChild>
|
|
55
|
+
<Button
|
|
56
|
+
variant="secondary"
|
|
57
|
+
role="combobox"
|
|
58
|
+
className={cn(
|
|
59
|
+
className,
|
|
60
|
+
'h-12 p-3 space-x-1.5 rounded-xl border-Colors-Border-Default bg-Colors-Background-Normal-Primary-Active shadow-background-default hover:bg-inherit justify-between [&>span]:line-clamp-1 [&>.dropdown-chevron]:aria-expanded:rotate-180'
|
|
61
|
+
)}
|
|
62
|
+
aria-expanded={open}
|
|
63
|
+
>
|
|
64
|
+
<span
|
|
65
|
+
className={
|
|
66
|
+
// placeholder 文本颜色调整
|
|
67
|
+
clsx(!value && 'text-Colors-Text-Subtler')
|
|
68
|
+
}
|
|
69
|
+
>
|
|
70
|
+
{value ? renderLabel(options, value, showParentLabel) : placeholder}
|
|
71
|
+
</span>
|
|
72
|
+
<ChevronDown className="dropdown-chevron h-5 w-5 text-Colors-Foreground-Subtle duration-200" />
|
|
73
|
+
</Button>
|
|
74
|
+
</DropdownMenuTrigger>
|
|
75
|
+
<DropdownMenuContent className={cn(className)}>
|
|
76
|
+
{options.map((option) => (
|
|
77
|
+
<Fragment key={option.value}>
|
|
78
|
+
{option.children && !!option.children.length ? (
|
|
79
|
+
<NestDropdownMenuRender
|
|
80
|
+
className={className}
|
|
81
|
+
option={option}
|
|
82
|
+
value={value}
|
|
83
|
+
onValueChange={onValueChange}
|
|
84
|
+
/>
|
|
85
|
+
) : (
|
|
86
|
+
<DropdownMenuItem
|
|
87
|
+
className="py-1"
|
|
88
|
+
onChange={() => onValueChange(option.value)}
|
|
89
|
+
>
|
|
90
|
+
{option.label}
|
|
91
|
+
</DropdownMenuItem>
|
|
92
|
+
)}
|
|
93
|
+
</Fragment>
|
|
94
|
+
))}
|
|
95
|
+
</DropdownMenuContent>
|
|
96
|
+
</DropdownMenu>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
interface NestDropDownP extends CommonP {
|
|
101
|
+
option: CascaderOption;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function NestDropdownMenuRender(props: NestDropDownP) {
|
|
105
|
+
const { option, value, onValueChange, className } = props;
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<DropdownMenuSub>
|
|
109
|
+
<DropdownMenuSubTrigger className="py-1">
|
|
110
|
+
{option.label}
|
|
111
|
+
</DropdownMenuSubTrigger>
|
|
112
|
+
<DropdownMenuPortal>
|
|
113
|
+
<DropdownMenuSubContent className={cn(className)} sideOffset={10}>
|
|
114
|
+
{option.children!.map((opt) => (
|
|
115
|
+
<Fragment key={opt.value}>
|
|
116
|
+
{opt.children && opt.children.length ? (
|
|
117
|
+
<NestDropdownMenuRender
|
|
118
|
+
className={className}
|
|
119
|
+
option={opt}
|
|
120
|
+
value={value}
|
|
121
|
+
onValueChange={onValueChange}
|
|
122
|
+
/>
|
|
123
|
+
) : (
|
|
124
|
+
<DropdownMenuItem
|
|
125
|
+
className="py-1 justify-between"
|
|
126
|
+
onClick={() => onValueChange(opt.value)}
|
|
127
|
+
>
|
|
128
|
+
<span>{opt.label}</span>
|
|
129
|
+
{value === opt.value && (
|
|
130
|
+
<Check className="h-4 w-4 text-Colors-Text-Brand-Default" />
|
|
131
|
+
)}
|
|
132
|
+
</DropdownMenuItem>
|
|
133
|
+
)}
|
|
134
|
+
</Fragment>
|
|
135
|
+
))}
|
|
136
|
+
</DropdownMenuSubContent>
|
|
137
|
+
</DropdownMenuPortal>
|
|
138
|
+
</DropdownMenuSub>
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function renderLabel(
|
|
143
|
+
options: CascaderOption[],
|
|
144
|
+
value: string,
|
|
145
|
+
showParentLabel = false,
|
|
146
|
+
path = ''
|
|
147
|
+
): string {
|
|
148
|
+
for (const option of options) {
|
|
149
|
+
// 如果当前路径不为空并且需要显示路径,则添加分隔符
|
|
150
|
+
const currentPath = showParentLabel
|
|
151
|
+
? path
|
|
152
|
+
? `${path}/${option.label}`
|
|
153
|
+
: option.label
|
|
154
|
+
: option.label;
|
|
155
|
+
|
|
156
|
+
// 检查当前项的值是否匹配
|
|
157
|
+
if (option.value === value) {
|
|
158
|
+
return currentPath;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// 如果当前项有子项,则递归搜索子项
|
|
162
|
+
if (option.children) {
|
|
163
|
+
const childPath = renderLabel(
|
|
164
|
+
option.children,
|
|
165
|
+
value,
|
|
166
|
+
showParentLabel,
|
|
167
|
+
currentPath
|
|
168
|
+
);
|
|
169
|
+
if (childPath) return childPath; // 如果在子项中找到匹配,则返回构建的路径
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// 如果没有找到匹配项,则返回空字符串
|
|
174
|
+
return '';
|
|
175
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
4
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
|
|
7
|
+
import { cn } from '@/lib/utils';
|
|
8
|
+
|
|
9
|
+
const CheckIcon = ({ className }: { className?: string }) => {
|
|
10
|
+
return (
|
|
11
|
+
<svg
|
|
12
|
+
className={className}
|
|
13
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
14
|
+
width="12"
|
|
15
|
+
height="12"
|
|
16
|
+
viewBox="0 0 12 12"
|
|
17
|
+
fill="none"
|
|
18
|
+
>
|
|
19
|
+
<path
|
|
20
|
+
d="M2.25 6.375L5.25 9.375L9.75 2.625"
|
|
21
|
+
stroke-width="1.5"
|
|
22
|
+
stroke-linecap="round"
|
|
23
|
+
stroke-linejoin="round"
|
|
24
|
+
/>
|
|
25
|
+
</svg>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const CheckIconBrand = ({ className }: { className?: string }) => {
|
|
30
|
+
return (
|
|
31
|
+
<svg
|
|
32
|
+
className={className}
|
|
33
|
+
width="10"
|
|
34
|
+
height="10"
|
|
35
|
+
viewBox="0 0 10 10"
|
|
36
|
+
fill="none"
|
|
37
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
38
|
+
>
|
|
39
|
+
<path
|
|
40
|
+
d="M1.25 5.375L4.25 8.375L8.75 1.625"
|
|
41
|
+
stroke-width="1.5"
|
|
42
|
+
stroke-linecap="round"
|
|
43
|
+
stroke-linejoin="round"
|
|
44
|
+
/>
|
|
45
|
+
</svg>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const checkboxVariants = cva(
|
|
50
|
+
'peer w-5 h-5 shrink-0 border-[1.5px] border-cc-Check-Box-border-default hover:border-cc-Check-Box-border-hover data-[state=checked]:border-cc-Check-Box-bg-default ring-offset-cc-Focus-Rings-Brand-default focus-visible:border-cc-Check-Box-border-default focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-cc-Focus-Rings-Brand-default focus-visible:ring-offset-1 disabled:border-pressed disabled:cursor-not-allowed disabled:opacity-30 data-[state=checked]:bg-cc-Check-Box-bg-default data-[state=checked]:text-cc-Check-Box-fg-default hover:data-[state=checked]:bg-cc-Check-Box-bg-hovered disabled:data-[state=checked]:text-cc-Check-Box-fg-alt disabled:data-[state=checked]:border-none rounded-sm overflow-hidden flex items-center justify-center text-current',
|
|
51
|
+
{
|
|
52
|
+
variants: {
|
|
53
|
+
variant: {
|
|
54
|
+
checkbox: 'rounded-sm',
|
|
55
|
+
circle: 'rounded-full',
|
|
56
|
+
radio: 'rounded-full',
|
|
57
|
+
'circle-static':
|
|
58
|
+
'rounded-full bg-beta-black-10 border-beta-white-100 hover:border-beta-white-100',
|
|
59
|
+
'circle-inverted':
|
|
60
|
+
'rounded-full data-[state=checked]:border-surface-default focus-visible:border-surface-default data-[state=checked]:bg-surface-default hover:data-[state=checked]:bg-surface-hovered data-[state=checked]:text-icon-brand',
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
defaultVariants: {
|
|
64
|
+
variant: 'checkbox',
|
|
65
|
+
},
|
|
66
|
+
}
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
const Checkbox = React.forwardRef<
|
|
70
|
+
React.ElementRef<typeof CheckboxPrimitive.Root>,
|
|
71
|
+
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root> &
|
|
72
|
+
VariantProps<typeof checkboxVariants> & {
|
|
73
|
+
label?: string;
|
|
74
|
+
caption?: string;
|
|
75
|
+
labelClassName?: string;
|
|
76
|
+
captionClassName?: string;
|
|
77
|
+
}
|
|
78
|
+
>(
|
|
79
|
+
(
|
|
80
|
+
{
|
|
81
|
+
className,
|
|
82
|
+
variant,
|
|
83
|
+
label,
|
|
84
|
+
labelClassName,
|
|
85
|
+
caption,
|
|
86
|
+
captionClassName,
|
|
87
|
+
...props
|
|
88
|
+
},
|
|
89
|
+
ref
|
|
90
|
+
) => {
|
|
91
|
+
const Component = label ? 'div' : React.Fragment;
|
|
92
|
+
return (
|
|
93
|
+
<Component
|
|
94
|
+
className={cn(
|
|
95
|
+
'flex items-center justify-center space-x-1.5 text-Colors-Text-Default',
|
|
96
|
+
caption && 'items-start'
|
|
97
|
+
)}
|
|
98
|
+
>
|
|
99
|
+
<CheckboxPrimitive.Root
|
|
100
|
+
ref={ref}
|
|
101
|
+
className={cn(checkboxVariants({ variant, className }))}
|
|
102
|
+
{...props}
|
|
103
|
+
>
|
|
104
|
+
<CheckboxPrimitive.Indicator>
|
|
105
|
+
{variant === 'radio' ? (
|
|
106
|
+
<div className="w-2 h-2 bg-cc-Check-Box-fg-default rounded-full" />
|
|
107
|
+
) : variant === 'circle-inverted' ? (
|
|
108
|
+
<CheckIconBrand className="w-3 h-3 stroke-cc-Check-Box-fg-default" />
|
|
109
|
+
) : (
|
|
110
|
+
<CheckIcon className="w-3 h-3 stroke-cc-Check-Box-fg-default" />
|
|
111
|
+
)}
|
|
112
|
+
</CheckboxPrimitive.Indicator>
|
|
113
|
+
</CheckboxPrimitive.Root>
|
|
114
|
+
{label && (
|
|
115
|
+
<p className={cn('text-sm', labelClassName)}>
|
|
116
|
+
{label}
|
|
117
|
+
{caption && (
|
|
118
|
+
<p
|
|
119
|
+
className={cn(
|
|
120
|
+
'text-sm text-Colors-Text-Subtler',
|
|
121
|
+
captionClassName
|
|
122
|
+
)}
|
|
123
|
+
>
|
|
124
|
+
{caption}
|
|
125
|
+
</p>
|
|
126
|
+
)}
|
|
127
|
+
</p>
|
|
128
|
+
)}
|
|
129
|
+
</Component>
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
);
|
|
133
|
+
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
|
|
134
|
+
|
|
135
|
+
export { Checkbox };
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { type DialogProps } from '@radix-ui/react-dialog';
|
|
4
|
+
import { Command as CommandPrimitive } from 'cmdk';
|
|
5
|
+
import { Search } from 'lucide-react';
|
|
6
|
+
import * as React from 'react';
|
|
7
|
+
|
|
8
|
+
import { Dialog, DialogContent } from './dialog';
|
|
9
|
+
import { cn } from '@/lib/utils';
|
|
10
|
+
|
|
11
|
+
const Command = React.forwardRef<
|
|
12
|
+
React.ElementRef<typeof CommandPrimitive>,
|
|
13
|
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive>
|
|
14
|
+
>(({ className, ...props }, ref) => (
|
|
15
|
+
<CommandPrimitive
|
|
16
|
+
ref={ref}
|
|
17
|
+
className={cn(
|
|
18
|
+
'flex h-full w-full flex-col overflow-hidden rounded-md bg-white text-slate-950 dark:bg-slate-950 dark:text-slate-50',
|
|
19
|
+
className
|
|
20
|
+
)}
|
|
21
|
+
{...props}
|
|
22
|
+
/>
|
|
23
|
+
));
|
|
24
|
+
Command.displayName = CommandPrimitive.displayName;
|
|
25
|
+
|
|
26
|
+
type CommandDialogProps = DialogProps;
|
|
27
|
+
|
|
28
|
+
const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
|
|
29
|
+
return (
|
|
30
|
+
<Dialog {...props}>
|
|
31
|
+
<DialogContent className="overflow-hidden p-0 shadow-lg">
|
|
32
|
+
<Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-slate-500 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5 dark:[&_[cmdk-group-heading]]:text-slate-400">
|
|
33
|
+
{children}
|
|
34
|
+
</Command>
|
|
35
|
+
</DialogContent>
|
|
36
|
+
</Dialog>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const CommandInput = React.forwardRef<
|
|
41
|
+
React.ElementRef<typeof CommandPrimitive.Input>,
|
|
42
|
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
|
|
43
|
+
>(({ className, ...props }, ref) => (
|
|
44
|
+
<div className="flex items-center border-b px-3" cmdk-input-wrapper="">
|
|
45
|
+
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
|
|
46
|
+
<CommandPrimitive.Input
|
|
47
|
+
ref={ref}
|
|
48
|
+
className={cn(
|
|
49
|
+
'flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-slate-500 disabled:cursor-not-allowed disabled:opacity-50 dark:placeholder:text-slate-400',
|
|
50
|
+
className
|
|
51
|
+
)}
|
|
52
|
+
{...props}
|
|
53
|
+
/>
|
|
54
|
+
</div>
|
|
55
|
+
));
|
|
56
|
+
|
|
57
|
+
CommandInput.displayName = CommandPrimitive.Input.displayName;
|
|
58
|
+
|
|
59
|
+
const CommandList = React.forwardRef<
|
|
60
|
+
React.ElementRef<typeof CommandPrimitive.List>,
|
|
61
|
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
|
|
62
|
+
>(({ className, ...props }, ref) => (
|
|
63
|
+
<CommandPrimitive.List
|
|
64
|
+
ref={ref}
|
|
65
|
+
className={cn('max-h-[300px] overflow-y-auto overflow-x-hidden', className)}
|
|
66
|
+
{...props}
|
|
67
|
+
/>
|
|
68
|
+
));
|
|
69
|
+
|
|
70
|
+
CommandList.displayName = CommandPrimitive.List.displayName;
|
|
71
|
+
|
|
72
|
+
const CommandEmpty = React.forwardRef<
|
|
73
|
+
React.ElementRef<typeof CommandPrimitive.Empty>,
|
|
74
|
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
|
|
75
|
+
>((props, ref) => (
|
|
76
|
+
<CommandPrimitive.Empty
|
|
77
|
+
ref={ref}
|
|
78
|
+
className="py-6 text-center text-sm"
|
|
79
|
+
{...props}
|
|
80
|
+
/>
|
|
81
|
+
));
|
|
82
|
+
|
|
83
|
+
CommandEmpty.displayName = CommandPrimitive.Empty.displayName;
|
|
84
|
+
|
|
85
|
+
const CommandGroup = React.forwardRef<
|
|
86
|
+
React.ElementRef<typeof CommandPrimitive.Group>,
|
|
87
|
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
|
|
88
|
+
>(({ className, ...props }, ref) => (
|
|
89
|
+
<CommandPrimitive.Group
|
|
90
|
+
ref={ref}
|
|
91
|
+
className={cn(
|
|
92
|
+
'overflow-hidden p-1 text-slate-950 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-slate-500 dark:text-slate-50 dark:[&_[cmdk-group-heading]]:text-slate-400',
|
|
93
|
+
className
|
|
94
|
+
)}
|
|
95
|
+
{...props}
|
|
96
|
+
/>
|
|
97
|
+
));
|
|
98
|
+
|
|
99
|
+
CommandGroup.displayName = CommandPrimitive.Group.displayName;
|
|
100
|
+
|
|
101
|
+
const CommandSeparator = React.forwardRef<
|
|
102
|
+
React.ElementRef<typeof CommandPrimitive.Separator>,
|
|
103
|
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
|
|
104
|
+
>(({ className, ...props }, ref) => (
|
|
105
|
+
<CommandPrimitive.Separator
|
|
106
|
+
ref={ref}
|
|
107
|
+
className={cn('-mx-1 h-px bg-slate-200 dark:bg-slate-800', className)}
|
|
108
|
+
{...props}
|
|
109
|
+
/>
|
|
110
|
+
));
|
|
111
|
+
CommandSeparator.displayName = CommandPrimitive.Separator.displayName;
|
|
112
|
+
|
|
113
|
+
const CommandItem = React.forwardRef<
|
|
114
|
+
React.ElementRef<typeof CommandPrimitive.Item>,
|
|
115
|
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
|
|
116
|
+
>(({ className, ...props }, ref) => (
|
|
117
|
+
<CommandPrimitive.Item
|
|
118
|
+
ref={ref}
|
|
119
|
+
className={cn(
|
|
120
|
+
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-slate-100 aria-selected:text-slate-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:aria-selected:bg-slate-800 dark:aria-selected:text-slate-50',
|
|
121
|
+
className
|
|
122
|
+
)}
|
|
123
|
+
{...props}
|
|
124
|
+
/>
|
|
125
|
+
));
|
|
126
|
+
|
|
127
|
+
CommandItem.displayName = CommandPrimitive.Item.displayName;
|
|
128
|
+
|
|
129
|
+
const CommandShortcut = ({
|
|
130
|
+
className,
|
|
131
|
+
...props
|
|
132
|
+
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
|
133
|
+
return (
|
|
134
|
+
<span
|
|
135
|
+
className={cn(
|
|
136
|
+
'ml-auto text-xs tracking-widest text-slate-500 dark:text-slate-400',
|
|
137
|
+
className
|
|
138
|
+
)}
|
|
139
|
+
{...props}
|
|
140
|
+
/>
|
|
141
|
+
);
|
|
142
|
+
};
|
|
143
|
+
CommandShortcut.displayName = 'CommandShortcut';
|
|
144
|
+
|
|
145
|
+
export {
|
|
146
|
+
Command,
|
|
147
|
+
CommandDialog,
|
|
148
|
+
CommandInput,
|
|
149
|
+
CommandList,
|
|
150
|
+
CommandEmpty,
|
|
151
|
+
CommandGroup,
|
|
152
|
+
CommandItem,
|
|
153
|
+
CommandShortcut,
|
|
154
|
+
CommandSeparator,
|
|
155
|
+
};
|