ng-number-flow 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,178 @@
1
+ # ng-number-flow
2
+
3
+ An Angular (19+ standalone) animated number component. A thin, dependency-light wrapper around
4
+ the framework-agnostic [`number-flow`](https://github.com/barvian/number-flow) web component —
5
+ the same animation/formatting engine used by the official React, Vue, and Svelte packages.
6
+
7
+ - 🎞️ Smooth rolling-digit transitions (Web Animations API)
8
+ - ♿ Accessible out of the box (`role="img"` + `aria-label`)
9
+ - 🌍 Locale-aware formatting via `Intl.NumberFormat`
10
+ - đź§© Group directive to synchronize animations across multiple numbers
11
+ - 🅰️ Standalone, `OnPush`, signal-based, zoneless-compatible; works with Angular 19 → latest
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm i ng-number-flow number-flow
17
+ # or
18
+ pnpm add ng-number-flow number-flow
19
+ ```
20
+
21
+ `number-flow` is a runtime dependency of the wrapper and installed automatically, but keeping it
22
+ in your own `package.json` is recommended so bundlers resolve it reliably.
23
+
24
+ ## Quick start
25
+
26
+ `NumberFlowComponent` is a standalone component with the selector `number-flow`. Import it and
27
+ bind a `value`:
28
+
29
+ ```ts
30
+ import { Component, signal } from '@angular/core';
31
+ import { NumberFlowComponent } from 'ng-number-flow';
32
+
33
+ @Component({
34
+ selector: 'app-demo',
35
+ standalone: true,
36
+ imports: [NumberFlowComponent],
37
+ template: `<number-flow [value]="count()" />`,
38
+ })
39
+ export class DemoComponent {
40
+ readonly count = signal(3500);
41
+ }
42
+ ```
43
+
44
+ Whenever `value` changes, the digits animate from the old value to the new one.
45
+
46
+ ## Formatting
47
+
48
+ Pass a standard [`Intl.NumberFormat` options](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#options)
49
+ object to `format`, and optionally `locales`, `prefix`, and `suffix`:
50
+
51
+ ```html
52
+ <!-- Currency -->
53
+ <number-flow
54
+ [value]="price()"
55
+ [format]="{ style: 'currency', currency: 'USD' }"
56
+ />
57
+
58
+ <!-- Percent -->
59
+ <number-flow
60
+ [value]="ratio()"
61
+ [format]="{ style: 'percent', maximumFractionDigits: 1 }"
62
+ />
63
+
64
+ <!-- Fixed decimals with prefix/suffix and a locale -->
65
+ <number-flow
66
+ [value]="amount()"
67
+ locales="de-DE"
68
+ prefix="$"
69
+ suffix=" USD"
70
+ [format]="{ minimumFractionDigits: 2, maximumFractionDigits: 2 }"
71
+ />
72
+ ```
73
+
74
+ `Intl.NumberFormat` instances are cached internally (keyed by `locales:format`), so re-renders
75
+ are cheap.
76
+
77
+ ## Grouping (synchronized animations)
78
+
79
+ Wrap multiple `number-flow` elements with the `numberFlowGroup` directive so their animations
80
+ start on the **same frame**, even when only some values change:
81
+
82
+ ```ts
83
+ import { Component, signal } from '@angular/core';
84
+ import { NumberFlowComponent, NumberFlowGroupDirective } from 'ng-number-flow';
85
+
86
+ @Component({
87
+ selector: 'app-stats',
88
+ standalone: true,
89
+ imports: [NumberFlowComponent, NumberFlowGroupDirective],
90
+ template: `
91
+ <div numberFlowGroup>
92
+ <number-flow [value]="wins()" /> / <number-flow [value]="total()" />
93
+ </div>
94
+ `,
95
+ })
96
+ export class StatsComponent {
97
+ readonly wins = signal(120);
98
+ readonly total = signal(480);
99
+ }
100
+ ```
101
+
102
+ To exclude a single child from group batching (animate it independently), set `[isolate]="true"`
103
+ on that `number-flow`.
104
+
105
+ ## API
106
+
107
+ ### `NumberFlowComponent` — `<number-flow>`
108
+
109
+ #### Inputs
110
+
111
+ | Input | Type | Default | Description |
112
+ | --- | --- | --- | --- |
113
+ | `value` | `number \| bigint \| string` (`Value`) | — | The number to display. Changing it triggers the animation. |
114
+ | `locales` | `Intl.LocalesArgument` | runtime default | BCP 47 locale(s) for formatting. |
115
+ | `format` | `Format` (`Intl.NumberFormatOptions`) | — | Number formatting options. |
116
+ | `prefix` | `string` | — | Static text rendered before the number. |
117
+ | `suffix` | `string` | — | Static text rendered after the number. |
118
+ | `animated` | `boolean` | `true` | Enable/disable animation. |
119
+ | `respectMotionPreference` | `boolean` | `true` | Skip animation when the OS requests reduced motion. |
120
+ | `transformTiming` | `EffectTiming` | `linear(...)` ~900ms | Timing for digit movement. |
121
+ | `spinTiming` | `EffectTiming` | falls back to `transformTiming` | Timing for the spin/roll effect. |
122
+ | `opacityTiming` | `EffectTiming` | `ease-out` 450ms | Timing for fade in/out of digits. |
123
+ | `trend` | `Trend` (`number \| (oldValue, value) => number`) | `Math.sign(value - old)` | Direction digits roll. |
124
+ | `plugins` | `Plugin[]` | — | `number-flow` plugins. |
125
+ | `digits` | `Digits` | — | Per-place digit constraints, e.g. `{ 1: { max: 5 } }`. |
126
+ | `isolate` | `boolean` | `false` | When inside a group, opt this element out of batched updates. |
127
+ | `willChange` | `boolean` | `false` | Add `will-change` hints for smoother animation of frequently-updating numbers. |
128
+ | `nonce` | `string` | — | CSP nonce for the injected style. |
129
+
130
+ #### Outputs
131
+
132
+ | Output | Payload | Description |
133
+ | --- | --- | --- |
134
+ | `animationsStart` | `void` | Emitted when a transition begins. |
135
+ | `animationsFinish` | `void` | Emitted when all transitions complete. |
136
+
137
+ ```html
138
+ <number-flow
139
+ [value]="count()"
140
+ (animationsStart)="onStart()"
141
+ (animationsFinish)="onFinish()"
142
+ />
143
+ ```
144
+
145
+ ### `NumberFlowGroupDirective` — `[numberFlowGroup]`
146
+
147
+ A standalone attribute directive. Place it on any container element to batch the animations of
148
+ all descendant `number-flow` components. No inputs.
149
+
150
+ ### Exported types
151
+
152
+ `Value`, `Format`, `Data`, `Trend`, `Digits`, `Props`, `Plugin`, and `NumberFlowElement`
153
+ (the underlying custom-element type) are re-exported for convenience.
154
+
155
+ ## How it works
156
+
157
+ The component renders an internal custom element (`<number-flow-ng>`, registered once via
158
+ `number-flow`'s `define()`) inside a host with `display: contents`, mirroring the React/Vue
159
+ wrapper pattern. Inputs are signal `input()`s; an `afterRenderEffect` syncs them onto the element
160
+ whenever they change, setting every property first and assigning `data` **last** (the engine's
161
+ required ordering), computing `data` with the core `formatToData` helper.
162
+
163
+ ## SSR
164
+
165
+ This release is **client-side only**. On the server the component renders nothing and initializes
166
+ in the browser — its render hooks (`afterNextRender` / `afterRenderEffect`) run on the client only.
167
+ Declarative-Shadow-DOM hydration is a planned follow-up.
168
+
169
+ ## Compatibility
170
+
171
+ - **Angular:** peer dependency `>=19.0.0`. Uses signal `input()` / `output()` / `viewChild()` and
172
+ `afterRenderEffect` (the last of which requires Angular 19+). Built and tested with the latest
173
+ Angular tooling.
174
+ - **Zone / zoneless:** works with both. Uses `OnPush` and native element events.
175
+
176
+ ## License
177
+
178
+ MIT — same as `number-flow`.
@@ -0,0 +1,187 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, viewChild, input, output, inject, DestroyRef, afterNextRender, afterRenderEffect, ChangeDetectionStrategy, CUSTOM_ELEMENTS_SCHEMA, Component, Directive } from '@angular/core';
3
+ import NumberFlowLite, { define, formatToData } from 'number-flow/lite';
4
+
5
+ const NUMBER_FLOW_GROUP = new InjectionToken('NUMBER_FLOW_GROUP');
6
+
7
+ const cache = new Map();
8
+ function getFormatter(locales, format) {
9
+ const key = `${locales ? JSON.stringify(locales) : ''}:${format ? JSON.stringify(format) : ''}`;
10
+ let formatter = cache.get(key);
11
+ if (!formatter) {
12
+ formatter = new Intl.NumberFormat(locales, format);
13
+ cache.set(key, formatter);
14
+ }
15
+ return formatter;
16
+ }
17
+
18
+ const NUMBER_FLOW_ELEMENT_NAME = 'number-flow-ng';
19
+ define(NUMBER_FLOW_ELEMENT_NAME, NumberFlowLite);
20
+
21
+ class NumberFlowComponent {
22
+ constructor() {
23
+ this.flowRef = viewChild.required('flow');
24
+ this.value = input(/* @ts-ignore */
25
+ ...(ngDevMode ? [undefined, { debugName: "value" }] : /* istanbul ignore next */ []));
26
+ this.locales = input(/* @ts-ignore */
27
+ ...(ngDevMode ? [undefined, { debugName: "locales" }] : /* istanbul ignore next */ []));
28
+ this.format = input(/* @ts-ignore */
29
+ ...(ngDevMode ? [undefined, { debugName: "format" }] : /* istanbul ignore next */ []));
30
+ this.prefix = input(/* @ts-ignore */
31
+ ...(ngDevMode ? [undefined, { debugName: "prefix" }] : /* istanbul ignore next */ []));
32
+ this.suffix = input(/* @ts-ignore */
33
+ ...(ngDevMode ? [undefined, { debugName: "suffix" }] : /* istanbul ignore next */ []));
34
+ this.animated = input(/* @ts-ignore */
35
+ ...(ngDevMode ? [undefined, { debugName: "animated" }] : /* istanbul ignore next */ []));
36
+ this.respectMotionPreference = input(/* @ts-ignore */
37
+ ...(ngDevMode ? [undefined, { debugName: "respectMotionPreference" }] : /* istanbul ignore next */ []));
38
+ this.transformTiming = input(/* @ts-ignore */
39
+ ...(ngDevMode ? [undefined, { debugName: "transformTiming" }] : /* istanbul ignore next */ []));
40
+ this.spinTiming = input(/* @ts-ignore */
41
+ ...(ngDevMode ? [undefined, { debugName: "spinTiming" }] : /* istanbul ignore next */ []));
42
+ this.opacityTiming = input(/* @ts-ignore */
43
+ ...(ngDevMode ? [undefined, { debugName: "opacityTiming" }] : /* istanbul ignore next */ []));
44
+ this.trend = input(/* @ts-ignore */
45
+ ...(ngDevMode ? [undefined, { debugName: "trend" }] : /* istanbul ignore next */ []));
46
+ this.plugins = input(/* @ts-ignore */
47
+ ...(ngDevMode ? [undefined, { debugName: "plugins" }] : /* istanbul ignore next */ []));
48
+ this.digits = input(/* @ts-ignore */
49
+ ...(ngDevMode ? [undefined, { debugName: "digits" }] : /* istanbul ignore next */ []));
50
+ this.isolate = input(false, /* @ts-ignore */
51
+ ...(ngDevMode ? [{ debugName: "isolate" }] : /* istanbul ignore next */ []));
52
+ this.willChange = input(false, /* @ts-ignore */
53
+ ...(ngDevMode ? [{ debugName: "willChange" }] : /* istanbul ignore next */ []));
54
+ this.nonce = input(/* @ts-ignore */
55
+ ...(ngDevMode ? [undefined, { debugName: "nonce" }] : /* istanbul ignore next */ []));
56
+ this.animationsStart = output();
57
+ this.animationsFinish = output();
58
+ this.group = inject(NUMBER_FLOW_GROUP, { optional: true });
59
+ this.destroyRef = inject(DestroyRef);
60
+ // One-time setup: wire events and register with the group. `afterNextRender`
61
+ // runs on the client only (never during SSR) and after the view exists, so the
62
+ // view child is guaranteed resolved.
63
+ afterNextRender(() => {
64
+ const el = this.flowRef().nativeElement;
65
+ const onStart = () => this.animationsStart.emit();
66
+ const onFinish = () => this.animationsFinish.emit();
67
+ el.addEventListener('animationsstart', onStart);
68
+ el.addEventListener('animationsfinish', onFinish);
69
+ const unregister = this.group?.register(el);
70
+ this.destroyRef.onDestroy(() => {
71
+ el.removeEventListener('animationsstart', onStart);
72
+ el.removeEventListener('animationsfinish', onFinish);
73
+ unregister?.();
74
+ });
75
+ });
76
+ // Reactive sync: push the current inputs onto the custom element whenever any of
77
+ // them change. Custom-element property assignment is DOM work, so it belongs in
78
+ // `afterRenderEffect` (client-only) rather than a plain `effect`.
79
+ afterRenderEffect({
80
+ write: () => {
81
+ const el = this.flowRef().nativeElement;
82
+ this.applyProps(el);
83
+ this.applyData(el);
84
+ }
85
+ });
86
+ }
87
+ applyProps(el) {
88
+ const d = NumberFlowLite.defaultProps;
89
+ el.animated = this.animated() ?? d.animated;
90
+ el.respectMotionPreference = this.respectMotionPreference() ?? d.respectMotionPreference;
91
+ el.transformTiming = this.transformTiming() ?? d.transformTiming;
92
+ el.spinTiming = this.spinTiming() ?? d.spinTiming;
93
+ el.opacityTiming = this.opacityTiming() ?? d.opacityTiming;
94
+ el.trend = this.trend() ?? d.trend;
95
+ el.plugins = this.plugins() ?? d.plugins;
96
+ el.digits = this.digits() ?? d.digits;
97
+ el.batched = !!this.group && !this.isolate();
98
+ if (this.willChange())
99
+ el.setAttribute('data-will-change', '');
100
+ else
101
+ el.removeAttribute('data-will-change');
102
+ }
103
+ applyData(el) {
104
+ const value = this.value();
105
+ if (value == null)
106
+ return;
107
+ const data = formatToData(value, getFormatter(this.locales(), this.format()), this.prefix(), this.suffix());
108
+ if (this.group && !this.isolate()) {
109
+ this.group.beginUpdate();
110
+ el.data = data;
111
+ this.group.endUpdate();
112
+ }
113
+ else {
114
+ el.data = data;
115
+ }
116
+ }
117
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NumberFlowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
118
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.5", type: NumberFlowComponent, isStandalone: true, selector: "number-flow", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, locales: { classPropertyName: "locales", publicName: "locales", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, prefix: { classPropertyName: "prefix", publicName: "prefix", isSignal: true, isRequired: false, transformFunction: null }, suffix: { classPropertyName: "suffix", publicName: "suffix", isSignal: true, isRequired: false, transformFunction: null }, animated: { classPropertyName: "animated", publicName: "animated", isSignal: true, isRequired: false, transformFunction: null }, respectMotionPreference: { classPropertyName: "respectMotionPreference", publicName: "respectMotionPreference", isSignal: true, isRequired: false, transformFunction: null }, transformTiming: { classPropertyName: "transformTiming", publicName: "transformTiming", isSignal: true, isRequired: false, transformFunction: null }, spinTiming: { classPropertyName: "spinTiming", publicName: "spinTiming", isSignal: true, isRequired: false, transformFunction: null }, opacityTiming: { classPropertyName: "opacityTiming", publicName: "opacityTiming", isSignal: true, isRequired: false, transformFunction: null }, trend: { classPropertyName: "trend", publicName: "trend", isSignal: true, isRequired: false, transformFunction: null }, plugins: { classPropertyName: "plugins", publicName: "plugins", isSignal: true, isRequired: false, transformFunction: null }, digits: { classPropertyName: "digits", publicName: "digits", isSignal: true, isRequired: false, transformFunction: null }, isolate: { classPropertyName: "isolate", publicName: "isolate", isSignal: true, isRequired: false, transformFunction: null }, willChange: { classPropertyName: "willChange", publicName: "willChange", isSignal: true, isRequired: false, transformFunction: null }, nonce: { classPropertyName: "nonce", publicName: "nonce", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { animationsStart: "animationsStart", animationsFinish: "animationsFinish" }, host: { styleAttribute: "display: contents" }, viewQueries: [{ propertyName: "flowRef", first: true, predicate: ["flow"], descendants: true, isSignal: true }], ngImport: i0, template: `<number-flow-ng #flow></number-flow-ng>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
119
+ }
120
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NumberFlowComponent, decorators: [{
121
+ type: Component,
122
+ args: [{
123
+ selector: 'number-flow',
124
+ standalone: true,
125
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
126
+ changeDetection: ChangeDetectionStrategy.OnPush,
127
+ template: `<number-flow-ng #flow></number-flow-ng>`,
128
+ host: { style: 'display: contents' }
129
+ }]
130
+ }], ctorParameters: () => [], propDecorators: { flowRef: [{ type: i0.ViewChild, args: ['flow', { isSignal: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], locales: [{ type: i0.Input, args: [{ isSignal: true, alias: "locales", required: false }] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }], prefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefix", required: false }] }], suffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffix", required: false }] }], animated: [{ type: i0.Input, args: [{ isSignal: true, alias: "animated", required: false }] }], respectMotionPreference: [{ type: i0.Input, args: [{ isSignal: true, alias: "respectMotionPreference", required: false }] }], transformTiming: [{ type: i0.Input, args: [{ isSignal: true, alias: "transformTiming", required: false }] }], spinTiming: [{ type: i0.Input, args: [{ isSignal: true, alias: "spinTiming", required: false }] }], opacityTiming: [{ type: i0.Input, args: [{ isSignal: true, alias: "opacityTiming", required: false }] }], trend: [{ type: i0.Input, args: [{ isSignal: true, alias: "trend", required: false }] }], plugins: [{ type: i0.Input, args: [{ isSignal: true, alias: "plugins", required: false }] }], digits: [{ type: i0.Input, args: [{ isSignal: true, alias: "digits", required: false }] }], isolate: [{ type: i0.Input, args: [{ isSignal: true, alias: "isolate", required: false }] }], willChange: [{ type: i0.Input, args: [{ isSignal: true, alias: "willChange", required: false }] }], nonce: [{ type: i0.Input, args: [{ isSignal: true, alias: "nonce", required: false }] }], animationsStart: [{ type: i0.Output, args: ["animationsStart"] }], animationsFinish: [{ type: i0.Output, args: ["animationsFinish"] }] } });
131
+
132
+ class Coordinator {
133
+ constructor() {
134
+ this.flows = new Set();
135
+ this.updating = false;
136
+ this.endScheduled = false;
137
+ }
138
+ register(el) {
139
+ this.flows.add(el);
140
+ return () => {
141
+ this.flows.delete(el);
142
+ };
143
+ }
144
+ beginUpdate() {
145
+ if (this.updating)
146
+ return;
147
+ this.updating = true;
148
+ this.flows.forEach((f) => {
149
+ if (f.created)
150
+ f.willUpdate();
151
+ });
152
+ }
153
+ endUpdate() {
154
+ if (this.endScheduled)
155
+ return;
156
+ this.endScheduled = true;
157
+ queueMicrotask(() => {
158
+ this.endScheduled = false;
159
+ if (!this.updating)
160
+ return;
161
+ this.flows.forEach((f) => {
162
+ if (f.created)
163
+ f.didUpdate();
164
+ });
165
+ this.updating = false;
166
+ });
167
+ }
168
+ }
169
+ class NumberFlowGroupDirective {
170
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NumberFlowGroupDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
171
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.5", type: NumberFlowGroupDirective, isStandalone: true, selector: "[numberFlowGroup]", providers: [{ provide: NUMBER_FLOW_GROUP, useFactory: () => new Coordinator() }], ngImport: i0 }); }
172
+ }
173
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NumberFlowGroupDirective, decorators: [{
174
+ type: Directive,
175
+ args: [{
176
+ selector: '[numberFlowGroup]',
177
+ standalone: true,
178
+ providers: [{ provide: NUMBER_FLOW_GROUP, useFactory: () => new Coordinator() }]
179
+ }]
180
+ }] });
181
+
182
+ /**
183
+ * Generated bundle index. Do not edit.
184
+ */
185
+
186
+ export { NUMBER_FLOW_GROUP, NumberFlowComponent, NumberFlowGroupDirective };
187
+ //# sourceMappingURL=ng-number-flow.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ng-number-flow.mjs","sources":["../../src/lib/number-flow.tokens.ts","../../src/lib/formatter-cache.ts","../../src/lib/number-flow.element.ts","../../src/lib/number-flow.component.ts","../../src/lib/number-flow-group.directive.ts","../../src/ng-number-flow.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\nimport type NumberFlowLite from 'number-flow/lite';\n\nexport interface NumberFlowGroupCoordinator {\n\tregister(el: NumberFlowLite): () => void;\n\tbeginUpdate(): void;\n\tendUpdate(): void;\n}\n\nexport const NUMBER_FLOW_GROUP = new InjectionToken<NumberFlowGroupCoordinator | null>(\n\t'NUMBER_FLOW_GROUP'\n);\n","import type { Format, Value } from 'number-flow/lite';\n\nconst cache = new Map<string, Intl.NumberFormat>();\n\nexport function getFormatter(\n\tlocales?: Intl.LocalesArgument,\n\tformat?: Format\n): Intl.NumberFormat {\n\tconst key = `${locales ? JSON.stringify(locales) : ''}:${format ? JSON.stringify(format) : ''}`;\n\tlet formatter = cache.get(key);\n\tif (!formatter) {\n\t\tformatter = new Intl.NumberFormat(locales, format);\n\t\tcache.set(key, formatter);\n\t}\n\treturn formatter;\n}\n\nexport type { Format, Value };\n","import NumberFlowLite, { define } from 'number-flow/lite';\n\nexport const NUMBER_FLOW_ELEMENT_NAME = 'number-flow-ng';\n\ndefine(NUMBER_FLOW_ELEMENT_NAME, NumberFlowLite);\n","import {\n\tafterNextRender,\n\tafterRenderEffect,\n\tChangeDetectionStrategy,\n\tComponent,\n\tCUSTOM_ELEMENTS_SCHEMA,\n\tDestroyRef,\n\tElementRef,\n\tinject,\n\tinput,\n\toutput,\n\tviewChild\n} from '@angular/core';\nimport NumberFlowLite, {\n\tformatToData,\n\ttype Digits,\n\ttype Format,\n\ttype Trend,\n\ttype Value\n} from 'number-flow/lite';\nimport type { Plugin } from 'number-flow/plugins';\nimport { getFormatter } from './formatter-cache';\nimport { NUMBER_FLOW_GROUP } from './number-flow.tokens';\nimport './number-flow.element';\n\n@Component({\n\tselector: 'number-flow',\n\tstandalone: true,\n\tschemas: [CUSTOM_ELEMENTS_SCHEMA],\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\ttemplate: `<number-flow-ng #flow></number-flow-ng>`,\n\thost: { style: 'display: contents' }\n})\nexport class NumberFlowComponent {\n\tprivate readonly flowRef = viewChild.required<ElementRef<NumberFlowLite>>('flow');\n\n\treadonly value = input<Value>();\n\treadonly locales = input<Intl.LocalesArgument>();\n\treadonly format = input<Format>();\n\treadonly prefix = input<string>();\n\treadonly suffix = input<string>();\n\treadonly animated = input<boolean>();\n\treadonly respectMotionPreference = input<boolean>();\n\treadonly transformTiming = input<EffectTiming>();\n\treadonly spinTiming = input<EffectTiming>();\n\treadonly opacityTiming = input<EffectTiming>();\n\treadonly trend = input<Trend>();\n\treadonly plugins = input<Plugin[]>();\n\treadonly digits = input<Digits>();\n\treadonly isolate = input(false);\n\treadonly willChange = input(false);\n\treadonly nonce = input<string>();\n\n\treadonly animationsStart = output<void>();\n\treadonly animationsFinish = output<void>();\n\n\tprivate readonly group = inject(NUMBER_FLOW_GROUP, { optional: true });\n\tprivate readonly destroyRef = inject(DestroyRef);\n\n\tconstructor() {\n\t\t// One-time setup: wire events and register with the group. `afterNextRender`\n\t\t// runs on the client only (never during SSR) and after the view exists, so the\n\t\t// view child is guaranteed resolved.\n\t\tafterNextRender(() => {\n\t\t\tconst el = this.flowRef().nativeElement;\n\n\t\t\tconst onStart = () => this.animationsStart.emit();\n\t\t\tconst onFinish = () => this.animationsFinish.emit();\n\t\t\tel.addEventListener('animationsstart', onStart);\n\t\t\tel.addEventListener('animationsfinish', onFinish);\n\n\t\t\tconst unregister = this.group?.register(el);\n\n\t\t\tthis.destroyRef.onDestroy(() => {\n\t\t\t\tel.removeEventListener('animationsstart', onStart);\n\t\t\t\tel.removeEventListener('animationsfinish', onFinish);\n\t\t\t\tunregister?.();\n\t\t\t});\n\t\t});\n\n\t\t// Reactive sync: push the current inputs onto the custom element whenever any of\n\t\t// them change. Custom-element property assignment is DOM work, so it belongs in\n\t\t// `afterRenderEffect` (client-only) rather than a plain `effect`.\n\t\tafterRenderEffect({\n\t\t\twrite: () => {\n\t\t\t\tconst el = this.flowRef().nativeElement;\n\t\t\t\tthis.applyProps(el);\n\t\t\t\tthis.applyData(el);\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate applyProps(el: NumberFlowLite): void {\n\t\tconst d = NumberFlowLite.defaultProps;\n\t\tel.animated = this.animated() ?? d.animated;\n\t\tel.respectMotionPreference = this.respectMotionPreference() ?? d.respectMotionPreference;\n\t\tel.transformTiming = this.transformTiming() ?? d.transformTiming;\n\t\tel.spinTiming = this.spinTiming() ?? d.spinTiming;\n\t\tel.opacityTiming = this.opacityTiming() ?? d.opacityTiming;\n\t\tel.trend = this.trend() ?? d.trend;\n\t\tel.plugins = this.plugins() ?? d.plugins;\n\t\tel.digits = this.digits() ?? d.digits;\n\t\tel.batched = !!this.group && !this.isolate();\n\n\t\tif (this.willChange()) el.setAttribute('data-will-change', '');\n\t\telse el.removeAttribute('data-will-change');\n\t}\n\n\tprivate applyData(el: NumberFlowLite): void {\n\t\tconst value = this.value();\n\t\tif (value == null) return;\n\n\t\tconst data = formatToData(\n\t\t\tvalue,\n\t\t\tgetFormatter(this.locales(), this.format()),\n\t\t\tthis.prefix(),\n\t\t\tthis.suffix()\n\t\t);\n\n\t\tif (this.group && !this.isolate()) {\n\t\t\tthis.group.beginUpdate();\n\t\t\tel.data = data;\n\t\t\tthis.group.endUpdate();\n\t\t} else {\n\t\t\tel.data = data;\n\t\t}\n\t}\n}\n","import { Directive } from '@angular/core';\nimport type NumberFlowLite from 'number-flow/lite';\nimport { NUMBER_FLOW_GROUP, type NumberFlowGroupCoordinator } from './number-flow.tokens';\n\nclass Coordinator implements NumberFlowGroupCoordinator {\n\tprivate readonly flows = new Set<NumberFlowLite>();\n\tprivate updating = false;\n\tprivate endScheduled = false;\n\n\tregister(el: NumberFlowLite): () => void {\n\t\tthis.flows.add(el);\n\t\treturn () => {\n\t\t\tthis.flows.delete(el);\n\t\t};\n\t}\n\n\tbeginUpdate(): void {\n\t\tif (this.updating) return;\n\t\tthis.updating = true;\n\t\tthis.flows.forEach((f) => {\n\t\t\tif ((f as { created?: boolean }).created) f.willUpdate();\n\t\t});\n\t}\n\n\tendUpdate(): void {\n\t\tif (this.endScheduled) return;\n\t\tthis.endScheduled = true;\n\t\tqueueMicrotask(() => {\n\t\t\tthis.endScheduled = false;\n\t\t\tif (!this.updating) return;\n\t\t\tthis.flows.forEach((f) => {\n\t\t\t\tif ((f as { created?: boolean }).created) f.didUpdate();\n\t\t\t});\n\t\t\tthis.updating = false;\n\t\t});\n\t}\n}\n\n@Directive({\n\tselector: '[numberFlowGroup]',\n\tstandalone: true,\n\tproviders: [{ provide: NUMBER_FLOW_GROUP, useFactory: () => new Coordinator() }]\n})\nexport class NumberFlowGroupDirective {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "ng-number-flow",
3
+ "version": "0.1.0",
4
+ "description": "An Angular (19+) standalone animated number component. A thin wrapper around number-flow.",
5
+ "license": "MIT",
6
+ "author": "phalla-doll",
7
+ "homepage": "https://github.com/phalla-doll/ng-number-flow",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/phalla-doll/ng-number-flow.git",
11
+ "directory": "packages/ng-number-flow"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/phalla-doll/ng-number-flow/issues"
15
+ },
16
+ "keywords": [
17
+ "angular",
18
+ "ng",
19
+ "accessible",
20
+ "odometer",
21
+ "animation",
22
+ "number-format",
23
+ "number-animation",
24
+ "animated-number"
25
+ ],
26
+ "sideEffects": [
27
+ "**/number-flow.element.ts"
28
+ ],
29
+ "publishConfig": {
30
+ "access": "public"
31
+ },
32
+ "peerDependencies": {
33
+ "@angular/core": ">=19.0.0"
34
+ },
35
+ "dependencies": {
36
+ "number-flow": "^0.6.1",
37
+ "tslib": "^2.7.0"
38
+ },
39
+ "module": "fesm2022/ng-number-flow.mjs",
40
+ "typings": "types/ng-number-flow.d.ts",
41
+ "exports": {
42
+ "./package.json": {
43
+ "default": "./package.json"
44
+ },
45
+ ".": {
46
+ "types": "./types/ng-number-flow.d.ts",
47
+ "default": "./fesm2022/ng-number-flow.mjs"
48
+ }
49
+ },
50
+ "type": "module"
51
+ }
@@ -0,0 +1,50 @@
1
+ import NumberFlowLite, { Format, Trend, Digits } from 'number-flow/lite';
2
+ export { Data, Digits, Format, default as NumberFlowElement, Props, Trend, Value } from 'number-flow/lite';
3
+ import { Plugin } from 'number-flow/plugins';
4
+ export { Plugin } from 'number-flow/plugins';
5
+ import * as _angular_core from '@angular/core';
6
+ import { InjectionToken } from '@angular/core';
7
+
8
+ interface NumberFlowGroupCoordinator {
9
+ register(el: NumberFlowLite): () => void;
10
+ beginUpdate(): void;
11
+ endUpdate(): void;
12
+ }
13
+ declare const NUMBER_FLOW_GROUP: InjectionToken<NumberFlowGroupCoordinator | null>;
14
+
15
+ declare class NumberFlowComponent {
16
+ private readonly flowRef;
17
+ readonly value: _angular_core.InputSignal<number | undefined>;
18
+ readonly locales: _angular_core.InputSignal<Intl.LocalesArgument>;
19
+ readonly format: _angular_core.InputSignal<Format | undefined>;
20
+ readonly prefix: _angular_core.InputSignal<string | undefined>;
21
+ readonly suffix: _angular_core.InputSignal<string | undefined>;
22
+ readonly animated: _angular_core.InputSignal<boolean | undefined>;
23
+ readonly respectMotionPreference: _angular_core.InputSignal<boolean | undefined>;
24
+ readonly transformTiming: _angular_core.InputSignal<EffectTiming | undefined>;
25
+ readonly spinTiming: _angular_core.InputSignal<EffectTiming | undefined>;
26
+ readonly opacityTiming: _angular_core.InputSignal<EffectTiming | undefined>;
27
+ readonly trend: _angular_core.InputSignal<Trend | undefined>;
28
+ readonly plugins: _angular_core.InputSignal<Plugin[] | undefined>;
29
+ readonly digits: _angular_core.InputSignal<Digits | undefined>;
30
+ readonly isolate: _angular_core.InputSignal<boolean>;
31
+ readonly willChange: _angular_core.InputSignal<boolean>;
32
+ readonly nonce: _angular_core.InputSignal<string | undefined>;
33
+ readonly animationsStart: _angular_core.OutputEmitterRef<void>;
34
+ readonly animationsFinish: _angular_core.OutputEmitterRef<void>;
35
+ private readonly group;
36
+ private readonly destroyRef;
37
+ constructor();
38
+ private applyProps;
39
+ private applyData;
40
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NumberFlowComponent, never>;
41
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NumberFlowComponent, "number-flow", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "locales": { "alias": "locales"; "required": false; "isSignal": true; }; "format": { "alias": "format"; "required": false; "isSignal": true; }; "prefix": { "alias": "prefix"; "required": false; "isSignal": true; }; "suffix": { "alias": "suffix"; "required": false; "isSignal": true; }; "animated": { "alias": "animated"; "required": false; "isSignal": true; }; "respectMotionPreference": { "alias": "respectMotionPreference"; "required": false; "isSignal": true; }; "transformTiming": { "alias": "transformTiming"; "required": false; "isSignal": true; }; "spinTiming": { "alias": "spinTiming"; "required": false; "isSignal": true; }; "opacityTiming": { "alias": "opacityTiming"; "required": false; "isSignal": true; }; "trend": { "alias": "trend"; "required": false; "isSignal": true; }; "plugins": { "alias": "plugins"; "required": false; "isSignal": true; }; "digits": { "alias": "digits"; "required": false; "isSignal": true; }; "isolate": { "alias": "isolate"; "required": false; "isSignal": true; }; "willChange": { "alias": "willChange"; "required": false; "isSignal": true; }; "nonce": { "alias": "nonce"; "required": false; "isSignal": true; }; }, { "animationsStart": "animationsStart"; "animationsFinish": "animationsFinish"; }, never, never, true, never>;
42
+ }
43
+
44
+ declare class NumberFlowGroupDirective {
45
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NumberFlowGroupDirective, never>;
46
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NumberFlowGroupDirective, "[numberFlowGroup]", never, {}, {}, never, never, true, never>;
47
+ }
48
+
49
+ export { NUMBER_FLOW_GROUP, NumberFlowComponent, NumberFlowGroupDirective };
50
+ export type { NumberFlowGroupCoordinator };