@adia-ai/web-components 0.6.35 → 0.6.37
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/CHANGELOG.md +56 -0
- package/components/badge/badge.a2ui.json +10 -0
- package/components/badge/badge.css +70 -0
- package/components/badge/badge.yaml +20 -0
- package/components/blockquote/blockquote.a2ui.json +121 -0
- package/components/blockquote/blockquote.class.js +68 -0
- package/components/blockquote/blockquote.css +46 -0
- package/components/blockquote/blockquote.d.ts +31 -0
- package/components/blockquote/blockquote.js +17 -0
- package/components/blockquote/blockquote.yaml +124 -0
- package/components/button/button.css +11 -3
- package/components/calendar-picker/calendar-picker.a2ui.json +15 -0
- package/components/calendar-picker/calendar-picker.class.js +7 -1
- package/components/calendar-picker/calendar-picker.yaml +14 -0
- package/components/color-input/color-input.a2ui.json +2 -2
- package/components/color-input/color-input.class.js +9 -2
- package/components/color-input/color-input.yaml +2 -2
- package/components/combobox/combobox.class.js +4 -0
- package/components/combobox/combobox.css +12 -0
- package/components/context-menu/context-menu.a2ui.json +159 -0
- package/components/context-menu/context-menu.class.js +275 -0
- package/components/context-menu/context-menu.css +56 -0
- package/components/context-menu/context-menu.d.ts +70 -0
- package/components/context-menu/context-menu.js +17 -0
- package/components/context-menu/context-menu.yaml +136 -0
- package/components/date-range-picker/date-range-picker.a2ui.json +15 -0
- package/components/date-range-picker/date-range-picker.class.js +3 -1
- package/components/date-range-picker/date-range-picker.css +4 -1
- package/components/date-range-picker/date-range-picker.yaml +14 -0
- package/components/datetime-picker/datetime-picker.a2ui.json +15 -0
- package/components/datetime-picker/datetime-picker.class.js +3 -1
- package/components/datetime-picker/datetime-picker.css +7 -1
- package/components/datetime-picker/datetime-picker.d.ts +2 -0
- package/components/datetime-picker/datetime-picker.yaml +14 -0
- package/components/empty-state/empty-state.class.js +2 -0
- package/components/feed/feed.class.js +13 -5
- package/components/feed/feed.css +14 -0
- package/components/index.js +9 -0
- package/components/input/input.css +15 -1
- package/components/input/input.test.js +40 -0
- package/components/integration-card/integration-card.class.js +9 -0
- package/components/integration-card/integration-card.test.js +4 -3
- package/components/nav-group/nav-group.css +7 -1
- package/components/number-format/number-format.a2ui.json +180 -0
- package/components/number-format/number-format.class.js +96 -0
- package/components/number-format/number-format.css +18 -0
- package/components/number-format/number-format.d.ts +68 -0
- package/components/number-format/number-format.js +17 -0
- package/components/number-format/number-format.yaml +204 -0
- package/components/pagination/pagination.a2ui.json +19 -2
- package/components/pagination/pagination.class.js +90 -37
- package/components/pagination/pagination.css +32 -127
- package/components/pagination/pagination.d.ts +8 -2
- package/components/pagination/pagination.test.js +195 -0
- package/components/pagination/pagination.yaml +22 -1
- package/components/password-strength/password-strength.a2ui.json +152 -0
- package/components/password-strength/password-strength.class.js +157 -0
- package/components/password-strength/password-strength.css +80 -0
- package/components/password-strength/password-strength.d.ts +59 -0
- package/components/password-strength/password-strength.js +17 -0
- package/components/password-strength/password-strength.yaml +153 -0
- package/components/popover/popover.css +43 -23
- package/components/popover/popover.yaml +8 -4
- package/components/qr-code/QR-TEST.svg +4 -0
- package/components/qr-code/qr-code.a2ui.json +154 -0
- package/components/qr-code/qr-code.class.js +129 -0
- package/components/qr-code/qr-code.css +41 -0
- package/components/qr-code/qr-code.d.ts +83 -0
- package/components/qr-code/qr-code.js +17 -0
- package/components/qr-code/qr-code.yaml +203 -0
- package/components/qr-code/qr-encoder.js +633 -0
- package/components/relative-time/relative-time.a2ui.json +120 -0
- package/components/relative-time/relative-time.class.js +136 -0
- package/components/relative-time/relative-time.css +22 -0
- package/components/relative-time/relative-time.d.ts +51 -0
- package/components/relative-time/relative-time.js +17 -0
- package/components/relative-time/relative-time.yaml +133 -0
- package/components/search/search.class.js +2 -0
- package/components/segmented/segmented.class.js +5 -1
- package/components/select/select.class.js +4 -0
- package/components/skip-nav/skip-nav.a2ui.json +92 -0
- package/components/skip-nav/skip-nav.class.js +45 -0
- package/components/skip-nav/skip-nav.css +54 -0
- package/components/skip-nav/skip-nav.d.ts +27 -0
- package/components/skip-nav/skip-nav.js +12 -0
- package/components/skip-nav/skip-nav.yaml +68 -0
- package/components/slider/slider.a2ui.json +16 -1
- package/components/slider/slider.class.js +264 -122
- package/components/slider/slider.css +82 -2
- package/components/slider/slider.d.ts +19 -3
- package/components/slider/slider.test.js +55 -0
- package/components/slider/slider.yaml +28 -6
- package/components/table/table.class.js +29 -6
- package/components/table/table.css +31 -4
- package/components/table-toolbar/table-toolbar.class.js +4 -1
- package/components/tag/tag.a2ui.json +10 -0
- package/components/tag/tag.class.js +8 -1
- package/components/tag/tag.css +108 -20
- package/components/tag/tag.d.ts +14 -0
- package/components/tag/tag.test.js +99 -1
- package/components/tag/tag.yaml +20 -0
- package/components/tags-input/tags-input.class.js +10 -3
- package/components/tags-input/tags-input.css +12 -3
- package/components/textarea/textarea.css +10 -1
- package/components/toast/toast.class.js +12 -4
- package/components/toc/toc.a2ui.json +159 -0
- package/components/toc/toc.class.js +222 -0
- package/components/toc/toc.css +92 -0
- package/components/toc/toc.d.ts +61 -0
- package/components/toc/toc.js +17 -0
- package/components/toc/toc.yaml +180 -0
- package/components/toolbar/toolbar.class.js +3 -0
- package/components/visually-hidden/visually-hidden.a2ui.json +71 -0
- package/components/visually-hidden/visually-hidden.class.js +14 -0
- package/components/visually-hidden/visually-hidden.css +25 -0
- package/components/visually-hidden/visually-hidden.d.ts +26 -0
- package/components/visually-hidden/visually-hidden.js +12 -0
- package/components/visually-hidden/visually-hidden.yaml +54 -0
- package/core/anchor.js +19 -3
- package/core/provider.js +19 -2
- package/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +101 -89
- package/package.json +1 -1
- package/styles/colors/semantics.css +11 -2
- package/styles/components.css +9 -0
- package/styles/resets.css +10 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://adiaui.dev/a2ui/v0_9/components/NumberFormat.json",
|
|
4
|
+
"title": "NumberFormat",
|
|
5
|
+
"description": "Display a numeric value with locale-aware formatting — currency,\npercentage, compact (1.2K / 3.4M), unit, or plain decimal. Wraps\n`Intl.NumberFormat`. Distinct from `<input-ui type=\"number\">`\n(an INPUT primitive); this is a DISPLAY primitive — read-only, no\nform participation, no keyboard handling. Pair with `<stat-ui>` for\nKPI surfaces or use standalone inline within prose.\n",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"allOf": [
|
|
8
|
+
{
|
|
9
|
+
"$ref": "common_types.json#/$defs/ComponentCommon"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"$ref": "common_types.json#/$defs/CatalogComponentCommon"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"properties": {
|
|
16
|
+
"compactDisplay": {
|
|
17
|
+
"description": "When [notation=\"compact\"], controls the compact-form length.\n`short` = \"1.2M\" (default); `long` = \"1.2 million\".\n",
|
|
18
|
+
"type": "string",
|
|
19
|
+
"enum": [
|
|
20
|
+
"short",
|
|
21
|
+
"long"
|
|
22
|
+
],
|
|
23
|
+
"default": "short"
|
|
24
|
+
},
|
|
25
|
+
"component": {
|
|
26
|
+
"const": "NumberFormat"
|
|
27
|
+
},
|
|
28
|
+
"currency": {
|
|
29
|
+
"description": "ISO 4217 currency code (e.g. \"USD\", \"EUR\", \"JPY\"). Required when\n[number-style=\"currency\"]; ignored otherwise.\n",
|
|
30
|
+
"type": "string",
|
|
31
|
+
"default": ""
|
|
32
|
+
},
|
|
33
|
+
"locale": {
|
|
34
|
+
"description": "BCP-47 locale tag for the formatter. Empty defaults to the\ndocument locale (`<html lang>`) then to browser default.\n",
|
|
35
|
+
"type": "string",
|
|
36
|
+
"default": ""
|
|
37
|
+
},
|
|
38
|
+
"maximumFractionDigits": {
|
|
39
|
+
"description": "Maximum fractional digits (0–20). Default `2` for decimal/\ncurrency/percent, `1` for compact notation.\n",
|
|
40
|
+
"type": "number",
|
|
41
|
+
"default": 2
|
|
42
|
+
},
|
|
43
|
+
"minimumFractionDigits": {
|
|
44
|
+
"description": "Minimum fractional digits (0–20). Padded with trailing zeros.\nUseful for currency display to force \".00\" suffix.\n",
|
|
45
|
+
"type": "number",
|
|
46
|
+
"default": 0
|
|
47
|
+
},
|
|
48
|
+
"notation": {
|
|
49
|
+
"description": "`Intl.NumberFormat` `notation` option. `standard` is the\nthousands-grouped form (1,234,567); `compact` is the abbreviated\nform (1.2M); `scientific` and `engineering` are the exponent\nforms. Defaults to `standard`.\n",
|
|
50
|
+
"type": "string",
|
|
51
|
+
"enum": [
|
|
52
|
+
"standard",
|
|
53
|
+
"compact",
|
|
54
|
+
"scientific",
|
|
55
|
+
"engineering"
|
|
56
|
+
],
|
|
57
|
+
"default": "standard"
|
|
58
|
+
},
|
|
59
|
+
"numberStyle": {
|
|
60
|
+
"description": "`Intl.NumberFormat` `style` option. `decimal` (default) renders a\nplain number with locale-aware grouping. `currency` requires\n[currency] to be set. `percent` formats 0–1 as 0%–100%. `unit`\nrequires [unit] to be set (e.g. \"kilobyte\", \"celsius\").\n",
|
|
61
|
+
"type": "string",
|
|
62
|
+
"enum": [
|
|
63
|
+
"decimal",
|
|
64
|
+
"currency",
|
|
65
|
+
"percent",
|
|
66
|
+
"unit"
|
|
67
|
+
],
|
|
68
|
+
"default": "decimal"
|
|
69
|
+
},
|
|
70
|
+
"signDisplay": {
|
|
71
|
+
"description": "`Intl.NumberFormat` `signDisplay` option. `auto` (default) shows\n\"−\" for negatives only; `always` shows \"+\" / \"−\"; `exceptZero`\nshows sign for non-zero only; `never` hides signs.\n",
|
|
72
|
+
"type": "string",
|
|
73
|
+
"enum": [
|
|
74
|
+
"auto",
|
|
75
|
+
"always",
|
|
76
|
+
"exceptZero",
|
|
77
|
+
"never"
|
|
78
|
+
],
|
|
79
|
+
"default": "auto"
|
|
80
|
+
},
|
|
81
|
+
"unit": {
|
|
82
|
+
"description": "`Intl.NumberFormat` unit identifier (e.g. \"kilometer-per-hour\",\n\"celsius\", \"byte\"). Required when [number-style=\"unit\"]; ignored\notherwise. See MDN's NumberFormat docs for the valid set.\n",
|
|
83
|
+
"type": "string",
|
|
84
|
+
"default": ""
|
|
85
|
+
},
|
|
86
|
+
"value": {
|
|
87
|
+
"description": "The numeric value to format. Empty string or non-numeric value\nrenders nothing.\n",
|
|
88
|
+
"type": "number",
|
|
89
|
+
"default": 0
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"required": [
|
|
93
|
+
"component"
|
|
94
|
+
],
|
|
95
|
+
"unevaluatedProperties": false,
|
|
96
|
+
"x-adiaui": {
|
|
97
|
+
"anti_patterns": [
|
|
98
|
+
{
|
|
99
|
+
"fix": "<number-format-ui value=\"0.5\" number-style=\"percent\"></number-format-ui>\n",
|
|
100
|
+
"why": "Renders \"5,000%\" — Intl.NumberFormat percent style multiplies the\ninput by 100. value=50 means \"5000%\".\n",
|
|
101
|
+
"wrong": "<number-format-ui value=\"50\" number-style=\"percent\"></number-format-ui>\n"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"fix": "<number-format-ui value=\"9.99\" number-style=\"currency\" currency=\"USD\"></number-format-ui>\n",
|
|
105
|
+
"why": "Missing [currency] code. Renders nothing rather than producing\nmalformed currency output.\n",
|
|
106
|
+
"wrong": "<number-format-ui value=\"9.99\" number-style=\"currency\"></number-format-ui>\n"
|
|
107
|
+
}
|
|
108
|
+
],
|
|
109
|
+
"category": "display",
|
|
110
|
+
"composes": [],
|
|
111
|
+
"events": {},
|
|
112
|
+
"examples": [
|
|
113
|
+
{
|
|
114
|
+
"description": "Plain locale-grouped number — default style.",
|
|
115
|
+
"a2ui": "[\n {\n \"id\": \"n\",\n \"component\": \"NumberFormat\",\n \"value\": 1234567.89\n }\n]\n",
|
|
116
|
+
"name": "decimal"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"description": "USD currency display.",
|
|
120
|
+
"a2ui": "[\n {\n \"id\": \"n\",\n \"component\": \"NumberFormat\",\n \"value\": 1299.99,\n \"numberStyle\": \"currency\",\n \"currency\": \"USD\"\n }\n]\n",
|
|
121
|
+
"name": "currency"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"description": "Fraction → percent (0.876 → 87.6%).",
|
|
125
|
+
"a2ui": "[\n {\n \"id\": \"n\",\n \"component\": \"NumberFormat\",\n \"value\": 0.876,\n \"numberStyle\": \"percent\",\n \"maximumFractionDigits\": 1\n }\n]\n",
|
|
126
|
+
"name": "percent"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"description": "Compact-form (1.2M, 3.4K).",
|
|
130
|
+
"a2ui": "[\n {\n \"id\": \"n\",\n \"component\": \"NumberFormat\",\n \"value\": 1234567,\n \"notation\": \"compact\"\n }\n]\n",
|
|
131
|
+
"name": "compact"
|
|
132
|
+
}
|
|
133
|
+
],
|
|
134
|
+
"keywords": [
|
|
135
|
+
"number-format",
|
|
136
|
+
"format",
|
|
137
|
+
"currency",
|
|
138
|
+
"percent",
|
|
139
|
+
"percentage",
|
|
140
|
+
"compact",
|
|
141
|
+
"number",
|
|
142
|
+
"locale",
|
|
143
|
+
"intl"
|
|
144
|
+
],
|
|
145
|
+
"name": "UINumberFormat",
|
|
146
|
+
"related": [
|
|
147
|
+
"stat",
|
|
148
|
+
"text",
|
|
149
|
+
"badge",
|
|
150
|
+
"input"
|
|
151
|
+
],
|
|
152
|
+
"slots": {},
|
|
153
|
+
"states": [
|
|
154
|
+
{
|
|
155
|
+
"description": "Default, displaying the formatted value.",
|
|
156
|
+
"name": "idle"
|
|
157
|
+
}
|
|
158
|
+
],
|
|
159
|
+
"status": "stable",
|
|
160
|
+
"synonyms": {
|
|
161
|
+
"currency": [
|
|
162
|
+
"number-format",
|
|
163
|
+
"money",
|
|
164
|
+
"price"
|
|
165
|
+
],
|
|
166
|
+
"number": [
|
|
167
|
+
"number-format",
|
|
168
|
+
"format"
|
|
169
|
+
],
|
|
170
|
+
"percent": [
|
|
171
|
+
"number-format",
|
|
172
|
+
"percentage"
|
|
173
|
+
]
|
|
174
|
+
},
|
|
175
|
+
"tag": "number-format-ui",
|
|
176
|
+
"tokens": {},
|
|
177
|
+
"traits": [],
|
|
178
|
+
"version": 1
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Non-side-effect class export for `<number-format-ui>`.
|
|
3
|
+
*
|
|
4
|
+
* Importing this file gives you the class without auto-registering the
|
|
5
|
+
* tag. Useful for test isolation, subclassing with tag-name override,
|
|
6
|
+
* or selective composition.
|
|
7
|
+
*
|
|
8
|
+
* The auto-register path stays at `@adia-ai/web-components/components/number-format`
|
|
9
|
+
* (which imports this file + calls `defineIfFree()`).
|
|
10
|
+
*
|
|
11
|
+
* @see ../../USAGE.md#registration--auto-vs-explicit
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* <number-format-ui value="1234567.89"></number-format-ui> → 1,234,567.89
|
|
16
|
+
* <number-format-ui value="1299.99" number-style="currency" currency="USD"></number-format-ui> → $1,299.99
|
|
17
|
+
* <number-format-ui value="0.876" number-style="percent"></number-format-ui> → 87.6%
|
|
18
|
+
* <number-format-ui value="1234567" notation="compact"></number-format-ui> → 1.2M
|
|
19
|
+
*
|
|
20
|
+
* Read-only display primitive wrapping `Intl.NumberFormat`. Distinct
|
|
21
|
+
* from `<input-ui type="number">` (a form-input primitive).
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { UIElement } from '../../core/element.js';
|
|
25
|
+
|
|
26
|
+
export class UINumberFormat extends UIElement {
|
|
27
|
+
static properties = {
|
|
28
|
+
value: { type: Number, default: 0, reflect: true },
|
|
29
|
+
numberStyle: { type: String, default: 'decimal', reflect: true, attribute: 'number-style' },
|
|
30
|
+
currency: { type: String, default: '', reflect: true },
|
|
31
|
+
unit: { type: String, default: '', reflect: true },
|
|
32
|
+
notation: { type: String, default: 'standard', reflect: true },
|
|
33
|
+
compactDisplay: { type: String, default: 'short', reflect: true, attribute: 'compact-display' },
|
|
34
|
+
minimumFractionDigits: { type: Number, default: 0, reflect: true, attribute: 'minimum-fraction-digits' },
|
|
35
|
+
maximumFractionDigits: { type: Number, default: 2, reflect: true, attribute: 'maximum-fraction-digits' },
|
|
36
|
+
locale: { type: String, default: '', reflect: true },
|
|
37
|
+
signDisplay: { type: String, default: 'auto', reflect: true, attribute: 'sign-display' },
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
static template = () => null;
|
|
41
|
+
|
|
42
|
+
#resolveLocale() {
|
|
43
|
+
if (this.locale) return this.locale;
|
|
44
|
+
return this.ownerDocument?.documentElement?.lang || undefined;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
#format() {
|
|
48
|
+
const v = Number(this.value);
|
|
49
|
+
if (!Number.isFinite(v)) return '';
|
|
50
|
+
|
|
51
|
+
// Validate required dependent props per style.
|
|
52
|
+
if (this.numberStyle === 'currency' && !this.currency) return '';
|
|
53
|
+
if (this.numberStyle === 'unit' && !this.unit) return '';
|
|
54
|
+
|
|
55
|
+
/** @type {Intl.NumberFormatOptions} */
|
|
56
|
+
const opts = {
|
|
57
|
+
style: this.numberStyle,
|
|
58
|
+
notation: this.notation,
|
|
59
|
+
signDisplay: this.signDisplay,
|
|
60
|
+
};
|
|
61
|
+
if (this.numberStyle === 'currency') opts.currency = this.currency;
|
|
62
|
+
if (this.numberStyle === 'unit') opts.unit = this.unit;
|
|
63
|
+
if (this.notation === 'compact') opts.compactDisplay = this.compactDisplay;
|
|
64
|
+
// Honor min/max fraction digits when explicitly set. The defaults
|
|
65
|
+
// (0 / 2) are reasonable for decimal+currency; compact notation
|
|
66
|
+
// typically wants 1 max but we let consumers override.
|
|
67
|
+
if (Number.isFinite(this.minimumFractionDigits)) opts.minimumFractionDigits = this.minimumFractionDigits;
|
|
68
|
+
if (Number.isFinite(this.maximumFractionDigits)) opts.maximumFractionDigits = this.maximumFractionDigits;
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
return new Intl.NumberFormat(this.#resolveLocale(), opts).format(v);
|
|
72
|
+
} catch {
|
|
73
|
+
return String(v);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
connected() {
|
|
78
|
+
super.connected();
|
|
79
|
+
// No special role — the rendered text is read by AT naturally; we
|
|
80
|
+
// expose the raw value via aria-label for screen-reader clarity in
|
|
81
|
+
// contexts where the formatted glyphs ("€", "M") might be parsed
|
|
82
|
+
// unpredictably by different readers.
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
render() {
|
|
86
|
+
const text = this.#format();
|
|
87
|
+
this.textContent = text;
|
|
88
|
+
// Mirror raw value via aria-label so screen readers can read the
|
|
89
|
+
// underlying number alongside the formatted glyphs.
|
|
90
|
+
if (text && Number.isFinite(Number(this.value))) {
|
|
91
|
+
this.setAttribute('aria-label', `${text} (raw: ${this.value})`);
|
|
92
|
+
} else {
|
|
93
|
+
this.removeAttribute('aria-label');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/* ═══════════════════════════════════════════════════════════════
|
|
2
|
+
NUMBER-FORMAT-UI — Read-only formatted numeric display.
|
|
3
|
+
═══════════════════════════════════════════════════════════════ */
|
|
4
|
+
|
|
5
|
+
@scope (number-format-ui) {
|
|
6
|
+
:where(:scope) {
|
|
7
|
+
--number-format-fg-default: inherit;
|
|
8
|
+
--number-format-font-default: inherit;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
:scope {
|
|
12
|
+
display: inline;
|
|
13
|
+
color: var(--number-format-fg, var(--number-format-fg-default));
|
|
14
|
+
font-family: var(--number-format-font, var(--number-format-font-default));
|
|
15
|
+
/* Tabular figures so column-aligned numeric displays line up cleanly. */
|
|
16
|
+
font-variant-numeric: tabular-nums;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<number-format-ui>` — Display a numeric value with locale-aware formatting — currency,
|
|
3
|
+
percentage, compact (1.2K / 3.4M), unit, or plain decimal. Wraps
|
|
4
|
+
`Intl.NumberFormat`. Distinct from `<input-ui type="number">`
|
|
5
|
+
(an INPUT primitive); this is a DISPLAY primitive — read-only, no
|
|
6
|
+
form participation, no keyboard handling. Pair with `<stat-ui>` for
|
|
7
|
+
KPI surfaces or use standalone inline within prose.
|
|
8
|
+
|
|
9
|
+
*
|
|
10
|
+
* @see https://ui-kit.exe.xyz/site/components/number-format
|
|
11
|
+
*
|
|
12
|
+
* Type declarations generated by scripts/build/dts-codegen.mjs from
|
|
13
|
+
* the component's `.a2ui.json` sidecar(s). Edit the source `.yaml`,
|
|
14
|
+
* run `npm run build:components`, then `npm run codegen:dts` to
|
|
15
|
+
* regenerate; or hand-author this file fully if rich event types are
|
|
16
|
+
* needed beyond what the yaml `events:` block can express.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { UIElement } from '../../core/element.js';
|
|
20
|
+
|
|
21
|
+
export class UINumberFormat extends UIElement {
|
|
22
|
+
/** When [notation="compact"], controls the compact-form length.
|
|
23
|
+
`short` = "1.2M" (default); `long` = "1.2 million".
|
|
24
|
+
*/
|
|
25
|
+
compactDisplay: 'short' | 'long';
|
|
26
|
+
/** ISO 4217 currency code (e.g. "USD", "EUR", "JPY"). Required when
|
|
27
|
+
[number-style="currency"]; ignored otherwise.
|
|
28
|
+
*/
|
|
29
|
+
currency: string;
|
|
30
|
+
/** BCP-47 locale tag for the formatter. Empty defaults to the
|
|
31
|
+
document locale (`<html lang>`) then to browser default.
|
|
32
|
+
*/
|
|
33
|
+
locale: string;
|
|
34
|
+
/** Maximum fractional digits (0–20). Default `2` for decimal/
|
|
35
|
+
currency/percent, `1` for compact notation.
|
|
36
|
+
*/
|
|
37
|
+
maximumFractionDigits: number;
|
|
38
|
+
/** Minimum fractional digits (0–20). Padded with trailing zeros.
|
|
39
|
+
Useful for currency display to force ".00" suffix.
|
|
40
|
+
*/
|
|
41
|
+
minimumFractionDigits: number;
|
|
42
|
+
/** `Intl.NumberFormat` `notation` option. `standard` is the
|
|
43
|
+
thousands-grouped form (1,234,567); `compact` is the abbreviated
|
|
44
|
+
form (1.2M); `scientific` and `engineering` are the exponent
|
|
45
|
+
forms. Defaults to `standard`.
|
|
46
|
+
*/
|
|
47
|
+
notation: 'standard' | 'compact' | 'scientific' | 'engineering';
|
|
48
|
+
/** `Intl.NumberFormat` `style` option. `decimal` (default) renders a
|
|
49
|
+
plain number with locale-aware grouping. `currency` requires
|
|
50
|
+
[currency] to be set. `percent` formats 0–1 as 0%–100%. `unit`
|
|
51
|
+
requires [unit] to be set (e.g. "kilobyte", "celsius").
|
|
52
|
+
*/
|
|
53
|
+
numberStyle: 'decimal' | 'currency' | 'percent' | 'unit';
|
|
54
|
+
/** `Intl.NumberFormat` `signDisplay` option. `auto` (default) shows
|
|
55
|
+
"−" for negatives only; `always` shows "+" / "−"; `exceptZero`
|
|
56
|
+
shows sign for non-zero only; `never` hides signs.
|
|
57
|
+
*/
|
|
58
|
+
signDisplay: 'auto' | 'always' | 'exceptZero' | 'never';
|
|
59
|
+
/** `Intl.NumberFormat` unit identifier (e.g. "kilometer-per-hour",
|
|
60
|
+
"celsius", "byte"). Required when [number-style="unit"]; ignored
|
|
61
|
+
otherwise. See MDN's NumberFormat docs for the valid set.
|
|
62
|
+
*/
|
|
63
|
+
unit: string;
|
|
64
|
+
/** The numeric value to format. Empty string or non-numeric value
|
|
65
|
+
renders nothing.
|
|
66
|
+
*/
|
|
67
|
+
value: number;
|
|
68
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<number-format-ui>` — auto-registers the tag on import.
|
|
3
|
+
*
|
|
4
|
+
* For non-side-effect class import (test isolation, tag override), use
|
|
5
|
+
* the `class` subpath:
|
|
6
|
+
*
|
|
7
|
+
* import { UINumberFormat } from '@adia-ai/web-components/components/number-format/class';
|
|
8
|
+
*
|
|
9
|
+
* @see ../../USAGE.md#registration--auto-vs-explicit
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { defineIfFree } from '../../core/register.js';
|
|
13
|
+
import { UINumberFormat } from './number-format.class.js';
|
|
14
|
+
|
|
15
|
+
defineIfFree('number-format-ui', UINumberFormat);
|
|
16
|
+
|
|
17
|
+
export { UINumberFormat };
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
$schema: ../../../../scripts/schemas/component.yaml.schema.json
|
|
2
|
+
name: UINumberFormat
|
|
3
|
+
tag: number-format-ui
|
|
4
|
+
status: stable
|
|
5
|
+
component: NumberFormat
|
|
6
|
+
category: display
|
|
7
|
+
version: 1
|
|
8
|
+
description: |
|
|
9
|
+
Display a numeric value with locale-aware formatting — currency,
|
|
10
|
+
percentage, compact (1.2K / 3.4M), unit, or plain decimal. Wraps
|
|
11
|
+
`Intl.NumberFormat`. Distinct from `<input-ui type="number">`
|
|
12
|
+
(an INPUT primitive); this is a DISPLAY primitive — read-only, no
|
|
13
|
+
form participation, no keyboard handling. Pair with `<stat-ui>` for
|
|
14
|
+
KPI surfaces or use standalone inline within prose.
|
|
15
|
+
props:
|
|
16
|
+
value:
|
|
17
|
+
description: |
|
|
18
|
+
The numeric value to format. Empty string or non-numeric value
|
|
19
|
+
renders nothing.
|
|
20
|
+
type: number
|
|
21
|
+
default: 0
|
|
22
|
+
reflect: true
|
|
23
|
+
numberStyle:
|
|
24
|
+
description: |
|
|
25
|
+
`Intl.NumberFormat` `style` option. `decimal` (default) renders a
|
|
26
|
+
plain number with locale-aware grouping. `currency` requires
|
|
27
|
+
[currency] to be set. `percent` formats 0–1 as 0%–100%. `unit`
|
|
28
|
+
requires [unit] to be set (e.g. "kilobyte", "celsius").
|
|
29
|
+
type: string
|
|
30
|
+
default: decimal
|
|
31
|
+
enum: [decimal, currency, percent, unit]
|
|
32
|
+
reflect: true
|
|
33
|
+
attribute: number-style
|
|
34
|
+
currency:
|
|
35
|
+
description: |
|
|
36
|
+
ISO 4217 currency code (e.g. "USD", "EUR", "JPY"). Required when
|
|
37
|
+
[number-style="currency"]; ignored otherwise.
|
|
38
|
+
type: string
|
|
39
|
+
default: ""
|
|
40
|
+
reflect: true
|
|
41
|
+
unit:
|
|
42
|
+
description: |
|
|
43
|
+
`Intl.NumberFormat` unit identifier (e.g. "kilometer-per-hour",
|
|
44
|
+
"celsius", "byte"). Required when [number-style="unit"]; ignored
|
|
45
|
+
otherwise. See MDN's NumberFormat docs for the valid set.
|
|
46
|
+
type: string
|
|
47
|
+
default: ""
|
|
48
|
+
reflect: true
|
|
49
|
+
notation:
|
|
50
|
+
description: |
|
|
51
|
+
`Intl.NumberFormat` `notation` option. `standard` is the
|
|
52
|
+
thousands-grouped form (1,234,567); `compact` is the abbreviated
|
|
53
|
+
form (1.2M); `scientific` and `engineering` are the exponent
|
|
54
|
+
forms. Defaults to `standard`.
|
|
55
|
+
type: string
|
|
56
|
+
default: standard
|
|
57
|
+
enum: [standard, compact, scientific, engineering]
|
|
58
|
+
reflect: true
|
|
59
|
+
compactDisplay:
|
|
60
|
+
description: |
|
|
61
|
+
When [notation="compact"], controls the compact-form length.
|
|
62
|
+
`short` = "1.2M" (default); `long` = "1.2 million".
|
|
63
|
+
type: string
|
|
64
|
+
default: short
|
|
65
|
+
enum: [short, long]
|
|
66
|
+
reflect: true
|
|
67
|
+
attribute: compact-display
|
|
68
|
+
minimumFractionDigits:
|
|
69
|
+
description: |
|
|
70
|
+
Minimum fractional digits (0–20). Padded with trailing zeros.
|
|
71
|
+
Useful for currency display to force ".00" suffix.
|
|
72
|
+
type: number
|
|
73
|
+
default: 0
|
|
74
|
+
reflect: true
|
|
75
|
+
attribute: minimum-fraction-digits
|
|
76
|
+
maximumFractionDigits:
|
|
77
|
+
description: |
|
|
78
|
+
Maximum fractional digits (0–20). Default `2` for decimal/
|
|
79
|
+
currency/percent, `1` for compact notation.
|
|
80
|
+
type: number
|
|
81
|
+
default: 2
|
|
82
|
+
reflect: true
|
|
83
|
+
attribute: maximum-fraction-digits
|
|
84
|
+
locale:
|
|
85
|
+
description: |
|
|
86
|
+
BCP-47 locale tag for the formatter. Empty defaults to the
|
|
87
|
+
document locale (`<html lang>`) then to browser default.
|
|
88
|
+
type: string
|
|
89
|
+
default: ""
|
|
90
|
+
reflect: true
|
|
91
|
+
signDisplay:
|
|
92
|
+
description: |
|
|
93
|
+
`Intl.NumberFormat` `signDisplay` option. `auto` (default) shows
|
|
94
|
+
"−" for negatives only; `always` shows "+" / "−"; `exceptZero`
|
|
95
|
+
shows sign for non-zero only; `never` hides signs.
|
|
96
|
+
type: string
|
|
97
|
+
default: auto
|
|
98
|
+
enum: [auto, always, exceptZero, never]
|
|
99
|
+
reflect: true
|
|
100
|
+
attribute: sign-display
|
|
101
|
+
events: {}
|
|
102
|
+
slots: {}
|
|
103
|
+
states:
|
|
104
|
+
- name: idle
|
|
105
|
+
description: Default, displaying the formatted value.
|
|
106
|
+
traits: []
|
|
107
|
+
tokens: {}
|
|
108
|
+
a2ui:
|
|
109
|
+
rules:
|
|
110
|
+
- rule: "Use for read-only numeric display with locale-aware formatting. For numeric INPUT use <input-ui type=number>; for KPI big-number display use <stat-ui>."
|
|
111
|
+
reason: "Display vs input vs metric separation."
|
|
112
|
+
- rule: "[number-style=currency] REQUIRES [currency] to be set to a valid ISO 4217 code. Without it the element renders nothing rather than producing malformed output."
|
|
113
|
+
reason: "Currency contract."
|
|
114
|
+
- rule: "[number-style=percent] treats the [value] as a fraction (0.5 → 50%). To display 50 as '50%' pass value=0.5 OR keep [number-style=decimal] and append '%' manually."
|
|
115
|
+
reason: "Percent semantics — Intl.NumberFormat convention."
|
|
116
|
+
- rule: "Compact notation auto-defaults maximumFractionDigits to 1. Override only when extra precision is needed (rare for compact display — defeats the purpose)."
|
|
117
|
+
reason: "Sensible defaults."
|
|
118
|
+
anti_patterns:
|
|
119
|
+
- wrong: |
|
|
120
|
+
<number-format-ui value="50" number-style="percent"></number-format-ui>
|
|
121
|
+
why: |
|
|
122
|
+
Renders "5,000%" — Intl.NumberFormat percent style multiplies the
|
|
123
|
+
input by 100. value=50 means "5000%".
|
|
124
|
+
fix: |
|
|
125
|
+
<number-format-ui value="0.5" number-style="percent"></number-format-ui>
|
|
126
|
+
- wrong: |
|
|
127
|
+
<number-format-ui value="9.99" number-style="currency"></number-format-ui>
|
|
128
|
+
why: |
|
|
129
|
+
Missing [currency] code. Renders nothing rather than producing
|
|
130
|
+
malformed currency output.
|
|
131
|
+
fix: |
|
|
132
|
+
<number-format-ui value="9.99" number-style="currency" currency="USD"></number-format-ui>
|
|
133
|
+
examples:
|
|
134
|
+
- name: decimal
|
|
135
|
+
description: Plain locale-grouped number — default style.
|
|
136
|
+
a2ui: |
|
|
137
|
+
[
|
|
138
|
+
{
|
|
139
|
+
"id": "n",
|
|
140
|
+
"component": "NumberFormat",
|
|
141
|
+
"value": 1234567.89
|
|
142
|
+
}
|
|
143
|
+
]
|
|
144
|
+
- name: currency
|
|
145
|
+
description: USD currency display.
|
|
146
|
+
a2ui: |
|
|
147
|
+
[
|
|
148
|
+
{
|
|
149
|
+
"id": "n",
|
|
150
|
+
"component": "NumberFormat",
|
|
151
|
+
"value": 1299.99,
|
|
152
|
+
"numberStyle": "currency",
|
|
153
|
+
"currency": "USD"
|
|
154
|
+
}
|
|
155
|
+
]
|
|
156
|
+
- name: percent
|
|
157
|
+
description: Fraction → percent (0.876 → 87.6%).
|
|
158
|
+
a2ui: |
|
|
159
|
+
[
|
|
160
|
+
{
|
|
161
|
+
"id": "n",
|
|
162
|
+
"component": "NumberFormat",
|
|
163
|
+
"value": 0.876,
|
|
164
|
+
"numberStyle": "percent",
|
|
165
|
+
"maximumFractionDigits": 1
|
|
166
|
+
}
|
|
167
|
+
]
|
|
168
|
+
- name: compact
|
|
169
|
+
description: Compact-form (1.2M, 3.4K).
|
|
170
|
+
a2ui: |
|
|
171
|
+
[
|
|
172
|
+
{
|
|
173
|
+
"id": "n",
|
|
174
|
+
"component": "NumberFormat",
|
|
175
|
+
"value": 1234567,
|
|
176
|
+
"notation": "compact"
|
|
177
|
+
}
|
|
178
|
+
]
|
|
179
|
+
keywords:
|
|
180
|
+
- number-format
|
|
181
|
+
- format
|
|
182
|
+
- currency
|
|
183
|
+
- percent
|
|
184
|
+
- percentage
|
|
185
|
+
- compact
|
|
186
|
+
- number
|
|
187
|
+
- locale
|
|
188
|
+
- intl
|
|
189
|
+
synonyms:
|
|
190
|
+
number:
|
|
191
|
+
- number-format
|
|
192
|
+
- format
|
|
193
|
+
currency:
|
|
194
|
+
- number-format
|
|
195
|
+
- money
|
|
196
|
+
- price
|
|
197
|
+
percent:
|
|
198
|
+
- number-format
|
|
199
|
+
- percentage
|
|
200
|
+
related:
|
|
201
|
+
- stat
|
|
202
|
+
- text
|
|
203
|
+
- badge
|
|
204
|
+
- input
|
|
@@ -26,14 +26,28 @@
|
|
|
26
26
|
"type": "number",
|
|
27
27
|
"default": 1
|
|
28
28
|
},
|
|
29
|
+
"size": {
|
|
30
|
+
"description": "Universal size — threads through to every nested `<button-ui size=…>`\nso pagination honors the substrate's 24/30/36 px size system\n(with [density] modifier). Default `md` matches `<button-ui>`'s\ndefault; pass `size=\"sm\"` for a denser numbered row.\n",
|
|
31
|
+
"type": "string",
|
|
32
|
+
"enum": [
|
|
33
|
+
"sm",
|
|
34
|
+
"md",
|
|
35
|
+
"lg"
|
|
36
|
+
],
|
|
37
|
+
"default": "md"
|
|
38
|
+
},
|
|
29
39
|
"total": {
|
|
30
40
|
"description": "Total number of pages.",
|
|
31
41
|
"type": "number",
|
|
32
42
|
"default": 1
|
|
33
43
|
},
|
|
34
44
|
"variant": {
|
|
35
|
-
"description": "Visual variant",
|
|
45
|
+
"description": "Visual variant — `default` (ghost buttons w/ hover bg) or `button` (1×1 bordered cells; active page filled).",
|
|
36
46
|
"type": "string",
|
|
47
|
+
"enum": [
|
|
48
|
+
"default",
|
|
49
|
+
"button"
|
|
50
|
+
],
|
|
37
51
|
"default": "default"
|
|
38
52
|
}
|
|
39
53
|
},
|
|
@@ -44,7 +58,10 @@
|
|
|
44
58
|
"x-adiaui": {
|
|
45
59
|
"anti_patterns": [],
|
|
46
60
|
"category": "navigation",
|
|
47
|
-
"composes": [
|
|
61
|
+
"composes": [
|
|
62
|
+
"button-ui",
|
|
63
|
+
"icon-ui"
|
|
64
|
+
],
|
|
48
65
|
"events": {
|
|
49
66
|
"page-change": {
|
|
50
67
|
"description": "Fired when a page button is clicked. detail contains { page }.",
|