@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.
Files changed (126) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/components/badge/badge.a2ui.json +10 -0
  3. package/components/badge/badge.css +70 -0
  4. package/components/badge/badge.yaml +20 -0
  5. package/components/blockquote/blockquote.a2ui.json +121 -0
  6. package/components/blockquote/blockquote.class.js +68 -0
  7. package/components/blockquote/blockquote.css +46 -0
  8. package/components/blockquote/blockquote.d.ts +31 -0
  9. package/components/blockquote/blockquote.js +17 -0
  10. package/components/blockquote/blockquote.yaml +124 -0
  11. package/components/button/button.css +11 -3
  12. package/components/calendar-picker/calendar-picker.a2ui.json +15 -0
  13. package/components/calendar-picker/calendar-picker.class.js +7 -1
  14. package/components/calendar-picker/calendar-picker.yaml +14 -0
  15. package/components/color-input/color-input.a2ui.json +2 -2
  16. package/components/color-input/color-input.class.js +9 -2
  17. package/components/color-input/color-input.yaml +2 -2
  18. package/components/combobox/combobox.class.js +4 -0
  19. package/components/combobox/combobox.css +12 -0
  20. package/components/context-menu/context-menu.a2ui.json +159 -0
  21. package/components/context-menu/context-menu.class.js +275 -0
  22. package/components/context-menu/context-menu.css +56 -0
  23. package/components/context-menu/context-menu.d.ts +70 -0
  24. package/components/context-menu/context-menu.js +17 -0
  25. package/components/context-menu/context-menu.yaml +136 -0
  26. package/components/date-range-picker/date-range-picker.a2ui.json +15 -0
  27. package/components/date-range-picker/date-range-picker.class.js +3 -1
  28. package/components/date-range-picker/date-range-picker.css +4 -1
  29. package/components/date-range-picker/date-range-picker.yaml +14 -0
  30. package/components/datetime-picker/datetime-picker.a2ui.json +15 -0
  31. package/components/datetime-picker/datetime-picker.class.js +3 -1
  32. package/components/datetime-picker/datetime-picker.css +7 -1
  33. package/components/datetime-picker/datetime-picker.d.ts +2 -0
  34. package/components/datetime-picker/datetime-picker.yaml +14 -0
  35. package/components/empty-state/empty-state.class.js +2 -0
  36. package/components/feed/feed.class.js +13 -5
  37. package/components/feed/feed.css +14 -0
  38. package/components/index.js +9 -0
  39. package/components/input/input.css +15 -1
  40. package/components/input/input.test.js +40 -0
  41. package/components/integration-card/integration-card.class.js +9 -0
  42. package/components/integration-card/integration-card.test.js +4 -3
  43. package/components/nav-group/nav-group.css +7 -1
  44. package/components/number-format/number-format.a2ui.json +180 -0
  45. package/components/number-format/number-format.class.js +96 -0
  46. package/components/number-format/number-format.css +18 -0
  47. package/components/number-format/number-format.d.ts +68 -0
  48. package/components/number-format/number-format.js +17 -0
  49. package/components/number-format/number-format.yaml +204 -0
  50. package/components/pagination/pagination.a2ui.json +19 -2
  51. package/components/pagination/pagination.class.js +90 -37
  52. package/components/pagination/pagination.css +32 -127
  53. package/components/pagination/pagination.d.ts +8 -2
  54. package/components/pagination/pagination.test.js +195 -0
  55. package/components/pagination/pagination.yaml +22 -1
  56. package/components/password-strength/password-strength.a2ui.json +152 -0
  57. package/components/password-strength/password-strength.class.js +157 -0
  58. package/components/password-strength/password-strength.css +80 -0
  59. package/components/password-strength/password-strength.d.ts +59 -0
  60. package/components/password-strength/password-strength.js +17 -0
  61. package/components/password-strength/password-strength.yaml +153 -0
  62. package/components/popover/popover.css +43 -23
  63. package/components/popover/popover.yaml +8 -4
  64. package/components/qr-code/QR-TEST.svg +4 -0
  65. package/components/qr-code/qr-code.a2ui.json +154 -0
  66. package/components/qr-code/qr-code.class.js +129 -0
  67. package/components/qr-code/qr-code.css +41 -0
  68. package/components/qr-code/qr-code.d.ts +83 -0
  69. package/components/qr-code/qr-code.js +17 -0
  70. package/components/qr-code/qr-code.yaml +203 -0
  71. package/components/qr-code/qr-encoder.js +633 -0
  72. package/components/relative-time/relative-time.a2ui.json +120 -0
  73. package/components/relative-time/relative-time.class.js +136 -0
  74. package/components/relative-time/relative-time.css +22 -0
  75. package/components/relative-time/relative-time.d.ts +51 -0
  76. package/components/relative-time/relative-time.js +17 -0
  77. package/components/relative-time/relative-time.yaml +133 -0
  78. package/components/search/search.class.js +2 -0
  79. package/components/segmented/segmented.class.js +5 -1
  80. package/components/select/select.class.js +4 -0
  81. package/components/skip-nav/skip-nav.a2ui.json +92 -0
  82. package/components/skip-nav/skip-nav.class.js +45 -0
  83. package/components/skip-nav/skip-nav.css +54 -0
  84. package/components/skip-nav/skip-nav.d.ts +27 -0
  85. package/components/skip-nav/skip-nav.js +12 -0
  86. package/components/skip-nav/skip-nav.yaml +68 -0
  87. package/components/slider/slider.a2ui.json +16 -1
  88. package/components/slider/slider.class.js +264 -122
  89. package/components/slider/slider.css +82 -2
  90. package/components/slider/slider.d.ts +19 -3
  91. package/components/slider/slider.test.js +55 -0
  92. package/components/slider/slider.yaml +28 -6
  93. package/components/table/table.class.js +29 -6
  94. package/components/table/table.css +31 -4
  95. package/components/table-toolbar/table-toolbar.class.js +4 -1
  96. package/components/tag/tag.a2ui.json +10 -0
  97. package/components/tag/tag.class.js +8 -1
  98. package/components/tag/tag.css +108 -20
  99. package/components/tag/tag.d.ts +14 -0
  100. package/components/tag/tag.test.js +99 -1
  101. package/components/tag/tag.yaml +20 -0
  102. package/components/tags-input/tags-input.class.js +10 -3
  103. package/components/tags-input/tags-input.css +12 -3
  104. package/components/textarea/textarea.css +10 -1
  105. package/components/toast/toast.class.js +12 -4
  106. package/components/toc/toc.a2ui.json +159 -0
  107. package/components/toc/toc.class.js +222 -0
  108. package/components/toc/toc.css +92 -0
  109. package/components/toc/toc.d.ts +61 -0
  110. package/components/toc/toc.js +17 -0
  111. package/components/toc/toc.yaml +180 -0
  112. package/components/toolbar/toolbar.class.js +3 -0
  113. package/components/visually-hidden/visually-hidden.a2ui.json +71 -0
  114. package/components/visually-hidden/visually-hidden.class.js +14 -0
  115. package/components/visually-hidden/visually-hidden.css +25 -0
  116. package/components/visually-hidden/visually-hidden.d.ts +26 -0
  117. package/components/visually-hidden/visually-hidden.js +12 -0
  118. package/components/visually-hidden/visually-hidden.yaml +54 -0
  119. package/core/anchor.js +19 -3
  120. package/core/provider.js +19 -2
  121. package/dist/web-components.min.css +1 -1
  122. package/dist/web-components.min.js +101 -89
  123. package/package.json +1 -1
  124. package/styles/colors/semantics.css +11 -2
  125. package/styles/components.css +9 -0
  126. 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 }.",