@joanroucoux/cairn-ui 0.8.2 → 0.9.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.
Files changed (124) hide show
  1. package/CHANGELOG.md +99 -0
  2. package/fesm2022/joanroucoux-cairn-ui-action-bar.mjs +57 -53
  3. package/fesm2022/joanroucoux-cairn-ui-action-bar.mjs.map +1 -1
  4. package/fesm2022/joanroucoux-cairn-ui-alert.mjs +155 -47
  5. package/fesm2022/joanroucoux-cairn-ui-alert.mjs.map +1 -1
  6. package/fesm2022/joanroucoux-cairn-ui-amount.mjs +220 -110
  7. package/fesm2022/joanroucoux-cairn-ui-amount.mjs.map +1 -1
  8. package/fesm2022/joanroucoux-cairn-ui-async.mjs +392 -216
  9. package/fesm2022/joanroucoux-cairn-ui-async.mjs.map +1 -1
  10. package/fesm2022/joanroucoux-cairn-ui-avatar.mjs +145 -68
  11. package/fesm2022/joanroucoux-cairn-ui-avatar.mjs.map +1 -1
  12. package/fesm2022/joanroucoux-cairn-ui-back-link.mjs +87 -47
  13. package/fesm2022/joanroucoux-cairn-ui-back-link.mjs.map +1 -1
  14. package/fesm2022/joanroucoux-cairn-ui-badge.mjs +83 -43
  15. package/fesm2022/joanroucoux-cairn-ui-badge.mjs.map +1 -1
  16. package/fesm2022/joanroucoux-cairn-ui-button.mjs +184 -104
  17. package/fesm2022/joanroucoux-cairn-ui-button.mjs.map +1 -1
  18. package/fesm2022/joanroucoux-cairn-ui-card.mjs +232 -137
  19. package/fesm2022/joanroucoux-cairn-ui-card.mjs.map +1 -1
  20. package/fesm2022/joanroucoux-cairn-ui-choice-chips.mjs +298 -102
  21. package/fesm2022/joanroucoux-cairn-ui-choice-chips.mjs.map +1 -1
  22. package/fesm2022/joanroucoux-cairn-ui-control.mjs +4 -17
  23. package/fesm2022/joanroucoux-cairn-ui-control.mjs.map +1 -1
  24. package/fesm2022/joanroucoux-cairn-ui-delta.mjs +150 -83
  25. package/fesm2022/joanroucoux-cairn-ui-delta.mjs.map +1 -1
  26. package/fesm2022/joanroucoux-cairn-ui-dialog.mjs +508 -471
  27. package/fesm2022/joanroucoux-cairn-ui-dialog.mjs.map +1 -1
  28. package/fesm2022/joanroucoux-cairn-ui-donut.mjs +255 -157
  29. package/fesm2022/joanroucoux-cairn-ui-donut.mjs.map +1 -1
  30. package/fesm2022/joanroucoux-cairn-ui-drawer.mjs +303 -0
  31. package/fesm2022/joanroucoux-cairn-ui-drawer.mjs.map +1 -0
  32. package/fesm2022/joanroucoux-cairn-ui-empty.mjs +76 -35
  33. package/fesm2022/joanroucoux-cairn-ui-empty.mjs.map +1 -1
  34. package/fesm2022/joanroucoux-cairn-ui-external-link.mjs +40 -31
  35. package/fesm2022/joanroucoux-cairn-ui-external-link.mjs.map +1 -1
  36. package/fesm2022/joanroucoux-cairn-ui-fact.mjs +188 -79
  37. package/fesm2022/joanroucoux-cairn-ui-fact.mjs.map +1 -1
  38. package/fesm2022/joanroucoux-cairn-ui-field.mjs +309 -173
  39. package/fesm2022/joanroucoux-cairn-ui-field.mjs.map +1 -1
  40. package/fesm2022/joanroucoux-cairn-ui-filter-chips.mjs +165 -87
  41. package/fesm2022/joanroucoux-cairn-ui-filter-chips.mjs.map +1 -1
  42. package/fesm2022/joanroucoux-cairn-ui-group-header.mjs +269 -0
  43. package/fesm2022/joanroucoux-cairn-ui-group-header.mjs.map +1 -0
  44. package/fesm2022/joanroucoux-cairn-ui-input.mjs +205 -85
  45. package/fesm2022/joanroucoux-cairn-ui-input.mjs.map +1 -1
  46. package/fesm2022/joanroucoux-cairn-ui-line-chart.mjs +838 -512
  47. package/fesm2022/joanroucoux-cairn-ui-line-chart.mjs.map +1 -1
  48. package/fesm2022/joanroucoux-cairn-ui-menu.mjs +401 -225
  49. package/fesm2022/joanroucoux-cairn-ui-menu.mjs.map +1 -1
  50. package/fesm2022/joanroucoux-cairn-ui-meter.mjs +143 -57
  51. package/fesm2022/joanroucoux-cairn-ui-meter.mjs.map +1 -1
  52. package/fesm2022/joanroucoux-cairn-ui-motion.mjs +367 -399
  53. package/fesm2022/joanroucoux-cairn-ui-motion.mjs.map +1 -1
  54. package/fesm2022/joanroucoux-cairn-ui-nav-item.mjs +73 -44
  55. package/fesm2022/joanroucoux-cairn-ui-nav-item.mjs.map +1 -1
  56. package/fesm2022/joanroucoux-cairn-ui-result-group.mjs +191 -0
  57. package/fesm2022/joanroucoux-cairn-ui-result-group.mjs.map +1 -0
  58. package/fesm2022/joanroucoux-cairn-ui-row.mjs +376 -146
  59. package/fesm2022/joanroucoux-cairn-ui-row.mjs.map +1 -1
  60. package/fesm2022/joanroucoux-cairn-ui-segmented.mjs +183 -81
  61. package/fesm2022/joanroucoux-cairn-ui-segmented.mjs.map +1 -1
  62. package/fesm2022/joanroucoux-cairn-ui-select-pill.mjs +233 -0
  63. package/fesm2022/joanroucoux-cairn-ui-select-pill.mjs.map +1 -0
  64. package/fesm2022/joanroucoux-cairn-ui-select.mjs +121 -67
  65. package/fesm2022/joanroucoux-cairn-ui-select.mjs.map +1 -1
  66. package/fesm2022/joanroucoux-cairn-ui-skeleton.mjs +129 -51
  67. package/fesm2022/joanroucoux-cairn-ui-skeleton.mjs.map +1 -1
  68. package/fesm2022/joanroucoux-cairn-ui-stale-link.mjs +80 -39
  69. package/fesm2022/joanroucoux-cairn-ui-stale-link.mjs.map +1 -1
  70. package/fesm2022/joanroucoux-cairn-ui-stat.mjs +85 -55
  71. package/fesm2022/joanroucoux-cairn-ui-stat.mjs.map +1 -1
  72. package/fesm2022/joanroucoux-cairn-ui-switch.mjs +48 -35
  73. package/fesm2022/joanroucoux-cairn-ui-switch.mjs.map +1 -1
  74. package/fesm2022/joanroucoux-cairn-ui-tab-bar.mjs +113 -69
  75. package/fesm2022/joanroucoux-cairn-ui-tab-bar.mjs.map +1 -1
  76. package/fesm2022/joanroucoux-cairn-ui-table.mjs +1036 -310
  77. package/fesm2022/joanroucoux-cairn-ui-table.mjs.map +1 -1
  78. package/fesm2022/joanroucoux-cairn-ui-toast.mjs +240 -127
  79. package/fesm2022/joanroucoux-cairn-ui-toast.mjs.map +1 -1
  80. package/fesm2022/joanroucoux-cairn-ui.mjs +0 -4
  81. package/package.json +17 -1
  82. package/styles/motion.css +1 -13
  83. package/styles/tokens.css +35 -64
  84. package/types/joanroucoux-cairn-ui-action-bar.d.ts +9 -14
  85. package/types/joanroucoux-cairn-ui-alert.d.ts +29 -15
  86. package/types/joanroucoux-cairn-ui-amount.d.ts +64 -32
  87. package/types/joanroucoux-cairn-ui-async.d.ts +85 -38
  88. package/types/joanroucoux-cairn-ui-avatar.d.ts +34 -22
  89. package/types/joanroucoux-cairn-ui-back-link.d.ts +20 -15
  90. package/types/joanroucoux-cairn-ui-badge.d.ts +22 -14
  91. package/types/joanroucoux-cairn-ui-button.d.ts +36 -18
  92. package/types/joanroucoux-cairn-ui-card.d.ts +48 -23
  93. package/types/joanroucoux-cairn-ui-choice-chips.d.ts +91 -35
  94. package/types/joanroucoux-cairn-ui-control.d.ts +9 -18
  95. package/types/joanroucoux-cairn-ui-delta.d.ts +46 -24
  96. package/types/joanroucoux-cairn-ui-dialog.d.ts +124 -57
  97. package/types/joanroucoux-cairn-ui-donut.d.ts +83 -46
  98. package/types/joanroucoux-cairn-ui-drawer.d.ts +73 -0
  99. package/types/joanroucoux-cairn-ui-empty.d.ts +20 -13
  100. package/types/joanroucoux-cairn-ui-external-link.d.ts +6 -10
  101. package/types/joanroucoux-cairn-ui-fact.d.ts +49 -25
  102. package/types/joanroucoux-cairn-ui-field.d.ts +72 -49
  103. package/types/joanroucoux-cairn-ui-filter-chips.d.ts +35 -20
  104. package/types/joanroucoux-cairn-ui-group-header.d.ts +58 -0
  105. package/types/joanroucoux-cairn-ui-input.d.ts +59 -37
  106. package/types/joanroucoux-cairn-ui-line-chart.d.ts +199 -89
  107. package/types/joanroucoux-cairn-ui-menu.d.ts +81 -44
  108. package/types/joanroucoux-cairn-ui-meter.d.ts +44 -22
  109. package/types/joanroucoux-cairn-ui-motion.d.ts +61 -75
  110. package/types/joanroucoux-cairn-ui-nav-item.d.ts +15 -13
  111. package/types/joanroucoux-cairn-ui-result-group.d.ts +52 -0
  112. package/types/joanroucoux-cairn-ui-row.d.ts +79 -37
  113. package/types/joanroucoux-cairn-ui-segmented.d.ts +51 -27
  114. package/types/joanroucoux-cairn-ui-select-pill.d.ts +52 -0
  115. package/types/joanroucoux-cairn-ui-select.d.ts +28 -18
  116. package/types/joanroucoux-cairn-ui-skeleton.d.ts +35 -18
  117. package/types/joanroucoux-cairn-ui-stale-link.d.ts +23 -16
  118. package/types/joanroucoux-cairn-ui-stat.d.ts +26 -21
  119. package/types/joanroucoux-cairn-ui-switch.d.ts +7 -11
  120. package/types/joanroucoux-cairn-ui-tab-bar.d.ts +20 -17
  121. package/types/joanroucoux-cairn-ui-table.d.ts +251 -89
  122. package/types/joanroucoux-cairn-ui-toast.d.ts +46 -36
  123. package/types/joanroucoux-cairn-ui.d.ts +1 -2
  124. package/fesm2022/joanroucoux-cairn-ui.mjs.map +0 -1
@@ -1,114 +1,224 @@
1
- import * as i0 from '@angular/core';
2
- import { InjectionToken, signal, input, inject, LOCALE_ID, booleanAttribute, computed, Component } from '@angular/core';
3
-
4
- const MINUS = '−';
5
- const EM_DASH = '—';
6
- const BULLETS = '••••';
7
- /** Formats a number or an amount for the locale, with a missing value as an em dash and masking behind four bullets. */
1
+ import * as i0 from "@angular/core";
2
+ import { Component, InjectionToken, LOCALE_ID, booleanAttribute, computed, inject, input, signal } from "@angular/core";
3
+ const MINUS = "−";
4
+ const EM_DASH = "—";
5
+ const BULLETS = "••••";
8
6
  function formatAmount(value, options, masked = false) {
9
- if (value === null || value === undefined || Number.isNaN(value)) {
10
- return EM_DASH;
11
- }
12
- const digits = options.fractionDigits ?? 2;
13
- const format = new Intl.NumberFormat(options.locale, {
14
- ...(options.currency ? { style: 'currency', currency: options.currency } : {}),
15
- minimumFractionDigits: digits,
16
- maximumFractionDigits: digits,
17
- });
18
- const magnitude = Math.abs(value);
19
- const parts = format.formatToParts(magnitude);
20
- if (masked) {
21
- let replaced = false;
22
- return parts
23
- .map((part) => {
24
- if (['integer', 'group', 'decimal', 'fraction'].includes(part.type)) {
25
- if (replaced) {
26
- return '';
27
- }
28
- replaced = true;
29
- return BULLETS;
30
- }
31
- return part.value;
32
- })
33
- .join('');
34
- }
35
- const text = parts.map((part) => part.value).join('');
36
- const isZero = Number(format.format(magnitude).replace(/[^\d]/g, '')) === 0;
37
- if (!options.signed || isZero) {
38
- return value < 0 && !isZero ? `${MINUS}${text}` : text;
39
- }
40
- return `${value > 0 ? '+' : MINUS}${text}`;
7
+ if (value === null || value === void 0 || Number.isNaN(value)) return EM_DASH;
8
+ const digits = options.fractionDigits ?? 2;
9
+ const format = new Intl.NumberFormat(options.locale, {
10
+ ...options.currency ? {
11
+ style: "currency",
12
+ currency: options.currency
13
+ } : {},
14
+ minimumFractionDigits: digits,
15
+ maximumFractionDigits: digits
16
+ });
17
+ const magnitude = Math.abs(value);
18
+ const parts = format.formatToParts(magnitude);
19
+ if (masked) {
20
+ let replaced = false;
21
+ return parts.map((part) => {
22
+ if ([
23
+ "integer",
24
+ "group",
25
+ "decimal",
26
+ "fraction"
27
+ ].includes(part.type)) {
28
+ if (replaced) return "";
29
+ replaced = true;
30
+ return BULLETS;
31
+ }
32
+ return part.value;
33
+ }).join("");
34
+ }
35
+ const text = parts.map((part) => part.value).join("");
36
+ const isZero = Number(format.format(magnitude).replace(/[^\d]/g, "")) === 0;
37
+ if (!options.signed || isZero) return value < 0 && !isZero ? `${MINUS}${text}` : text;
38
+ return `${value > 0 ? "+" : MINUS}${text}`;
41
39
  }
42
-
43
- /** App-wide "amounts are hidden" state. Defaults to never masked; the app overrides it. */
44
- const UI_AMOUNT_MASKED = new InjectionToken('UI_AMOUNT_MASKED', {
45
- providedIn: 'root',
46
- factory: () => signal(false),
40
+ const UI_AMOUNT_MASKED = new InjectionToken("UI_AMOUNT_MASKED", {
41
+ providedIn: "root",
42
+ factory: () => signal(false)
43
+ });
44
+ const AMOUNT_NUMERICS = ["tabular", "proportional"];
45
+ const AMOUNT_MASKINGS = ["dots", "hide"];
46
+ var UiAmount = class UiAmount {
47
+ value = input(...ngDevMode ? [void 0, { debugName: "value" }] : /* istanbul ignore next */ []);
48
+ currency = input(...ngDevMode ? [void 0, { debugName: "currency" }] : /* istanbul ignore next */ []);
49
+ locale = input(inject(LOCALE_ID), ...ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []);
50
+ signed = input(false, {
51
+ ...ngDevMode ? { debugName: "signed" } : /* istanbul ignore next */ {},
52
+ transform: booleanAttribute
53
+ });
54
+ fractionDigits = input(2, ...ngDevMode ? [{ debugName: "fractionDigits" }] : /* istanbul ignore next */ []);
55
+ numeric = input("tabular", ...ngDevMode ? [{ debugName: "numeric" }] : /* istanbul ignore next */ []);
56
+ whenMasked = input("dots", ...ngDevMode ? [{ debugName: "whenMasked" }] : /* istanbul ignore next */ []);
57
+ #masked = inject(UI_AMOUNT_MASKED);
58
+ hidden = computed(() => this.#masked() && this.whenMasked() === "hide", ...ngDevMode ? [{ debugName: "hidden" }] : /* istanbul ignore next */ []);
59
+ text = computed(() => formatAmount(this.value(), {
60
+ locale: this.locale(),
61
+ currency: this.currency(),
62
+ signed: this.signed(),
63
+ fractionDigits: this.fractionDigits()
64
+ }, this.#masked()), ...ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []);
65
+ classes = computed(() => {
66
+ const missing = this.value() === null || this.value() === void 0;
67
+ return [
68
+ "whitespace-nowrap",
69
+ this.numeric() === "tabular" ? "tabular-nums" : "",
70
+ missing ? "text-(--subtle-foreground)" : ""
71
+ ].filter(Boolean).join(" ");
72
+ }, ...ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []);
73
+ static ɵfac = i0.ɵɵngDeclareFactory({
74
+ minVersion: "12.0.0",
75
+ version: "22.2.0",
76
+ ngImport: i0,
77
+ type: UiAmount,
78
+ deps: [],
79
+ target: i0.ɵɵFactoryTarget.Component
80
+ });
81
+ static ɵcmp = i0.ɵɵngDeclareComponent({
82
+ minVersion: "17.1.0",
83
+ version: "22.2.0",
84
+ type: UiAmount,
85
+ isStandalone: true,
86
+ selector: "ui-amount",
87
+ inputs: {
88
+ value: {
89
+ classPropertyName: "value",
90
+ publicName: "value",
91
+ isSignal: true,
92
+ isRequired: false,
93
+ transformFunction: null
94
+ },
95
+ currency: {
96
+ classPropertyName: "currency",
97
+ publicName: "currency",
98
+ isSignal: true,
99
+ isRequired: false,
100
+ transformFunction: null
101
+ },
102
+ locale: {
103
+ classPropertyName: "locale",
104
+ publicName: "locale",
105
+ isSignal: true,
106
+ isRequired: false,
107
+ transformFunction: null
108
+ },
109
+ signed: {
110
+ classPropertyName: "signed",
111
+ publicName: "signed",
112
+ isSignal: true,
113
+ isRequired: false,
114
+ transformFunction: null
115
+ },
116
+ fractionDigits: {
117
+ classPropertyName: "fractionDigits",
118
+ publicName: "fractionDigits",
119
+ isSignal: true,
120
+ isRequired: false,
121
+ transformFunction: null
122
+ },
123
+ numeric: {
124
+ classPropertyName: "numeric",
125
+ publicName: "numeric",
126
+ isSignal: true,
127
+ isRequired: false,
128
+ transformFunction: null
129
+ },
130
+ whenMasked: {
131
+ classPropertyName: "whenMasked",
132
+ publicName: "whenMasked",
133
+ isSignal: true,
134
+ isRequired: false,
135
+ transformFunction: null
136
+ }
137
+ },
138
+ host: { properties: {
139
+ "class": "classes()",
140
+ "attr.hidden": "hidden() || null"
141
+ } },
142
+ ngImport: i0,
143
+ template: "{{ text() }}",
144
+ isInline: true
145
+ });
146
+ };
147
+ i0.ɵɵngDeclareClassMetadata({
148
+ minVersion: "12.0.0",
149
+ version: "22.2.0",
150
+ ngImport: i0,
151
+ type: UiAmount,
152
+ decorators: [{
153
+ type: Component,
154
+ args: [{
155
+ selector: "ui-amount",
156
+ template: "{{ text() }}",
157
+ host: {
158
+ "[class]": "classes()",
159
+ "[attr.hidden]": "hidden() || null"
160
+ }
161
+ }]
162
+ }],
163
+ propDecorators: {
164
+ value: [{
165
+ type: i0.Input,
166
+ args: [{
167
+ isSignal: true,
168
+ alias: "value",
169
+ required: false
170
+ }]
171
+ }],
172
+ currency: [{
173
+ type: i0.Input,
174
+ args: [{
175
+ isSignal: true,
176
+ alias: "currency",
177
+ required: false
178
+ }]
179
+ }],
180
+ locale: [{
181
+ type: i0.Input,
182
+ args: [{
183
+ isSignal: true,
184
+ alias: "locale",
185
+ required: false
186
+ }]
187
+ }],
188
+ signed: [{
189
+ type: i0.Input,
190
+ args: [{
191
+ isSignal: true,
192
+ alias: "signed",
193
+ required: false
194
+ }]
195
+ }],
196
+ fractionDigits: [{
197
+ type: i0.Input,
198
+ args: [{
199
+ isSignal: true,
200
+ alias: "fractionDigits",
201
+ required: false
202
+ }]
203
+ }],
204
+ numeric: [{
205
+ type: i0.Input,
206
+ args: [{
207
+ isSignal: true,
208
+ alias: "numeric",
209
+ required: false
210
+ }]
211
+ }],
212
+ whenMasked: [{
213
+ type: i0.Input,
214
+ args: [{
215
+ isSignal: true,
216
+ alias: "whenMasked",
217
+ required: false
218
+ }]
219
+ }]
220
+ }
47
221
  });
48
- /** Available figure styles. `AmountNumeric` is derived from this tuple. */
49
- const AMOUNT_NUMERICS = ['tabular', 'proportional'];
50
- /** Available masking behaviors. `AmountMasking` is derived from this tuple. */
51
- const AMOUNT_MASKINGS = ['dots', 'hide'];
52
- /**
53
- * A number or an amount of money, formatted for the locale and masked when the app hides amounts.
54
- *
55
- * @example
56
- * <ui-amount [value]="total" currency="EUR" numeric="proportional" />
57
- * <ui-amount [value]="dayChange" currency="EUR" signed whenMasked="hide" />
58
- */
59
- class UiAmount {
60
- value = input(/* @ts-ignore */
61
- ...(ngDevMode ? [undefined, { debugName: "value" }] : /* istanbul ignore next */ []));
62
- currency = input(/* @ts-ignore */
63
- ...(ngDevMode ? [undefined, { debugName: "currency" }] : /* istanbul ignore next */ []));
64
- locale = input(inject(LOCALE_ID), /* @ts-ignore */
65
- ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
66
- signed = input(false, { ...(ngDevMode ? { debugName: "signed" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
67
- fractionDigits = input(2, /* @ts-ignore */
68
- ...(ngDevMode ? [{ debugName: "fractionDigits" }] : /* istanbul ignore next */ []));
69
- numeric = input('tabular', /* @ts-ignore */
70
- ...(ngDevMode ? [{ debugName: "numeric" }] : /* istanbul ignore next */ []));
71
- whenMasked = input('dots', /* @ts-ignore */
72
- ...(ngDevMode ? [{ debugName: "whenMasked" }] : /* istanbul ignore next */ []));
73
- #masked = inject(UI_AMOUNT_MASKED);
74
- hidden = computed(() => this.#masked() && this.whenMasked() === 'hide', /* @ts-ignore */
75
- ...(ngDevMode ? [{ debugName: "hidden" }] : /* istanbul ignore next */ []));
76
- text = computed(() => formatAmount(this.value(), {
77
- locale: this.locale(),
78
- currency: this.currency(),
79
- signed: this.signed(),
80
- fractionDigits: this.fractionDigits(),
81
- }, this.#masked()), /* @ts-ignore */
82
- ...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []));
83
- classes = computed(() => {
84
- const missing = this.value() === null || this.value() === undefined;
85
- return [
86
- 'whitespace-nowrap',
87
- this.numeric() === 'tabular' ? 'tabular-nums' : '',
88
- missing ? 'text-(--subtle-foreground)' : '',
89
- ]
90
- .filter(Boolean)
91
- .join(' ');
92
- }, /* @ts-ignore */
93
- ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
94
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: UiAmount, deps: [], target: i0.ɵɵFactoryTarget.Component });
95
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.7", type: UiAmount, isStandalone: true, selector: "ui-amount", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, currency: { classPropertyName: "currency", publicName: "currency", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, signed: { classPropertyName: "signed", publicName: "signed", isSignal: true, isRequired: false, transformFunction: null }, fractionDigits: { classPropertyName: "fractionDigits", publicName: "fractionDigits", isSignal: true, isRequired: false, transformFunction: null }, numeric: { classPropertyName: "numeric", publicName: "numeric", isSignal: true, isRequired: false, transformFunction: null }, whenMasked: { classPropertyName: "whenMasked", publicName: "whenMasked", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()", "attr.hidden": "hidden() || null" } }, ngImport: i0, template: '{{ text() }}', isInline: true });
96
- }
97
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: UiAmount, decorators: [{
98
- type: Component,
99
- args: [{
100
- selector: 'ui-amount',
101
- template: '{{ text() }}',
102
- host: {
103
- '[class]': 'classes()',
104
- '[attr.hidden]': 'hidden() || null',
105
- },
106
- }]
107
- }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], currency: [{ type: i0.Input, args: [{ isSignal: true, alias: "currency", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], signed: [{ type: i0.Input, args: [{ isSignal: true, alias: "signed", required: false }] }], fractionDigits: [{ type: i0.Input, args: [{ isSignal: true, alias: "fractionDigits", required: false }] }], numeric: [{ type: i0.Input, args: [{ isSignal: true, alias: "numeric", required: false }] }], whenMasked: [{ type: i0.Input, args: [{ isSignal: true, alias: "whenMasked", required: false }] }] } });
108
-
109
- /**
110
- * Generated bundle index. Do not edit.
111
- */
112
-
113
222
  export { AMOUNT_MASKINGS, AMOUNT_NUMERICS, UI_AMOUNT_MASKED, UiAmount, formatAmount };
114
- //# sourceMappingURL=joanroucoux-cairn-ui-amount.mjs.map
223
+
224
+ //# sourceMappingURL=joanroucoux-cairn-ui-amount.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"joanroucoux-cairn-ui-amount.mjs","sources":["../../../projects/ui/amount/format-amount.ts","../../../projects/ui/amount/amount.ts","../../../projects/ui/amount/joanroucoux-cairn-ui-amount.ts"],"sourcesContent":["const MINUS = '−';\nconst EM_DASH = '—';\nconst BULLETS = '••••';\n\nexport type AmountFormatOptions = {\n locale: string;\n currency?: string;\n signed?: boolean;\n fractionDigits?: number;\n};\n\n/** Formats a number or an amount for the locale, with a missing value as an em dash and masking behind four bullets. */\nexport function formatAmount(value: number | null | undefined, options: AmountFormatOptions, masked = false): string {\n if (value === null || value === undefined || Number.isNaN(value)) {\n return EM_DASH;\n }\n const digits = options.fractionDigits ?? 2;\n const format = new Intl.NumberFormat(options.locale, {\n ...(options.currency ? { style: 'currency', currency: options.currency } : {}),\n minimumFractionDigits: digits,\n maximumFractionDigits: digits,\n });\n const magnitude = Math.abs(value);\n const parts = format.formatToParts(magnitude);\n\n if (masked) {\n let replaced = false;\n return parts\n .map((part) => {\n if (['integer', 'group', 'decimal', 'fraction'].includes(part.type)) {\n if (replaced) {\n return '';\n }\n replaced = true;\n return BULLETS;\n }\n return part.value;\n })\n .join('');\n }\n\n const text = parts.map((part) => part.value).join('');\n const isZero = Number(format.format(magnitude).replace(/[^\\d]/g, '')) === 0;\n if (!options.signed || isZero) {\n return value < 0 && !isZero ? `${MINUS}${text}` : text;\n }\n return `${value > 0 ? '+' : MINUS}${text}`;\n}\n","import {\n Component,\n InjectionToken,\n LOCALE_ID,\n type Signal,\n booleanAttribute,\n computed,\n inject,\n input,\n signal,\n} from '@angular/core';\n\nimport { formatAmount } from './format-amount';\n\n/** App-wide \"amounts are hidden\" state. Defaults to never masked; the app overrides it. */\nexport const UI_AMOUNT_MASKED = new InjectionToken<Signal<boolean>>('UI_AMOUNT_MASKED', {\n providedIn: 'root',\n factory: () => signal(false),\n});\n\n/** Available figure styles. `AmountNumeric` is derived from this tuple. */\nexport const AMOUNT_NUMERICS = ['tabular', 'proportional'] as const;\nexport type AmountNumeric = (typeof AMOUNT_NUMERICS)[number];\n\n/** Available masking behaviors. `AmountMasking` is derived from this tuple. */\nexport const AMOUNT_MASKINGS = ['dots', 'hide'] as const;\nexport type AmountMasking = (typeof AMOUNT_MASKINGS)[number];\n\n/**\n * A number or an amount of money, formatted for the locale and masked when the app hides amounts.\n *\n * @example\n * <ui-amount [value]=\"total\" currency=\"EUR\" numeric=\"proportional\" />\n * <ui-amount [value]=\"dayChange\" currency=\"EUR\" signed whenMasked=\"hide\" />\n */\n@Component({\n selector: 'ui-amount',\n template: '{{ text() }}',\n host: {\n '[class]': 'classes()',\n '[attr.hidden]': 'hidden() || null',\n },\n})\nexport class UiAmount {\n readonly value = input<number | null | undefined>();\n readonly currency = input<string>();\n readonly locale = input<string>(inject(LOCALE_ID));\n readonly signed = input(false, { transform: booleanAttribute });\n readonly fractionDigits = input(2);\n readonly numeric = input<AmountNumeric>('tabular');\n readonly whenMasked = input<AmountMasking>('dots');\n\n readonly #masked = inject(UI_AMOUNT_MASKED);\n\n protected readonly hidden = computed(() => this.#masked() && this.whenMasked() === 'hide');\n\n protected readonly text = computed(() =>\n formatAmount(\n this.value(),\n {\n locale: this.locale(),\n currency: this.currency(),\n signed: this.signed(),\n fractionDigits: this.fractionDigits(),\n },\n this.#masked(),\n ),\n );\n\n protected readonly classes = computed(() => {\n const missing = this.value() === null || this.value() === undefined;\n\n return [\n 'whitespace-nowrap',\n this.numeric() === 'tabular' ? 'tabular-nums' : '',\n missing ? 'text-(--subtle-foreground)' : '',\n ]\n .filter(Boolean)\n .join(' ');\n });\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;AAAA,MAAM,KAAK,GAAG,GAAG;AACjB,MAAM,OAAO,GAAG,GAAG;AACnB,MAAM,OAAO,GAAG,MAAM;AAStB;AACM,SAAU,YAAY,CAAC,KAAgC,EAAE,OAA4B,EAAE,MAAM,GAAG,KAAK,EAAA;AACzG,IAAA,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;AAChE,QAAA,OAAO,OAAO;IAChB;AACA,IAAA,MAAM,MAAM,GAAG,OAAO,CAAC,cAAc,IAAI,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE;QACnD,IAAI,OAAO,CAAC,QAAQ,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC;AAC9E,QAAA,qBAAqB,EAAE,MAAM;AAC7B,QAAA,qBAAqB,EAAE,MAAM;AAC9B,KAAA,CAAC;IACF,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;IACjC,MAAM,KAAK,GAAG,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC;IAE7C,IAAI,MAAM,EAAE;QACV,IAAI,QAAQ,GAAG,KAAK;AACpB,QAAA,OAAO;AACJ,aAAA,GAAG,CAAC,CAAC,IAAI,KAAI;AACZ,YAAA,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBACnE,IAAI,QAAQ,EAAE;AACZ,oBAAA,OAAO,EAAE;gBACX;gBACA,QAAQ,GAAG,IAAI;AACf,gBAAA,OAAO,OAAO;YAChB;YACA,OAAO,IAAI,CAAC,KAAK;AACnB,QAAA,CAAC;aACA,IAAI,CAAC,EAAE,CAAC;IACb;IAEA,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;IACrD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC;AAC3E,IAAA,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,MAAM,EAAE;AAC7B,QAAA,OAAO,KAAK,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAA,EAAG,KAAK,GAAG,IAAI,CAAA,CAAE,GAAG,IAAI;IACxD;AACA,IAAA,OAAO,CAAA,EAAG,KAAK,GAAG,CAAC,GAAG,GAAG,GAAG,KAAK,CAAA,EAAG,IAAI,EAAE;AAC5C;;ACjCA;MACa,gBAAgB,GAAG,IAAI,cAAc,CAAkB,kBAAkB,EAAE;AACtF,IAAA,UAAU,EAAE,MAAM;AAClB,IAAA,OAAO,EAAE,MAAM,MAAM,CAAC,KAAK,CAAC;AAC7B,CAAA;AAED;MACa,eAAe,GAAG,CAAC,SAAS,EAAE,cAAc;AAGzD;MACa,eAAe,GAAG,CAAC,MAAM,EAAE,MAAM;AAG9C;;;;;;AAMG;MASU,QAAQ,CAAA;AACV,IAAA,KAAK,GAAG,KAAK;yFAA6B;AAC1C,IAAA,QAAQ,GAAG,KAAK;4FAAU;AAC1B,IAAA,MAAM,GAAG,KAAK,CAAS,MAAM,CAAC,SAAS,CAAC;+EAAC;IACzC,MAAM,GAAG,KAAK,CAAC,KAAK,8EAAI,SAAS,EAAE,gBAAgB,EAAA,CAAG;IACtD,cAAc,GAAG,KAAK,CAAC,CAAC;uFAAC;IACzB,OAAO,GAAG,KAAK,CAAgB,SAAS;gFAAC;IACzC,UAAU,GAAG,KAAK,CAAgB,MAAM;mFAAC;AAEzC,IAAA,OAAO,GAAG,MAAM,CAAC,gBAAgB,CAAC;AAExB,IAAA,MAAM,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,IAAI,IAAI,CAAC,UAAU,EAAE,KAAK,MAAM;+EAAC;AAEvE,IAAA,IAAI,GAAG,QAAQ,CAAC,MACjC,YAAY,CACV,IAAI,CAAC,KAAK,EAAE,EACZ;AACE,QAAA,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE;AACrB,QAAA,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE;AACzB,QAAA,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE;AACrB,QAAA,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE;AACtC,KAAA,EACD,IAAI,CAAC,OAAO,EAAE,CACf;6EACF;AAEkB,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAK;AACzC,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,EAAE,KAAK,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,KAAK,SAAS;QAEnE,OAAO;YACL,mBAAmB;AACnB,YAAA,IAAI,CAAC,OAAO,EAAE,KAAK,SAAS,GAAG,cAAc,GAAG,EAAE;AAClD,YAAA,OAAO,GAAG,4BAA4B,GAAG,EAAE;AAC5C;aACE,MAAM,CAAC,OAAO;aACd,IAAI,CAAC,GAAG,CAAC;IACd,CAAC;gFAAC;uGApCS,QAAQ,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAR,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,QAAQ,2iCANT,cAAc,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA;;2FAMb,QAAQ,EAAA,UAAA,EAAA,CAAA;kBARpB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,WAAW;AACrB,oBAAA,QAAQ,EAAE,cAAc;AACxB,oBAAA,IAAI,EAAE;AACJ,wBAAA,SAAS,EAAE,WAAW;AACtB,wBAAA,eAAe,EAAE,kBAAkB;AACpC,qBAAA;AACF,iBAAA;;;AC1CD;;AAEG;;;;"}
1
+ {"version":3,"file":"joanroucoux-cairn-ui-amount.mjs","names":[],"sources":["../../../projects/ui/amount/format-amount.ts","../../../projects/ui/amount/amount.ts"],"sourcesContent":["const MINUS = '−';\nconst EM_DASH = '—';\nconst BULLETS = '••••';\n\nexport type AmountFormatOptions = {\n locale: string;\n currency?: string;\n signed?: boolean;\n fractionDigits?: number;\n};\n\n/** Formats a number or an amount for the locale. A missing value is an em dash, a masked one four bullets. */\nexport function formatAmount(value: number | null | undefined, options: AmountFormatOptions, masked = false): string {\n if (value === null || value === undefined || Number.isNaN(value)) {\n return EM_DASH;\n }\n const digits = options.fractionDigits ?? 2;\n const format = new Intl.NumberFormat(options.locale, {\n ...(options.currency ? { style: 'currency', currency: options.currency } : {}),\n minimumFractionDigits: digits,\n maximumFractionDigits: digits,\n });\n const magnitude = Math.abs(value);\n const parts = format.formatToParts(magnitude);\n\n if (masked) {\n let replaced = false;\n return parts\n .map((part) => {\n if (['integer', 'group', 'decimal', 'fraction'].includes(part.type)) {\n if (replaced) {\n return '';\n }\n replaced = true;\n return BULLETS;\n }\n return part.value;\n })\n .join('');\n }\n\n const text = parts.map((part) => part.value).join('');\n const isZero = Number(format.format(magnitude).replace(/[^\\d]/g, '')) === 0;\n if (!options.signed || isZero) {\n return value < 0 && !isZero ? `${MINUS}${text}` : text;\n }\n return `${value > 0 ? '+' : MINUS}${text}`;\n}\n","import {\n Component,\n InjectionToken,\n LOCALE_ID,\n type Signal,\n booleanAttribute,\n computed,\n inject,\n input,\n signal,\n} from '@angular/core';\n\nimport { formatAmount } from './format-amount';\n\n/** App-wide \"amounts are hidden\" state. Defaults to never masked; the app overrides it. */\nexport const UI_AMOUNT_MASKED = new InjectionToken<Signal<boolean>>('UI_AMOUNT_MASKED', {\n providedIn: 'root',\n factory: () => signal(false),\n});\n\n/** Available figure styles. */\nexport const AMOUNT_NUMERICS = ['tabular', 'proportional'] as const;\nexport type AmountNumeric = (typeof AMOUNT_NUMERICS)[number];\n\n/** Available masking behaviors. */\nexport const AMOUNT_MASKINGS = ['dots', 'hide'] as const;\nexport type AmountMasking = (typeof AMOUNT_MASKINGS)[number];\n\n/**\n * A number or an amount of money, formatted for the locale and masked when the app hides amounts.\n *\n * @example\n * <ui-amount [value]=\"total\" currency=\"EUR\" numeric=\"proportional\" />\n * <ui-amount [value]=\"dayChange\" currency=\"EUR\" signed whenMasked=\"hide\" />\n */\n@Component({\n selector: 'ui-amount',\n template: '{{ text() }}',\n host: {\n '[class]': 'classes()',\n '[attr.hidden]': 'hidden() || null',\n },\n})\nexport class UiAmount {\n readonly value = input<number | null | undefined>();\n readonly currency = input<string>();\n readonly locale = input<string>(inject(LOCALE_ID));\n readonly signed = input(false, { transform: booleanAttribute });\n readonly fractionDigits = input(2);\n readonly numeric = input<AmountNumeric>('tabular');\n readonly whenMasked = input<AmountMasking>('dots');\n\n readonly #masked = inject(UI_AMOUNT_MASKED);\n\n protected readonly hidden = computed(() => this.#masked() && this.whenMasked() === 'hide');\n\n protected readonly text = computed(() =>\n formatAmount(\n this.value(),\n {\n locale: this.locale(),\n currency: this.currency(),\n signed: this.signed(),\n fractionDigits: this.fractionDigits(),\n },\n this.#masked(),\n ),\n );\n\n protected readonly classes = computed(() => {\n const missing = this.value() === null || this.value() === undefined;\n\n return [\n 'whitespace-nowrap',\n this.numeric() === 'tabular' ? 'tabular-nums' : '',\n missing ? 'text-(--subtle-foreground)' : '',\n ]\n .filter(Boolean)\n .join(' ');\n });\n}\n"],"mappings":"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"}