seven-design-ui 0.0.1

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 (157) hide show
  1. package/.eslintrc.json +35 -0
  2. package/.prettierrc.json +10 -0
  3. package/CONTRIBUTING.md +350 -0
  4. package/PROJECT_STRUCTURE.md +343 -0
  5. package/README.md +83 -0
  6. package/app/globals.css +125 -0
  7. package/app/layout.tsx +45 -0
  8. package/app/page.tsx +202 -0
  9. package/components/theme-provider.tsx +11 -0
  10. package/components/ui/accordion.tsx +66 -0
  11. package/components/ui/alert-dialog.tsx +157 -0
  12. package/components/ui/alert.tsx +66 -0
  13. package/components/ui/aspect-ratio.tsx +11 -0
  14. package/components/ui/avatar.tsx +53 -0
  15. package/components/ui/badge.tsx +46 -0
  16. package/components/ui/breadcrumb.tsx +109 -0
  17. package/components/ui/button-group.tsx +83 -0
  18. package/components/ui/button.tsx +60 -0
  19. package/components/ui/calendar.tsx +213 -0
  20. package/components/ui/card.tsx +92 -0
  21. package/components/ui/carousel.tsx +241 -0
  22. package/components/ui/chart.tsx +353 -0
  23. package/components/ui/checkbox.tsx +32 -0
  24. package/components/ui/collapsible.tsx +33 -0
  25. package/components/ui/command.tsx +184 -0
  26. package/components/ui/context-menu.tsx +252 -0
  27. package/components/ui/dialog.tsx +143 -0
  28. package/components/ui/drawer.tsx +135 -0
  29. package/components/ui/dropdown-menu.tsx +257 -0
  30. package/components/ui/empty.tsx +104 -0
  31. package/components/ui/field.tsx +244 -0
  32. package/components/ui/form.tsx +167 -0
  33. package/components/ui/hover-card.tsx +44 -0
  34. package/components/ui/input-group.tsx +169 -0
  35. package/components/ui/input-otp.tsx +77 -0
  36. package/components/ui/input.tsx +21 -0
  37. package/components/ui/item.tsx +193 -0
  38. package/components/ui/kbd.tsx +28 -0
  39. package/components/ui/label.tsx +24 -0
  40. package/components/ui/menubar.tsx +276 -0
  41. package/components/ui/navigation-menu.tsx +166 -0
  42. package/components/ui/pagination.tsx +127 -0
  43. package/components/ui/popover.tsx +48 -0
  44. package/components/ui/progress.tsx +31 -0
  45. package/components/ui/radio-group.tsx +45 -0
  46. package/components/ui/resizable.tsx +56 -0
  47. package/components/ui/scroll-area.tsx +58 -0
  48. package/components/ui/select.tsx +185 -0
  49. package/components/ui/separator.tsx +28 -0
  50. package/components/ui/sheet.tsx +139 -0
  51. package/components/ui/sidebar.tsx +726 -0
  52. package/components/ui/skeleton.tsx +13 -0
  53. package/components/ui/slider.tsx +63 -0
  54. package/components/ui/sonner.tsx +25 -0
  55. package/components/ui/spinner.tsx +16 -0
  56. package/components/ui/switch.tsx +31 -0
  57. package/components/ui/table.tsx +116 -0
  58. package/components/ui/tabs.tsx +66 -0
  59. package/components/ui/textarea.tsx +18 -0
  60. package/components/ui/toast.tsx +129 -0
  61. package/components/ui/toaster.tsx +35 -0
  62. package/components/ui/toggle-group.tsx +73 -0
  63. package/components/ui/toggle.tsx +47 -0
  64. package/components/ui/tooltip.tsx +61 -0
  65. package/components/ui/use-mobile.tsx +19 -0
  66. package/components/ui/use-toast.ts +191 -0
  67. package/components.json +21 -0
  68. package/docs/components/button.mdx +155 -0
  69. package/docs/components/input.mdx +157 -0
  70. package/docs/components/pagination.mdx +186 -0
  71. package/docs/components/switch.mdx +134 -0
  72. package/docs/doc_build/.nojekyll +0 -0
  73. package/docs/doc_build/404.html +15 -0
  74. package/docs/doc_build/components/button.html +39 -0
  75. package/docs/doc_build/components/input.html +39 -0
  76. package/docs/doc_build/components/pagination.html +39 -0
  77. package/docs/doc_build/components/switch.html +38 -0
  78. package/docs/doc_build/guide/introduction.html +58 -0
  79. package/docs/doc_build/guide/quick-start.html +98 -0
  80. package/docs/doc_build/guide/theme.html +139 -0
  81. package/docs/doc_build/index.html +15 -0
  82. package/docs/doc_build/logo.svg +1 -0
  83. package/docs/doc_build/static/css/styles.5a3e7113.css +1 -0
  84. package/docs/doc_build/static/js/414.04bb58dd.js +6 -0
  85. package/docs/doc_build/static/js/414.04bb58dd.js.LICENSE.txt +21 -0
  86. package/docs/doc_build/static/js/async/166.f43be01a.js +2 -0
  87. package/docs/doc_build/static/js/async/166.f43be01a.js.LICENSE.txt +19 -0
  88. package/docs/doc_build/static/js/async/218.cd780e24.js +1 -0
  89. package/docs/doc_build/static/js/async/232.11414fd7.js +1 -0
  90. package/docs/doc_build/static/js/async/416.b217df75.js +1 -0
  91. package/docs/doc_build/static/js/async/509.97958e51.js +1 -0
  92. package/docs/doc_build/static/js/async/512.9047d21e.js +1 -0
  93. package/docs/doc_build/static/js/async/531.131f5963.js +1 -0
  94. package/docs/doc_build/static/js/async/562.b402b94f.js +2 -0
  95. package/docs/doc_build/static/js/async/562.b402b94f.js.LICENSE.txt +11 -0
  96. package/docs/doc_build/static/js/async/637.cb5d76c9.js +1 -0
  97. package/docs/doc_build/static/js/async/712.558b85be.js +1 -0
  98. package/docs/doc_build/static/js/index.0991c749.js +1 -0
  99. package/docs/doc_build/static/js/lib-react.ce4199ca.js +2 -0
  100. package/docs/doc_build/static/js/lib-react.ce4199ca.js.LICENSE.txt +49 -0
  101. package/docs/doc_build/static/js/lib-router.4000fe55.js +2 -0
  102. package/docs/doc_build/static/js/lib-router.4000fe55.js.LICENSE.txt +32 -0
  103. package/docs/doc_build/static/js/styles.f2af9a40.js +1 -0
  104. package/docs/doc_build/static/search_index.72c9c372.json +1 -0
  105. package/docs/docs/public/logo.svg +1 -0
  106. package/docs/guide/introduction.md +50 -0
  107. package/docs/guide/quick-start.md +132 -0
  108. package/docs/guide/theme.md +230 -0
  109. package/docs/index.md +85 -0
  110. package/docs/package.json +22 -0
  111. package/docs/public/logo.svg +1 -0
  112. package/docs/rspress.config.ts +116 -0
  113. package/hooks/use-mobile.ts +19 -0
  114. package/hooks/use-toast.ts +191 -0
  115. package/next.config.mjs +11 -0
  116. package/package.json +75 -0
  117. package/packages/components/package.json +34 -0
  118. package/packages/components/src/button/Button.tsx +83 -0
  119. package/packages/components/src/button/button.css +256 -0
  120. package/packages/components/src/button/index.ts +2 -0
  121. package/packages/components/src/index.ts +8 -0
  122. package/packages/components/src/input/Input.tsx +230 -0
  123. package/packages/components/src/input/index.ts +2 -0
  124. package/packages/components/src/input/input.css +99 -0
  125. package/packages/components/src/pagination/Pagination.tsx +271 -0
  126. package/packages/components/src/pagination/index.ts +1 -0
  127. package/packages/components/src/pagination/pagination.css +225 -0
  128. package/packages/components/src/switch/Switch.tsx +145 -0
  129. package/packages/components/src/switch/index.ts +2 -0
  130. package/packages/components/src/switch/switch.css +119 -0
  131. package/packages/components/tsconfig.json +12 -0
  132. package/packages/components/vite.config.ts +31 -0
  133. package/packages/core/package.json +23 -0
  134. package/packages/core/src/hooks/useControllableState.ts +31 -0
  135. package/packages/core/src/hooks/useEventListener.ts +37 -0
  136. package/packages/core/src/index.ts +7 -0
  137. package/packages/core/src/utils/classnames.ts +48 -0
  138. package/packages/core/tsconfig.json +12 -0
  139. package/packages/core/vite.config.ts +24 -0
  140. package/packages/theme/package.json +20 -0
  141. package/packages/theme/src/index.css +138 -0
  142. package/packages/theme/src/index.ts +1 -0
  143. package/packages/theme/vite.config.ts +21 -0
  144. package/play/index.html +13 -0
  145. package/play/package.json +25 -0
  146. package/play/src/App.tsx +237 -0
  147. package/play/src/index.css +93 -0
  148. package/play/src/main.tsx +14 -0
  149. package/play/tsconfig.json +8 -0
  150. package/play/vite.config.ts +10 -0
  151. package/pnpm-workspace.yaml +4 -0
  152. package/postcss.config.mjs +8 -0
  153. package/public/logo.svg +1 -0
  154. package/scripts/build.sh +19 -0
  155. package/scripts/deploy-docs.js +38 -0
  156. package/styles/globals.css +125 -0
  157. package/tsconfig.json +30 -0
@@ -0,0 +1,61 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import * as TooltipPrimitive from '@radix-ui/react-tooltip'
5
+
6
+ import { cn } from '@/lib/utils'
7
+
8
+ function TooltipProvider({
9
+ delayDuration = 0,
10
+ ...props
11
+ }: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
12
+ return (
13
+ <TooltipPrimitive.Provider
14
+ data-slot="tooltip-provider"
15
+ delayDuration={delayDuration}
16
+ {...props}
17
+ />
18
+ )
19
+ }
20
+
21
+ function Tooltip({
22
+ ...props
23
+ }: React.ComponentProps<typeof TooltipPrimitive.Root>) {
24
+ return (
25
+ <TooltipProvider>
26
+ <TooltipPrimitive.Root data-slot="tooltip" {...props} />
27
+ </TooltipProvider>
28
+ )
29
+ }
30
+
31
+ function TooltipTrigger({
32
+ ...props
33
+ }: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
34
+ return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
35
+ }
36
+
37
+ function TooltipContent({
38
+ className,
39
+ sideOffset = 0,
40
+ children,
41
+ ...props
42
+ }: React.ComponentProps<typeof TooltipPrimitive.Content>) {
43
+ return (
44
+ <TooltipPrimitive.Portal>
45
+ <TooltipPrimitive.Content
46
+ data-slot="tooltip-content"
47
+ sideOffset={sideOffset}
48
+ className={cn(
49
+ 'bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance',
50
+ className,
51
+ )}
52
+ {...props}
53
+ >
54
+ {children}
55
+ <TooltipPrimitive.Arrow className="bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
56
+ </TooltipPrimitive.Content>
57
+ </TooltipPrimitive.Portal>
58
+ )
59
+ }
60
+
61
+ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
@@ -0,0 +1,19 @@
1
+ import * as React from 'react'
2
+
3
+ const MOBILE_BREAKPOINT = 768
4
+
5
+ export function useIsMobile() {
6
+ const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
7
+
8
+ React.useEffect(() => {
9
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
10
+ const onChange = () => {
11
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
12
+ }
13
+ mql.addEventListener('change', onChange)
14
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
15
+ return () => mql.removeEventListener('change', onChange)
16
+ }, [])
17
+
18
+ return !!isMobile
19
+ }
@@ -0,0 +1,191 @@
1
+ 'use client'
2
+
3
+ // Inspired by react-hot-toast library
4
+ import * as React from 'react'
5
+
6
+ import type { ToastActionElement, ToastProps } from '@/components/ui/toast'
7
+
8
+ const TOAST_LIMIT = 1
9
+ const TOAST_REMOVE_DELAY = 1000000
10
+
11
+ type ToasterToast = ToastProps & {
12
+ id: string
13
+ title?: React.ReactNode
14
+ description?: React.ReactNode
15
+ action?: ToastActionElement
16
+ }
17
+
18
+ const actionTypes = {
19
+ ADD_TOAST: 'ADD_TOAST',
20
+ UPDATE_TOAST: 'UPDATE_TOAST',
21
+ DISMISS_TOAST: 'DISMISS_TOAST',
22
+ REMOVE_TOAST: 'REMOVE_TOAST',
23
+ } as const
24
+
25
+ let count = 0
26
+
27
+ function genId() {
28
+ count = (count + 1) % Number.MAX_SAFE_INTEGER
29
+ return count.toString()
30
+ }
31
+
32
+ type ActionType = typeof actionTypes
33
+
34
+ type Action =
35
+ | {
36
+ type: ActionType['ADD_TOAST']
37
+ toast: ToasterToast
38
+ }
39
+ | {
40
+ type: ActionType['UPDATE_TOAST']
41
+ toast: Partial<ToasterToast>
42
+ }
43
+ | {
44
+ type: ActionType['DISMISS_TOAST']
45
+ toastId?: ToasterToast['id']
46
+ }
47
+ | {
48
+ type: ActionType['REMOVE_TOAST']
49
+ toastId?: ToasterToast['id']
50
+ }
51
+
52
+ interface State {
53
+ toasts: ToasterToast[]
54
+ }
55
+
56
+ const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>()
57
+
58
+ const addToRemoveQueue = (toastId: string) => {
59
+ if (toastTimeouts.has(toastId)) {
60
+ return
61
+ }
62
+
63
+ const timeout = setTimeout(() => {
64
+ toastTimeouts.delete(toastId)
65
+ dispatch({
66
+ type: 'REMOVE_TOAST',
67
+ toastId: toastId,
68
+ })
69
+ }, TOAST_REMOVE_DELAY)
70
+
71
+ toastTimeouts.set(toastId, timeout)
72
+ }
73
+
74
+ export const reducer = (state: State, action: Action): State => {
75
+ switch (action.type) {
76
+ case 'ADD_TOAST':
77
+ return {
78
+ ...state,
79
+ toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
80
+ }
81
+
82
+ case 'UPDATE_TOAST':
83
+ return {
84
+ ...state,
85
+ toasts: state.toasts.map((t) =>
86
+ t.id === action.toast.id ? { ...t, ...action.toast } : t,
87
+ ),
88
+ }
89
+
90
+ case 'DISMISS_TOAST': {
91
+ const { toastId } = action
92
+
93
+ // ! Side effects ! - This could be extracted into a dismissToast() action,
94
+ // but I'll keep it here for simplicity
95
+ if (toastId) {
96
+ addToRemoveQueue(toastId)
97
+ } else {
98
+ state.toasts.forEach((toast) => {
99
+ addToRemoveQueue(toast.id)
100
+ })
101
+ }
102
+
103
+ return {
104
+ ...state,
105
+ toasts: state.toasts.map((t) =>
106
+ t.id === toastId || toastId === undefined
107
+ ? {
108
+ ...t,
109
+ open: false,
110
+ }
111
+ : t,
112
+ ),
113
+ }
114
+ }
115
+ case 'REMOVE_TOAST':
116
+ if (action.toastId === undefined) {
117
+ return {
118
+ ...state,
119
+ toasts: [],
120
+ }
121
+ }
122
+ return {
123
+ ...state,
124
+ toasts: state.toasts.filter((t) => t.id !== action.toastId),
125
+ }
126
+ }
127
+ }
128
+
129
+ const listeners: Array<(state: State) => void> = []
130
+
131
+ let memoryState: State = { toasts: [] }
132
+
133
+ function dispatch(action: Action) {
134
+ memoryState = reducer(memoryState, action)
135
+ listeners.forEach((listener) => {
136
+ listener(memoryState)
137
+ })
138
+ }
139
+
140
+ type Toast = Omit<ToasterToast, 'id'>
141
+
142
+ function toast({ ...props }: Toast) {
143
+ const id = genId()
144
+
145
+ const update = (props: ToasterToast) =>
146
+ dispatch({
147
+ type: 'UPDATE_TOAST',
148
+ toast: { ...props, id },
149
+ })
150
+ const dismiss = () => dispatch({ type: 'DISMISS_TOAST', toastId: id })
151
+
152
+ dispatch({
153
+ type: 'ADD_TOAST',
154
+ toast: {
155
+ ...props,
156
+ id,
157
+ open: true,
158
+ onOpenChange: (open) => {
159
+ if (!open) dismiss()
160
+ },
161
+ },
162
+ })
163
+
164
+ return {
165
+ id: id,
166
+ dismiss,
167
+ update,
168
+ }
169
+ }
170
+
171
+ function useToast() {
172
+ const [state, setState] = React.useState<State>(memoryState)
173
+
174
+ React.useEffect(() => {
175
+ listeners.push(setState)
176
+ return () => {
177
+ const index = listeners.indexOf(setState)
178
+ if (index > -1) {
179
+ listeners.splice(index, 1)
180
+ }
181
+ }
182
+ }, [state])
183
+
184
+ return {
185
+ ...state,
186
+ toast,
187
+ dismiss: (toastId?: string) => dispatch({ type: 'DISMISS_TOAST', toastId }),
188
+ }
189
+ }
190
+
191
+ export { useToast, toast }
@@ -0,0 +1,21 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema.json",
3
+ "style": "new-york",
4
+ "rsc": true,
5
+ "tsx": true,
6
+ "tailwind": {
7
+ "config": "",
8
+ "css": "app/globals.css",
9
+ "baseColor": "neutral",
10
+ "cssVariables": true,
11
+ "prefix": ""
12
+ },
13
+ "aliases": {
14
+ "components": "@/components",
15
+ "utils": "@/lib/utils",
16
+ "ui": "@/components/ui",
17
+ "lib": "@/lib",
18
+ "hooks": "@/hooks"
19
+ },
20
+ "iconLibrary": "lucide"
21
+ }
@@ -0,0 +1,155 @@
1
+ import { Button } from '@seven-design-ui/components'
2
+ import React from 'react'
3
+
4
+ # Button 按钮
5
+
6
+ 常用的操作按钮。
7
+
8
+ ## 基础用法
9
+
10
+ 使用 `type`、`plain`、`round` 和 `circle` 来定义按钮的样式。
11
+
12
+ ```tsx preview
13
+ export default function Demo() {
14
+ return (
15
+ <div style={{ display: 'flex', gap: '12px', flexWrap: 'wrap' }}>
16
+ <Button>默认按钮</Button>
17
+ <Button type="primary">主要按钮</Button>
18
+ <Button type="success">成功按钮</Button>
19
+ <Button type="warning">警告按钮</Button>
20
+ <Button type="danger">危险按钮</Button>
21
+ <Button type="info">信息按钮</Button>
22
+ </div>
23
+ )
24
+ }
25
+ ```
26
+
27
+ ## 朴素按钮
28
+
29
+ 使用 `plain` 属性来创建朴素按钮,朴素按钮的文字为按钮颜色,背景为白色。
30
+
31
+ ```tsx preview
32
+ export default function Demo() {
33
+ return (
34
+ <div style={{ display: 'flex', gap: '12px', flexWrap: 'wrap' }}>
35
+ <Button plain>朴素按钮</Button>
36
+ <Button type="primary" plain>
37
+ 主要按钮
38
+ </Button>
39
+ <Button type="success" plain>
40
+ 成功按钮
41
+ </Button>
42
+ <Button type="warning" plain>
43
+ 警告按钮
44
+ </Button>
45
+ <Button type="danger" plain>
46
+ 危险按钮
47
+ </Button>
48
+ <Button type="info" plain>
49
+ 信息按钮
50
+ </Button>
51
+ </div>
52
+ )
53
+ }
54
+ ```
55
+
56
+ ## 圆角按钮
57
+
58
+ 使用 `round` 属性来创建圆角按钮。
59
+
60
+ ```tsx preview
61
+ export default function Demo() {
62
+ return (
63
+ <div style={{ display: 'flex', gap: '12px', flexWrap: 'wrap' }}>
64
+ <Button round>圆角按钮</Button>
65
+ <Button type="primary" round>
66
+ 主要按钮
67
+ </Button>
68
+ <Button type="success" round>
69
+ 成功按钮
70
+ </Button>
71
+ </div>
72
+ )
73
+ }
74
+ ```
75
+
76
+ ## 不同尺寸
77
+
78
+ Button 组件提供除了默认值以外的三种尺寸,可以在不同场景下选择合适的按钮尺寸。
79
+
80
+ ```tsx preview
81
+ export default function Demo() {
82
+ return (
83
+ <div style={{ display: 'flex', gap: '12px', alignItems: 'center' }}>
84
+ <Button size="large">大型按钮</Button>
85
+ <Button>默认按钮</Button>
86
+ <Button size="small">小型按钮</Button>
87
+ </div>
88
+ )
89
+ }
90
+ ```
91
+
92
+ ## 禁用状态
93
+
94
+ 你可以使用 `disabled` 属性来定义按钮是否被禁用。
95
+
96
+ ```tsx preview
97
+ export default function Demo() {
98
+ return (
99
+ <div style={{ display: 'flex', gap: '12px', flexWrap: 'wrap' }}>
100
+ <Button disabled>默认按钮</Button>
101
+ <Button type="primary" disabled>
102
+ 主要按钮
103
+ </Button>
104
+ <Button type="success" disabled>
105
+ 成功按钮
106
+ </Button>
107
+ </div>
108
+ )
109
+ }
110
+ ```
111
+
112
+ ## 加载状态
113
+
114
+ 通过设置 `loading` 属性为 `true` 来显示加载中状态。
115
+
116
+ ```tsx preview
117
+ export default function LoadingButton() {
118
+ const [loading, setLoading] = React.useState(false)
119
+
120
+ const handleClick = () => {
121
+ setLoading(true)
122
+ setTimeout(() => setLoading(false), 2000)
123
+ }
124
+
125
+ return (
126
+ <Button type="primary" loading={loading} onClick={handleClick}>
127
+ {loading ? '加载中...' : '点击加载'}
128
+ </Button>
129
+ )
130
+ }
131
+ ```
132
+
133
+ ## API
134
+
135
+ ### Props
136
+
137
+ | 属性 | 说明 | 类型 | 默认值 |
138
+ | ----------- | -------------------- | -------------------------------------------------------------- | --------- |
139
+ | type | 按钮类型 | `'default' \| 'primary' \| 'success' \| 'warning' \| 'danger' \| 'info'` | `default` |
140
+ | size | 按钮尺寸 | `'large' \| 'default' \| 'small'` | `default` |
141
+ | plain | 是否为朴素按钮 | `boolean` | `false` |
142
+ | round | 是否为圆角按钮 | `boolean` | `false` |
143
+ | circle | 是否为圆形按钮 | `boolean` | `false` |
144
+ | loading | 是否为加载中状态 | `boolean` | `false` |
145
+ | disabled | 是否禁用 | `boolean` | `false` |
146
+ | nativeType | 原生 type 属性 | `'button' \| 'submit' \| 'reset'` | `button` |
147
+ | icon | 图标组件 | `React.ReactNode` | - |
148
+ | className | 自定义类名 | `string` | - |
149
+ | onClick | 点击事件回调 | `(e: React.MouseEvent) => void` | - |
150
+
151
+ ### Events
152
+
153
+ | 事件名 | 说明 | 类型 |
154
+ | ------- | -------------- | ----------------------------------- |
155
+ | onClick | 点击按钮时触发 | `(e: React.MouseEvent) => void` |
@@ -0,0 +1,157 @@
1
+ import { Input } from '@seven-design-ui/components'
2
+ import React from 'react'
3
+
4
+ # Input 输入框
5
+
6
+ 通过鼠标或键盘输入内容,是最基础的表单域的包装。
7
+
8
+ ## 基础用法
9
+
10
+ 基本的输入框用法。
11
+
12
+ ```tsx preview
13
+ export default function BasicInput() {
14
+ const [value, setValue] = React.useState('')
15
+
16
+ return (
17
+ <div>
18
+ <Input
19
+ placeholder="请输入内容"
20
+ value={value}
21
+ onInput={setValue}
22
+ style={{ width: '300px' }}
23
+ />
24
+ <p style={{ marginTop: '12px', color: '#606266' }}>输入的内容:{value}</p>
25
+ </div>
26
+ )
27
+ }
28
+ ```
29
+
30
+ ## 禁用状态
31
+
32
+ 通过 `disabled` 属性指定是否禁用 input 组件。
33
+
34
+ ```tsx preview
35
+ export default function Demo() {
36
+ return <Input placeholder="禁用状态" disabled style={{ width: '300px' }} />
37
+ }
38
+ ```
39
+
40
+ ## 可清空
41
+
42
+ 使用 `clearable` 属性即可得到一个可清空的输入框。
43
+
44
+ ```tsx preview
45
+ export default function ClearableInput() {
46
+ const [value, setValue] = React.useState('可以清空的内容')
47
+
48
+ return (
49
+ <Input
50
+ placeholder="请输入内容"
51
+ value={value}
52
+ onInput={setValue}
53
+ clearable
54
+ style={{ width: '300px' }}
55
+ />
56
+ )
57
+ }
58
+ ```
59
+
60
+ ## 密码输入框
61
+
62
+ 使用 `showPassword` 属性即可得到一个可切换显示隐藏的密码框。
63
+
64
+ ```tsx preview
65
+ export default function Demo() {
66
+ return (
67
+ <Input
68
+ placeholder="请输入密码"
69
+ type="password"
70
+ showPassword
71
+ style={{ width: '300px' }}
72
+ />
73
+ )
74
+ }
75
+ ```
76
+
77
+ ## 不同尺寸
78
+
79
+ 使用 `size` 属性改变输入框大小。除了默认大小外,还有另外两个选项:`large`、`small`。
80
+
81
+ ```tsx preview
82
+ export default function Demo() {
83
+ return (
84
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
85
+ <Input placeholder="大尺寸" size="large" style={{ width: '300px' }} />
86
+ <Input placeholder="默认尺寸" style={{ width: '300px' }} />
87
+ <Input placeholder="小尺寸" size="small" style={{ width: '300px' }} />
88
+ </div>
89
+ )
90
+ }
91
+ ```
92
+
93
+ ## 带图标的输入框
94
+
95
+ 使用 `prefixIcon` 和 `suffixIcon` 属性在 input 组件首部和尾部增加显示图标。
96
+
97
+ ```tsx preview
98
+ export default function Demo() {
99
+ return (
100
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
101
+ <Input
102
+ placeholder="请输入内容"
103
+ prefixIcon={
104
+ <svg viewBox="0 0 1024 1024" width="14" height="14">
105
+ <path
106
+ fill="currentColor"
107
+ d="M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896zm23.744 191.488c-52.096 0-92.928 14.784-123.2 44.352-30.976 29.568-45.76 70.4-45.76 122.496h80.256c0-29.568 5.632-52.8 17.6-68.992 13.376-19.712 35.2-28.864 66.176-28.864 23.936 0 42.944 6.336 56.32 19.712 12.672 13.376 19.712 31.68 19.712 54.912 0 17.6-6.336 34.496-19.008 49.984l-11.776 14.08-30.272 34.496c-52.8 59.136-75.328 102.4-75.328 133.376v20.224h80.96V608c0-22.528 1.408-36.608 4.928-47.68 2.816-12.672 15.488-28.864 37.376-48.576l23.232-27.392c12.672-14.08 24.64-28.16 35.2-43.648 23.936-35.904 35.2-71.104 35.2-107.712 0-52.096-17.6-93.632-51.904-123.904-32.896-30.272-78.08-45.056-133.376-45.056zM512 704a48 48 0 1 0 0 96 48 48 0 0 0 0-96z"
108
+ />
109
+ </svg>
110
+ }
111
+ style={{ width: '300px' }}
112
+ />
113
+ <Input
114
+ placeholder="请输入内容"
115
+ suffixIcon={
116
+ <svg viewBox="0 0 1024 1024" width="14" height="14">
117
+ <path
118
+ fill="currentColor"
119
+ d="M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896zm0 393.664L407.936 353.6a38.4 38.4 0 1 0-54.336 54.336L457.664 512 353.6 616.064a38.4 38.4 0 1 0 54.336 54.336L512 566.336 616.064 670.4a38.4 38.4 0 1 0 54.336-54.336L566.336 512 670.4 407.936a38.4 38.4 0 1 0-54.336-54.336L512 457.664z"
120
+ />
121
+ </svg>
122
+ }
123
+ style={{ width: '300px' }}
124
+ />
125
+ </div>
126
+ )
127
+ }
128
+ ```
129
+
130
+ ## API
131
+
132
+ ### Props
133
+
134
+ | 属性 | 说明 | 类型 | 默认值 |
135
+ | ------------ | -------------------- | ----------------- | --------- |
136
+ | type | 输入框类型 | `string` | `text` |
137
+ | size | 输入框尺寸 | `'large' \| 'default' \| 'small'` | `default` |
138
+ | disabled | 是否禁用 | `boolean` | `false` |
139
+ | readOnly | 是否只读 | `boolean` | `false` |
140
+ | clearable | 是否可清空 | `boolean` | `false` |
141
+ | showPassword | 是否显示密码切换按钮 | `boolean` | `false` |
142
+ | prefixIcon | 前置图标 | `React.ReactNode` | - |
143
+ | suffixIcon | 后置图标 | `React.ReactNode` | - |
144
+ | placeholder | 输入框占位文本 | `string` | - |
145
+ | value | 输入框值(受控) | `string` | - |
146
+ | defaultValue | 默认值(非受控) | `string` | - |
147
+ | className | 自定义类名 | `string` | - |
148
+
149
+ ### Events
150
+
151
+ | 事件名 | 说明 | 类型 |
152
+ | -------- | ---------------------- | --------------------------------------- |
153
+ | onInput | 输入时触发 | `(value: string) => void` |
154
+ | onChange | 值改变时触发 | `(e: React.ChangeEvent) => void` |
155
+ | onClear | 点击清空按钮时触发 | `() => void` |
156
+ | onFocus | 获得焦点时触发 | `(e: React.FocusEvent) => void` |
157
+ | onBlur | 失去焦点时触发 | `(e: React.FocusEvent) => void` |