@aspire-ui/element-component-pro 1.0.6 → 1.0.8

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.
@@ -0,0 +1,118 @@
1
+ /** 进位方式:向下取整、向上取整、四舍五入 */
2
+ export type FormattedNumberRounding = 'floor' | 'ceil' | 'round'
3
+
4
+ /** 仅保留数字、至多一个小数点、可选前导负号 */
5
+ export function sanitizeNumericInput(raw: string): string {
6
+ const t = raw.trim()
7
+ if (!t) return ''
8
+ let i = 0
9
+ let res = ''
10
+ if (t[0] === '-') {
11
+ res = '-'
12
+ i = 1
13
+ }
14
+ let dot = false
15
+ for (; i < t.length; i++) {
16
+ const c = t[i]
17
+ if (c >= '0' && c <= '9') {
18
+ res += c
19
+ continue
20
+ }
21
+ if (c === '.' && !dot) {
22
+ dot = true
23
+ if (res === '' || res === '-') res += '0'
24
+ res += '.'
25
+ }
26
+ }
27
+ return res
28
+ }
29
+
30
+ export function stripNumberGrouping(s: string): string {
31
+ return s.replace(/,/g, '').trim()
32
+ }
33
+
34
+ function maxAbsValue(integerDigits: number, decimalPlaces: number): number {
35
+ const maxInt = Math.pow(10, integerDigits) - 1
36
+ if (decimalPlaces <= 0) return maxInt
37
+ return maxInt + (1 - Math.pow(10, -decimalPlaces))
38
+ }
39
+
40
+ /** 按整数位数上限约束绝对值 */
41
+ export function clampByIntegerDigits(
42
+ value: number,
43
+ integerDigits: number,
44
+ decimalPlaces: number
45
+ ): number {
46
+ const max = maxAbsValue(integerDigits, decimalPlaces)
47
+ const sign = value < 0 ? -1 : 1
48
+ const abs = Math.abs(value)
49
+ if (abs <= max) return value
50
+ return sign * max
51
+ }
52
+
53
+ export function roundToDecimals(
54
+ value: number,
55
+ decimalPlaces: number,
56
+ rounding: FormattedNumberRounding
57
+ ): number {
58
+ if (decimalPlaces <= 0) {
59
+ switch (rounding) {
60
+ case 'floor':
61
+ return Math.floor(value)
62
+ case 'ceil':
63
+ return Math.ceil(value)
64
+ default:
65
+ return Math.round(value)
66
+ }
67
+ }
68
+ const factor = Math.pow(10, decimalPlaces)
69
+ const x = value * factor
70
+ let y: number
71
+ switch (rounding) {
72
+ case 'floor':
73
+ y = Math.floor(x)
74
+ break
75
+ case 'ceil':
76
+ y = Math.ceil(x)
77
+ break
78
+ default:
79
+ y = Math.round(x)
80
+ }
81
+ return y / factor
82
+ }
83
+
84
+ /**
85
+ * 解析 → 按整数位夹紧 → 按小数位与进位方式舍入 → 再夹紧(防止舍入后越界)
86
+ */
87
+ export function normalizeNumericValue(
88
+ value: number,
89
+ integerDigits: number,
90
+ decimalPlaces: number,
91
+ rounding: FormattedNumberRounding
92
+ ): number {
93
+ let v = clampByIntegerDigits(value, integerDigits, decimalPlaces)
94
+ v = roundToDecimals(v, decimalPlaces, rounding)
95
+ v = clampByIntegerDigits(v, integerDigits, decimalPlaces)
96
+ return v
97
+ }
98
+
99
+ /** 千分位格式化展示(整数部分),小数部分固定 m 位 */
100
+ export function formatWithThousands(value: number, decimalPlaces: number): string {
101
+ if (Number.isNaN(value) || !Number.isFinite(value)) return ''
102
+ const fixed = value.toFixed(Math.max(0, decimalPlaces))
103
+ const neg = fixed.startsWith('-')
104
+ const body = neg ? fixed.slice(1) : fixed
105
+ const [intPart, decPart] = body.split('.')
106
+ const withSep = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
107
+ if (decimalPlaces <= 0 || decPart === undefined) return (neg ? '-' : '') + withSep
108
+ return (neg ? '-' : '') + withSep + '.' + decPart
109
+ }
110
+
111
+ /** 编辑态:无千分位,去掉多余尾部 0(在 m 位精度内) */
112
+ export function numberToEditString(value: number, decimalPlaces: number): string {
113
+ if (Number.isNaN(value) || !Number.isFinite(value)) return ''
114
+ let s = value.toFixed(Math.max(0, decimalPlaces))
115
+ s = s.replace(/(\.\d*?)0+$/, '$1')
116
+ s = s.replace(/\.$/, '')
117
+ return s
118
+ }
@@ -0,0 +1,56 @@
1
+ export type TooltipValue = boolean | string | Record<string, unknown>
2
+
3
+ export const hasTooltipContent = (value: unknown): boolean => {
4
+ if (Array.isArray(value)) return value.length > 0
5
+ return value !== undefined && value !== null && String(value).trim() !== ''
6
+ }
7
+
8
+ export const getTooltipContent = (value: unknown): string => {
9
+ if (Array.isArray(value)) {
10
+ return value.map((item) => String(item)).join(', ')
11
+ }
12
+ if (value === undefined || value === null) return ''
13
+ if (typeof value === 'object') return JSON.stringify(value)
14
+ return String(value)
15
+ }
16
+
17
+ export const normalizeTooltipConfig = (
18
+ tooltip: TooltipValue | null | undefined,
19
+ fallbackValue?: unknown
20
+ ): Record<string, unknown> | null => {
21
+ if (!tooltip) return null
22
+
23
+ if (tooltip === true) {
24
+ return {
25
+ content: getTooltipContent(fallbackValue),
26
+ placement: 'top',
27
+ effect: 'dark',
28
+ disabled: !hasTooltipContent(fallbackValue),
29
+ }
30
+ }
31
+
32
+ if (typeof tooltip === 'string') {
33
+ return {
34
+ content: tooltip,
35
+ placement: 'top',
36
+ effect: 'dark',
37
+ }
38
+ }
39
+
40
+ const normalized = { ...tooltip }
41
+ const hasExplicitContent = Object.prototype.hasOwnProperty.call(normalized, 'content')
42
+ if (!hasExplicitContent) {
43
+ normalized.content = getTooltipContent(fallbackValue)
44
+ }
45
+ if (!Object.prototype.hasOwnProperty.call(normalized, 'placement')) {
46
+ normalized.placement = 'top'
47
+ }
48
+ if (!Object.prototype.hasOwnProperty.call(normalized, 'effect')) {
49
+ normalized.effect = 'dark'
50
+ }
51
+ if (!Object.prototype.hasOwnProperty.call(normalized, 'disabled')) {
52
+ normalized.disabled = !hasTooltipContent(normalized.content)
53
+ }
54
+
55
+ return normalized
56
+ }
package/src/vite-env.d.ts CHANGED
@@ -1 +1,6 @@
1
1
  /// <reference types="vite/client" />
2
+
3
+ declare module '*.md?raw' {
4
+ const content: string
5
+ export default content
6
+ }