@wallarm-org/design-system 1.3.0 → 1.4.0
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/dist/components/FormatNumber/FormatNumber.d.ts +32 -0
- package/dist/components/FormatNumber/FormatNumber.js +122 -0
- package/dist/components/FormatNumber/index.d.ts +1 -0
- package/dist/components/FormatNumber/index.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/metadata/components.json +347 -2
- package/dist/utils/abbreviateNumber.d.ts +18 -2
- package/dist/utils/abbreviateNumber.js +62 -4
- package/package.json +1 -1
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { FC, HTMLAttributes, Ref } from 'react';
|
|
2
|
+
import type { TestableProps } from '../../utils/testId';
|
|
3
|
+
type FormatNumberNotation = 'compact' | 'standard';
|
|
4
|
+
type FormatNumberType = 'decimal' | 'percent' | 'byte';
|
|
5
|
+
interface FormatNumberBaseProps {
|
|
6
|
+
/** Numeric value to display. null/undefined renders em dash + "No data" tooltip. */
|
|
7
|
+
value: number | null | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Formatting category. Default: 'decimal'.
|
|
10
|
+
* - 'decimal': plain number with optional abbreviation
|
|
11
|
+
* - 'percent': percentage with boundary safety
|
|
12
|
+
* - 'byte': decimal byte units: 512 B, 2.3 GB
|
|
13
|
+
*/
|
|
14
|
+
type?: FormatNumberType;
|
|
15
|
+
/**
|
|
16
|
+
* 'compact' abbreviates (12k, 59.6M); 'standard' shows full value.
|
|
17
|
+
* Default: 'compact'. Only applies to type='decimal' and type='byte'.
|
|
18
|
+
*/
|
|
19
|
+
notation?: FormatNumberNotation;
|
|
20
|
+
/**
|
|
21
|
+
* Unit label for accessible name + tooltip: "requests", "errors".
|
|
22
|
+
* Appended after a space. Only meaningful for type='decimal'.
|
|
23
|
+
*/
|
|
24
|
+
unit?: string;
|
|
25
|
+
/** Decimal places for percent. Default: 0. */
|
|
26
|
+
decimals?: number;
|
|
27
|
+
ref?: Ref<HTMLSpanElement>;
|
|
28
|
+
}
|
|
29
|
+
type FormatNumberNativeProps = Omit<HTMLAttributes<HTMLSpanElement>, 'className'>;
|
|
30
|
+
export type FormatNumberProps = FormatNumberNativeProps & FormatNumberBaseProps & TestableProps;
|
|
31
|
+
export declare const FormatNumber: FC<FormatNumberProps>;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { abbreviateNumber, formatBytes, formatFullNumber, formatPercent } from "../../utils/abbreviateNumber.js";
|
|
3
|
+
import { cn } from "../../utils/cn.js";
|
|
4
|
+
import { Text } from "../Text/index.js";
|
|
5
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "../Tooltip/index.js";
|
|
6
|
+
const DASHED_UNDERLINE = 'border-b-1 border-dashed border-border-strong-primary';
|
|
7
|
+
const FormatNumber = ({ value, type = 'decimal', notation = 'compact', unit, decimals = 0, ref, ...props })=>{
|
|
8
|
+
if (null == value) return /*#__PURE__*/ jsxs(Tooltip, {
|
|
9
|
+
children: [
|
|
10
|
+
/*#__PURE__*/ jsx(TooltipTrigger, {
|
|
11
|
+
asChild: true,
|
|
12
|
+
children: /*#__PURE__*/ jsx("span", {
|
|
13
|
+
ref: ref,
|
|
14
|
+
"data-slot": "format-number",
|
|
15
|
+
...props,
|
|
16
|
+
children: /*#__PURE__*/ jsx(Text, {
|
|
17
|
+
size: "sm",
|
|
18
|
+
color: "secondary",
|
|
19
|
+
children: "—"
|
|
20
|
+
})
|
|
21
|
+
})
|
|
22
|
+
}),
|
|
23
|
+
/*#__PURE__*/ jsx(TooltipContent, {
|
|
24
|
+
children: "No data"
|
|
25
|
+
})
|
|
26
|
+
]
|
|
27
|
+
});
|
|
28
|
+
if (!Number.isFinite(value)) return /*#__PURE__*/ jsx("span", {
|
|
29
|
+
ref: ref,
|
|
30
|
+
"data-slot": "format-number",
|
|
31
|
+
...props,
|
|
32
|
+
children: /*#__PURE__*/ jsx(Text, {
|
|
33
|
+
size: "sm",
|
|
34
|
+
color: "secondary",
|
|
35
|
+
children: "—"
|
|
36
|
+
})
|
|
37
|
+
});
|
|
38
|
+
if ('percent' === type) return /*#__PURE__*/ jsx("span", {
|
|
39
|
+
ref: ref,
|
|
40
|
+
"data-slot": "format-number",
|
|
41
|
+
...props,
|
|
42
|
+
children: /*#__PURE__*/ jsx(Text, {
|
|
43
|
+
size: "sm",
|
|
44
|
+
children: formatPercent(value, decimals)
|
|
45
|
+
})
|
|
46
|
+
});
|
|
47
|
+
if ('byte' === type) {
|
|
48
|
+
const { display, full } = formatBytes(value);
|
|
49
|
+
const isAbbreviated = 'compact' === notation && value >= 1000;
|
|
50
|
+
if (isAbbreviated) return /*#__PURE__*/ jsxs(Tooltip, {
|
|
51
|
+
children: [
|
|
52
|
+
/*#__PURE__*/ jsx(TooltipTrigger, {
|
|
53
|
+
asChild: true,
|
|
54
|
+
children: /*#__PURE__*/ jsx("span", {
|
|
55
|
+
ref: ref,
|
|
56
|
+
"data-slot": "format-number",
|
|
57
|
+
"aria-label": full,
|
|
58
|
+
...props,
|
|
59
|
+
children: /*#__PURE__*/ jsx(Text, {
|
|
60
|
+
size: "sm",
|
|
61
|
+
children: /*#__PURE__*/ jsx("span", {
|
|
62
|
+
className: cn('whitespace-nowrap tabular-nums', DASHED_UNDERLINE),
|
|
63
|
+
children: display
|
|
64
|
+
})
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
}),
|
|
68
|
+
/*#__PURE__*/ jsx(TooltipContent, {
|
|
69
|
+
children: full
|
|
70
|
+
})
|
|
71
|
+
]
|
|
72
|
+
});
|
|
73
|
+
return /*#__PURE__*/ jsx("span", {
|
|
74
|
+
ref: ref,
|
|
75
|
+
"data-slot": "format-number",
|
|
76
|
+
...props,
|
|
77
|
+
children: /*#__PURE__*/ jsx(Text, {
|
|
78
|
+
size: "sm",
|
|
79
|
+
children: full
|
|
80
|
+
})
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
const abbreviated = abbreviateNumber(value);
|
|
84
|
+
const fullValue = formatFullNumber(value);
|
|
85
|
+
const isAbbreviated = 'compact' === notation && Math.abs(value) >= 1000;
|
|
86
|
+
const fullWithUnit = unit ? `${fullValue}\u00A0${unit}` : fullValue;
|
|
87
|
+
if (isAbbreviated) return /*#__PURE__*/ jsxs(Tooltip, {
|
|
88
|
+
children: [
|
|
89
|
+
/*#__PURE__*/ jsx(TooltipTrigger, {
|
|
90
|
+
asChild: true,
|
|
91
|
+
children: /*#__PURE__*/ jsx("span", {
|
|
92
|
+
ref: ref,
|
|
93
|
+
"data-slot": "format-number",
|
|
94
|
+
"aria-label": fullWithUnit,
|
|
95
|
+
...props,
|
|
96
|
+
children: /*#__PURE__*/ jsx(Text, {
|
|
97
|
+
size: "sm",
|
|
98
|
+
children: /*#__PURE__*/ jsx("span", {
|
|
99
|
+
className: cn('whitespace-nowrap tabular-nums', DASHED_UNDERLINE),
|
|
100
|
+
children: abbreviated
|
|
101
|
+
})
|
|
102
|
+
})
|
|
103
|
+
})
|
|
104
|
+
}),
|
|
105
|
+
/*#__PURE__*/ jsx(TooltipContent, {
|
|
106
|
+
children: fullWithUnit
|
|
107
|
+
})
|
|
108
|
+
]
|
|
109
|
+
});
|
|
110
|
+
const displayValue = unit ? `${fullValue}\u00A0${unit}` : fullValue;
|
|
111
|
+
return /*#__PURE__*/ jsx("span", {
|
|
112
|
+
ref: ref,
|
|
113
|
+
"data-slot": "format-number",
|
|
114
|
+
...props,
|
|
115
|
+
children: /*#__PURE__*/ jsx(Text, {
|
|
116
|
+
size: "sm",
|
|
117
|
+
children: displayValue
|
|
118
|
+
})
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
FormatNumber.displayName = 'FormatNumber';
|
|
122
|
+
export { FormatNumber };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { FormatNumber, type FormatNumberProps } from './FormatNumber';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { FormatNumber } from "./FormatNumber.js";
|
package/dist/index.d.ts
CHANGED
|
@@ -36,6 +36,7 @@ export { Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLab
|
|
|
36
36
|
export { type Condition, type ExprNode, type FieldMetadata, type FieldType, FilterInput, FilterInputChip, type FilterInputChipData, type FilterInputChipProps, type FilterInputChipVariant, FilterInputFieldMenu, type FilterInputFieldMenuProps, FilterInputOperatorMenu, type FilterInputOperatorMenuProps, type FilterInputProps, type FilterOperator, type Group, } from './components/FilterInput';
|
|
37
37
|
export { Flex, type FlexProps } from './components/Flex';
|
|
38
38
|
export { FormatDateTime, type FormatDateTimeProps } from './components/FormatDateTime';
|
|
39
|
+
export { FormatNumber, type FormatNumberProps } from './components/FormatNumber';
|
|
39
40
|
export { Heading, type HeadingProps } from './components/Heading';
|
|
40
41
|
export { HTTP_METHOD_COLOR, HTTP_METHODS, HttpMethod, type HttpMethodName, type HttpMethodProps, } from './components/HttpMethod';
|
|
41
42
|
export { Indicator, type IndicatorProps } from './components/Indicator';
|
package/dist/index.js
CHANGED
|
@@ -25,6 +25,7 @@ export { Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLab
|
|
|
25
25
|
export { FilterInput, FilterInputChip, FilterInputFieldMenu, FilterInputOperatorMenu } from "./components/FilterInput/index.js";
|
|
26
26
|
export { Flex } from "./components/Flex/index.js";
|
|
27
27
|
export { FormatDateTime } from "./components/FormatDateTime/index.js";
|
|
28
|
+
export { FormatNumber } from "./components/FormatNumber/index.js";
|
|
28
29
|
export { Heading } from "./components/Heading/index.js";
|
|
29
30
|
export { HTTP_METHODS, HTTP_METHOD_COLOR, HttpMethod } from "./components/HttpMethod/index.js";
|
|
30
31
|
export { Indicator } from "./components/Indicator/index.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
3
|
-
"generatedAt": "2026-08-
|
|
2
|
+
"version": "1.3.0",
|
|
3
|
+
"generatedAt": "2026-08-20T21:26:32.176Z",
|
|
4
4
|
"components": [
|
|
5
5
|
{
|
|
6
6
|
"name": "Accordion",
|
|
@@ -31504,6 +31504,351 @@
|
|
|
31504
31504
|
}
|
|
31505
31505
|
]
|
|
31506
31506
|
},
|
|
31507
|
+
{
|
|
31508
|
+
"name": "FormatNumber",
|
|
31509
|
+
"importPath": "@wallarm-org/design-system/FormatNumber",
|
|
31510
|
+
"props": [
|
|
31511
|
+
{
|
|
31512
|
+
"name": "defaultChecked",
|
|
31513
|
+
"type": "boolean | undefined",
|
|
31514
|
+
"required": false
|
|
31515
|
+
},
|
|
31516
|
+
{
|
|
31517
|
+
"name": "defaultValue",
|
|
31518
|
+
"type": "string | number | readonly string[] | undefined",
|
|
31519
|
+
"required": false
|
|
31520
|
+
},
|
|
31521
|
+
{
|
|
31522
|
+
"name": "suppressContentEditableWarning",
|
|
31523
|
+
"type": "boolean | undefined",
|
|
31524
|
+
"required": false
|
|
31525
|
+
},
|
|
31526
|
+
{
|
|
31527
|
+
"name": "suppressHydrationWarning",
|
|
31528
|
+
"type": "boolean | undefined",
|
|
31529
|
+
"required": false
|
|
31530
|
+
},
|
|
31531
|
+
{
|
|
31532
|
+
"name": "accessKey",
|
|
31533
|
+
"type": "string | undefined",
|
|
31534
|
+
"required": false
|
|
31535
|
+
},
|
|
31536
|
+
{
|
|
31537
|
+
"name": "autoCapitalize",
|
|
31538
|
+
"type": "\"off\" | \"none\" | \"on\" | \"sentences\" | \"words\" | \"characters\" | (string & {}) | undefined",
|
|
31539
|
+
"required": false
|
|
31540
|
+
},
|
|
31541
|
+
{
|
|
31542
|
+
"name": "autoFocus",
|
|
31543
|
+
"type": "boolean | undefined",
|
|
31544
|
+
"required": false
|
|
31545
|
+
},
|
|
31546
|
+
{
|
|
31547
|
+
"name": "contentEditable",
|
|
31548
|
+
"type": "Booleanish | \"inherit\" | \"plaintext-only\" | undefined",
|
|
31549
|
+
"required": false
|
|
31550
|
+
},
|
|
31551
|
+
{
|
|
31552
|
+
"name": "contextMenu",
|
|
31553
|
+
"type": "string | undefined",
|
|
31554
|
+
"required": false
|
|
31555
|
+
},
|
|
31556
|
+
{
|
|
31557
|
+
"name": "dir",
|
|
31558
|
+
"type": "string | undefined",
|
|
31559
|
+
"required": false
|
|
31560
|
+
},
|
|
31561
|
+
{
|
|
31562
|
+
"name": "draggable",
|
|
31563
|
+
"type": "Booleanish | undefined",
|
|
31564
|
+
"required": false
|
|
31565
|
+
},
|
|
31566
|
+
{
|
|
31567
|
+
"name": "enterKeyHint",
|
|
31568
|
+
"type": "\"enter\" | \"done\" | \"go\" | \"next\" | \"previous\" | \"search\" | \"send\" | undefined",
|
|
31569
|
+
"required": false
|
|
31570
|
+
},
|
|
31571
|
+
{
|
|
31572
|
+
"name": "hidden",
|
|
31573
|
+
"type": "boolean | undefined",
|
|
31574
|
+
"required": false
|
|
31575
|
+
},
|
|
31576
|
+
{
|
|
31577
|
+
"name": "id",
|
|
31578
|
+
"type": "string | undefined",
|
|
31579
|
+
"required": false
|
|
31580
|
+
},
|
|
31581
|
+
{
|
|
31582
|
+
"name": "lang",
|
|
31583
|
+
"type": "string | undefined",
|
|
31584
|
+
"required": false
|
|
31585
|
+
},
|
|
31586
|
+
{
|
|
31587
|
+
"name": "nonce",
|
|
31588
|
+
"type": "string | undefined",
|
|
31589
|
+
"required": false
|
|
31590
|
+
},
|
|
31591
|
+
{
|
|
31592
|
+
"name": "slot",
|
|
31593
|
+
"type": "string | undefined",
|
|
31594
|
+
"required": false
|
|
31595
|
+
},
|
|
31596
|
+
{
|
|
31597
|
+
"name": "spellCheck",
|
|
31598
|
+
"type": "Booleanish | undefined",
|
|
31599
|
+
"required": false
|
|
31600
|
+
},
|
|
31601
|
+
{
|
|
31602
|
+
"name": "tabIndex",
|
|
31603
|
+
"type": "number | undefined",
|
|
31604
|
+
"required": false
|
|
31605
|
+
},
|
|
31606
|
+
{
|
|
31607
|
+
"name": "title",
|
|
31608
|
+
"type": "string | undefined",
|
|
31609
|
+
"required": false
|
|
31610
|
+
},
|
|
31611
|
+
{
|
|
31612
|
+
"name": "translate",
|
|
31613
|
+
"type": "\"yes\" | \"no\" | undefined",
|
|
31614
|
+
"required": false
|
|
31615
|
+
},
|
|
31616
|
+
{
|
|
31617
|
+
"name": "radioGroup",
|
|
31618
|
+
"type": "string | undefined",
|
|
31619
|
+
"required": false
|
|
31620
|
+
},
|
|
31621
|
+
{
|
|
31622
|
+
"name": "role",
|
|
31623
|
+
"type": "AriaRole | undefined",
|
|
31624
|
+
"required": false
|
|
31625
|
+
},
|
|
31626
|
+
{
|
|
31627
|
+
"name": "about",
|
|
31628
|
+
"type": "string | undefined",
|
|
31629
|
+
"required": false
|
|
31630
|
+
},
|
|
31631
|
+
{
|
|
31632
|
+
"name": "content",
|
|
31633
|
+
"type": "string | undefined",
|
|
31634
|
+
"required": false
|
|
31635
|
+
},
|
|
31636
|
+
{
|
|
31637
|
+
"name": "datatype",
|
|
31638
|
+
"type": "string | undefined",
|
|
31639
|
+
"required": false
|
|
31640
|
+
},
|
|
31641
|
+
{
|
|
31642
|
+
"name": "inlist",
|
|
31643
|
+
"type": "any",
|
|
31644
|
+
"required": false
|
|
31645
|
+
},
|
|
31646
|
+
{
|
|
31647
|
+
"name": "prefix",
|
|
31648
|
+
"type": "string | undefined",
|
|
31649
|
+
"required": false
|
|
31650
|
+
},
|
|
31651
|
+
{
|
|
31652
|
+
"name": "property",
|
|
31653
|
+
"type": "string | undefined",
|
|
31654
|
+
"required": false
|
|
31655
|
+
},
|
|
31656
|
+
{
|
|
31657
|
+
"name": "rel",
|
|
31658
|
+
"type": "string | undefined",
|
|
31659
|
+
"required": false
|
|
31660
|
+
},
|
|
31661
|
+
{
|
|
31662
|
+
"name": "resource",
|
|
31663
|
+
"type": "string | undefined",
|
|
31664
|
+
"required": false
|
|
31665
|
+
},
|
|
31666
|
+
{
|
|
31667
|
+
"name": "rev",
|
|
31668
|
+
"type": "string | undefined",
|
|
31669
|
+
"required": false
|
|
31670
|
+
},
|
|
31671
|
+
{
|
|
31672
|
+
"name": "typeof",
|
|
31673
|
+
"type": "string | undefined",
|
|
31674
|
+
"required": false
|
|
31675
|
+
},
|
|
31676
|
+
{
|
|
31677
|
+
"name": "vocab",
|
|
31678
|
+
"type": "string | undefined",
|
|
31679
|
+
"required": false
|
|
31680
|
+
},
|
|
31681
|
+
{
|
|
31682
|
+
"name": "autoCorrect",
|
|
31683
|
+
"type": "string | undefined",
|
|
31684
|
+
"required": false
|
|
31685
|
+
},
|
|
31686
|
+
{
|
|
31687
|
+
"name": "autoSave",
|
|
31688
|
+
"type": "string | undefined",
|
|
31689
|
+
"required": false
|
|
31690
|
+
},
|
|
31691
|
+
{
|
|
31692
|
+
"name": "color",
|
|
31693
|
+
"type": "string | undefined",
|
|
31694
|
+
"required": false
|
|
31695
|
+
},
|
|
31696
|
+
{
|
|
31697
|
+
"name": "itemProp",
|
|
31698
|
+
"type": "string | undefined",
|
|
31699
|
+
"required": false
|
|
31700
|
+
},
|
|
31701
|
+
{
|
|
31702
|
+
"name": "itemScope",
|
|
31703
|
+
"type": "boolean | undefined",
|
|
31704
|
+
"required": false
|
|
31705
|
+
},
|
|
31706
|
+
{
|
|
31707
|
+
"name": "itemType",
|
|
31708
|
+
"type": "string | undefined",
|
|
31709
|
+
"required": false
|
|
31710
|
+
},
|
|
31711
|
+
{
|
|
31712
|
+
"name": "itemID",
|
|
31713
|
+
"type": "string | undefined",
|
|
31714
|
+
"required": false
|
|
31715
|
+
},
|
|
31716
|
+
{
|
|
31717
|
+
"name": "itemRef",
|
|
31718
|
+
"type": "string | undefined",
|
|
31719
|
+
"required": false
|
|
31720
|
+
},
|
|
31721
|
+
{
|
|
31722
|
+
"name": "results",
|
|
31723
|
+
"type": "number | undefined",
|
|
31724
|
+
"required": false
|
|
31725
|
+
},
|
|
31726
|
+
{
|
|
31727
|
+
"name": "security",
|
|
31728
|
+
"type": "string | undefined",
|
|
31729
|
+
"required": false
|
|
31730
|
+
},
|
|
31731
|
+
{
|
|
31732
|
+
"name": "unselectable",
|
|
31733
|
+
"type": "\"off\" | \"on\" | undefined",
|
|
31734
|
+
"required": false
|
|
31735
|
+
},
|
|
31736
|
+
{
|
|
31737
|
+
"name": "popover",
|
|
31738
|
+
"type": "\"\" | \"auto\" | \"manual\" | \"hint\" | undefined",
|
|
31739
|
+
"required": false
|
|
31740
|
+
},
|
|
31741
|
+
{
|
|
31742
|
+
"name": "popoverTargetAction",
|
|
31743
|
+
"type": "\"toggle\" | \"show\" | \"hide\" | undefined",
|
|
31744
|
+
"required": false
|
|
31745
|
+
},
|
|
31746
|
+
{
|
|
31747
|
+
"name": "popoverTarget",
|
|
31748
|
+
"type": "string | undefined",
|
|
31749
|
+
"required": false
|
|
31750
|
+
},
|
|
31751
|
+
{
|
|
31752
|
+
"name": "inert",
|
|
31753
|
+
"type": "boolean | undefined",
|
|
31754
|
+
"required": false,
|
|
31755
|
+
"description": "@see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/inert}"
|
|
31756
|
+
},
|
|
31757
|
+
{
|
|
31758
|
+
"name": "inputMode",
|
|
31759
|
+
"type": "\"none\" | \"search\" | \"text\" | \"tel\" | \"url\" | \"email\" | \"numeric\" | \"decimal\" | undefined",
|
|
31760
|
+
"required": false,
|
|
31761
|
+
"description": "Hints at the type of data that might be entered by the user while editing the element or its contents"
|
|
31762
|
+
},
|
|
31763
|
+
{
|
|
31764
|
+
"name": "is",
|
|
31765
|
+
"type": "string | undefined",
|
|
31766
|
+
"required": false,
|
|
31767
|
+
"description": "Specify that a standard HTML element should behave like a defined custom built-in element"
|
|
31768
|
+
},
|
|
31769
|
+
{
|
|
31770
|
+
"name": "exportparts",
|
|
31771
|
+
"type": "string | undefined",
|
|
31772
|
+
"required": false,
|
|
31773
|
+
"description": "@see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/exportparts}"
|
|
31774
|
+
},
|
|
31775
|
+
{
|
|
31776
|
+
"name": "part",
|
|
31777
|
+
"type": "string | undefined",
|
|
31778
|
+
"required": false,
|
|
31779
|
+
"description": "@see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/part}"
|
|
31780
|
+
},
|
|
31781
|
+
{
|
|
31782
|
+
"name": "value",
|
|
31783
|
+
"type": "number | null | undefined",
|
|
31784
|
+
"required": true,
|
|
31785
|
+
"description": "Numeric value to display. null/undefined renders em dash + \"No data\" tooltip."
|
|
31786
|
+
},
|
|
31787
|
+
{
|
|
31788
|
+
"name": "type",
|
|
31789
|
+
"type": "FormatNumberType | undefined",
|
|
31790
|
+
"required": false,
|
|
31791
|
+
"description": "Formatting category. Default: 'decimal'.\n- 'decimal': plain number with optional abbreviation\n- 'percent': percentage with boundary safety\n- 'byte': decimal byte units: 512 B, 2.3 GB",
|
|
31792
|
+
"defaultValue": "decimal"
|
|
31793
|
+
},
|
|
31794
|
+
{
|
|
31795
|
+
"name": "notation",
|
|
31796
|
+
"type": "FormatNumberNotation | undefined",
|
|
31797
|
+
"required": false,
|
|
31798
|
+
"description": "'compact' abbreviates (12k, 59.6M); 'standard' shows full value.\nDefault: 'compact'. Only applies to type='decimal' and type='byte'.",
|
|
31799
|
+
"defaultValue": "compact"
|
|
31800
|
+
},
|
|
31801
|
+
{
|
|
31802
|
+
"name": "unit",
|
|
31803
|
+
"type": "string | undefined",
|
|
31804
|
+
"required": false,
|
|
31805
|
+
"description": "Unit label for accessible name + tooltip: \"requests\", \"errors\".\nAppended after a space. Only meaningful for type='decimal'."
|
|
31806
|
+
},
|
|
31807
|
+
{
|
|
31808
|
+
"name": "decimals",
|
|
31809
|
+
"type": "number | undefined",
|
|
31810
|
+
"required": false,
|
|
31811
|
+
"description": "Decimal places for percent. Default: 0.",
|
|
31812
|
+
"defaultValue": "0"
|
|
31813
|
+
}
|
|
31814
|
+
],
|
|
31815
|
+
"variants": [],
|
|
31816
|
+
"subComponents": [],
|
|
31817
|
+
"examples": [
|
|
31818
|
+
{
|
|
31819
|
+
"name": "Compact",
|
|
31820
|
+
"code": "() => (\n <div className='grid grid-cols-[1fr_1fr] items-center gap-x-16 gap-y-12'>\n {compactValues.map(v => (\n <>\n <Text key={`label-${v}`} size='sm' color='secondary' align='right'>\n {v.toLocaleString('en-US')}\n </Text>\n <FormatNumber key={v} value={v} />\n </>\n ))}\n </div>\n)"
|
|
31821
|
+
},
|
|
31822
|
+
{
|
|
31823
|
+
"name": "Standard",
|
|
31824
|
+
"code": "() => (\n <div className='grid grid-cols-[1fr_1fr] items-center gap-x-16 gap-y-12'>\n {compactValues.map(v => (\n <>\n <Text key={`label-${v}`} size='sm' color='secondary' align='right'>\n {v.toLocaleString('en-US')}\n </Text>\n <FormatNumber key={v} value={v} notation='standard' />\n </>\n ))}\n </div>\n)"
|
|
31825
|
+
},
|
|
31826
|
+
{
|
|
31827
|
+
"name": "WithUnit",
|
|
31828
|
+
"code": "() => (\n <div className='grid grid-cols-[1fr_1fr] items-center gap-x-16 gap-y-12'>\n <Text size='sm' color='secondary' align='right'>\n 42\n </Text>\n <FormatNumber value={42} unit='requests' />\n\n <Text size='sm' color='secondary' align='right'>\n 12,042\n </Text>\n <FormatNumber value={12_042} unit='requests' />\n\n <Text size='sm' color='secondary' align='right'>\n 59,614,283\n </Text>\n <FormatNumber value={59_614_283} unit='errors' />\n\n <Text size='sm' color='secondary' align='right'>\n 500 (standard)\n </Text>\n <FormatNumber value={500} unit='requests' notation='standard' />\n </div>\n)"
|
|
31829
|
+
},
|
|
31830
|
+
{
|
|
31831
|
+
"name": "Percent",
|
|
31832
|
+
"code": "() => (\n <div className='grid grid-cols-[1fr_1fr] items-center gap-x-16 gap-y-12'>\n <Text size='sm' color='secondary' align='right'>\n 0%\n </Text>\n <FormatNumber value={0} type='percent' />\n\n <Text size='sm' color='secondary' align='right'>\n 0.02% (decimals=0)\n </Text>\n <FormatNumber value={0.02} type='percent' />\n\n <Text size='sm' color='secondary' align='right'>\n 0.02% (decimals=1)\n </Text>\n <FormatNumber value={0.02} type='percent' decimals={1} />\n\n <Text size='sm' color='secondary' align='right'>\n 25.5%\n </Text>\n <FormatNumber value={25.5} type='percent' decimals={1} />\n\n <Text size='sm' color='secondary' align='right'>\n 50%\n </Text>\n <FormatNumber value={50} type='percent' />\n\n <Text size='sm' color='secondary' align='right'>\n 99.97% (decimals=0)\n </Text>\n <FormatNumber value={99.97} type='percent' />\n\n <Text size='sm' color='secondary' align='right'>\n 99.97% (decimals=1)\n </Text>\n <FormatNumber value={99.97} type='percent' decimals={1} />\n\n <Text size='sm' color='secondary' align='right'>\n 100%\n </Text>\n <FormatNumber value={100} type='percent' />\n </div>\n)"
|
|
31833
|
+
},
|
|
31834
|
+
{
|
|
31835
|
+
"name": "Bytes",
|
|
31836
|
+
"code": "() => (\n <div className='grid grid-cols-[1fr_1fr] items-center gap-x-16 gap-y-12'>\n <Text size='sm' color='secondary' align='right'>\n 512 (compact)\n </Text>\n <FormatNumber value={512} type='byte' />\n\n <Text size='sm' color='secondary' align='right'>\n 3,400 (compact)\n </Text>\n <FormatNumber value={3_400} type='byte' />\n\n <Text size='sm' color='secondary' align='right'>\n 12,700,000 (compact)\n </Text>\n <FormatNumber value={12_700_000} type='byte' />\n\n <Text size='sm' color='secondary' align='right'>\n 2,345,678,901 (compact)\n </Text>\n <FormatNumber value={2_345_678_901} type='byte' />\n\n <Text size='sm' color='secondary' align='right'>\n 1,100,000,000,000 (compact)\n </Text>\n <FormatNumber value={1_100_000_000_000} type='byte' />\n\n <Text size='sm' color='secondary' align='right'>\n 12,700,000 (standard)\n </Text>\n <FormatNumber value={12_700_000} type='byte' notation='standard' />\n </div>\n)"
|
|
31837
|
+
},
|
|
31838
|
+
{
|
|
31839
|
+
"name": "NegativeValues",
|
|
31840
|
+
"code": "() => (\n <div className='grid grid-cols-[1fr_1fr] items-center gap-x-16 gap-y-12'>\n <Text size='sm' color='secondary' align='right'>\n -42\n </Text>\n <FormatNumber value={-42} />\n\n <Text size='sm' color='secondary' align='right'>\n -12,042\n </Text>\n <FormatNumber value={-12_042} />\n\n <Text size='sm' color='secondary' align='right'>\n -59,614,283\n </Text>\n <FormatNumber value={-59_614_283} />\n </div>\n)"
|
|
31841
|
+
},
|
|
31842
|
+
{
|
|
31843
|
+
"name": "NullValue",
|
|
31844
|
+
"code": "() => (\n <div className='grid grid-cols-[1fr_1fr] items-center gap-x-16 gap-y-12'>\n <Text size='sm' color='secondary' align='right'>\n null\n </Text>\n <FormatNumber value={null} />\n\n <Text size='sm' color='secondary' align='right'>\n undefined\n </Text>\n <FormatNumber value={undefined} />\n </div>\n)"
|
|
31845
|
+
},
|
|
31846
|
+
{
|
|
31847
|
+
"name": "SpecialValues",
|
|
31848
|
+
"code": "() => (\n <div className='grid grid-cols-[1fr_1fr] items-center gap-x-16 gap-y-12'>\n <Text size='sm' color='secondary' align='right'>\n 0\n </Text>\n <FormatNumber value={0} />\n\n <Text size='sm' color='secondary' align='right'>\n NaN\n </Text>\n <FormatNumber value={Number.NaN} />\n\n <Text size='sm' color='secondary' align='right'>\n Infinity\n </Text>\n <FormatNumber value={Number.POSITIVE_INFINITY} />\n </div>\n)"
|
|
31849
|
+
}
|
|
31850
|
+
]
|
|
31851
|
+
},
|
|
31507
31852
|
{
|
|
31508
31853
|
"name": "Heading",
|
|
31509
31854
|
"importPath": "@wallarm-org/design-system/Heading",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Abbreviate a number for table cells: `12042` → `"12k"`, `59614283` → `"59.
|
|
2
|
+
* Abbreviate a number for table cells: `12042` → `"12k"`, `59614283` → `"59.6M"`.
|
|
3
3
|
*
|
|
4
4
|
* Rules (from the Number display & abbreviation guide):
|
|
5
|
-
* - Suffixes: k (10³),
|
|
5
|
+
* - Suffixes: k (10³), M (10⁶), B (10⁹), T (10¹²) — k lowercase, rest uppercase, no space
|
|
6
6
|
* - Boundary: moves to next suffix when rounding would reach 1000×
|
|
7
7
|
* - Precision: ≥100 → 0 decimals; 10–99 → 1 decimal (drop .0); 1–9.9 → 1 decimal
|
|
8
8
|
* - Negative numbers supported
|
|
@@ -12,3 +12,19 @@ export declare const abbreviateNumber: (value: number) => string;
|
|
|
12
12
|
* Format a number with thousand separators for tooltips: `59614283` → `"59,614,283"`.
|
|
13
13
|
*/
|
|
14
14
|
export declare const formatFullNumber: (value: number) => string;
|
|
15
|
+
/**
|
|
16
|
+
* Format a percentage with boundary safety:
|
|
17
|
+
* - Never show 100% when real value < 100 → ">99%" (or ">99.9%" etc.)
|
|
18
|
+
* - Never show 0% when real value > 0 → "<1%" (or "<0.1%" etc.)
|
|
19
|
+
* - `decimals` controls fractional precision (default 0)
|
|
20
|
+
*/
|
|
21
|
+
export declare const formatPercent: (value: number, decimals?: number) => string;
|
|
22
|
+
/**
|
|
23
|
+
* Format bytes using decimal (SI) units: 512 B, 3.4 KB, 12.7 MB, 2.3 GB, 1.1 TB.
|
|
24
|
+
* Same decimal precision rules as abbreviateNumber.
|
|
25
|
+
* Returns `{ display, full }` where `full` = "2,345,678,901 bytes".
|
|
26
|
+
*/
|
|
27
|
+
export declare const formatBytes: (value: number) => {
|
|
28
|
+
display: string;
|
|
29
|
+
full: string;
|
|
30
|
+
};
|
|
@@ -2,17 +2,17 @@ const tiers = [
|
|
|
2
2
|
[
|
|
3
3
|
999500000000,
|
|
4
4
|
1e12,
|
|
5
|
-
'
|
|
5
|
+
'T'
|
|
6
6
|
],
|
|
7
7
|
[
|
|
8
8
|
999500000,
|
|
9
9
|
1e9,
|
|
10
|
-
'
|
|
10
|
+
'B'
|
|
11
11
|
],
|
|
12
12
|
[
|
|
13
13
|
999500,
|
|
14
14
|
1e6,
|
|
15
|
-
'
|
|
15
|
+
'M'
|
|
16
16
|
],
|
|
17
17
|
[
|
|
18
18
|
1000,
|
|
@@ -36,4 +36,62 @@ const abbreviateNumber = (value)=>{
|
|
|
36
36
|
return `${sign}${formatted}${suffix}`;
|
|
37
37
|
};
|
|
38
38
|
const formatFullNumber = (value)=>fullFormatter.format(value);
|
|
39
|
-
|
|
39
|
+
const formatPercent = (value, decimals = 0)=>{
|
|
40
|
+
if (0 === value) return '0%';
|
|
41
|
+
if (100 === value) return '100%';
|
|
42
|
+
const factor = 10 ** decimals;
|
|
43
|
+
const rounded = Math.round(value * factor) / factor;
|
|
44
|
+
if (value > 0 && 0 === rounded) {
|
|
45
|
+
const threshold = 1 / factor;
|
|
46
|
+
return `<${threshold}%`;
|
|
47
|
+
}
|
|
48
|
+
if (value < 100 && 100 === rounded) {
|
|
49
|
+
const max = 100 - 1 / factor;
|
|
50
|
+
return `>${decimals > 0 ? max.toFixed(decimals) : String(max)}%`;
|
|
51
|
+
}
|
|
52
|
+
return `${decimals > 0 ? rounded.toFixed(decimals) : String(rounded)}%`;
|
|
53
|
+
};
|
|
54
|
+
const byteTiers = [
|
|
55
|
+
[
|
|
56
|
+
999500000000,
|
|
57
|
+
1e12,
|
|
58
|
+
'TB'
|
|
59
|
+
],
|
|
60
|
+
[
|
|
61
|
+
999500000,
|
|
62
|
+
1e9,
|
|
63
|
+
'GB'
|
|
64
|
+
],
|
|
65
|
+
[
|
|
66
|
+
999500,
|
|
67
|
+
1e6,
|
|
68
|
+
'MB'
|
|
69
|
+
],
|
|
70
|
+
[
|
|
71
|
+
1000,
|
|
72
|
+
1e3,
|
|
73
|
+
'KB'
|
|
74
|
+
]
|
|
75
|
+
];
|
|
76
|
+
const formatBytes = (value)=>{
|
|
77
|
+
const full = `${fullFormatter.format(value)} bytes`;
|
|
78
|
+
if (value < 1000) return {
|
|
79
|
+
display: `${value} B`,
|
|
80
|
+
full
|
|
81
|
+
};
|
|
82
|
+
const tier = byteTiers.find(([threshold])=>value >= threshold);
|
|
83
|
+
if (!tier) return {
|
|
84
|
+
display: `${value} B`,
|
|
85
|
+
full
|
|
86
|
+
};
|
|
87
|
+
const [, divisor, suffix] = tier;
|
|
88
|
+
const scaled = value / divisor;
|
|
89
|
+
const precision = scaled >= 100 ? 0 : 1;
|
|
90
|
+
const rounded = Math.round(scaled * 10 ** precision) / 10 ** precision;
|
|
91
|
+
const formatted = rounded % 1 === 0 ? String(rounded) : rounded.toFixed(1);
|
|
92
|
+
return {
|
|
93
|
+
display: `${formatted} ${suffix}`,
|
|
94
|
+
full
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
export { abbreviateNumber, formatBytes, formatFullNumber, formatPercent };
|