@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.
Files changed (172) hide show
  1. package/dist/cjs/biz-components/BrandEquity/BrandEquity.js +1 -1
  2. package/dist/cjs/biz-components/BrandEquity/BrandEquity.js.map +2 -2
  3. package/dist/cjs/biz-components/Category/index.js +1 -1
  4. package/dist/cjs/biz-components/Category/index.js.map +2 -2
  5. package/dist/cjs/biz-components/Evaluate/index.d.ts +1 -0
  6. package/dist/cjs/biz-components/Evaluate/index.js +1 -1
  7. package/dist/cjs/biz-components/Evaluate/index.js.map +3 -3
  8. package/dist/cjs/biz-components/Marquee/index.js +1 -1
  9. package/dist/cjs/biz-components/Marquee/index.js.map +2 -2
  10. package/dist/cjs/biz-components/MemberEquity/index.js +30 -30
  11. package/dist/cjs/biz-components/MemberEquity/index.js.map +2 -2
  12. package/dist/cjs/biz-components/ShelfDisplay/index.js +9 -9
  13. package/dist/cjs/biz-components/ShelfDisplay/index.js.map +2 -2
  14. package/dist/cjs/biz-components/Slogan/index.js +1 -1
  15. package/dist/cjs/biz-components/Slogan/index.js.map +2 -2
  16. package/dist/cjs/components/button.js +1 -1
  17. package/dist/cjs/components/button.js.map +2 -2
  18. package/dist/cjs/components/card.js +1 -1
  19. package/dist/cjs/components/card.js.map +2 -2
  20. package/dist/cjs/components/carousel.js +1 -1
  21. package/dist/cjs/components/carousel.js.map +2 -2
  22. package/dist/cjs/components/container.js +1 -1
  23. package/dist/cjs/components/container.js.map +2 -2
  24. package/dist/cjs/components/dialog.js +1 -1
  25. package/dist/cjs/components/dialog.js.map +2 -2
  26. package/dist/cjs/components/gird.js +1 -1
  27. package/dist/cjs/components/gird.js.map +2 -2
  28. package/dist/cjs/components/heading.d.ts +1 -1
  29. package/dist/cjs/components/heading.js +1 -1
  30. package/dist/cjs/components/heading.js.map +2 -2
  31. package/dist/cjs/components/text.js +1 -1
  32. package/dist/cjs/components/text.js.map +1 -1
  33. package/dist/cjs/stories/container.stories.js +6 -6
  34. package/dist/cjs/stories/container.stories.js.map +2 -2
  35. package/dist/cjs/stories/dialog.stories.js +1 -1
  36. package/dist/cjs/stories/dialog.stories.js.map +2 -2
  37. package/dist/cjs/stories/evaluate.stories.js +1 -1
  38. package/dist/cjs/stories/evaluate.stories.js.map +2 -2
  39. package/dist/cjs/stories/heading.stories.d.ts +3 -2
  40. package/dist/cjs/stories/heading.stories.js +1 -1
  41. package/dist/cjs/stories/heading.stories.js.map +2 -2
  42. package/dist/cjs/stories/text.stories.js +1 -1
  43. package/dist/cjs/stories/text.stories.js.map +2 -2
  44. package/dist/esm/biz-components/BrandEquity/BrandEquity.js +1 -1
  45. package/dist/esm/biz-components/BrandEquity/BrandEquity.js.map +2 -2
  46. package/dist/esm/biz-components/Category/index.js +1 -1
  47. package/dist/esm/biz-components/Category/index.js.map +2 -2
  48. package/dist/esm/biz-components/Evaluate/index.d.ts +1 -0
  49. package/dist/esm/biz-components/Evaluate/index.js +1 -1
  50. package/dist/esm/biz-components/Evaluate/index.js.map +3 -3
  51. package/dist/esm/biz-components/Marquee/index.js +1 -1
  52. package/dist/esm/biz-components/Marquee/index.js.map +2 -2
  53. package/dist/esm/biz-components/MemberEquity/index.js +29 -29
  54. package/dist/esm/biz-components/MemberEquity/index.js.map +2 -2
  55. package/dist/esm/biz-components/ShelfDisplay/index.js +9 -9
  56. package/dist/esm/biz-components/ShelfDisplay/index.js.map +2 -2
  57. package/dist/esm/biz-components/Slogan/index.js +1 -1
  58. package/dist/esm/biz-components/Slogan/index.js.map +2 -2
  59. package/dist/esm/components/button.js +1 -1
  60. package/dist/esm/components/button.js.map +2 -2
  61. package/dist/esm/components/card.js +1 -1
  62. package/dist/esm/components/card.js.map +2 -2
  63. package/dist/esm/components/carousel.js +1 -1
  64. package/dist/esm/components/carousel.js.map +2 -2
  65. package/dist/esm/components/container.js +1 -1
  66. package/dist/esm/components/container.js.map +2 -2
  67. package/dist/esm/components/dialog.js +1 -1
  68. package/dist/esm/components/dialog.js.map +2 -2
  69. package/dist/esm/components/gird.js +1 -1
  70. package/dist/esm/components/gird.js.map +2 -2
  71. package/dist/esm/components/heading.d.ts +1 -1
  72. package/dist/esm/components/heading.js +1 -1
  73. package/dist/esm/components/heading.js.map +2 -2
  74. package/dist/esm/components/text.js +1 -1
  75. package/dist/esm/components/text.js.map +1 -1
  76. package/dist/esm/stories/container.stories.js +6 -6
  77. package/dist/esm/stories/container.stories.js.map +2 -2
  78. package/dist/esm/stories/dialog.stories.js +1 -1
  79. package/dist/esm/stories/dialog.stories.js.map +2 -2
  80. package/dist/esm/stories/evaluate.stories.js +1 -1
  81. package/dist/esm/stories/evaluate.stories.js.map +2 -2
  82. package/dist/esm/stories/heading.stories.d.ts +3 -2
  83. package/dist/esm/stories/heading.stories.js +1 -1
  84. package/dist/esm/stories/heading.stories.js.map +2 -2
  85. package/dist/esm/stories/text.stories.js +2 -2
  86. package/dist/esm/stories/text.stories.js.map +2 -2
  87. package/package.json +2 -3
  88. package/style.css +69 -34
  89. package/src/biz-components/BrandEquity/BrandEquity.tsx +0 -77
  90. package/src/biz-components/BrandEquity/index.ts +0 -1
  91. package/src/biz-components/Category/index.tsx +0 -57
  92. package/src/biz-components/Evaluate/index.tsx +0 -85
  93. package/src/biz-components/HeroBanner/HeroBanner.tsx +0 -103
  94. package/src/biz-components/HeroBanner/index.tsx +0 -1
  95. package/src/biz-components/HeroBanner/types.ts +0 -28
  96. package/src/biz-components/Marquee/index.tsx +0 -79
  97. package/src/biz-components/MemberEquity/index.tsx +0 -114
  98. package/src/biz-components/MemberEquity/types.ts +0 -26
  99. package/src/biz-components/Shelf/Shelf.tsx +0 -22
  100. package/src/biz-components/Shelf/index.ts +0 -1
  101. package/src/biz-components/Shelf/types.ts +0 -6
  102. package/src/biz-components/ShelfDisplay/index.tsx +0 -142
  103. package/src/biz-components/Slogan/index.tsx +0 -53
  104. package/src/biz-components/Slogan/types.ts +0 -25
  105. package/src/biz-components/index.ts +0 -11
  106. package/src/components/alert.tsx +0 -124
  107. package/src/components/avatar.tsx +0 -126
  108. package/src/components/badge.tsx +0 -27
  109. package/src/components/button.tsx +0 -183
  110. package/src/components/card.tsx +0 -51
  111. package/src/components/carousel.tsx +0 -352
  112. package/src/components/checkbox.tsx +0 -42
  113. package/src/components/color.tsx +0 -77
  114. package/src/components/container.tsx +0 -28
  115. package/src/components/dialog.tsx +0 -98
  116. package/src/components/drawer.tsx +0 -115
  117. package/src/components/drop-down.tsx +0 -182
  118. package/src/components/gird.tsx +0 -90
  119. package/src/components/heading.tsx +0 -80
  120. package/src/components/index.ts +0 -26
  121. package/src/components/input-number.tsx +0 -216
  122. package/src/components/input.tsx +0 -79
  123. package/src/components/link.tsx +0 -99
  124. package/src/components/picture.tsx +0 -100
  125. package/src/components/popover.tsx +0 -31
  126. package/src/components/radio.tsx +0 -85
  127. package/src/components/skeleton.tsx +0 -41
  128. package/src/components/tabs.tsx +0 -78
  129. package/src/components/text.tsx +0 -99
  130. package/src/components/theme.tsx +0 -20
  131. package/src/helpers/component-props.ts +0 -17
  132. package/src/helpers/constants.ts +0 -0
  133. package/src/helpers/index.ts +0 -2
  134. package/src/helpers/utils.ts +0 -16
  135. package/src/icons/spinner.tsx +0 -26
  136. package/src/index.ts +0 -1
  137. package/src/shared/Styles.tsx +0 -94
  138. package/src/stories/HeroBanner.stories.tsx +0 -86
  139. package/src/stories/MemberEquity.stories.tsx +0 -107
  140. package/src/stories/alert.stories.tsx +0 -41
  141. package/src/stories/avatar.stories.tsx +0 -83
  142. package/src/stories/badge.stories.tsx +0 -40
  143. package/src/stories/brandEquity.stories.tsx +0 -73
  144. package/src/stories/button.stories.tsx +0 -145
  145. package/src/stories/card.stories.tsx +0 -97
  146. package/src/stories/carousel.stories.tsx +0 -161
  147. package/src/stories/category.stories.tsx +0 -52
  148. package/src/stories/checkbox.stories.tsx +0 -93
  149. package/src/stories/container.stories.tsx +0 -97
  150. package/src/stories/dialog.stories.tsx +0 -74
  151. package/src/stories/drawer.stories.tsx +0 -88
  152. package/src/stories/drop-down.stories.tsx +0 -83
  153. package/src/stories/evaluate.stories.tsx +0 -53
  154. package/src/stories/grid.stories.tsx +0 -190
  155. package/src/stories/heading.stories.tsx +0 -96
  156. package/src/stories/input-number.stories.tsx +0 -52
  157. package/src/stories/input.stories.tsx +0 -64
  158. package/src/stories/link.stories.tsx +0 -142
  159. package/src/stories/marquee.stories.tsx +0 -102
  160. package/src/stories/picture.stories.tsx +0 -51
  161. package/src/stories/popover.stories.tsx +0 -41
  162. package/src/stories/radio.stories.tsx +0 -55
  163. package/src/stories/shelf.stories.tsx +0 -35
  164. package/src/stories/shelfDisplay.stories.tsx +0 -69
  165. package/src/stories/skeleton.stories.tsx +0 -67
  166. package/src/stories/slogan.stories.tsx +0 -99
  167. package/src/stories/tabs.stories.tsx +0 -179
  168. package/src/stories/text.stories.tsx +0 -130
  169. package/src/styles/global.css +0 -4
  170. package/src/styles/index.css +0 -0
  171. package/src/types/index.ts +0 -0
  172. 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 }
@@ -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 }
@@ -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 }
@@ -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 }