@easy-editor/materials-dashboard-number-flip 0.0.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 (44) hide show
  1. package/.vite/plugins/vite-plugin-external-deps.ts +224 -0
  2. package/.vite/plugins/vite-plugin-material-dev.ts +218 -0
  3. package/CHANGELOG.md +7 -0
  4. package/LICENSE +9 -0
  5. package/dist/component.esm.js +167 -0
  6. package/dist/component.esm.js.map +1 -0
  7. package/dist/component.js +176 -0
  8. package/dist/component.js.map +1 -0
  9. package/dist/component.min.js +2 -0
  10. package/dist/component.min.js.map +1 -0
  11. package/dist/index.cjs +573 -0
  12. package/dist/index.cjs.map +1 -0
  13. package/dist/index.esm.js +570 -0
  14. package/dist/index.esm.js.map +1 -0
  15. package/dist/index.js +578 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/index.min.js +2 -0
  18. package/dist/index.min.js.map +1 -0
  19. package/dist/meta.esm.js +407 -0
  20. package/dist/meta.esm.js.map +1 -0
  21. package/dist/meta.js +418 -0
  22. package/dist/meta.js.map +1 -0
  23. package/dist/meta.min.js +2 -0
  24. package/dist/meta.min.js.map +1 -0
  25. package/dist/src/component.d.ts +43 -0
  26. package/dist/src/configure.d.ts +7 -0
  27. package/dist/src/constants.d.ts +16 -0
  28. package/dist/src/index.d.ts +6 -0
  29. package/dist/src/meta.d.ts +7 -0
  30. package/dist/src/snippets.d.ts +7 -0
  31. package/package.json +65 -0
  32. package/rollup.config.js +222 -0
  33. package/src/component.module.css +56 -0
  34. package/src/component.tsx +179 -0
  35. package/src/configure.ts +342 -0
  36. package/src/constants.ts +18 -0
  37. package/src/index.tsx +7 -0
  38. package/src/meta.ts +28 -0
  39. package/src/snippets.ts +80 -0
  40. package/src/type.d.ts +8 -0
  41. package/tsconfig.build.json +12 -0
  42. package/tsconfig.json +9 -0
  43. package/tsconfig.test.json +7 -0
  44. package/vite.config.ts +54 -0
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@easy-editor/materials-dashboard-number-flip",
3
+ "version": "0.0.2",
4
+ "description": "Number Flip component for EasyEditor dashboard",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.esm.js",
12
+ "require": "./dist/index.cjs"
13
+ }
14
+ },
15
+ "publishConfig": {
16
+ "access": "public",
17
+ "jsdelivr": "dist/index.min.js",
18
+ "registry": "https://registry.npmjs.org/"
19
+ },
20
+ "homepage": "https://github.com/Easy-Editor/EasyMaterials",
21
+ "license": "MIT",
22
+ "author": "JinSo <kimjinso@qq.com>",
23
+ "keywords": [
24
+ "@easy-editor",
25
+ "easyeditor",
26
+ "low-code",
27
+ "dashboard",
28
+ "number-flip",
29
+ "component",
30
+ "react"
31
+ ],
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/Easy-Editor/EasyMaterials",
35
+ "directory": "packages/dashboard/number-flip"
36
+ },
37
+ "bugs": {
38
+ "url": "https://github.com/Easy-Editor/EasyMaterials/issues"
39
+ },
40
+ "peerDependencies": {
41
+ "@easy-editor/core": "*",
42
+ "react": "^18 || ^19",
43
+ "react-dom": "^18 || ^19",
44
+ "@types/react": "^18 || ^19",
45
+ "@types/react-dom": "^18 || ^19"
46
+ },
47
+ "dependencies": {
48
+ "@easy-editor/materials-shared": "0.0.0"
49
+ },
50
+ "scripts": {
51
+ "dev": "vite",
52
+ "dev:debug": "vite --port 5024",
53
+ "format": "biome format --write .",
54
+ "lint": "biome check .",
55
+ "build": "npm-run-all -nl build:*",
56
+ "build:clean": "rimraf dist/",
57
+ "build:js": "rollup -c",
58
+ "build:types": "pnpm types",
59
+ "types": "npm-run-all -nl types:*",
60
+ "types:src": "tsc --project tsconfig.build.json",
61
+ "test-types": "tsc --project tsconfig.test.json"
62
+ },
63
+ "module": "dist/index.esm.js",
64
+ "unpkg": "dist/index.min.js"
65
+ }
@@ -0,0 +1,222 @@
1
+ import babel from '@rollup/plugin-babel'
2
+ import commonjs from '@rollup/plugin-commonjs'
3
+ import nodeResolve from '@rollup/plugin-node-resolve'
4
+ import json from '@rollup/plugin-json'
5
+ import { terser } from 'rollup-plugin-terser'
6
+ import cleanup from 'rollup-plugin-cleanup'
7
+ import postcss from 'rollup-plugin-postcss'
8
+ import pkg from './package.json' with { type: 'json' }
9
+
10
+ const GLOBAL_NAME = 'EasyEditorMaterialsStatisticNumber'
11
+
12
+ // 外部依赖(不打包进组件)
13
+ const external = ['react', 'react-dom', 'react/jsx-runtime', '@easy-editor/core']
14
+
15
+ const globals = {
16
+ react: 'React',
17
+ 'react-dom': 'ReactDOM',
18
+ 'react/jsx-runtime': 'jsxRuntime',
19
+ '@easy-editor/core': 'EasyEditorCore',
20
+ }
21
+
22
+ const plugins = [
23
+ nodeResolve({
24
+ extensions: ['.js', '.ts', '.jsx', '.tsx'],
25
+ }),
26
+ commonjs(),
27
+ json(),
28
+ postcss({
29
+ modules: {
30
+ generateScopedName: '[name]__[local]___[hash:base64:5]',
31
+ },
32
+ autoModules: true,
33
+ minimize: true,
34
+ inject: true,
35
+ }),
36
+ babel({
37
+ extensions: ['.js', '.ts', '.jsx', '.tsx'],
38
+ exclude: 'node_modules/**',
39
+ babelrc: false,
40
+ babelHelpers: 'bundled',
41
+ presets: [
42
+ ['@babel/preset-react', { runtime: 'automatic' }],
43
+ [
44
+ '@babel/preset-typescript',
45
+ {
46
+ allowDeclareFields: true,
47
+ },
48
+ ],
49
+ ],
50
+ }),
51
+ cleanup({
52
+ comments: ['some', /PURE/],
53
+ extensions: ['.js', '.ts'],
54
+ }),
55
+ ]
56
+
57
+ export default [
58
+ /* ---------------------------------- 元数据构建 --------------------------------- */
59
+ // 元数据 ESM 构建(用于动态 import)
60
+ {
61
+ input: 'src/meta.ts',
62
+ output: [
63
+ {
64
+ file: 'dist/meta.esm.js',
65
+ format: 'esm',
66
+ sourcemap: true,
67
+ banner: `/* @easy-editor/materials-dashboard-statistic-number v${pkg.version} (meta, esm) */`,
68
+ exports: 'named',
69
+ },
70
+ ],
71
+ plugins,
72
+ external,
73
+ },
74
+ // 元数据 UMD 构建(备用方案)
75
+ {
76
+ input: 'src/meta.ts',
77
+ output: [
78
+ {
79
+ file: 'dist/meta.js',
80
+ format: 'umd',
81
+ name: `${GLOBAL_NAME}Meta`,
82
+ globals,
83
+ sourcemap: true,
84
+ banner: `/* @easy-editor/materials-dashboard-statistic-number v${pkg.version} (meta) */`,
85
+ exports: 'named',
86
+ },
87
+ ],
88
+ plugins,
89
+ external,
90
+ },
91
+ // 元数据压缩版本(UMD,备用方案)
92
+ {
93
+ input: 'src/meta.ts',
94
+ output: [
95
+ {
96
+ file: 'dist/meta.min.js',
97
+ format: 'umd',
98
+ name: `${GLOBAL_NAME}Meta`,
99
+ globals,
100
+ sourcemap: true,
101
+ banner: `/* @easy-editor/materials-dashboard-statistic-number v${pkg.version} (meta, minified) */`,
102
+ exports: 'named',
103
+ },
104
+ ],
105
+ plugins: [...plugins, terser()],
106
+ external,
107
+ },
108
+
109
+ /* ---------------------------------- 组件构建 ---------------------------------- */
110
+ // 组件 ESM 构建(用于动态 import)
111
+ {
112
+ input: 'src/component.tsx',
113
+ output: [
114
+ {
115
+ file: 'dist/component.esm.js',
116
+ format: 'esm',
117
+ sourcemap: true,
118
+ banner: `/* @easy-editor/materials-dashboard-statistic-number v${pkg.version} (component, esm) */`,
119
+ exports: 'named',
120
+ },
121
+ ],
122
+ plugins,
123
+ external,
124
+ },
125
+ // 组件 UMD 构建(备用方案)
126
+ {
127
+ input: 'src/component.tsx',
128
+ output: [
129
+ {
130
+ file: 'dist/component.js',
131
+ format: 'umd',
132
+ name: `${GLOBAL_NAME}Component`,
133
+ globals,
134
+ sourcemap: true,
135
+ banner: `/* @easy-editor/materials-dashboard-statistic-number v${pkg.version} (component) */`,
136
+ exports: 'named',
137
+ },
138
+ ],
139
+ plugins,
140
+ external,
141
+ },
142
+ // 组件压缩版本(UMD,备用方案)
143
+ {
144
+ input: 'src/component.tsx',
145
+ output: [
146
+ {
147
+ file: 'dist/component.min.js',
148
+ format: 'umd',
149
+ name: `${GLOBAL_NAME}Component`,
150
+ globals,
151
+ sourcemap: true,
152
+ banner: `/* @easy-editor/materials-dashboard-statistic-number v${pkg.version} (component, minified) */`,
153
+ exports: 'named',
154
+ },
155
+ ],
156
+ plugins: [...plugins, terser()],
157
+ external,
158
+ },
159
+
160
+ /* ---------------------------------- 完整构建 ---------------------------------- */
161
+ // UMD 构建(用于 CDN 和浏览器)
162
+ {
163
+ input: 'src/index.tsx',
164
+ output: [
165
+ {
166
+ file: 'dist/index.js',
167
+ format: 'umd',
168
+ name: GLOBAL_NAME,
169
+ globals,
170
+ sourcemap: true,
171
+ banner: `/* @easy-editor/materials-dashboard-statistic-number v${pkg.version} */`,
172
+ exports: 'named',
173
+ },
174
+ ],
175
+ plugins,
176
+ external,
177
+ },
178
+ // ESM 构建(用于现代打包工具)
179
+ {
180
+ input: 'src/index.tsx',
181
+ output: [
182
+ {
183
+ file: 'dist/index.esm.js',
184
+ format: 'esm',
185
+ sourcemap: true,
186
+ },
187
+ ],
188
+ plugins,
189
+ external,
190
+ },
191
+ // CJS 构建(用于 Node.js)
192
+ {
193
+ input: 'src/index.tsx',
194
+ output: [
195
+ {
196
+ file: 'dist/index.cjs',
197
+ format: 'cjs',
198
+ sourcemap: true,
199
+ exports: 'named',
200
+ },
201
+ ],
202
+ plugins,
203
+ external,
204
+ },
205
+ // 压缩版本(用于生产环境)
206
+ {
207
+ input: 'src/index.tsx',
208
+ output: [
209
+ {
210
+ file: 'dist/index.min.js',
211
+ format: 'umd',
212
+ name: GLOBAL_NAME,
213
+ globals,
214
+ sourcemap: true,
215
+ banner: `/* @easy-editor/materials-dashboard-statistic-number v${pkg.version} (minified) */`,
216
+ exports: 'named',
217
+ },
218
+ ],
219
+ plugins: [...plugins, terser()],
220
+ external,
221
+ },
222
+ ]
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Number Flip Component Styles
3
+ * 数字翻牌组件样式
4
+ */
5
+
6
+ .container {
7
+ box-sizing: border-box;
8
+ display: flex;
9
+ flex-direction: column;
10
+ align-items: center;
11
+ justify-content: center;
12
+ width: 100%;
13
+ height: 100%;
14
+ gap: 8px;
15
+ }
16
+
17
+ .content {
18
+ display: flex;
19
+ align-items: baseline;
20
+ gap: 4px;
21
+ }
22
+
23
+ .prefix {
24
+ font-weight: 600;
25
+ opacity: 0.8;
26
+ }
27
+
28
+ .prefixDigital {
29
+ font-family: "Courier New", Courier, monospace;
30
+ }
31
+
32
+ .value {
33
+ font-weight: 700;
34
+ }
35
+
36
+ .valueDigital {
37
+ font-family: "Courier New", Courier, monospace;
38
+ letter-spacing: 0.05em;
39
+ }
40
+
41
+ .suffix {
42
+ margin-left: 4px;
43
+ font-weight: 500;
44
+ opacity: 0.7;
45
+ }
46
+
47
+ .suffixDigital {
48
+ font-family: "Courier New", Courier, monospace;
49
+ }
50
+
51
+ .trend {
52
+ display: flex;
53
+ align-items: center;
54
+ gap: 4px;
55
+ font-weight: 500;
56
+ }
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Number Flip Component
3
+ * 数字翻牌组件 - 用于展示 KPI、统计数字等
4
+ */
5
+
6
+ import type { CSSProperties, Ref } from 'react'
7
+ import { cn } from '@easy-editor/materials-shared'
8
+ import styles from './component.module.css'
9
+
10
+ export type TrendType = 'up' | 'down' | 'flat'
11
+
12
+ export interface NumberFlipProps {
13
+ ref?: Ref<HTMLDivElement>
14
+ /** 数值 */
15
+ value?: number
16
+ /** 小数位数 */
17
+ decimals?: number
18
+ /** 是否显示千分位分隔符 */
19
+ separator?: boolean
20
+ /** 前缀 */
21
+ prefix?: string
22
+ /** 后缀 */
23
+ suffix?: string
24
+ /** 字体大小 */
25
+ fontSize?: number
26
+ /** 字体类型 */
27
+ fontFamily?: 'digital' | 'default'
28
+ /** 颜色 */
29
+ color?: string
30
+ /** 发光强度 (0-2) */
31
+ glowIntensity?: number
32
+ /** 是否显示趋势 */
33
+ trendEnable?: boolean
34
+ /** 趋势值 */
35
+ trendValue?: number
36
+ /** 趋势类型 */
37
+ trendType?: TrendType
38
+ /** 趋势后缀 */
39
+ trendSuffix?: string
40
+ /** 趋势上升颜色 */
41
+ trendUpColor?: string
42
+ /** 趋势下降颜色 */
43
+ trendDownColor?: string
44
+ /** 外部样式 */
45
+ style?: CSSProperties
46
+ }
47
+
48
+ const formatNumber = (value: number, decimals: number, separator: boolean): string => {
49
+ const fixed = value.toFixed(decimals)
50
+ if (!separator) {
51
+ return fixed
52
+ }
53
+
54
+ const [intPart, decPart] = fixed.split('.')
55
+ const formattedInt = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
56
+ return decPart ? `${formattedInt}.${decPart}` : formattedInt
57
+ }
58
+
59
+ const TrendIndicator: React.FC<{
60
+ type: TrendType
61
+ value: number
62
+ suffix: string
63
+ upColor: string
64
+ downColor: string
65
+ size: number
66
+ }> = ({ type, value, suffix, upColor, downColor, size }) => {
67
+ let color = '#8899aa'
68
+ if (type === 'up') {
69
+ color = upColor
70
+ } else if (type === 'down') {
71
+ color = downColor
72
+ }
73
+
74
+ return (
75
+ <div className={styles.trend} style={{ fontSize: size * 0.35 }}>
76
+ {type !== 'flat' && (
77
+ <svg
78
+ aria-label={`Trend ${type}`}
79
+ fill='none'
80
+ height={size * 0.3}
81
+ role='img'
82
+ style={{
83
+ transform: type === 'down' ? 'rotate(180deg)' : undefined,
84
+ }}
85
+ viewBox='0 0 24 24'
86
+ width={size * 0.3}
87
+ >
88
+ <title>Trend arrow {type}</title>
89
+ <path d='M12 4L20 14H4L12 4Z' fill={color} />
90
+ </svg>
91
+ )}
92
+ {type === 'flat' && <span style={{ color, marginRight: 4 }}>—</span>}
93
+ <span style={{ color }}>
94
+ {value}
95
+ {suffix}
96
+ </span>
97
+ </div>
98
+ )
99
+ }
100
+
101
+ export const NumberFlip: React.FC<NumberFlipProps> = ({
102
+ ref,
103
+ value = 0,
104
+ decimals = 0,
105
+ separator = true,
106
+ prefix = '',
107
+ suffix = '',
108
+ fontSize = 48,
109
+ fontFamily = 'digital',
110
+ color = '#00d4ff',
111
+ glowIntensity = 0.5,
112
+ trendEnable = false,
113
+ trendValue = 0,
114
+ trendType = 'up',
115
+ trendSuffix = '%',
116
+ trendUpColor = '#52c41a',
117
+ trendDownColor = '#ff4d4f',
118
+ style: externalStyle,
119
+ }) => {
120
+ const isDigital = fontFamily === 'digital'
121
+ const formattedValue = formatNumber(value, decimals, separator)
122
+
123
+ // 计算发光效果的 text-shadow
124
+ const glowShadow =
125
+ glowIntensity > 0
126
+ ? `0 0 ${10 * glowIntensity}px ${color}, 0 0 ${20 * glowIntensity}px ${color}40, 0 0 ${30 * glowIntensity}px ${color}20`
127
+ : 'none'
128
+
129
+ return (
130
+ <div className={styles.container} ref={ref} style={externalStyle}>
131
+ <div className={styles.content}>
132
+ {prefix ? (
133
+ <span
134
+ className={cn(styles.prefix, isDigital && styles.prefixDigital)}
135
+ style={{
136
+ fontSize: `${fontSize * 0.5}px`,
137
+ color,
138
+ }}
139
+ >
140
+ {prefix}
141
+ </span>
142
+ ) : null}
143
+ <span
144
+ className={cn(styles.value, isDigital && styles.valueDigital)}
145
+ style={{
146
+ fontSize: `${fontSize}px`,
147
+ color,
148
+ textShadow: glowShadow,
149
+ }}
150
+ >
151
+ {formattedValue}
152
+ </span>
153
+ {suffix ? (
154
+ <span
155
+ className={cn(styles.suffix, isDigital && styles.suffixDigital)}
156
+ style={{
157
+ fontSize: `${fontSize * 0.4}px`,
158
+ color,
159
+ }}
160
+ >
161
+ {suffix}
162
+ </span>
163
+ ) : null}
164
+ </div>
165
+ {trendEnable ? (
166
+ <TrendIndicator
167
+ downColor={trendDownColor}
168
+ size={fontSize}
169
+ suffix={trendSuffix}
170
+ type={trendType}
171
+ upColor={trendUpColor}
172
+ value={trendValue}
173
+ />
174
+ ) : null}
175
+ </div>
176
+ )
177
+ }
178
+
179
+ export default NumberFlip