@anker-in/headless-ui 0.0.27-alpha.0 → 0.0.27-alpha.2
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/cjs/biz-components/BrandEquity/BrandEquity.js +1 -1
- package/dist/cjs/biz-components/BrandEquity/BrandEquity.js.map +2 -2
- package/dist/cjs/biz-components/Category/index.js +1 -1
- package/dist/cjs/biz-components/Category/index.js.map +2 -2
- package/dist/cjs/biz-components/Evaluate/index.d.ts +1 -0
- package/dist/cjs/biz-components/Evaluate/index.js +1 -1
- package/dist/cjs/biz-components/Evaluate/index.js.map +3 -3
- package/dist/cjs/biz-components/Marquee/index.js +1 -1
- package/dist/cjs/biz-components/Marquee/index.js.map +2 -2
- package/dist/cjs/biz-components/MemberEquity/index.js +30 -30
- package/dist/cjs/biz-components/MemberEquity/index.js.map +2 -2
- package/dist/cjs/biz-components/ShelfDisplay/index.js +9 -9
- package/dist/cjs/biz-components/ShelfDisplay/index.js.map +2 -2
- package/dist/cjs/biz-components/Slogan/index.js +1 -1
- package/dist/cjs/biz-components/Slogan/index.js.map +2 -2
- package/dist/cjs/components/button.js +1 -1
- package/dist/cjs/components/button.js.map +2 -2
- package/dist/cjs/components/card.js +1 -1
- package/dist/cjs/components/card.js.map +2 -2
- package/dist/cjs/components/carousel.js +1 -1
- package/dist/cjs/components/carousel.js.map +2 -2
- package/dist/cjs/components/container.js +1 -1
- package/dist/cjs/components/container.js.map +2 -2
- package/dist/cjs/components/dialog.js +1 -1
- package/dist/cjs/components/dialog.js.map +2 -2
- package/dist/cjs/components/gird.js +1 -1
- package/dist/cjs/components/gird.js.map +2 -2
- package/dist/cjs/components/heading.d.ts +1 -1
- package/dist/cjs/components/heading.js +1 -1
- package/dist/cjs/components/heading.js.map +2 -2
- package/dist/cjs/components/text.js +1 -1
- package/dist/cjs/components/text.js.map +1 -1
- package/dist/cjs/stories/container.stories.js +6 -6
- package/dist/cjs/stories/container.stories.js.map +2 -2
- package/dist/cjs/stories/dialog.stories.js +1 -1
- package/dist/cjs/stories/dialog.stories.js.map +2 -2
- package/dist/cjs/stories/evaluate.stories.js +1 -1
- package/dist/cjs/stories/evaluate.stories.js.map +2 -2
- package/dist/cjs/stories/heading.stories.d.ts +3 -2
- package/dist/cjs/stories/heading.stories.js +1 -1
- package/dist/cjs/stories/heading.stories.js.map +2 -2
- package/dist/cjs/stories/text.stories.js +1 -1
- package/dist/cjs/stories/text.stories.js.map +2 -2
- package/dist/esm/biz-components/BrandEquity/BrandEquity.js +1 -1
- package/dist/esm/biz-components/BrandEquity/BrandEquity.js.map +2 -2
- package/dist/esm/biz-components/Category/index.js +1 -1
- package/dist/esm/biz-components/Category/index.js.map +2 -2
- package/dist/esm/biz-components/Evaluate/index.d.ts +1 -0
- package/dist/esm/biz-components/Evaluate/index.js +1 -1
- package/dist/esm/biz-components/Evaluate/index.js.map +3 -3
- package/dist/esm/biz-components/Marquee/index.js +1 -1
- package/dist/esm/biz-components/Marquee/index.js.map +2 -2
- package/dist/esm/biz-components/MemberEquity/index.js +29 -29
- package/dist/esm/biz-components/MemberEquity/index.js.map +2 -2
- package/dist/esm/biz-components/ShelfDisplay/index.js +9 -9
- package/dist/esm/biz-components/ShelfDisplay/index.js.map +2 -2
- package/dist/esm/biz-components/Slogan/index.js +1 -1
- package/dist/esm/biz-components/Slogan/index.js.map +2 -2
- package/dist/esm/components/button.js +1 -1
- package/dist/esm/components/button.js.map +2 -2
- package/dist/esm/components/card.js +1 -1
- package/dist/esm/components/card.js.map +2 -2
- package/dist/esm/components/carousel.js +1 -1
- package/dist/esm/components/carousel.js.map +2 -2
- package/dist/esm/components/container.js +1 -1
- package/dist/esm/components/container.js.map +2 -2
- package/dist/esm/components/dialog.js +1 -1
- package/dist/esm/components/dialog.js.map +2 -2
- package/dist/esm/components/gird.js +1 -1
- package/dist/esm/components/gird.js.map +2 -2
- package/dist/esm/components/heading.d.ts +1 -1
- package/dist/esm/components/heading.js +1 -1
- package/dist/esm/components/heading.js.map +2 -2
- package/dist/esm/components/text.js +1 -1
- package/dist/esm/components/text.js.map +1 -1
- package/dist/esm/stories/container.stories.js +6 -6
- package/dist/esm/stories/container.stories.js.map +2 -2
- package/dist/esm/stories/dialog.stories.js +1 -1
- package/dist/esm/stories/dialog.stories.js.map +2 -2
- package/dist/esm/stories/evaluate.stories.js +1 -1
- package/dist/esm/stories/evaluate.stories.js.map +2 -2
- package/dist/esm/stories/heading.stories.d.ts +3 -2
- package/dist/esm/stories/heading.stories.js +1 -1
- package/dist/esm/stories/heading.stories.js.map +2 -2
- package/dist/esm/stories/text.stories.js +2 -2
- package/dist/esm/stories/text.stories.js.map +2 -2
- package/package.json +2 -3
- package/style.css +69 -34
- package/src/biz-components/BrandEquity/BrandEquity.tsx +0 -77
- package/src/biz-components/BrandEquity/index.ts +0 -1
- package/src/biz-components/Category/index.tsx +0 -57
- package/src/biz-components/Evaluate/index.tsx +0 -85
- package/src/biz-components/HeroBanner/HeroBanner.tsx +0 -103
- package/src/biz-components/HeroBanner/index.tsx +0 -1
- package/src/biz-components/HeroBanner/types.ts +0 -28
- package/src/biz-components/Marquee/index.tsx +0 -79
- package/src/biz-components/MemberEquity/index.tsx +0 -114
- package/src/biz-components/MemberEquity/types.ts +0 -26
- package/src/biz-components/Shelf/Shelf.tsx +0 -22
- package/src/biz-components/Shelf/index.ts +0 -1
- package/src/biz-components/Shelf/types.ts +0 -6
- package/src/biz-components/ShelfDisplay/index.tsx +0 -142
- package/src/biz-components/Slogan/index.tsx +0 -53
- package/src/biz-components/Slogan/types.ts +0 -25
- package/src/biz-components/index.ts +0 -11
- package/src/components/alert.tsx +0 -124
- package/src/components/avatar.tsx +0 -126
- package/src/components/badge.tsx +0 -27
- package/src/components/button.tsx +0 -183
- package/src/components/card.tsx +0 -51
- package/src/components/carousel.tsx +0 -352
- package/src/components/checkbox.tsx +0 -42
- package/src/components/color.tsx +0 -77
- package/src/components/container.tsx +0 -28
- package/src/components/dialog.tsx +0 -98
- package/src/components/drawer.tsx +0 -115
- package/src/components/drop-down.tsx +0 -182
- package/src/components/gird.tsx +0 -90
- package/src/components/heading.tsx +0 -80
- package/src/components/index.ts +0 -26
- package/src/components/input-number.tsx +0 -216
- package/src/components/input.tsx +0 -79
- package/src/components/link.tsx +0 -99
- package/src/components/picture.tsx +0 -100
- package/src/components/popover.tsx +0 -31
- package/src/components/radio.tsx +0 -85
- package/src/components/skeleton.tsx +0 -41
- package/src/components/tabs.tsx +0 -78
- package/src/components/text.tsx +0 -99
- package/src/components/theme.tsx +0 -20
- package/src/helpers/component-props.ts +0 -17
- package/src/helpers/constants.ts +0 -0
- package/src/helpers/index.ts +0 -2
- package/src/helpers/utils.ts +0 -16
- package/src/icons/spinner.tsx +0 -26
- package/src/index.ts +0 -1
- package/src/shared/Styles.tsx +0 -94
- package/src/stories/HeroBanner.stories.tsx +0 -86
- package/src/stories/MemberEquity.stories.tsx +0 -107
- package/src/stories/alert.stories.tsx +0 -41
- package/src/stories/avatar.stories.tsx +0 -83
- package/src/stories/badge.stories.tsx +0 -40
- package/src/stories/brandEquity.stories.tsx +0 -73
- package/src/stories/button.stories.tsx +0 -145
- package/src/stories/card.stories.tsx +0 -97
- package/src/stories/carousel.stories.tsx +0 -161
- package/src/stories/category.stories.tsx +0 -52
- package/src/stories/checkbox.stories.tsx +0 -93
- package/src/stories/container.stories.tsx +0 -97
- package/src/stories/dialog.stories.tsx +0 -74
- package/src/stories/drawer.stories.tsx +0 -88
- package/src/stories/drop-down.stories.tsx +0 -83
- package/src/stories/evaluate.stories.tsx +0 -53
- package/src/stories/grid.stories.tsx +0 -190
- package/src/stories/heading.stories.tsx +0 -96
- package/src/stories/input-number.stories.tsx +0 -52
- package/src/stories/input.stories.tsx +0 -64
- package/src/stories/link.stories.tsx +0 -142
- package/src/stories/marquee.stories.tsx +0 -102
- package/src/stories/picture.stories.tsx +0 -51
- package/src/stories/popover.stories.tsx +0 -41
- package/src/stories/radio.stories.tsx +0 -55
- package/src/stories/shelf.stories.tsx +0 -35
- package/src/stories/shelfDisplay.stories.tsx +0 -69
- package/src/stories/skeleton.stories.tsx +0 -67
- package/src/stories/slogan.stories.tsx +0 -99
- package/src/stories/tabs.stories.tsx +0 -179
- package/src/stories/text.stories.tsx +0 -130
- package/src/styles/global.css +0 -4
- package/src/styles/index.css +0 -0
- package/src/types/index.ts +0 -0
- package/src/types/props.ts +0 -5
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
import { cn } from '../helpers/index.js'
|
|
3
|
-
import { Slot } from '@radix-ui/react-slot'
|
|
4
|
-
import { PlusIcon, MinusIcon } from '@radix-ui/react-icons'
|
|
5
|
-
import React, { useState, useEffect, forwardRef } from 'react'
|
|
6
|
-
import type { ChangeEvent, KeyboardEvent, FocusEvent } from 'react'
|
|
7
|
-
import { type VariantProps, cva } from 'class-variance-authority'
|
|
8
|
-
import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'
|
|
9
|
-
|
|
10
|
-
// 定义 InputNumber 的样式变体
|
|
11
|
-
const InputNumberVariants = cva('size-full border bg-transparent text-center text-base outline-none', {
|
|
12
|
-
variants: {
|
|
13
|
-
status: {
|
|
14
|
-
default: 'border-lines-1 group-hover:border-lines-2',
|
|
15
|
-
success: 'border-lines-3 group-hover:border-lines-3',
|
|
16
|
-
warning: 'border-lines-4 group-hover:border-lines-4',
|
|
17
|
-
error: 'border-lines-5 group-hover:border-lines-5',
|
|
18
|
-
},
|
|
19
|
-
disabled: {
|
|
20
|
-
true: 'border-lines-1 group-hover:border-lines-1 text-info-quaternary cursor-not-allowed',
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
type ColorType = 'default' | 'success' | 'warning' | 'error' | null
|
|
26
|
-
|
|
27
|
-
// 定义组件类型,继承 div 标签标准属性
|
|
28
|
-
type InputNumberElement = React.ElementRef<'div'>
|
|
29
|
-
|
|
30
|
-
type InputNumberProps = {
|
|
31
|
-
/** 定义子组件作为父组件的类型,详细使用方式请参考radix-ui */
|
|
32
|
-
asChild?: boolean
|
|
33
|
-
/** 类名*/
|
|
34
|
-
className?: string
|
|
35
|
-
/** 输入框下方提示文本,会根据不同的 status 呈现不同的样式*/
|
|
36
|
-
tips?: string
|
|
37
|
-
/** 文本框状态*/
|
|
38
|
-
status?: ColorType
|
|
39
|
-
/** 数字输入框的值 */
|
|
40
|
-
value?: number
|
|
41
|
-
/** 数字输入框的初始值 */
|
|
42
|
-
defaultValue?: number
|
|
43
|
-
/** 数值改变步数 */
|
|
44
|
-
step?: number
|
|
45
|
-
/** 最小值 */
|
|
46
|
-
min?: number
|
|
47
|
-
/** 最大值 */
|
|
48
|
-
max?: number
|
|
49
|
-
/** 是否禁用*/
|
|
50
|
-
disabled?: boolean
|
|
51
|
-
/** 是否只读*/
|
|
52
|
-
readonly?: boolean
|
|
53
|
-
/** 样式*/
|
|
54
|
-
style?: React.CSSProperties
|
|
55
|
-
/** 值变化时触发*/
|
|
56
|
-
onChange?: (value: number) => void
|
|
57
|
-
/** 失去焦点时触发*/
|
|
58
|
-
onBlur?: (value: number, e: FocusEvent) => void
|
|
59
|
-
/** 按下回车键时触发*/
|
|
60
|
-
onEnter?: (value: number, e: KeyboardEvent) => void
|
|
61
|
-
} & VariantProps<typeof InputNumberVariants> &
|
|
62
|
-
ComponentPropsWithout<'div', RemovedProps>
|
|
63
|
-
|
|
64
|
-
const InputNumber = forwardRef<InputNumberElement, InputNumberProps>(
|
|
65
|
-
(
|
|
66
|
-
{
|
|
67
|
-
value,
|
|
68
|
-
defaultValue = 0,
|
|
69
|
-
step = 1,
|
|
70
|
-
min = 0,
|
|
71
|
-
max,
|
|
72
|
-
tips,
|
|
73
|
-
style,
|
|
74
|
-
children,
|
|
75
|
-
asChild = false,
|
|
76
|
-
disabled = false,
|
|
77
|
-
readonly = false,
|
|
78
|
-
status = 'default',
|
|
79
|
-
className,
|
|
80
|
-
onChange,
|
|
81
|
-
onBlur,
|
|
82
|
-
onEnter,
|
|
83
|
-
},
|
|
84
|
-
ref
|
|
85
|
-
) => {
|
|
86
|
-
const [inputValue, setInputValue] = useState<number | string>(defaultValue)
|
|
87
|
-
|
|
88
|
-
const Comp = asChild ? Slot : 'div'
|
|
89
|
-
|
|
90
|
-
const baseClassName = cn('border-lines-1 flex size-12 items-center justify-center border text-base', {
|
|
91
|
-
'group-hover:border-lines-2': !disabled,
|
|
92
|
-
'text-info-quaternary cursor-not-allowed': disabled,
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
const textColor = (type: ColorType, flag: boolean) => {
|
|
96
|
-
if (flag) return 'text-lines-1'
|
|
97
|
-
return {
|
|
98
|
-
default: 'text-lines-1',
|
|
99
|
-
success: 'text-lines-3',
|
|
100
|
-
warning: 'text-lines-4',
|
|
101
|
-
error: 'text-lines-5',
|
|
102
|
-
}[type || 'default']
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const isValue = (params: string) => {
|
|
106
|
-
return params === '' || /^[0-9]+$/.test(params)
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const handleInputChange = (e: ChangeEvent<HTMLInputElement>) => {
|
|
110
|
-
if (disabled || readonly) return
|
|
111
|
-
const value = e.target.value
|
|
112
|
-
// 允许空字符串,或仅包含整数的字符串
|
|
113
|
-
if (isValue(value)) {
|
|
114
|
-
setInputValue(value)
|
|
115
|
-
if (value !== '') {
|
|
116
|
-
let newValue = Number(value)
|
|
117
|
-
if (max !== undefined && newValue > max) {
|
|
118
|
-
newValue = max
|
|
119
|
-
}
|
|
120
|
-
if (min !== undefined && newValue < min) {
|
|
121
|
-
newValue = min
|
|
122
|
-
}
|
|
123
|
-
onChange?.(newValue)
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const handleBlur = (e: FocusEvent<HTMLInputElement>) => {
|
|
129
|
-
if (disabled || readonly) return
|
|
130
|
-
if (inputValue === '' || isNaN(Number(inputValue))) {
|
|
131
|
-
const newValue = min !== undefined ? min : 0
|
|
132
|
-
setInputValue(newValue)
|
|
133
|
-
onBlur?.(newValue, e)
|
|
134
|
-
} else {
|
|
135
|
-
const newValue = Number(inputValue)
|
|
136
|
-
setInputValue(newValue)
|
|
137
|
-
onBlur?.(newValue, e)
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const increment = () => {
|
|
142
|
-
if (disabled || readonly) return
|
|
143
|
-
let newValue = Number(inputValue) + (step ? Math.ceil(Number(step)) : 1)
|
|
144
|
-
if (max !== undefined && newValue > max) {
|
|
145
|
-
newValue = max
|
|
146
|
-
}
|
|
147
|
-
setInputValue(newValue)
|
|
148
|
-
onChange?.(newValue)
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const decrement = () => {
|
|
152
|
-
if (disabled || readonly) return
|
|
153
|
-
let newValue = Number(inputValue) - (step ? Math.ceil(Number(step)) : 1)
|
|
154
|
-
if (min !== undefined && newValue < min) {
|
|
155
|
-
newValue = min
|
|
156
|
-
}
|
|
157
|
-
setInputValue(newValue)
|
|
158
|
-
onChange?.(newValue)
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const handleKeyDown = (e: any) => {
|
|
162
|
-
if (disabled || readonly) return
|
|
163
|
-
if (e.key === 'Enter') {
|
|
164
|
-
const initalValue = e.target?.value
|
|
165
|
-
onEnter?.(initalValue, e)
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
useEffect(() => {
|
|
170
|
-
setInputValue(value || 0)
|
|
171
|
-
}, [value])
|
|
172
|
-
|
|
173
|
-
return (
|
|
174
|
-
<Comp
|
|
175
|
-
ref={ref}
|
|
176
|
-
{...(style ? { style: style } : null)}
|
|
177
|
-
className={cn({ 'group flex items-center': !asChild }, className)}
|
|
178
|
-
>
|
|
179
|
-
{asChild ? (
|
|
180
|
-
children
|
|
181
|
-
) : (
|
|
182
|
-
<>
|
|
183
|
-
<button onClick={increment} className={baseClassName}>
|
|
184
|
-
<PlusIcon />
|
|
185
|
-
</button>
|
|
186
|
-
<div className="relative mx-1.5 h-[52px] w-[105px]">
|
|
187
|
-
<input
|
|
188
|
-
type="text"
|
|
189
|
-
value={inputValue}
|
|
190
|
-
disabled={disabled}
|
|
191
|
-
readOnly={readonly}
|
|
192
|
-
onBlur={handleBlur}
|
|
193
|
-
onKeyDown={handleKeyDown}
|
|
194
|
-
onChange={handleInputChange}
|
|
195
|
-
className={cn(InputNumberVariants({ status, disabled }))}
|
|
196
|
-
/>
|
|
197
|
-
{tips ? (
|
|
198
|
-
<span className={cn(textColor(status, disabled), 'absolute -bottom-4 left-0 w-full truncate text-xs')}>
|
|
199
|
-
{tips}
|
|
200
|
-
</span>
|
|
201
|
-
) : null}
|
|
202
|
-
</div>
|
|
203
|
-
<button onClick={decrement} className={baseClassName}>
|
|
204
|
-
<MinusIcon />
|
|
205
|
-
</button>
|
|
206
|
-
</>
|
|
207
|
-
)}
|
|
208
|
-
</Comp>
|
|
209
|
-
)
|
|
210
|
-
}
|
|
211
|
-
)
|
|
212
|
-
|
|
213
|
-
InputNumber.displayName = 'InputNumber'
|
|
214
|
-
|
|
215
|
-
export default InputNumber
|
|
216
|
-
export type { InputNumberProps }
|
package/src/components/input.tsx
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import * as React from 'react'
|
|
4
|
-
import { cn } from '../helpers/index.js'
|
|
5
|
-
import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'
|
|
6
|
-
import { cva, type VariantProps } from 'class-variance-authority'
|
|
7
|
-
|
|
8
|
-
const inputVariants = cva(
|
|
9
|
-
'border-input w-full bg-background focus-visible:outline-none flex flex-row items-center overflow-hidden rounded-md border',
|
|
10
|
-
{
|
|
11
|
-
variants: {
|
|
12
|
-
size: {
|
|
13
|
-
sm: 'h-8 text-sm',
|
|
14
|
-
base: 'h-10',
|
|
15
|
-
lg: 'h-12 text-lg',
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
defaultVariants: {
|
|
19
|
-
size: 'base',
|
|
20
|
-
},
|
|
21
|
-
}
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
export interface InputProps extends ComponentPropsWithout<'input', 'size'>, VariantProps<typeof inputVariants> {}
|
|
25
|
-
|
|
26
|
-
type InputSlotElement = React.ElementRef<'div'>
|
|
27
|
-
interface InputSlotProps extends ComponentPropsWithout<'div', RemovedProps> {
|
|
28
|
-
/**
|
|
29
|
-
* 插槽的位置
|
|
30
|
-
* default: right
|
|
31
|
-
*/
|
|
32
|
-
side?: 'left' | 'right'
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* InputSlot
|
|
37
|
-
* 用来在 Input 组件中插入额外的内容,比如icon ,按钮
|
|
38
|
-
*/
|
|
39
|
-
const InputSlot = React.forwardRef<InputSlotElement, InputSlotProps>((props, forwardedRef) => {
|
|
40
|
-
const { className, side = 'right', children, ...slotProps } = props
|
|
41
|
-
|
|
42
|
-
return (
|
|
43
|
-
<div
|
|
44
|
-
ref={forwardedRef}
|
|
45
|
-
{...slotProps}
|
|
46
|
-
className={cn('flex h-full items-center', className, {
|
|
47
|
-
'-order-1': side === 'left',
|
|
48
|
-
'order-2': side === 'right',
|
|
49
|
-
})}
|
|
50
|
-
>
|
|
51
|
-
{children}
|
|
52
|
-
</div>
|
|
53
|
-
)
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
const Input = React.forwardRef<React.ElementRef<'input'>, InputProps>(
|
|
57
|
-
({ className, type, size, children, ...props }, ref) => {
|
|
58
|
-
if (!React.isValidElement(children)) {
|
|
59
|
-
return <input type={type} className={cn(inputVariants({ size }), 'px-3', className)} ref={ref} {...props} />
|
|
60
|
-
}
|
|
61
|
-
return (
|
|
62
|
-
<div className={cn(inputVariants({ size }), className)}>
|
|
63
|
-
<input
|
|
64
|
-
type={type}
|
|
65
|
-
className={cn(
|
|
66
|
-
'placeholder:text-muted-foreground flex size-full file:border-0 file:bg-transparent file:font-medium focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 px-3'
|
|
67
|
-
)}
|
|
68
|
-
ref={ref}
|
|
69
|
-
{...props}
|
|
70
|
-
/>
|
|
71
|
-
{children}
|
|
72
|
-
</div>
|
|
73
|
-
)
|
|
74
|
-
}
|
|
75
|
-
)
|
|
76
|
-
Input.displayName = 'Input'
|
|
77
|
-
InputSlot.displayName = 'InputSlot'
|
|
78
|
-
|
|
79
|
-
export { Input, InputSlot }
|
package/src/components/link.tsx
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import type { ReactNode } from 'react'
|
|
3
|
-
import { Slot } from '@radix-ui/react-slot'
|
|
4
|
-
import { cn } from '../helpers/index.js'
|
|
5
|
-
import { type VariantProps, cva } from 'class-variance-authority'
|
|
6
|
-
import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'
|
|
7
|
-
|
|
8
|
-
// 定义 link 的样式变体
|
|
9
|
-
const linkVariants = cva('tracking transition-colors', {
|
|
10
|
-
variants: {
|
|
11
|
-
size: {
|
|
12
|
-
small: 'text-xs', // 小
|
|
13
|
-
medium: 'text-sm', // 中
|
|
14
|
-
large: 'text-base', // 大
|
|
15
|
-
},
|
|
16
|
-
underline: {
|
|
17
|
-
none: 'no-underline', // 不展示
|
|
18
|
-
hover: 'hover:underline', // hover展示下划线
|
|
19
|
-
always: 'underline', // 永久展示
|
|
20
|
-
},
|
|
21
|
-
hoverColor: {
|
|
22
|
-
none: 'text-current', // 鼠标进入无变化
|
|
23
|
-
hover: 'hover:text-brand-0', // 鼠标进入改变字体颜色
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
})
|
|
27
|
-
// 定义组件类型,继承 a 标签标准属性
|
|
28
|
-
type LinkElement = React.ElementRef<'a'>
|
|
29
|
-
type LinkProps = {
|
|
30
|
-
/** 定义子组件作为父组件的类型,详细使用方式请参考radix-ui */
|
|
31
|
-
asChild?: boolean
|
|
32
|
-
/** 类名*/
|
|
33
|
-
className?: string
|
|
34
|
-
/** 禁用链接 */
|
|
35
|
-
disabled?: boolean
|
|
36
|
-
/** 后置图标*/
|
|
37
|
-
suffixIcon?: ReactNode
|
|
38
|
-
/** 跳转链接*/
|
|
39
|
-
href?: string
|
|
40
|
-
/** 样式*/
|
|
41
|
-
style?: React.CSSProperties
|
|
42
|
-
/** 点击事件,禁用状态无法触发*/
|
|
43
|
-
onClick?: Function
|
|
44
|
-
} & VariantProps<typeof linkVariants> &
|
|
45
|
-
ComponentPropsWithout<'a', RemovedProps>
|
|
46
|
-
|
|
47
|
-
const Link = React.forwardRef<LinkElement, LinkProps>(
|
|
48
|
-
(
|
|
49
|
-
{
|
|
50
|
-
children,
|
|
51
|
-
size = 'small',
|
|
52
|
-
hoverColor,
|
|
53
|
-
className,
|
|
54
|
-
asChild = false,
|
|
55
|
-
href,
|
|
56
|
-
style,
|
|
57
|
-
underline,
|
|
58
|
-
disabled = false,
|
|
59
|
-
suffixIcon,
|
|
60
|
-
onClick,
|
|
61
|
-
...props // 这里会包含 href、target、rel 等标准 anchor 属性
|
|
62
|
-
}: LinkProps,
|
|
63
|
-
forwardedRef
|
|
64
|
-
) => {
|
|
65
|
-
const Comp = asChild ? Slot : 'a'
|
|
66
|
-
|
|
67
|
-
const handleClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
|
|
68
|
-
!disabled && onClick?.(event)
|
|
69
|
-
if (disabled || !href) {
|
|
70
|
-
event.preventDefault()
|
|
71
|
-
return
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return (
|
|
76
|
-
<Comp
|
|
77
|
-
ref={forwardedRef}
|
|
78
|
-
onClick={handleClick}
|
|
79
|
-
href={disabled ? undefined : href}
|
|
80
|
-
className={cn(linkVariants({ size, underline, hoverColor }), className, {
|
|
81
|
-
'flex items-center': suffixIcon,
|
|
82
|
-
'cursor-pointer': !disabled,
|
|
83
|
-
'text-info-quaternary cursor-not-allowed': disabled,
|
|
84
|
-
})}
|
|
85
|
-
{...(style ? { style: style } : null)}
|
|
86
|
-
{...props}
|
|
87
|
-
>
|
|
88
|
-
<>
|
|
89
|
-
{children}
|
|
90
|
-
<span className="svg">{suffixIcon}</span>
|
|
91
|
-
</>
|
|
92
|
-
</Comp>
|
|
93
|
-
)
|
|
94
|
-
}
|
|
95
|
-
)
|
|
96
|
-
Link.displayName = 'Link'
|
|
97
|
-
|
|
98
|
-
export default Link
|
|
99
|
-
export type { LinkProps }
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
import React, { useCallback, useMemo } from 'react'
|
|
3
|
-
|
|
4
|
-
const APPEND_FILE_SUFFIX_MATCH_DOMAIN = ['cdn.shopify.com', 'cdn.shopifycdn.net', 'www.facebook.com']
|
|
5
|
-
|
|
6
|
-
const MAX_SIZE = 3960
|
|
7
|
-
const FIXED_MAX_SIZE = 3980
|
|
8
|
-
|
|
9
|
-
export interface PictureProps extends React.ImgHTMLAttributes<HTMLImageElement> {
|
|
10
|
-
/** picture 内部img 标签的类名 */
|
|
11
|
-
imgClassName?: string
|
|
12
|
-
/** 图片url , 支持传入不同分辨率下的图片,比如,格式 "url1 1920, url2 1080, url3 767" */
|
|
13
|
-
source?: string
|
|
14
|
-
/** 图片质量 */
|
|
15
|
-
quality?: number
|
|
16
|
-
/** 响应式图片,对应picture 下source 的max-width */
|
|
17
|
-
deviceSizes?: number[]
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const isMatchDomain = (srcDomain: string) => {
|
|
21
|
-
return APPEND_FILE_SUFFIX_MATCH_DOMAIN.some(domain => srcDomain == domain)
|
|
22
|
-
}
|
|
23
|
-
const idMatchFileExtensions = (fileName: string = '') => /\.(png|apng|jpg|jpeg|gif|svg|webp|tif)/.test(fileName)
|
|
24
|
-
|
|
25
|
-
const Picture = ({
|
|
26
|
-
imgClassName = '',
|
|
27
|
-
source = '',
|
|
28
|
-
quality = 2,
|
|
29
|
-
deviceSizes = [375, 767, 1023, 1279, 1439, 1539, 1919],
|
|
30
|
-
className,
|
|
31
|
-
...rest
|
|
32
|
-
}: PictureProps) => {
|
|
33
|
-
const imgSrcSetsize = useCallback(({ src, width }: { src: string; width: number }) => {
|
|
34
|
-
const size = width
|
|
35
|
-
try {
|
|
36
|
-
const parsedUrl = new URL(src)
|
|
37
|
-
if (!isMatchDomain(parsedUrl.hostname)) {
|
|
38
|
-
return src
|
|
39
|
-
}
|
|
40
|
-
const fileName = parsedUrl.pathname.split('/').pop() || ''
|
|
41
|
-
if (idMatchFileExtensions(fileName) && !/_[0-9]{2,4}x/.test(src)) {
|
|
42
|
-
const [name, extension] = fileName.split('.')
|
|
43
|
-
return `${parsedUrl.origin}${parsedUrl.pathname.replace(
|
|
44
|
-
fileName,
|
|
45
|
-
`${name}_${size < MAX_SIZE ? size : FIXED_MAX_SIZE}x.${extension}`
|
|
46
|
-
)}`
|
|
47
|
-
}
|
|
48
|
-
} catch (error) {
|
|
49
|
-
return src
|
|
50
|
-
}
|
|
51
|
-
}, [])
|
|
52
|
-
|
|
53
|
-
const sourceSrcSet = useCallback(
|
|
54
|
-
({ srcArr, width }: { srcArr: string[][]; width: number }) => {
|
|
55
|
-
const computedWidth = width * quality
|
|
56
|
-
const def = imgSrcSetsize({ src: srcArr[0][0], width: computedWidth })
|
|
57
|
-
let result
|
|
58
|
-
srcArr.forEach(ele => {
|
|
59
|
-
var img = ele[0]
|
|
60
|
-
if (ele.length > 1 && parseInt(ele[1], 10) >= width) {
|
|
61
|
-
result = imgSrcSetsize({ src: img, width: computedWidth })
|
|
62
|
-
}
|
|
63
|
-
})
|
|
64
|
-
const srcset = result || def
|
|
65
|
-
return <source key={width} srcSet={srcset} media={`(max-width: ${width}px)`} />
|
|
66
|
-
},
|
|
67
|
-
[imgSrcSetsize, quality]
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
const sourceList = useMemo(() => {
|
|
71
|
-
if (typeof source !== 'string' || !source) return []
|
|
72
|
-
let srcArr
|
|
73
|
-
try {
|
|
74
|
-
srcArr = source
|
|
75
|
-
.replace(/[\r\n]/g, '')
|
|
76
|
-
.replace(/\s\s+/g, ' ')
|
|
77
|
-
.split(',')
|
|
78
|
-
.map(item => item.split(' ').filter(Boolean))
|
|
79
|
-
} catch (error) {
|
|
80
|
-
console.log(error)
|
|
81
|
-
return []
|
|
82
|
-
}
|
|
83
|
-
const sourceList = deviceSizes.map(width => {
|
|
84
|
-
return sourceSrcSet({ srcArr, width })
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
const img = imgSrcSetsize({ src: srcArr[0][0], width: 1920 * quality })
|
|
88
|
-
|
|
89
|
-
sourceList.push(<img key="default" src={img} className={`w-full ${imgClassName}`} {...rest} />)
|
|
90
|
-
return sourceList
|
|
91
|
-
}, [deviceSizes, imgClassName, imgSrcSetsize, quality, rest, source, sourceSrcSet])
|
|
92
|
-
|
|
93
|
-
return (
|
|
94
|
-
<picture className={`block overflow-hidden ${className}`}>
|
|
95
|
-
{sourceList}
|
|
96
|
-
{rest.children}
|
|
97
|
-
</picture>
|
|
98
|
-
)
|
|
99
|
-
}
|
|
100
|
-
export default Picture
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import * as React from 'react'
|
|
4
|
-
import * as PopoverPrimitive from '@radix-ui/react-popover'
|
|
5
|
-
|
|
6
|
-
import { cn } from '../helpers/utils.js'
|
|
7
|
-
|
|
8
|
-
const Popover = PopoverPrimitive.Root
|
|
9
|
-
|
|
10
|
-
const PopoverTrigger = PopoverPrimitive.Trigger
|
|
11
|
-
|
|
12
|
-
const PopoverContent = React.forwardRef<
|
|
13
|
-
React.ElementRef<typeof PopoverPrimitive.Content>,
|
|
14
|
-
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
|
|
15
|
-
>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (
|
|
16
|
-
<PopoverPrimitive.Portal>
|
|
17
|
-
<PopoverPrimitive.Content
|
|
18
|
-
ref={ref}
|
|
19
|
-
align={align}
|
|
20
|
-
sideOffset={sideOffset}
|
|
21
|
-
className={cn(
|
|
22
|
-
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 rounded-md border p-4 shadow-md outline-none',
|
|
23
|
-
className
|
|
24
|
-
)}
|
|
25
|
-
{...props}
|
|
26
|
-
/>
|
|
27
|
-
</PopoverPrimitive.Portal>
|
|
28
|
-
))
|
|
29
|
-
PopoverContent.displayName = PopoverPrimitive.Content.displayName
|
|
30
|
-
|
|
31
|
-
export { Popover, PopoverTrigger, PopoverContent }
|
package/src/components/radio.tsx
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import * as React from 'react'
|
|
4
|
-
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group'
|
|
5
|
-
import { Text } from './text.js'
|
|
6
|
-
import { CheckIcon } from '@radix-ui/react-icons'
|
|
7
|
-
import { cva, type VariantProps } from 'class-variance-authority'
|
|
8
|
-
import { cn } from '../helpers/index.js'
|
|
9
|
-
|
|
10
|
-
const RadioContext = React.createContext<{ size?: 'sm' | 'base' | 'lg' }>({
|
|
11
|
-
size: 'base',
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
const radioGroupVariants = cva(
|
|
15
|
-
'border-primary text-primary ring-offset-background focus-visible:ring-ring aspect-square rounded-full border focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground',
|
|
16
|
-
{
|
|
17
|
-
variants: {
|
|
18
|
-
size: {
|
|
19
|
-
sm: 'size-[14px]',
|
|
20
|
-
base: 'size-4',
|
|
21
|
-
lg: 'size-5',
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
defaultVariants: {
|
|
25
|
-
size: 'base',
|
|
26
|
-
},
|
|
27
|
-
}
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
interface RadioGroupProps extends React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root> {
|
|
31
|
-
/** 尺寸 */
|
|
32
|
-
size?: 'sm' | 'base' | 'lg'
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const RadioGroup = React.forwardRef<React.ElementRef<typeof RadioGroupPrimitive.Root>, RadioGroupProps>(
|
|
36
|
-
({ className, children, size, ...props }, ref) => {
|
|
37
|
-
return (
|
|
38
|
-
<RadioGroupPrimitive.Root className={cn('grid gap-2', className)} {...props} ref={ref}>
|
|
39
|
-
<RadioContext.Provider value={{ size }}>{children}</RadioContext.Provider>
|
|
40
|
-
</RadioGroupPrimitive.Root>
|
|
41
|
-
)
|
|
42
|
-
}
|
|
43
|
-
)
|
|
44
|
-
RadioGroup.displayName = 'RadioGroup'
|
|
45
|
-
|
|
46
|
-
interface RadioGroupItemProps
|
|
47
|
-
extends React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>,
|
|
48
|
-
VariantProps<typeof radioGroupVariants> {}
|
|
49
|
-
|
|
50
|
-
const RadioGroupItem = React.forwardRef<React.ElementRef<typeof RadioGroupPrimitive.Item>, RadioGroupItemProps>(
|
|
51
|
-
({ className, size, children, ...props }, ref) => {
|
|
52
|
-
const { size: sizeFromParent } = React.useContext(RadioContext)
|
|
53
|
-
|
|
54
|
-
const ItemRadio = (
|
|
55
|
-
<RadioGroupPrimitive.Item
|
|
56
|
-
ref={ref}
|
|
57
|
-
className={cn(
|
|
58
|
-
radioGroupVariants({
|
|
59
|
-
size: size ?? sizeFromParent,
|
|
60
|
-
}),
|
|
61
|
-
className
|
|
62
|
-
)}
|
|
63
|
-
{...props}
|
|
64
|
-
>
|
|
65
|
-
<RadioGroupPrimitive.Indicator className="flex items-center justify-center text-current w-full h-full">
|
|
66
|
-
<CheckIcon />
|
|
67
|
-
</RadioGroupPrimitive.Indicator>
|
|
68
|
-
</RadioGroupPrimitive.Item>
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
if (children) {
|
|
72
|
-
return (
|
|
73
|
-
<Text as="label" className={cn('flex items-center gap-1', className)}>
|
|
74
|
-
{ItemRadio}
|
|
75
|
-
{children}
|
|
76
|
-
</Text>
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
|
-
return ItemRadio
|
|
80
|
-
}
|
|
81
|
-
)
|
|
82
|
-
RadioGroupItem.displayName = 'RadioGroupItem'
|
|
83
|
-
|
|
84
|
-
export { RadioGroup, RadioGroupItem }
|
|
85
|
-
export type { RadioGroupProps, RadioGroupItemProps }
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import * as React from 'react'
|
|
2
|
-
import { cn } from '../helpers/index.js'
|
|
3
|
-
import { Slot } from '@radix-ui/react-slot'
|
|
4
|
-
import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js'
|
|
5
|
-
|
|
6
|
-
type SkeletonElement = React.ElementRef<'span'>
|
|
7
|
-
|
|
8
|
-
interface SkeletonProps extends ComponentPropsWithout<'span', RemovedProps> {
|
|
9
|
-
/** 是否正在加载 , 默认是true*/
|
|
10
|
-
loading?: boolean
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const Skeleton = React.forwardRef<SkeletonElement, SkeletonProps>((props, forwardedRef) => {
|
|
14
|
-
const { children, className, loading = true, ...skeletonProps } = props
|
|
15
|
-
|
|
16
|
-
if (!loading) return children
|
|
17
|
-
const Tag = React.isValidElement(children) ? Slot : 'span'
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<Tag
|
|
21
|
-
ref={forwardedRef}
|
|
22
|
-
className={cn(
|
|
23
|
-
`bg-skeleton animate-pulse empty:block data-[inline-skeleton=true]:leading-[0] !bg-none !bg-clip-border !border-none !shadow-none
|
|
24
|
-
!text-transparent !outline-none !select-none !cursor-default !pointer-events-none !decoration-clone
|
|
25
|
-
after:!invisible before:!invisible [&>*]:!invisible
|
|
26
|
-
`,
|
|
27
|
-
className
|
|
28
|
-
)}
|
|
29
|
-
data-inline-skeleton={React.isValidElement(children) ? undefined : true}
|
|
30
|
-
tabIndex={-1}
|
|
31
|
-
{...skeletonProps}
|
|
32
|
-
>
|
|
33
|
-
{children}
|
|
34
|
-
</Tag>
|
|
35
|
-
)
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
Skeleton.displayName = 'Skeleton'
|
|
39
|
-
|
|
40
|
-
export default Skeleton
|
|
41
|
-
export type { SkeletonProps }
|