create-react-docs-ui 0.5.2 → 0.5.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-react-docs-ui",
3
- "version": "0.5.2",
3
+ "version": "0.5.4",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "bin": {
@@ -13,6 +13,7 @@
13
13
  "template/vite-plugin-mdx-components.ts",
14
14
  "template/public/**/*",
15
15
  "template/src/main.tsx",
16
+ "template/src/index.css",
16
17
  "template/src/react-docs-ui.d.ts",
17
18
  "template/src/vite-env.d.ts",
18
19
  "template/src/components/**/*",
@@ -10,7 +10,7 @@
10
10
  },
11
11
  "dependencies": {
12
12
  "react": "^19.0.0",
13
- "react-docs-ui": "^0.5.1",
13
+ "react-docs-ui": "^0.5.3",
14
14
  "react-dom": "^19.0.0",
15
15
  "react-router-dom": "^7.8.0"
16
16
  },
@@ -50,6 +50,10 @@ The Alert component supports multiple types: info, success, warning, error
50
50
  An error occurred, please check and try again.
51
51
  </Alert>
52
52
 
53
+ <Alert type="success" title="Success" icon="/images/success.svg">
54
+ Congratulations! The operation has been completed successfully.
55
+ </Alert>
56
+
53
57
  ### Feature Component
54
58
 
55
59
  The Feature component is used to display feature highlights:
@@ -86,24 +90,6 @@ The Callout component is used to emphasize important content:
86
90
  This is a secondary style Callout used for supplementary information.
87
91
  </Callout>
88
92
 
89
- ### StepList Component
90
-
91
- The StepList component is used to display step processes:
92
-
93
- <StepList>
94
- <StepList.Step title="Install Dependencies">
95
- Run the `npm install` command to install the required dependencies for the project.
96
- </StepList.Step>
97
- <StepList.Step title="Configure Environment">
98
- Configure environment variables and development environment according to project requirements.
99
- </StepList.Step>
100
- <StepList.Step title="Start Project">
101
- Run `npm run dev` to start the development server.
102
- </StepList.Step>
103
- <StepList.Step title="Start Development">
104
- Start writing code to implement your functional requirements.
105
- </StepList.Step>
106
- </StepList>
107
93
 
108
94
  ### BadgeList Component
109
95
 
@@ -51,7 +51,9 @@ Alert 组件支持多种类型:info、success、warning、error
51
51
  发生了一个错误,请检查后重试。
52
52
  </Alert>
53
53
 
54
-
54
+ <Alert type="success" title="Success" icon="/images/success.svg">
55
+ 恭喜!操作已成功完成。
56
+ </Alert>
55
57
 
56
58
  ### Feature 组件
57
59
 
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free v7.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path d="M434.8 70.1c14.3 10.4 17.5 30.4 7.1 44.7l-256 352c-5.5 7.6-14 12.3-23.4 13.1s-18.5-2.7-25.1-9.3l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l101.5 101.5 234-321.7c10.4-14.3 30.4-17.5 44.7-7.1z"/></svg>
@@ -3,27 +3,139 @@ import * as React from 'react'
3
3
  interface AlertProps {
4
4
  type?: 'info' | 'success' | 'warning' | 'error'
5
5
  title?: string
6
+ icon?: string | React.ReactNode
6
7
  children: React.ReactNode
7
8
  }
8
9
 
9
- export function Alert({ type = 'info', title, children }: AlertProps) {
10
- const styles = {
11
- info: 'border-blue-200 bg-blue-50 text-blue-800 dark:border-blue-800 dark:bg-blue-950 dark:text-blue-200',
12
- success: 'border-green-200 bg-green-50 text-green-800 dark:border-green-800 dark:bg-green-950 dark:text-green-200',
13
- warning: 'border-yellow-200 bg-yellow-50 text-yellow-800 dark:border-yellow-800 dark:bg-yellow-950 dark:text-yellow-200',
14
- error: 'border-red-200 bg-red-50 text-red-800 dark:border-red-800 dark:bg-red-950 dark:text-red-200'
10
+ export function Alert({ type = 'info', title, icon, children }: AlertProps) {
11
+ const [isDarkMode, setIsDarkMode] = React.useState(false)
12
+
13
+ React.useEffect(() => {
14
+ setIsDarkMode(document.documentElement.classList.contains('dark'))
15
+ const observer = new MutationObserver(() => {
16
+ setIsDarkMode(document.documentElement.classList.contains('dark'))
17
+ })
18
+ observer.observe(document.documentElement, {
19
+ attributes: true,
20
+ attributeFilter: ['class']
21
+ })
22
+ return () => observer.disconnect()
23
+ }, [])
24
+
25
+ const styles: Record<string, React.CSSProperties> = {
26
+ info: {
27
+ border: '1px solid #bfdbfe',
28
+ backgroundColor: '#eff6ff',
29
+ color: '#1e40af'
30
+ },
31
+ success: {
32
+ border: '1px solid #bbf7d0',
33
+ backgroundColor: '#f0fdf4',
34
+ color: '#166534'
35
+ },
36
+ warning: {
37
+ border: '1px solid #fef9c3',
38
+ backgroundColor: '#fefce8',
39
+ color: '#854d0e'
40
+ },
41
+ error: {
42
+ border: '1px solid #fecaca',
43
+ backgroundColor: '#fef2f2',
44
+ color: '#991b1b'
45
+ }
15
46
  }
16
47
 
17
- const icons = {
48
+ const darkStyles: Record<string, React.CSSProperties> = {
49
+ info: {
50
+ border: '1px solid rgba(30, 58, 138, 0.15)',
51
+ backgroundColor: 'rgba(30, 58, 138, 0.1)',
52
+ color: '#bfdbfe'
53
+ },
54
+ success: {
55
+ border: '1px solid rgba(22, 101, 52, 0.15)',
56
+ backgroundColor: 'rgba(22, 101, 52, 0.1)',
57
+ color: '#bbf7d0'
58
+ },
59
+ warning: {
60
+ border: '1px solid rgba(133, 77, 14, 0.15)',
61
+ backgroundColor: 'rgba(133, 77, 14, 0.1)',
62
+ color: '#fef9c3'
63
+ },
64
+ error: {
65
+ border: '1px solid rgba(153, 27, 27, 0.2)',
66
+ backgroundColor: 'rgba(153, 27, 27, 0.15)',
67
+ color: '#fecaca'
68
+ }
69
+ }
70
+
71
+ const defaultIcons = {
18
72
  info: 'ℹ️',
19
73
  success: '✅',
20
74
  warning: '⚠️',
21
75
  error: '❌'
22
76
  }
23
77
 
78
+ // 判断 icon 的类型并渲染
79
+ const renderIcon = () => {
80
+ if (icon === undefined) {
81
+ return defaultIcons[type]
82
+ }
83
+
84
+ if (React.isValidElement(icon)) {
85
+ // 如果是 React 元素(如 SVG 组件)
86
+ const iconElement = icon as React.ReactElement<any>
87
+ return React.cloneElement(iconElement, {
88
+ style: {
89
+ display: 'inline-block',
90
+ verticalAlign: 'middle',
91
+ width: '1.25rem',
92
+ height: '1.25rem',
93
+ marginRight: '0.5rem',
94
+ ...(iconElement.props?.style || {})
95
+ }
96
+ })
97
+ }
98
+
99
+ if (typeof icon === 'string' && icon.startsWith('/')) {
100
+ // 如果是路径字符串,渲染为图片
101
+ return (
102
+ <img
103
+ src={icon}
104
+ alt=""
105
+ style={{
106
+ display: 'inline-block',
107
+ verticalAlign: 'middle',
108
+ width: '1.25rem',
109
+ height: '1.25rem',
110
+ marginRight: '0.5rem'
111
+ }}
112
+ />
113
+ )
114
+ }
115
+
116
+ // 否则作为字符串渲染
117
+ return icon
118
+ }
119
+
24
120
  return (
25
- <div className={`my-4 rounded-lg border p-4 ${styles[type]}`}>
26
- {title && <div className="mb-2 font-semibold">{icons[type]} {title}</div>}
121
+ <div style={{
122
+ margin: '1rem 0',
123
+ borderRadius: '0.5rem',
124
+ border: '1px solid',
125
+ padding: '1rem',
126
+ ...(isDarkMode ? darkStyles[type] : styles[type])
127
+ }}>
128
+ {title && (
129
+ <div style={{
130
+ marginBottom: '0.5rem',
131
+ fontWeight: '600',
132
+ display: 'flex',
133
+ alignItems: 'center'
134
+ }}>
135
+ {renderIcon()}
136
+ <span>{title}</span>
137
+ </div>
138
+ )}
27
139
  <div>{children}</div>
28
140
  </div>
29
141
  )
@@ -10,16 +10,74 @@ interface BadgeListProps {
10
10
  }
11
11
 
12
12
  function Badge({ variant = 'default', children }: BadgeProps) {
13
- const styles = {
14
- default: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200',
15
- success: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200',
16
- warning: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200',
17
- error: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200',
18
- info: 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200'
13
+ const [isDarkMode, setIsDarkMode] = React.useState(false)
14
+
15
+ React.useEffect(() => {
16
+ setIsDarkMode(document.documentElement.classList.contains('dark'))
17
+ const observer = new MutationObserver(() => {
18
+ setIsDarkMode(document.documentElement.classList.contains('dark'))
19
+ })
20
+ observer.observe(document.documentElement, {
21
+ attributes: true,
22
+ attributeFilter: ['class']
23
+ })
24
+ return () => observer.disconnect()
25
+ }, [])
26
+
27
+ const styles: Record<string, React.CSSProperties> = {
28
+ default: {
29
+ backgroundColor: '#f3f4f6',
30
+ color: '#1f2937'
31
+ },
32
+ success: {
33
+ backgroundColor: '#dcfce7',
34
+ color: '#166534'
35
+ },
36
+ warning: {
37
+ backgroundColor: '#fef9c3',
38
+ color: '#854d0e'
39
+ },
40
+ error: {
41
+ backgroundColor: '#fee2e2',
42
+ color: '#991b1b'
43
+ },
44
+ info: {
45
+ backgroundColor: '#dbeafe',
46
+ color: '#1e40af'
47
+ }
48
+ }
49
+
50
+ const darkStyles: Record<string, React.CSSProperties> = {
51
+ default: {
52
+ backgroundColor: 'rgba(55, 65, 81, 0.2)',
53
+ color: '#e5e7eb'
54
+ },
55
+ success: {
56
+ backgroundColor: 'rgba(22, 101, 52, 0.2)',
57
+ color: '#bbf7d0'
58
+ },
59
+ warning: {
60
+ backgroundColor: 'rgba(133, 77, 14, 0.2)',
61
+ color: '#fef9c3'
62
+ },
63
+ error: {
64
+ backgroundColor: 'rgba(153, 27, 27, 0.2)',
65
+ color: '#fecaca'
66
+ },
67
+ info: {
68
+ backgroundColor: 'rgba(30, 58, 138, 0.2)',
69
+ color: '#bfdbfe'
70
+ }
19
71
  }
20
72
 
21
73
  return (
22
- <span className={`inline-block rounded-full px-3 py-1 text-sm ${styles[variant]}`}>
74
+ <span style={{
75
+ display: 'inline-block',
76
+ borderRadius: '9999px',
77
+ padding: '0.25rem 0.75rem',
78
+ fontSize: '0.875rem',
79
+ ...(isDarkMode ? darkStyles[variant] : styles[variant])
80
+ }}>
23
81
  {children}
24
82
  </span>
25
83
  )
@@ -27,8 +85,13 @@ function Badge({ variant = 'default', children }: BadgeProps) {
27
85
 
28
86
  export function BadgeList({ children }: BadgeListProps) {
29
87
  return (
30
- <div className="my-4 flex flex-wrap gap-2">
31
- {React.Children.map(children, child =>
88
+ <div style={{
89
+ margin: '1rem 0',
90
+ display: 'flex',
91
+ flexWrap: 'wrap',
92
+ gap: '0.5rem'
93
+ }}>
94
+ {React.Children.map(children, child =>
32
95
  React.isValidElement(child) ? child : null
33
96
  )}
34
97
  </div>
@@ -6,14 +6,58 @@ interface CalloutProps {
6
6
  }
7
7
 
8
8
  export function Callout({ variant = 'default', children }: CalloutProps) {
9
- const styles = {
10
- default: 'border-l-4 border-gray-500 bg-gray-50 dark:bg-gray-800',
11
- primary: 'border-l-4 border-blue-500 bg-blue-50 dark:bg-blue-950',
12
- secondary: 'border-l-4 border-purple-500 bg-purple-50 dark:bg-purple-950'
9
+ const [isDarkMode, setIsDarkMode] = React.useState(false)
10
+
11
+ React.useEffect(() => {
12
+ setIsDarkMode(document.documentElement.classList.contains('dark'))
13
+ const observer = new MutationObserver(() => {
14
+ setIsDarkMode(document.documentElement.classList.contains('dark'))
15
+ })
16
+ observer.observe(document.documentElement, {
17
+ attributes: true,
18
+ attributeFilter: ['class']
19
+ })
20
+ return () => observer.disconnect()
21
+ }, [])
22
+
23
+ const styles: Record<string, React.CSSProperties> = {
24
+ default: {
25
+ borderLeft: '4px solid #6b7280',
26
+ backgroundColor: '#f9fafb'
27
+ },
28
+ primary: {
29
+ borderLeft: '4px solid #3b82f6',
30
+ backgroundColor: '#eff6ff'
31
+ },
32
+ secondary: {
33
+ borderLeft: '4px solid #8b5cf6',
34
+ backgroundColor: '#faf5ff'
35
+ }
36
+ }
37
+
38
+ const darkStyles: Record<string, React.CSSProperties> = {
39
+ default: {
40
+ borderLeft: '4px solid rgba(75, 85, 99, 0.2)',
41
+ backgroundColor: 'rgba(17, 24, 39, 0.2)'
42
+ },
43
+ primary: {
44
+ borderLeft: '4px solid rgba(30, 58, 138, 0.2)',
45
+ backgroundColor: 'rgba(30, 58, 138, 0.2)'
46
+ },
47
+ secondary: {
48
+ borderLeft: '4px solid rgba(88, 28, 135, 0.2)',
49
+ backgroundColor: 'rgba(88, 28, 135, 0.2)'
50
+ }
13
51
  }
14
52
 
15
53
  return (
16
- <div className={`my-4 rounded-r-lg p-4 ${styles[variant]}`}>
54
+ <div style={{
55
+ margin: '1rem 0',
56
+ borderTopRightRadius: '0.5rem',
57
+ borderBottomRightRadius: '0.5rem',
58
+ padding: '1rem',
59
+ ...(isDarkMode ? darkStyles[variant] : styles[variant])
60
+ }}>
17
61
  {children}
18
62
  </div>
19
63
  )
@@ -6,10 +6,10 @@ interface FeatureProps {
6
6
 
7
7
  export function Feature({ icon = '🚀', title, description }: FeatureProps) {
8
8
  return (
9
- <div className="my-4 rounded-lg border border-gray-200 p-6 shadow-sm hover:shadow-md transition-shadow dark:border-gray-700">
9
+ <div className="my-4 rounded-lg border border-gray-200 p-6 shadow-sm hover:shadow-md transition-shadow dark:border-gray-600">
10
10
  <div className="mb-3 text-4xl">{icon}</div>
11
11
  <h3 className="mb-2 text-lg font-semibold">{title}</h3>
12
- <p className="text-gray-600 dark:text-gray-300">{description}</p>
12
+ <p className="text-gray-600 dark:text-gray-400">{description}</p>
13
13
  </div>
14
14
  )
15
15
  }
@@ -7,13 +7,13 @@ interface MyTipProps {
7
7
 
8
8
  export function MyTip({ title, children }: MyTipProps) {
9
9
  return (
10
- <div className="my-4 rounded-lg border border-green-200 bg-green-50 p-4 dark:border-green-800 dark:bg-green-950">
10
+ <div className="my-4 rounded-lg border border-green-200 bg-green-50 p-4 dark:border-green-800/60 dark:bg-green-950/80">
11
11
  {title && (
12
12
  <div className="mb-2 font-semibold text-green-900 dark:text-green-100">
13
13
  💡 {title}
14
14
  </div>
15
15
  )}
16
- <div className="text-green-800 dark:text-green-200">{children}</div>
16
+ <div className="text-green-800 dark:text-green-300">{children}</div>
17
17
  </div>
18
18
  )
19
19
  }
@@ -0,0 +1,3 @@
1
+ @import "tailwindcss";
2
+
3
+ @custom-variant dark (&:where(.dark, .dark *));
@@ -1,62 +0,0 @@
1
- import * as React from 'react'
2
-
3
- interface StepProps {
4
- step: number
5
- title: string
6
- children: React.ReactNode
7
- }
8
-
9
- interface StepListProps {
10
- children: React.ReactNode
11
- }
12
-
13
- function Step({ step, title, 'data-title': dataTitle, children }: StepProps & { 'data-title'?: string }) {
14
- // 优先使用 title,如果没有则使用 data-title
15
- const displayTitle = title || dataTitle
16
-
17
- return (
18
- <div className="relative pb-8 last:pb-0">
19
- <div className="absolute left-0 top-0 flex h-8 w-8 items-center justify-center rounded-full bg-blue-500 text-sm font-bold text-white">
20
- {step}
21
- </div>
22
- <div className="ml-12">
23
- <h4 className="mb-2 font-semibold">{displayTitle}</h4>
24
- <div className="text-gray-600 dark:text-gray-300">{children}</div>
25
- </div>
26
- </div>
27
- )
28
- }
29
-
30
- export function StepList({ children }: StepListProps) {
31
- const steps = React.Children.toArray(children).filter(
32
- (child): child is React.ReactElement<StepProps> => {
33
- if (!React.isValidElement(child)) return false
34
-
35
- const childProps = child.props as any
36
-
37
- // 检查 props 中是否有 data-title 属性(通过我们的转换,title 变成了 data-title)
38
- if (childProps && Object.prototype.hasOwnProperty.call(childProps, 'data-title')) return true
39
-
40
- // 检查 props 中是否有 node.tagName === 'steplist-step'
41
- if (childProps?.node?.tagName === 'steplist-step') return true
42
-
43
- // 检查 props 中是否有 title 属性(直接使用的情况)
44
- if (childProps && Object.prototype.hasOwnProperty.call(childProps, 'title')) return true
45
-
46
- return false
47
- }
48
- )
49
-
50
- return (
51
- <div className="my-4 rounded-lg border border-gray-200 p-6 dark:border-gray-700">
52
- {steps.map((step, index) =>
53
- React.cloneElement(step, {
54
- key: index,
55
- step: index + 1
56
- })
57
- )}
58
- </div>
59
- )
60
- }
61
-
62
- StepList.Step = Step