ngwr 13.0.1 → 14.0.1
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 +69 -13
- package/aurora/aurora.scss +1 -1
- package/aurora/styles/_dark.scss +21 -0
- package/aurora/styles/_index.scss +11 -30
- package/aurora/styles/_rules.scss +25 -0
- package/border-glow/styles/_dark.scss +46 -0
- package/border-glow/styles/_index.scss +5 -0
- package/border-glow/styles/_rules.scss +0 -31
- package/button/styles/_index.scss +16 -0
- package/color-picker/styles/_index.scss +43 -5
- package/event-calendar/styles/_index.scss +15 -0
- package/fesm2022/ngwr-action-sheet.mjs +3 -3
- package/fesm2022/ngwr-affix.mjs +3 -3
- package/fesm2022/ngwr-alert.mjs +7 -7
- package/fesm2022/ngwr-alert.mjs.map +1 -1
- package/fesm2022/ngwr-anchor.mjs +3 -3
- package/fesm2022/ngwr-aurora.mjs +4 -4
- package/fesm2022/ngwr-aurora.mjs.map +1 -1
- package/fesm2022/ngwr-avatar.mjs +3 -3
- package/fesm2022/ngwr-back-top.mjs +14 -4
- package/fesm2022/ngwr-back-top.mjs.map +1 -1
- package/fesm2022/ngwr-badge.mjs +6 -6
- package/fesm2022/ngwr-bar-chart.mjs +3 -3
- package/fesm2022/ngwr-blur-text.mjs +16 -5
- package/fesm2022/ngwr-blur-text.mjs.map +1 -1
- package/fesm2022/ngwr-border-glow.mjs +4 -4
- package/fesm2022/ngwr-border-glow.mjs.map +1 -1
- package/fesm2022/ngwr-breadcrumbs.mjs +7 -7
- package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
- package/fesm2022/ngwr-burger.mjs +3 -3
- package/fesm2022/ngwr-button.mjs +88 -10
- package/fesm2022/ngwr-button.mjs.map +1 -1
- package/fesm2022/ngwr-calendar-heatmap.mjs +3 -3
- package/fesm2022/ngwr-calendar-testing.mjs +15 -0
- package/fesm2022/ngwr-calendar-testing.mjs.map +1 -1
- package/fesm2022/ngwr-calendar.mjs +53 -7
- package/fesm2022/ngwr-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-card.mjs +9 -9
- package/fesm2022/ngwr-carousel.mjs +6 -6
- package/fesm2022/ngwr-cascader.mjs +4 -4
- package/fesm2022/ngwr-cascader.mjs.map +1 -1
- package/fesm2022/ngwr-checkbox.mjs +6 -6
- package/fesm2022/ngwr-circular-text.mjs +23 -4
- package/fesm2022/ngwr-circular-text.mjs.map +1 -1
- package/fesm2022/ngwr-click-spark.mjs +3 -3
- package/fesm2022/ngwr-clipboard.mjs +3 -3
- package/fesm2022/ngwr-collapse.mjs +9 -9
- package/fesm2022/ngwr-collapse.mjs.map +1 -1
- package/fesm2022/ngwr-color-picker-testing.mjs +23 -7
- package/fesm2022/ngwr-color-picker-testing.mjs.map +1 -1
- package/fesm2022/ngwr-color-picker.mjs +93 -14
- package/fesm2022/ngwr-color-picker.mjs.map +1 -1
- package/fesm2022/ngwr-command-palette.mjs +29 -5
- package/fesm2022/ngwr-command-palette.mjs.map +1 -1
- package/fesm2022/ngwr-compare.mjs +3 -3
- package/fesm2022/ngwr-confetti.mjs +3 -3
- package/fesm2022/ngwr-context-menu.mjs +18 -12
- package/fesm2022/ngwr-context-menu.mjs.map +1 -1
- package/fesm2022/ngwr-cookie.mjs +3 -3
- package/fesm2022/ngwr-counter.mjs +6 -6
- package/fesm2022/ngwr-date-adapters-fns.mjs +104 -36
- package/fesm2022/ngwr-date-adapters-fns.mjs.map +1 -1
- package/fesm2022/ngwr-date-adapters-luxon.mjs +3 -3
- package/fesm2022/ngwr-date-picker-testing.mjs +10 -2
- package/fesm2022/ngwr-date-picker-testing.mjs.map +1 -1
- package/fesm2022/ngwr-date-picker.mjs +118 -28
- package/fesm2022/ngwr-date-picker.mjs.map +1 -1
- package/fesm2022/ngwr-date.mjs +483 -82
- package/fesm2022/ngwr-date.mjs.map +1 -1
- package/fesm2022/ngwr-decrypt-text.mjs +3 -3
- package/fesm2022/ngwr-density.mjs +6 -6
- package/fesm2022/ngwr-descriptions.mjs +6 -6
- package/fesm2022/ngwr-dialog.mjs +15 -15
- package/fesm2022/ngwr-directives.mjs +12 -12
- package/fesm2022/ngwr-divider.mjs +3 -3
- package/fesm2022/ngwr-donut-chart.mjs +3 -3
- package/fesm2022/ngwr-drag-drop.mjs +37 -9
- package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
- package/fesm2022/ngwr-drawer.mjs +18 -18
- package/fesm2022/ngwr-dropdown.mjs +29 -12
- package/fesm2022/ngwr-dropdown.mjs.map +1 -1
- package/fesm2022/ngwr-empty.mjs +3 -3
- package/fesm2022/ngwr-event-calendar-testing.mjs.map +1 -1
- package/fesm2022/ngwr-event-calendar.mjs +6 -6
- package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-falling-text.mjs +3 -3
- package/fesm2022/ngwr-file-upload.mjs +55 -15
- package/fesm2022/ngwr-file-upload.mjs.map +1 -1
- package/fesm2022/ngwr-form-testing.mjs +13 -7
- package/fesm2022/ngwr-form-testing.mjs.map +1 -1
- package/fesm2022/ngwr-form.mjs +44 -25
- package/fesm2022/ngwr-form.mjs.map +1 -1
- package/fesm2022/ngwr-fuzzy-text.mjs +3 -3
- package/fesm2022/ngwr-gauge.mjs +3 -3
- package/fesm2022/ngwr-glitch-text.mjs +3 -3
- package/fesm2022/ngwr-gradient-text.mjs +3 -3
- package/fesm2022/ngwr-hotkey.mjs +6 -6
- package/fesm2022/ngwr-i18n-en.mjs +63 -1
- package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ru.mjs +28 -1
- package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
- package/fesm2022/ngwr-i18n.mjs +159 -31
- package/fesm2022/ngwr-i18n.mjs.map +1 -1
- package/fesm2022/ngwr-icon.mjs +6 -6
- package/fesm2022/ngwr-image-cropper.mjs +3 -3
- package/fesm2022/ngwr-input-number.mjs +5 -5
- package/fesm2022/ngwr-input-number.mjs.map +1 -1
- package/fesm2022/ngwr-input-otp.mjs +23 -5
- package/fesm2022/ngwr-input-otp.mjs.map +1 -1
- package/fesm2022/ngwr-input.mjs +37 -26
- package/fesm2022/ngwr-input.mjs.map +1 -1
- package/fesm2022/ngwr-keyboard.mjs +3 -3
- package/fesm2022/ngwr-knob-testing.mjs.map +1 -1
- package/fesm2022/ngwr-knob.mjs +22 -4
- package/fesm2022/ngwr-knob.mjs.map +1 -1
- package/fesm2022/ngwr-layout.mjs +15 -15
- package/fesm2022/ngwr-lightbox.mjs +4 -4
- package/fesm2022/ngwr-lightbox.mjs.map +1 -1
- package/fesm2022/ngwr-line-chart.mjs +3 -3
- package/fesm2022/ngwr-list.mjs +7 -7
- package/fesm2022/ngwr-list.mjs.map +1 -1
- package/fesm2022/ngwr-loading-bar-router.mjs +73 -0
- package/fesm2022/ngwr-loading-bar-router.mjs.map +1 -0
- package/fesm2022/ngwr-loading-bar.mjs +27 -38
- package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
- package/fesm2022/ngwr-markdown.mjs +6 -6
- package/fesm2022/ngwr-marquee.mjs +3 -3
- package/fesm2022/ngwr-media.mjs +3 -3
- package/fesm2022/ngwr-mention.mjs +109 -19
- package/fesm2022/ngwr-mention.mjs.map +1 -1
- package/fesm2022/ngwr-meta.mjs +6 -6
- package/fesm2022/ngwr-meter-group.mjs +3 -3
- package/fesm2022/ngwr-overlay.mjs +6 -6
- package/fesm2022/ngwr-page-header.mjs +3 -3
- package/fesm2022/ngwr-pagination-testing.mjs +11 -10
- package/fesm2022/ngwr-pagination-testing.mjs.map +1 -1
- package/fesm2022/ngwr-pagination.mjs +67 -32
- package/fesm2022/ngwr-pagination.mjs.map +1 -1
- package/fesm2022/ngwr-pipes.mjs +21 -21
- package/fesm2022/ngwr-platform.mjs +9 -9
- package/fesm2022/ngwr-popconfirm.mjs +7 -6
- package/fesm2022/ngwr-popconfirm.mjs.map +1 -1
- package/fesm2022/ngwr-popover.mjs +7 -6
- package/fesm2022/ngwr-popover.mjs.map +1 -1
- package/fesm2022/ngwr-progress.mjs +3 -3
- package/fesm2022/ngwr-pull-to-refresh.mjs +3 -3
- package/fesm2022/ngwr-qr.mjs +3 -3
- package/fesm2022/ngwr-radio.mjs +6 -6
- package/fesm2022/ngwr-rating.mjs +48 -22
- package/fesm2022/ngwr-rating.mjs.map +1 -1
- package/fesm2022/ngwr-result.mjs +12 -12
- package/fesm2022/ngwr-rotating-text.mjs +3 -3
- package/fesm2022/ngwr-scroll.mjs +3 -3
- package/fesm2022/ngwr-segmented.mjs +12 -8
- package/fesm2022/ngwr-segmented.mjs.map +1 -1
- package/fesm2022/ngwr-select.mjs +217 -59
- package/fesm2022/ngwr-select.mjs.map +1 -1
- package/fesm2022/ngwr-shiny-text.mjs +7 -7
- package/fesm2022/ngwr-shiny-text.mjs.map +1 -1
- package/fesm2022/ngwr-sidebar.mjs +3 -3
- package/fesm2022/ngwr-skeleton.mjs +3 -3
- package/fesm2022/ngwr-slider.mjs +12 -8
- package/fesm2022/ngwr-slider.mjs.map +1 -1
- package/fesm2022/ngwr-sparkline.mjs +3 -3
- package/fesm2022/ngwr-speed-dial.mjs +3 -3
- package/fesm2022/ngwr-spinner.mjs +3 -3
- package/fesm2022/ngwr-splash-cursor.mjs +3 -3
- package/fesm2022/ngwr-split-text.mjs +3 -3
- package/fesm2022/ngwr-splitter-testing.mjs.map +1 -1
- package/fesm2022/ngwr-splitter.mjs +3 -3
- package/fesm2022/ngwr-spotlight-card.mjs +7 -7
- package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
- package/fesm2022/ngwr-squircle.mjs +7 -6
- package/fesm2022/ngwr-squircle.mjs.map +1 -1
- package/fesm2022/ngwr-star-border.mjs +4 -4
- package/fesm2022/ngwr-star-border.mjs.map +1 -1
- package/fesm2022/ngwr-statistic.mjs +44 -13
- package/fesm2022/ngwr-statistic.mjs.map +1 -1
- package/fesm2022/ngwr-stepper.mjs +6 -6
- package/fesm2022/ngwr-storage.mjs +11 -3
- package/fesm2022/ngwr-storage.mjs.map +1 -1
- package/fesm2022/ngwr-switch.mjs +3 -3
- package/fesm2022/ngwr-table.mjs +51 -28
- package/fesm2022/ngwr-table.mjs.map +1 -1
- package/fesm2022/ngwr-tabs-router.mjs +158 -0
- package/fesm2022/ngwr-tabs-router.mjs.map +1 -0
- package/fesm2022/ngwr-tabs-testing.mjs +13 -11
- package/fesm2022/ngwr-tabs-testing.mjs.map +1 -1
- package/fesm2022/ngwr-tabs.mjs +104 -16
- package/fesm2022/ngwr-tabs.mjs.map +1 -1
- package/fesm2022/ngwr-textarea.mjs +46 -6
- package/fesm2022/ngwr-textarea.mjs.map +1 -1
- package/fesm2022/ngwr-theme.mjs +90 -4
- package/fesm2022/ngwr-theme.mjs.map +1 -1
- package/fesm2022/ngwr-tilt-card.mjs +7 -7
- package/fesm2022/ngwr-tilt-card.mjs.map +1 -1
- package/fesm2022/ngwr-timeline.mjs +6 -6
- package/fesm2022/ngwr-toast.mjs +116 -11
- package/fesm2022/ngwr-toast.mjs.map +1 -1
- package/fesm2022/ngwr-toolbar.mjs +3 -3
- package/fesm2022/ngwr-tour.mjs +6 -6
- package/fesm2022/ngwr-tour.mjs.map +1 -1
- package/fesm2022/ngwr-transfer.mjs +4 -4
- package/fesm2022/ngwr-transfer.mjs.map +1 -1
- package/fesm2022/ngwr-tree.mjs +35 -12
- package/fesm2022/ngwr-tree.mjs.map +1 -1
- package/fesm2022/ngwr-typewriter.mjs +3 -3
- package/fesm2022/ngwr-typography.mjs +3 -3
- package/fesm2022/ngwr-utils.mjs +37 -1
- package/fesm2022/ngwr-utils.mjs.map +1 -1
- package/fesm2022/ngwr-version.mjs +1 -1
- package/fesm2022/ngwr-version.mjs.map +1 -1
- package/fesm2022/ngwr-virtual-scroll.mjs +3 -3
- package/fesm2022/ngwr-waves.mjs +4 -4
- package/fesm2022/ngwr-waves.mjs.map +1 -1
- package/fesm2022/ngwr-window-testing.mjs +10 -2
- package/fesm2022/ngwr-window-testing.mjs.map +1 -1
- package/fesm2022/ngwr-window.mjs +15 -15
- package/fesm2022/ngwr-window.mjs.map +1 -1
- package/i18n/en.json +33 -6
- package/i18n/ru.json +33 -6
- package/llms-full.txt +29 -20
- package/llms.txt +127 -25
- package/mcp/catalog.js +3 -3
- package/mcp/providers.js +11 -0
- package/package.json +9 -1
- package/schematics/migrations/v13/index.js +101 -0
- package/schematics/migrations/v14/index.js +422 -0
- package/schematics/migrations.json +10 -0
- package/schematics/page/templates.js +1 -1
- package/schematics/use/symbol-map.json +1 -0
- package/shiny-text/styles/_dark.scss +20 -0
- package/shiny-text/styles/_index.scss +5 -0
- package/shiny-text/styles/_rules.scss +0 -4
- package/skills/ngwr/SKILL.md +4 -1
- package/skills/ngwr/references/catalog.md +2 -0
- package/skills/ngwr/references/setup.md +4 -0
- package/spotlight-card/styles/_dark.scss +21 -0
- package/spotlight-card/styles/_index.scss +5 -0
- package/spotlight-card/styles/_rules.scss +0 -6
- package/star-border/styles/_dark.scss +21 -0
- package/star-border/styles/_index.scss +5 -0
- package/star-border/styles/_rules.scss +0 -5
- package/stepper/styles/_index.scss +19 -1
- package/textarea/styles/_index.scss +14 -6
- package/theme/styles/_colors.scss +102 -0
- package/theme/styles/_focus.scss +31 -1
- package/tilt-card/styles/_dark.scss +21 -0
- package/tilt-card/styles/_index.scss +5 -0
- package/tilt-card/styles/_rules.scss +0 -5
- package/toast/styles/_index.scss +12 -4
- package/types/ngwr-alert.d.ts +3 -3
- package/types/ngwr-blur-text.d.ts +8 -0
- package/types/ngwr-button.d.ts +45 -2
- package/types/ngwr-calendar-testing.d.ts +21 -4
- package/types/ngwr-calendar.d.ts +37 -0
- package/types/ngwr-circular-text.d.ts +9 -0
- package/types/ngwr-collapse.d.ts +19 -15
- package/types/ngwr-color-picker-testing.d.ts +10 -4
- package/types/ngwr-color-picker.d.ts +70 -2
- package/types/ngwr-command-palette.d.ts +14 -0
- package/types/ngwr-context-menu.d.ts +1 -1
- package/types/ngwr-date-adapters-fns.d.ts +71 -29
- package/types/ngwr-date-picker-testing.d.ts +206 -185
- package/types/ngwr-date-picker.d.ts +7 -0
- package/types/ngwr-date.d.ts +143 -13
- package/types/ngwr-drag-drop.d.ts +19 -0
- package/types/ngwr-dropdown.d.ts +18 -2
- package/types/ngwr-event-calendar-testing.d.ts +12 -9
- package/types/ngwr-file-upload.d.ts +31 -3
- package/types/ngwr-form-testing.d.ts +13 -7
- package/types/ngwr-form.d.ts +47 -12
- package/types/ngwr-i18n.d.ts +89 -7
- package/types/ngwr-input-number.d.ts +1 -1
- package/types/ngwr-input-otp.d.ts +3 -0
- package/types/ngwr-input.d.ts +13 -5
- package/types/ngwr-knob-testing.d.ts +8 -4
- package/types/ngwr-knob.d.ts +18 -0
- package/types/ngwr-loading-bar-router.d.ts +35 -0
- package/types/ngwr-loading-bar.d.ts +19 -9
- package/types/ngwr-mention.d.ts +13 -0
- package/types/ngwr-pagination-testing.d.ts +11 -10
- package/types/ngwr-pagination.d.ts +39 -10
- package/types/ngwr-popconfirm.d.ts +1 -1
- package/types/ngwr-popover.d.ts +1 -1
- package/types/ngwr-rating.d.ts +25 -4
- package/types/ngwr-segmented.d.ts +1 -0
- package/types/ngwr-select.d.ts +110 -19
- package/types/ngwr-slider.d.ts +1 -0
- package/types/ngwr-splitter-testing.d.ts +9 -4
- package/types/ngwr-squircle.d.ts +1 -1
- package/types/ngwr-statistic.d.ts +22 -2
- package/types/ngwr-storage.d.ts +39 -1
- package/types/ngwr-table.d.ts +24 -5
- package/types/ngwr-tabs-router.d.ts +67 -0
- package/types/ngwr-tabs-testing.d.ts +12 -10
- package/types/ngwr-tabs.d.ts +103 -6
- package/types/ngwr-textarea.d.ts +29 -0
- package/types/ngwr-theme.d.ts +92 -2
- package/types/ngwr-toast.d.ts +53 -0
- package/types/ngwr-tree.d.ts +10 -2
- package/types/ngwr-utils.d.ts +33 -1
- package/types/ngwr-version.d.ts +1 -1
- package/types/ngwr-window-testing.d.ts +11 -3
- package/types/ngwr-window.d.ts +11 -4
- package/waves/styles/_dark.scss +19 -0
- package/waves/styles/_index.scss +5 -0
- package/waves/styles/_rules.scss +0 -3
- package/window/styles/_index.scss +1 -1
|
@@ -2,6 +2,7 @@ import { coerceNumberProperty, coerceBooleanProperty } from '@angular/cdk/coerci
|
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
3
|
import { inject, LOCALE_ID, input, computed, signal, effect, untracked, ViewEncapsulation, Component, output, DestroyRef, PLATFORM_ID, afterNextRender } from '@angular/core';
|
|
4
4
|
import { WrCountUp } from 'ngwr/counter';
|
|
5
|
+
import { useI18nText, useI18nFormatter } from 'ngwr/i18n';
|
|
5
6
|
import { WrPlatform } from 'ngwr/platform';
|
|
6
7
|
import { numAttr } from 'ngwr/utils';
|
|
7
8
|
import { isPlatformBrowser } from '@angular/common';
|
|
@@ -115,8 +116,13 @@ class WrStatistic {
|
|
|
115
116
|
const n = coerceNumberProperty(v, Number.NaN);
|
|
116
117
|
return Number.isFinite(n) ? n : null;
|
|
117
118
|
} });
|
|
118
|
-
|
|
119
|
-
|
|
119
|
+
// The default moved from the literal `'%'` to `null` so the catalog gets a
|
|
120
|
+
// say. `%` is a string the LIBRARY owns and no locale could reach: a locale
|
|
121
|
+
// that writes it differently — or writes it as a word — had nowhere to put
|
|
122
|
+
// that but a per-instance binding on every `<wr-statistic>` on the page. A
|
|
123
|
+
// bound value still wins, exactly as before, which is what makes this safe.
|
|
124
|
+
/** Unit appended to the delta value. Falls back to `statistic.deltaSuffix`, then `'%'`. */
|
|
125
|
+
deltaSuffix = input(null, /* @ts-ignore */
|
|
120
126
|
...(ngDevMode ? [{ debugName: "deltaSuffix" }] : /* istanbul ignore next */ []));
|
|
121
127
|
hasDelta = computed(() => this.delta() !== null, /* @ts-ignore */
|
|
122
128
|
...(ngDevMode ? [{ debugName: "hasDelta" }] : /* istanbul ignore next */ []));
|
|
@@ -127,18 +133,43 @@ class WrStatistic {
|
|
|
127
133
|
return d > 0 ? 'up' : 'down';
|
|
128
134
|
}, /* @ts-ignore */
|
|
129
135
|
...(ngDevMode ? [{ debugName: "deltaDirection" }] : /* istanbul ignore next */ []));
|
|
136
|
+
resolvedDeltaSuffix = useI18nText(this.deltaSuffix, 'statistic.deltaSuffix', '%');
|
|
137
|
+
/** `{{value}}{{suffix}}` — the join, so a locale owns the space before the unit. */
|
|
138
|
+
deltaFormat = useI18nFormatter('statistic.delta', '{{value}}{{suffix}}');
|
|
139
|
+
/**
|
|
140
|
+
* The delta chip, e.g. `+12.4%`.
|
|
141
|
+
*
|
|
142
|
+
* It was `` `${sign}${d}${suffix}` ``, printed one line under a value that
|
|
143
|
+
* goes through `Intl.NumberFormat` — so the two disagreed inside one
|
|
144
|
+
* component: ar-SA showed `١٬٢٣٤٬٥٦٧٫٨٩` above a Latin `12.4%`, and de-DE
|
|
145
|
+
* `1.234.567,89` above `+12.4%`. The sign comes from `signDisplay`, which also
|
|
146
|
+
* fixes the RTL half of it: `+` written by hand is a neutral character that
|
|
147
|
+
* the BiDi algorithm moves to the other end of the number.
|
|
148
|
+
*
|
|
149
|
+
* The digit count is taken from the number rather than from `precision()`,
|
|
150
|
+
* which describes the VALUE and not the delta — so what renders is the same
|
|
151
|
+
* digits as before, in the locale's own numerals. One exception, and it is an
|
|
152
|
+
* improvement rather than a regression: a magnitude JavaScript prints in
|
|
153
|
+
* exponent notation (`1e-7`, `1e+21`) used to reach the DOM that way and is
|
|
154
|
+
* now formatted as a number.
|
|
155
|
+
*/
|
|
130
156
|
deltaText = computed(() => {
|
|
131
157
|
const d = this.delta();
|
|
132
158
|
if (d === null)
|
|
133
159
|
return '';
|
|
134
|
-
const
|
|
135
|
-
|
|
160
|
+
const decimals = Math.min(20, (String(Math.abs(d)).split('.')[1] ?? '').length);
|
|
161
|
+
const value = new Intl.NumberFormat(this.locale, {
|
|
162
|
+
signDisplay: 'exceptZero',
|
|
163
|
+
minimumFractionDigits: decimals,
|
|
164
|
+
maximumFractionDigits: decimals,
|
|
165
|
+
}).format(d);
|
|
166
|
+
return this.deltaFormat({ value, suffix: this.resolvedDeltaSuffix() });
|
|
136
167
|
}, /* @ts-ignore */
|
|
137
168
|
...(ngDevMode ? [{ debugName: "deltaText" }] : /* istanbul ignore next */ []));
|
|
138
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
139
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
169
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrStatistic, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
170
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: WrStatistic, isStandalone: true, selector: "wr-statistic", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", 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 }, precision: { classPropertyName: "precision", publicName: "precision", isSignal: true, isRequired: false, transformFunction: null }, animate: { classPropertyName: "animate", publicName: "animate", isSignal: true, isRequired: false, transformFunction: null }, duration: { classPropertyName: "duration", publicName: "duration", isSignal: true, isRequired: false, transformFunction: null }, delta: { classPropertyName: "delta", publicName: "delta", isSignal: true, isRequired: false, transformFunction: null }, deltaSuffix: { classPropertyName: "deltaSuffix", publicName: "deltaSuffix", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "wr-statistic" }, ngImport: i0, template: "@if (label()) {\n <div class=\"wr-statistic__label\">{{ label() }}</div>\n}\n<div class=\"wr-statistic__value\">\n @if (prefix()) {\n <span class=\"wr-statistic__prefix\">{{ prefix() }}</span>\n }\n @if (animated()) {\n <wr-count-up\n class=\"wr-statistic__number\"\n [from]=\"animateFrom()\"\n [to]=\"numericValue() ?? 0\"\n [decimals]=\"precision()\"\n [duration]=\"duration()\"\n />\n } @else {\n <span class=\"wr-statistic__number\">{{ displayValue() }}</span>\n }\n @if (suffix()) {\n <span class=\"wr-statistic__suffix\">{{ suffix() }}</span>\n }\n</div>\n@if (hasDelta()) {\n <div [class]=\"`wr-statistic__delta wr-statistic__delta--${deltaDirection()}`\">\n @if (deltaDirection() === 'up') {\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M5 1 L9 8 L1 8 Z\" fill=\"currentColor\" />\n </svg>\n } @else if (deltaDirection() === 'down') {\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M5 9 L9 2 L1 2 Z\" fill=\"currentColor\" />\n </svg>\n }\n <span>{{ deltaText() }}</span>\n </div>\n}\n", dependencies: [{ kind: "component", type: WrCountUp, selector: "wr-count-up", inputs: ["from", "to", "duration", "delay", "easing", "trigger", "direction", "decimals", "prefix", "suffix", "grouping"], outputs: ["started", "completed"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
140
171
|
}
|
|
141
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
172
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrStatistic, decorators: [{
|
|
142
173
|
type: Component,
|
|
143
174
|
args: [{ selector: 'wr-statistic', encapsulation: ViewEncapsulation.None, host: { class: 'wr-statistic' }, imports: [WrCountUp], template: "@if (label()) {\n <div class=\"wr-statistic__label\">{{ label() }}</div>\n}\n<div class=\"wr-statistic__value\">\n @if (prefix()) {\n <span class=\"wr-statistic__prefix\">{{ prefix() }}</span>\n }\n @if (animated()) {\n <wr-count-up\n class=\"wr-statistic__number\"\n [from]=\"animateFrom()\"\n [to]=\"numericValue() ?? 0\"\n [decimals]=\"precision()\"\n [duration]=\"duration()\"\n />\n } @else {\n <span class=\"wr-statistic__number\">{{ displayValue() }}</span>\n }\n @if (suffix()) {\n <span class=\"wr-statistic__suffix\">{{ suffix() }}</span>\n }\n</div>\n@if (hasDelta()) {\n <div [class]=\"`wr-statistic__delta wr-statistic__delta--${deltaDirection()}`\">\n @if (deltaDirection() === 'up') {\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M5 1 L9 8 L1 8 Z\" fill=\"currentColor\" />\n </svg>\n } @else if (deltaDirection() === 'down') {\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M5 9 L9 2 L1 2 Z\" fill=\"currentColor\" />\n </svg>\n }\n <span>{{ deltaText() }}</span>\n </div>\n}\n" }]
|
|
144
175
|
}], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], prefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefix", required: false }] }], suffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffix", required: false }] }], precision: [{ type: i0.Input, args: [{ isSignal: true, alias: "precision", required: false }] }], animate: [{ type: i0.Input, args: [{ isSignal: true, alias: "animate", required: false }] }], duration: [{ type: i0.Input, args: [{ isSignal: true, alias: "duration", required: false }] }], delta: [{ type: i0.Input, args: [{ isSignal: true, alias: "delta", required: false }] }], deltaSuffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "deltaSuffix", required: false }] }] } });
|
|
@@ -290,10 +321,10 @@ class WrStatisticCountdown {
|
|
|
290
321
|
this.countdownEnd.emit();
|
|
291
322
|
}
|
|
292
323
|
}
|
|
293
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
294
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
324
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrStatisticCountdown, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
325
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: WrStatisticCountdown, isStandalone: true, selector: "wr-statistic-countdown", inputs: { target: { classPropertyName: "target", publicName: "target", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, endText: { classPropertyName: "endText", publicName: "endText", isSignal: true, isRequired: false, transformFunction: null }, tickMs: { classPropertyName: "tickMs", publicName: "tickMs", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { countdownEnd: "countdownEnd" }, host: { classAttribute: "wr-statistic" }, ngImport: i0, template: "@if (label()) {\n <div class=\"wr-statistic__label\">{{ label() }}</div>\n}\n<div class=\"wr-statistic__value\">\n <span class=\"wr-statistic__number\">{{ display() }}</span>\n</div>\n", encapsulation: i0.ViewEncapsulation.None });
|
|
295
326
|
}
|
|
296
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
327
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrStatisticCountdown, decorators: [{
|
|
297
328
|
type: Component,
|
|
298
329
|
args: [{ selector: 'wr-statistic-countdown', encapsulation: ViewEncapsulation.None, host: { class: 'wr-statistic' }, template: "@if (label()) {\n <div class=\"wr-statistic__label\">{{ label() }}</div>\n}\n<div class=\"wr-statistic__value\">\n <span class=\"wr-statistic__number\">{{ display() }}</span>\n</div>\n" }]
|
|
299
330
|
}], ctorParameters: () => [], propDecorators: { target: [{ type: i0.Input, args: [{ isSignal: true, alias: "target", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }], endText: [{ type: i0.Input, args: [{ isSignal: true, alias: "endText", required: false }] }], tickMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "tickMs", required: false }] }], countdownEnd: [{ type: i0.Output, args: ["countdownEnd"] }] } });
|
|
@@ -336,10 +367,10 @@ class WrStatisticGroup {
|
|
|
336
367
|
* width allows. @default 0
|
|
337
368
|
*/
|
|
338
369
|
columns = input(0, { ...(ngDevMode ? { debugName: "columns" } : /* istanbul ignore next */ {}), transform: (v) => Math.max(0, coerceNumberProperty(v, 0)) });
|
|
339
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
340
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.
|
|
370
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrStatisticGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
371
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.5", type: WrStatisticGroup, isStandalone: true, selector: "wr-statistic-group", inputs: { min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.--wr-statistic-group-min": "min()", "style.--wr-statistic-group-columns": "columns() || null" }, classAttribute: "wr-statistic-group" }, ngImport: i0, template: '<div class="wr-statistic-group__grid"><ng-content /></div>', isInline: true, encapsulation: i0.ViewEncapsulation.None });
|
|
341
372
|
}
|
|
342
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
373
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrStatisticGroup, decorators: [{
|
|
343
374
|
type: Component,
|
|
344
375
|
args: [{
|
|
345
376
|
selector: 'wr-statistic-group',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-statistic.mjs","sources":["../../../projects/lib/statistic/statistic.ts","../../../projects/lib/statistic/statistic.html","../../../projects/lib/statistic/statistic-countdown.ts","../../../projects/lib/statistic/statistic-countdown.html","../../../projects/lib/statistic/statistic-group.ts","../../../projects/lib/statistic/ngwr-statistic.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport {\n Component,\n LOCALE_ID,\n ViewEncapsulation,\n computed,\n effect,\n inject,\n input,\n signal,\n untracked,\n} from '@angular/core';\n\nimport { WrCountUp } from 'ngwr/counter';\nimport { WrPlatform } from 'ngwr/platform';\nimport { numAttr } from 'ngwr/utils';\n\n/**\n * KPI card — label + big number + optional prefix/suffix + delta. Pair\n * with `<wr-statistic-group>` for a responsive dashboard grid.\n *\n * When `value` is numeric the number counts up (eased) from its previous\n * value to the new one on every change — see `animate`. String values and\n * `prefers-reduced-motion` render instantly.\n *\n * @example\n * ```html\n * <wr-statistic label=\"Active users\" [value]=\"12345\" suffix=\"users\" />\n * <wr-statistic label=\"Revenue\" [value]=\"9512\" prefix=\"$\" [delta]=\"12.4\" />\n * <wr-statistic label=\"Churn\" [value]=\"1.8\" suffix=\"%\" [precision]=\"1\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/statistic\n */\n@Component({\n selector: 'wr-statistic',\n templateUrl: './statistic.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-statistic' },\n imports: [WrCountUp],\n})\nexport class WrStatistic {\n private readonly platform = inject(WrPlatform);\n private readonly locale = inject(LOCALE_ID);\n\n readonly label = input<string>('');\n\n /** The number (or string) to display in the main slot. */\n readonly value = input<number | string | null>(null);\n\n /** Prefix glyph / symbol (e.g. `'$'`). */\n readonly prefix = input<string>('');\n\n /** Suffix glyph / unit (e.g. `'%'`, `'kg'`). */\n readonly suffix = input<string>('');\n\n /** Fixed number of decimals applied to numeric values. @default 0 */\n readonly precision = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /**\n * Count up to a new numeric `value` instead of swapping instantly. Always\n * off for string values or under `prefers-reduced-motion`. @default true\n */\n readonly animate = input(true, { transform: coerceBooleanProperty });\n\n /** Count-up duration (ms). @default 700 */\n readonly duration = input(700, { transform: numAttr(700) });\n\n /**\n * The current value coerced to a finite number, or `null` when `value` is\n * a non-numeric string / empty / nullish (rendered as-is).\n */\n protected readonly numericValue = computed<number | null>(() => {\n const raw = this.value();\n if (raw === null || raw === '') return null;\n const n = typeof raw === 'number' ? raw : coerceNumberProperty(raw, Number.NaN);\n return Number.isFinite(n) ? n : null;\n });\n\n /** Whether the value should count up (browser, numeric, opted-in, motion allowed). */\n protected readonly animated = computed<boolean>(\n () =>\n this.platform.isBrowser && this.animate() && !this.platform.prefersReducedMotion() && this.numericValue() !== null\n );\n\n /** Animation start — the previously-rendered numeric value (0 on first paint). */\n protected readonly animateFrom = signal(0);\n\n /** Bookkeeping: the last numeric value seen, fed back as the next `from`. */\n private readonly lastNumeric = signal(0);\n\n constructor() {\n // Whenever the numeric value changes, snapshot the prior value as the\n // count-up start, then remember the new one for the next transition.\n effect(() => {\n const next = this.numericValue();\n if (next === null) return;\n untracked(() => {\n this.animateFrom.set(this.lastNumeric());\n this.lastNumeric.set(next);\n });\n });\n }\n\n /**\n * Static (non-animated) display string. Numeric values honour `precision`\n * and locale grouping so they match the count-up output; everything else\n * renders verbatim with an em-dash fallback.\n */\n protected readonly displayValue = computed<string>(() => {\n const n = this.numericValue();\n if (n !== null) {\n return new Intl.NumberFormat(this.locale, {\n minimumFractionDigits: this.precision(),\n maximumFractionDigits: this.precision(),\n }).format(n);\n }\n // `numericValue` above already reads `''` as \"no value\"; rendering it\n // verbatim put an empty card on screen instead of the placeholder.\n const raw = this.value();\n return raw === null || raw === undefined || raw === '' ? '—' : String(raw);\n });\n\n /**\n * Optional delta vs previous period — shown as `+x.x%` (or `-x.x%`).\n * Use `deltaSuffix` to change the trailing unit.\n */\n readonly delta = input<number | null>(null, {\n transform: (v: unknown): number | null => {\n if (v === null || v === undefined || v === '') return null;\n const n = coerceNumberProperty(v, Number.NaN);\n return Number.isFinite(n) ? n : null;\n },\n });\n\n /** Unit appended to the delta value. @default '%' */\n readonly deltaSuffix = input<string>('%');\n\n protected readonly hasDelta = computed(() => this.delta() !== null);\n\n protected readonly deltaDirection = computed<'up' | 'down' | 'flat'>(() => {\n const d = this.delta();\n if (d === null || d === 0) return 'flat';\n return d > 0 ? 'up' : 'down';\n });\n\n protected readonly deltaText = computed(() => {\n const d = this.delta();\n if (d === null) return '';\n const sign = d > 0 ? '+' : '';\n return `${sign}${d}${this.deltaSuffix()}`;\n });\n}\n","@if (label()) {\n <div class=\"wr-statistic__label\">{{ label() }}</div>\n}\n<div class=\"wr-statistic__value\">\n @if (prefix()) {\n <span class=\"wr-statistic__prefix\">{{ prefix() }}</span>\n }\n @if (animated()) {\n <wr-count-up\n class=\"wr-statistic__number\"\n [from]=\"animateFrom()\"\n [to]=\"numericValue() ?? 0\"\n [decimals]=\"precision()\"\n [duration]=\"duration()\"\n />\n } @else {\n <span class=\"wr-statistic__number\">{{ displayValue() }}</span>\n }\n @if (suffix()) {\n <span class=\"wr-statistic__suffix\">{{ suffix() }}</span>\n }\n</div>\n@if (hasDelta()) {\n <div [class]=\"`wr-statistic__delta wr-statistic__delta--${deltaDirection()}`\">\n @if (deltaDirection() === 'up') {\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M5 1 L9 8 L1 8 Z\" fill=\"currentColor\" />\n </svg>\n } @else if (deltaDirection() === 'down') {\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M5 9 L9 2 L1 2 Z\" fill=\"currentColor\" />\n </svg>\n }\n <span>{{ deltaText() }}</span>\n </div>\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n PLATFORM_ID,\n ViewEncapsulation,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\n\nimport { numAttr } from 'ngwr/utils';\n\n// Helpers\n\nfunction toMs(value: Date | string | number): number {\n if (value instanceof Date) return value.getTime();\n if (typeof value === 'number') return value;\n return new Date(value).getTime();\n}\n\nfunction pad(n: number, width: number): string {\n return String(n).padStart(width, '0');\n}\n\nfunction formatRemaining(ms: number, fmt: string): string {\n const days = Math.floor(ms / 86_400_000);\n const hours = Math.floor((ms % 86_400_000) / 3_600_000);\n const minutes = Math.floor((ms % 3_600_000) / 60_000);\n const seconds = Math.floor((ms % 60_000) / 1000);\n const millis = ms % 1000;\n // Single-pass tokenizer so we never re-scan output for tokens. The\n // previous sequential `.replace()` chain leaked: e.g. `D days HH:mm:ss`\n // → `1 day42 11:59:42` because the `/s/g` step at the end re-matched\n // the literal `s` inside `days`. Longest-token-first ordering inside\n // the alternation handles `DD`>`D`, `HH`>`H`, `mm`>`m`, `SSS`>`ss`>`s`.\n return fmt.replace(/(?<![A-Za-z])(?:SSS|DD|HH|mm|ss|D|H|m|s)(?![A-Za-z])/g, token => {\n switch (token) {\n case 'DD':\n return pad(days, 2);\n case 'D':\n return String(days);\n case 'HH':\n return pad(hours, 2);\n case 'H':\n return String(hours);\n case 'mm':\n return pad(minutes, 2);\n case 'm':\n return String(minutes);\n case 'ss':\n return pad(seconds, 2);\n case 's':\n return String(seconds);\n case 'SSS':\n return pad(millis, 3);\n default:\n return token;\n }\n });\n}\n\n/**\n * Live-counting variant of `<wr-statistic>` that targets a future date\n * and ticks down to zero. The format string uses Day/Hour/Minute/Second\n * tokens (`D`, `H`, `m`, `s`, double for zero-padded, plus `SSS` for\n * milliseconds).\n *\n * @example\n * ```html\n * <wr-statistic-countdown\n * label=\"Launch in\"\n * [target]=\"launchDate\"\n * format=\"D days HH:mm:ss\"\n * (countdownEnd)=\"onLive()\"\n * />\n * ```\n *\n * @see https://ngwr.dev/reference/components/statistic\n */\n@Component({\n selector: 'wr-statistic-countdown',\n templateUrl: './statistic-countdown.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-statistic' },\n})\nexport class WrStatisticCountdown {\n /** Target date / timestamp the countdown is running down to. */\n readonly target = input.required<Date | string | number>();\n\n /** Label rendered above the value. */\n readonly label = input<string>('');\n\n /**\n * Format string. Tokens: `D`/`DD` (days), `H`/`HH` (hours),\n * `m`/`mm` (minutes), `s`/`ss` (seconds), `SSS` (milliseconds).\n * Double-letter forms zero-pad to width 2. @default 'HH:mm:ss'\n */\n readonly format = input<string>('HH:mm:ss');\n\n /** Optional text shown once the countdown reaches zero. */\n readonly endText = input<string | null>(null);\n\n /**\n * Tick interval in ms. Drop to ~16 for `SSS` (millisecond display). Floored\n * at one frame — `0` (or an unparseable value) asked `setInterval` to run as\n * fast as the browser would allow, which is a busy loop, not a countdown.\n * @default 1000\n */\n readonly tickMs = input(1000, { transform: (v: unknown): number => Math.max(16, numAttr(1000)(v)) });\n\n /** Fires once when the countdown crosses zero. */\n readonly countdownEnd = output<void>();\n\n private readonly destroyRef = inject(DestroyRef);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n\n private readonly targetMs = computed(() => toMs(this.target()));\n\n /**\n * Milliseconds left, or `null` when `target` does not parse to a date at all.\n * `new Date('nope').getTime()` is `NaN`, and `NaN` propagated all the way to\n * the screen as `NaN:NaN:NaN` — and, worse, `tick` compared it to `0` and so\n * never fired `countdownEnd`, while a guard that only clamped the text would\n * have fired it immediately for a target that was never reached.\n */\n private remainingMs(): number | null {\n const target = this.targetMs();\n return Number.isFinite(target) ? Math.max(0, target - Date.now()) : null;\n }\n\n /** Remaining milliseconds (live signal). */\n protected readonly remaining = signal(0);\n protected readonly finished = signal(false);\n\n protected readonly display = computed(() => {\n if (this.finished() && this.endText() != null) return this.endText()!;\n return formatRemaining(this.remaining(), this.format());\n });\n\n constructor() {\n // Seed once synchronously so SSR / first paint shows a sane value.\n effect(() => {\n const ms = this.remainingMs();\n this.remaining.set(ms ?? 0);\n this.finished.set(ms === 0);\n });\n\n if (!this.isBrowser) return;\n\n afterNextRender(() => {\n const handle = setInterval(() => this.tick(), this.tickMs());\n this.destroyRef.onDestroy(() => clearInterval(handle));\n });\n }\n\n private tick(): void {\n const ms = this.remainingMs();\n if (ms === null) return;\n this.remaining.set(ms);\n if (ms === 0 && !this.finished()) {\n this.finished.set(true);\n this.countdownEnd.emit();\n }\n }\n}\n","@if (label()) {\n <div class=\"wr-statistic__label\">{{ label() }}</div>\n}\n<div class=\"wr-statistic__value\">\n <span class=\"wr-statistic__number\">{{ display() }}</span>\n</div>\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceNumberProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, input } from '@angular/core';\n\n/**\n * Dashboard grid for `<wr-statistic>` cards. The column count follows the\n * group's OWN width — an intrinsic container-query grid sized by its box, not\n * a viewport media query — so it reflows correctly inside any column, card, or\n * split pane. Columns are never narrower than `min`; `columns` optionally caps\n * how many ever sit side by side on a wide container.\n *\n * @example\n * ```html\n * <wr-statistic-group [columns]=\"4\" min=\"11rem\">\n * <wr-statistic label=\"Active users\" [value]=\"12345\" />\n * <wr-statistic label=\"Revenue\" [value]=\"9512\" prefix=\"$\" [delta]=\"12.4\" />\n * <wr-statistic label=\"Churn\" [value]=\"1.8\" suffix=\"%\" [delta]=\"-0.4\" />\n * <wr-statistic label=\"Sessions\" [value]=\"48210\" />\n * </wr-statistic-group>\n * ```\n *\n * @see https://ngwr.dev/reference/components/statistic\n */\n@Component({\n selector: 'wr-statistic-group',\n template: '<div class=\"wr-statistic-group__grid\"><ng-content /></div>',\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'wr-statistic-group',\n '[style.--wr-statistic-group-min]': 'min()',\n '[style.--wr-statistic-group-columns]': 'columns() || null',\n },\n})\nexport class WrStatisticGroup {\n /**\n * Minimum width of each column before the grid reflows to fewer columns.\n * Any CSS length — smaller packs more cards per row. @default '12rem'\n */\n readonly min = input<string>('12rem');\n\n /**\n * Cap on how many columns ever sit side by side on a wide container. `0`\n * (default) leaves it uncapped — fit as many `min`-wide columns as the\n * width allows. @default 0\n */\n readonly columns = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngwr-statistic.mjs","sources":["../../../projects/lib/statistic/statistic.ts","../../../projects/lib/statistic/statistic.html","../../../projects/lib/statistic/statistic-countdown.ts","../../../projects/lib/statistic/statistic-countdown.html","../../../projects/lib/statistic/statistic-group.ts","../../../projects/lib/statistic/ngwr-statistic.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport {\n Component,\n LOCALE_ID,\n ViewEncapsulation,\n computed,\n effect,\n inject,\n input,\n signal,\n untracked,\n} from '@angular/core';\n\nimport { WrCountUp } from 'ngwr/counter';\nimport { useI18nFormatter, useI18nText } from 'ngwr/i18n';\nimport { WrPlatform } from 'ngwr/platform';\nimport { numAttr } from 'ngwr/utils';\n\n/**\n * KPI card — label + big number + optional prefix/suffix + delta. Pair\n * with `<wr-statistic-group>` for a responsive dashboard grid.\n *\n * When `value` is numeric the number counts up (eased) from its previous\n * value to the new one on every change — see `animate`. String values and\n * `prefers-reduced-motion` render instantly.\n *\n * @example\n * ```html\n * <wr-statistic label=\"Active users\" [value]=\"12345\" suffix=\"users\" />\n * <wr-statistic label=\"Revenue\" [value]=\"9512\" prefix=\"$\" [delta]=\"12.4\" />\n * <wr-statistic label=\"Churn\" [value]=\"1.8\" suffix=\"%\" [precision]=\"1\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/statistic\n */\n@Component({\n selector: 'wr-statistic',\n templateUrl: './statistic.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-statistic' },\n imports: [WrCountUp],\n})\nexport class WrStatistic {\n private readonly platform = inject(WrPlatform);\n private readonly locale = inject(LOCALE_ID);\n\n readonly label = input<string>('');\n\n /** The number (or string) to display in the main slot. */\n readonly value = input<number | string | null>(null);\n\n /** Prefix glyph / symbol (e.g. `'$'`). */\n readonly prefix = input<string>('');\n\n /** Suffix glyph / unit (e.g. `'%'`, `'kg'`). */\n readonly suffix = input<string>('');\n\n /** Fixed number of decimals applied to numeric values. @default 0 */\n readonly precision = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /**\n * Count up to a new numeric `value` instead of swapping instantly. Always\n * off for string values or under `prefers-reduced-motion`. @default true\n */\n readonly animate = input(true, { transform: coerceBooleanProperty });\n\n /** Count-up duration (ms). @default 700 */\n readonly duration = input(700, { transform: numAttr(700) });\n\n /**\n * The current value coerced to a finite number, or `null` when `value` is\n * a non-numeric string / empty / nullish (rendered as-is).\n */\n protected readonly numericValue = computed<number | null>(() => {\n const raw = this.value();\n if (raw === null || raw === '') return null;\n const n = typeof raw === 'number' ? raw : coerceNumberProperty(raw, Number.NaN);\n return Number.isFinite(n) ? n : null;\n });\n\n /** Whether the value should count up (browser, numeric, opted-in, motion allowed). */\n protected readonly animated = computed<boolean>(\n () =>\n this.platform.isBrowser && this.animate() && !this.platform.prefersReducedMotion() && this.numericValue() !== null\n );\n\n /** Animation start — the previously-rendered numeric value (0 on first paint). */\n protected readonly animateFrom = signal(0);\n\n /** Bookkeeping: the last numeric value seen, fed back as the next `from`. */\n private readonly lastNumeric = signal(0);\n\n constructor() {\n // Whenever the numeric value changes, snapshot the prior value as the\n // count-up start, then remember the new one for the next transition.\n effect(() => {\n const next = this.numericValue();\n if (next === null) return;\n untracked(() => {\n this.animateFrom.set(this.lastNumeric());\n this.lastNumeric.set(next);\n });\n });\n }\n\n /**\n * Static (non-animated) display string. Numeric values honour `precision`\n * and locale grouping so they match the count-up output; everything else\n * renders verbatim with an em-dash fallback.\n */\n protected readonly displayValue = computed<string>(() => {\n const n = this.numericValue();\n if (n !== null) {\n return new Intl.NumberFormat(this.locale, {\n minimumFractionDigits: this.precision(),\n maximumFractionDigits: this.precision(),\n }).format(n);\n }\n // `numericValue` above already reads `''` as \"no value\"; rendering it\n // verbatim put an empty card on screen instead of the placeholder.\n const raw = this.value();\n return raw === null || raw === undefined || raw === '' ? '—' : String(raw);\n });\n\n /**\n * Optional delta vs previous period — shown as `+x.x%` (or `-x.x%`).\n * Use `deltaSuffix` to change the trailing unit.\n */\n readonly delta = input<number | null>(null, {\n transform: (v: unknown): number | null => {\n if (v === null || v === undefined || v === '') return null;\n const n = coerceNumberProperty(v, Number.NaN);\n return Number.isFinite(n) ? n : null;\n },\n });\n\n // The default moved from the literal `'%'` to `null` so the catalog gets a\n // say. `%` is a string the LIBRARY owns and no locale could reach: a locale\n // that writes it differently — or writes it as a word — had nowhere to put\n // that but a per-instance binding on every `<wr-statistic>` on the page. A\n // bound value still wins, exactly as before, which is what makes this safe.\n /** Unit appended to the delta value. Falls back to `statistic.deltaSuffix`, then `'%'`. */\n readonly deltaSuffix = input<string | null>(null);\n\n protected readonly hasDelta = computed(() => this.delta() !== null);\n\n protected readonly deltaDirection = computed<'up' | 'down' | 'flat'>(() => {\n const d = this.delta();\n if (d === null || d === 0) return 'flat';\n return d > 0 ? 'up' : 'down';\n });\n\n protected readonly resolvedDeltaSuffix = useI18nText(this.deltaSuffix, 'statistic.deltaSuffix', '%');\n\n /** `{{value}}{{suffix}}` — the join, so a locale owns the space before the unit. */\n private readonly deltaFormat = useI18nFormatter('statistic.delta', '{{value}}{{suffix}}');\n\n /**\n * The delta chip, e.g. `+12.4%`.\n *\n * It was `` `${sign}${d}${suffix}` ``, printed one line under a value that\n * goes through `Intl.NumberFormat` — so the two disagreed inside one\n * component: ar-SA showed `١٬٢٣٤٬٥٦٧٫٨٩` above a Latin `12.4%`, and de-DE\n * `1.234.567,89` above `+12.4%`. The sign comes from `signDisplay`, which also\n * fixes the RTL half of it: `+` written by hand is a neutral character that\n * the BiDi algorithm moves to the other end of the number.\n *\n * The digit count is taken from the number rather than from `precision()`,\n * which describes the VALUE and not the delta — so what renders is the same\n * digits as before, in the locale's own numerals. One exception, and it is an\n * improvement rather than a regression: a magnitude JavaScript prints in\n * exponent notation (`1e-7`, `1e+21`) used to reach the DOM that way and is\n * now formatted as a number.\n */\n protected readonly deltaText = computed(() => {\n const d = this.delta();\n if (d === null) return '';\n const decimals = Math.min(20, (String(Math.abs(d)).split('.')[1] ?? '').length);\n const value = new Intl.NumberFormat(this.locale, {\n signDisplay: 'exceptZero',\n minimumFractionDigits: decimals,\n maximumFractionDigits: decimals,\n }).format(d);\n return this.deltaFormat({ value, suffix: this.resolvedDeltaSuffix() });\n });\n}\n","@if (label()) {\n <div class=\"wr-statistic__label\">{{ label() }}</div>\n}\n<div class=\"wr-statistic__value\">\n @if (prefix()) {\n <span class=\"wr-statistic__prefix\">{{ prefix() }}</span>\n }\n @if (animated()) {\n <wr-count-up\n class=\"wr-statistic__number\"\n [from]=\"animateFrom()\"\n [to]=\"numericValue() ?? 0\"\n [decimals]=\"precision()\"\n [duration]=\"duration()\"\n />\n } @else {\n <span class=\"wr-statistic__number\">{{ displayValue() }}</span>\n }\n @if (suffix()) {\n <span class=\"wr-statistic__suffix\">{{ suffix() }}</span>\n }\n</div>\n@if (hasDelta()) {\n <div [class]=\"`wr-statistic__delta wr-statistic__delta--${deltaDirection()}`\">\n @if (deltaDirection() === 'up') {\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M5 1 L9 8 L1 8 Z\" fill=\"currentColor\" />\n </svg>\n } @else if (deltaDirection() === 'down') {\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" aria-hidden=\"true\">\n <path d=\"M5 9 L9 2 L1 2 Z\" fill=\"currentColor\" />\n </svg>\n }\n <span>{{ deltaText() }}</span>\n </div>\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n PLATFORM_ID,\n ViewEncapsulation,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\n\nimport { numAttr } from 'ngwr/utils';\n\n// Helpers\n\nfunction toMs(value: Date | string | number): number {\n if (value instanceof Date) return value.getTime();\n if (typeof value === 'number') return value;\n return new Date(value).getTime();\n}\n\nfunction pad(n: number, width: number): string {\n return String(n).padStart(width, '0');\n}\n\nfunction formatRemaining(ms: number, fmt: string): string {\n const days = Math.floor(ms / 86_400_000);\n const hours = Math.floor((ms % 86_400_000) / 3_600_000);\n const minutes = Math.floor((ms % 3_600_000) / 60_000);\n const seconds = Math.floor((ms % 60_000) / 1000);\n const millis = ms % 1000;\n // Single-pass tokenizer so we never re-scan output for tokens. The\n // previous sequential `.replace()` chain leaked: e.g. `D days HH:mm:ss`\n // → `1 day42 11:59:42` because the `/s/g` step at the end re-matched\n // the literal `s` inside `days`. Longest-token-first ordering inside\n // the alternation handles `DD`>`D`, `HH`>`H`, `mm`>`m`, `SSS`>`ss`>`s`.\n return fmt.replace(/(?<![A-Za-z])(?:SSS|DD|HH|mm|ss|D|H|m|s)(?![A-Za-z])/g, token => {\n switch (token) {\n case 'DD':\n return pad(days, 2);\n case 'D':\n return String(days);\n case 'HH':\n return pad(hours, 2);\n case 'H':\n return String(hours);\n case 'mm':\n return pad(minutes, 2);\n case 'm':\n return String(minutes);\n case 'ss':\n return pad(seconds, 2);\n case 's':\n return String(seconds);\n case 'SSS':\n return pad(millis, 3);\n default:\n return token;\n }\n });\n}\n\n/**\n * Live-counting variant of `<wr-statistic>` that targets a future date\n * and ticks down to zero. The format string uses Day/Hour/Minute/Second\n * tokens (`D`, `H`, `m`, `s`, double for zero-padded, plus `SSS` for\n * milliseconds).\n *\n * @example\n * ```html\n * <wr-statistic-countdown\n * label=\"Launch in\"\n * [target]=\"launchDate\"\n * format=\"D days HH:mm:ss\"\n * (countdownEnd)=\"onLive()\"\n * />\n * ```\n *\n * @see https://ngwr.dev/reference/components/statistic\n */\n@Component({\n selector: 'wr-statistic-countdown',\n templateUrl: './statistic-countdown.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-statistic' },\n})\nexport class WrStatisticCountdown {\n /** Target date / timestamp the countdown is running down to. */\n readonly target = input.required<Date | string | number>();\n\n /** Label rendered above the value. */\n readonly label = input<string>('');\n\n /**\n * Format string. Tokens: `D`/`DD` (days), `H`/`HH` (hours),\n * `m`/`mm` (minutes), `s`/`ss` (seconds), `SSS` (milliseconds).\n * Double-letter forms zero-pad to width 2. @default 'HH:mm:ss'\n */\n readonly format = input<string>('HH:mm:ss');\n\n /** Optional text shown once the countdown reaches zero. */\n readonly endText = input<string | null>(null);\n\n /**\n * Tick interval in ms. Drop to ~16 for `SSS` (millisecond display). Floored\n * at one frame — `0` (or an unparseable value) asked `setInterval` to run as\n * fast as the browser would allow, which is a busy loop, not a countdown.\n * @default 1000\n */\n readonly tickMs = input(1000, { transform: (v: unknown): number => Math.max(16, numAttr(1000)(v)) });\n\n /** Fires once when the countdown crosses zero. */\n readonly countdownEnd = output<void>();\n\n private readonly destroyRef = inject(DestroyRef);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n\n private readonly targetMs = computed(() => toMs(this.target()));\n\n /**\n * Milliseconds left, or `null` when `target` does not parse to a date at all.\n * `new Date('nope').getTime()` is `NaN`, and `NaN` propagated all the way to\n * the screen as `NaN:NaN:NaN` — and, worse, `tick` compared it to `0` and so\n * never fired `countdownEnd`, while a guard that only clamped the text would\n * have fired it immediately for a target that was never reached.\n */\n private remainingMs(): number | null {\n const target = this.targetMs();\n return Number.isFinite(target) ? Math.max(0, target - Date.now()) : null;\n }\n\n /** Remaining milliseconds (live signal). */\n protected readonly remaining = signal(0);\n protected readonly finished = signal(false);\n\n protected readonly display = computed(() => {\n if (this.finished() && this.endText() != null) return this.endText()!;\n return formatRemaining(this.remaining(), this.format());\n });\n\n constructor() {\n // Seed once synchronously so SSR / first paint shows a sane value.\n effect(() => {\n const ms = this.remainingMs();\n this.remaining.set(ms ?? 0);\n this.finished.set(ms === 0);\n });\n\n if (!this.isBrowser) return;\n\n afterNextRender(() => {\n const handle = setInterval(() => this.tick(), this.tickMs());\n this.destroyRef.onDestroy(() => clearInterval(handle));\n });\n }\n\n private tick(): void {\n const ms = this.remainingMs();\n if (ms === null) return;\n this.remaining.set(ms);\n if (ms === 0 && !this.finished()) {\n this.finished.set(true);\n this.countdownEnd.emit();\n }\n }\n}\n","@if (label()) {\n <div class=\"wr-statistic__label\">{{ label() }}</div>\n}\n<div class=\"wr-statistic__value\">\n <span class=\"wr-statistic__number\">{{ display() }}</span>\n</div>\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceNumberProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, input } from '@angular/core';\n\n/**\n * Dashboard grid for `<wr-statistic>` cards. The column count follows the\n * group's OWN width — an intrinsic container-query grid sized by its box, not\n * a viewport media query — so it reflows correctly inside any column, card, or\n * split pane. Columns are never narrower than `min`; `columns` optionally caps\n * how many ever sit side by side on a wide container.\n *\n * @example\n * ```html\n * <wr-statistic-group [columns]=\"4\" min=\"11rem\">\n * <wr-statistic label=\"Active users\" [value]=\"12345\" />\n * <wr-statistic label=\"Revenue\" [value]=\"9512\" prefix=\"$\" [delta]=\"12.4\" />\n * <wr-statistic label=\"Churn\" [value]=\"1.8\" suffix=\"%\" [delta]=\"-0.4\" />\n * <wr-statistic label=\"Sessions\" [value]=\"48210\" />\n * </wr-statistic-group>\n * ```\n *\n * @see https://ngwr.dev/reference/components/statistic\n */\n@Component({\n selector: 'wr-statistic-group',\n template: '<div class=\"wr-statistic-group__grid\"><ng-content /></div>',\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'wr-statistic-group',\n '[style.--wr-statistic-group-min]': 'min()',\n '[style.--wr-statistic-group-columns]': 'columns() || null',\n },\n})\nexport class WrStatisticGroup {\n /**\n * Minimum width of each column before the grid reflows to fewer columns.\n * Any CSS length — smaller packs more cards per row. @default '12rem'\n */\n readonly min = input<string>('12rem');\n\n /**\n * Cap on how many columns ever sit side by side on a wide container. `0`\n * (default) leaves it uncapped — fit as many `min`-wide columns as the\n * width allows. @default 0\n */\n readonly columns = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -55,10 +55,10 @@ class WrStep {
|
|
|
55
55
|
stepper = inject(WR_STEPPER);
|
|
56
56
|
isActive = computed(() => this._index() === this.stepper.active(), /* @ts-ignore */
|
|
57
57
|
...(ngDevMode ? [{ debugName: "isActive" }] : /* istanbul ignore next */ []));
|
|
58
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
59
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.
|
|
58
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrStep, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
59
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.5", type: WrStep, isStandalone: true, selector: "wr-step", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, optional: { classPropertyName: "optional", publicName: "optional", isSignal: true, isRequired: false, transformFunction: null }, completed: { classPropertyName: "completed", publicName: "completed", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.wr-step--active": "isActive()" }, classAttribute: "wr-step" }, ngImport: i0, template: '<ng-content />', isInline: true, encapsulation: i0.ViewEncapsulation.None });
|
|
60
60
|
}
|
|
61
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
61
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrStep, decorators: [{
|
|
62
62
|
type: Component,
|
|
63
63
|
args: [{
|
|
64
64
|
selector: 'wr-step',
|
|
@@ -192,8 +192,8 @@ class WrStepper {
|
|
|
192
192
|
prev() {
|
|
193
193
|
this.goTo(this.active() - 1);
|
|
194
194
|
}
|
|
195
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
196
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
195
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrStepper, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
196
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: WrStepper, isStandalone: true, selector: "wr-stepper", inputs: { active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, linear: { classPropertyName: "linear", publicName: "linear", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { active: "activeChange" }, host: { properties: { "class": "classes()" } }, providers: [
|
|
197
197
|
{
|
|
198
198
|
provide: WR_STEPPER,
|
|
199
199
|
// eslint-disable-next-line @angular-eslint/no-forward-ref
|
|
@@ -201,7 +201,7 @@ class WrStepper {
|
|
|
201
201
|
},
|
|
202
202
|
], queries: [{ propertyName: "steps", predicate: WrStep, isSignal: true }], ngImport: i0, template: "<ol class=\"wr-stepper__headers\" role=\"list\">\n @for (step of steps(); track $index) {\n <li\n class=\"wr-stepper__header\"\n [class.wr-stepper__header--active]=\"$index === active()\"\n [class.wr-stepper__header--completed]=\"isCompleted($index)\"\n [class.wr-stepper__header--reachable]=\"isReachable($index)\"\n [class.wr-stepper__header--disabled]=\"step.disabled()\"\n >\n <button\n type=\"button\"\n class=\"wr-stepper__header-button\"\n [disabled]=\"!isReachable($index) || step.disabled()\"\n [attr.aria-current]=\"$index === active() ? 'step' : null\"\n (click)=\"onHeaderClick($index)\"\n >\n <span class=\"wr-stepper__indicator\" aria-hidden=\"true\">\n @if (isCompleted($index)) {\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\">\n <path\n d=\"M3 7.5 L6 10.5 L11 4.5\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.75\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n } @else {\n {{ $index + 1 }}\n }\n </span>\n <span class=\"wr-stepper__label\">\n {{ step.label() }}\n @if (step.optional()) {\n <small class=\"wr-stepper__optional\">{{ optionalLabel() }}</small>\n }\n @if (step.description()) {\n <small class=\"wr-stepper__description\">{{ step.description() }}</small>\n }\n </span>\n </button>\n @if (!$last) {\n <span class=\"wr-stepper__connector\" aria-hidden=\"true\"></span>\n }\n </li>\n }\n</ol>\n\n<div class=\"wr-stepper__body\">\n <ng-content />\n</div>\n", encapsulation: i0.ViewEncapsulation.None });
|
|
203
203
|
}
|
|
204
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
204
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrStepper, decorators: [{
|
|
205
205
|
type: Component,
|
|
206
206
|
args: [{ selector: 'wr-stepper', encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()' }, providers: [
|
|
207
207
|
{
|
|
@@ -109,6 +109,9 @@ function isEnvelope(x) {
|
|
|
109
109
|
* lazily on the next `get` / `watch` read.
|
|
110
110
|
* - **Reactive watch** — `watch(key)` returns a `Signal` that updates on
|
|
111
111
|
* local writes and cross-tab `storage` events.
|
|
112
|
+
* - **On-disk format** — values are wrapped in a {@link WrStorageEnvelope}
|
|
113
|
+
* (`{"v":…,"e":…}`) while `json` is on. Anything reading the same key from
|
|
114
|
+
* outside Angular has to unwrap it.
|
|
112
115
|
*
|
|
113
116
|
* SSR-safe: the default engine factory returns an in-memory shim when
|
|
114
117
|
* `localStorage` is unavailable, so reads always work.
|
|
@@ -180,6 +183,11 @@ class WrStorage {
|
|
|
180
183
|
/**
|
|
181
184
|
* Write `value` at `key`. Per-call `ttl` (ms) overrides the config
|
|
182
185
|
* default. JSON-serializable values only when `json` is on (the default).
|
|
186
|
+
*
|
|
187
|
+
* What lands in the engine is a {@link WrStorageEnvelope} —
|
|
188
|
+
* `{"v":<value>}`, plus `"e"` when a TTL applies — not the bare value. Code
|
|
189
|
+
* outside Angular that reads the same key has to unwrap it; see the envelope's
|
|
190
|
+
* own docs for the exact format.
|
|
183
191
|
*/
|
|
184
192
|
set(key, value, opts) {
|
|
185
193
|
const fk = this.fullKey(key);
|
|
@@ -306,10 +314,10 @@ class WrStorage {
|
|
|
306
314
|
this.listenerInstalled = false;
|
|
307
315
|
});
|
|
308
316
|
}
|
|
309
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
310
|
-
static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.
|
|
317
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrStorage, deps: [], target: i0.ɵɵFactoryTarget.Service });
|
|
318
|
+
static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.5", ngImport: i0, type: WrStorage });
|
|
311
319
|
}
|
|
312
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
320
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrStorage, decorators: [{
|
|
313
321
|
type: Service
|
|
314
322
|
}] });
|
|
315
323
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-storage.mjs","sources":["../../../projects/lib/storage/storage-config.ts","../../../projects/lib/storage/storage-engine.ts","../../../projects/lib/storage/storage.ts","../../../projects/lib/storage/provide-wr-storage.ts","../../../projects/lib/storage/ngwr-storage.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { InjectionToken } from '@angular/core';\n\nimport type { WrStorageConfigResolved } from './interfaces';\n\nexport const DEFAULT_WR_STORAGE_CONFIG: WrStorageConfigResolved = {\n prefix: '',\n json: true,\n ttl: 0,\n};\n\nexport const WR_STORAGE_CONFIG = new InjectionToken<WrStorageConfigResolved>('WR_STORAGE_CONFIG', {\n providedIn: 'root',\n factory: () => DEFAULT_WR_STORAGE_CONFIG,\n});\n\nexport type { WrStorageConfig, WrStorageConfigResolved } from './interfaces';\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { InjectionToken } from '@angular/core';\n\nimport type { WrStorageEngine } from './interfaces';\n\n/**\n * Probe a `Storage` candidate to confirm it's writable. Safari private\n * mode, disabled cookies, and storage-blocked iframes all throw on\n * `setItem` — fall back to memory in those cases.\n */\nfunction probe(engine: WrStorageEngine): boolean {\n try {\n const k = '__wr_storage_probe__';\n engine.setItem(k, '1');\n engine.removeItem(k);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * In-memory implementation of `Storage`. Used as the SSR / private-mode\n * fallback. Exported so consumers can opt into it explicitly for tests.\n */\nexport function createMemoryStorage(): WrStorageEngine {\n const map = new Map<string, string>();\n return {\n get length(): number {\n return map.size;\n },\n clear(): void {\n map.clear();\n },\n getItem(key: string): string | null {\n return map.has(key) ? map.get(key)! : null;\n },\n key(i: number): string | null {\n return Array.from(map.keys())[i] ?? null;\n },\n removeItem(key: string): void {\n map.delete(key);\n },\n setItem(key: string, value: string): void {\n map.set(key, value);\n },\n };\n}\n\n/**\n * Injection token for the active storage engine. Override at any\n * injector level to swap engines (e.g. a feature module uses\n * `sessionStorage`; the rest uses `localStorage`):\n *\n * ```ts\n * providers: [{ provide: WR_STORAGE_ENGINE, useValue: sessionStorage }]\n * ```\n *\n * The default factory returns `localStorage` in the browser when it's\n * actually writable, an in-memory map otherwise.\n */\nexport const WR_STORAGE_ENGINE = new InjectionToken<WrStorageEngine>('WR_STORAGE_ENGINE', {\n providedIn: 'root',\n factory: () => {\n if (typeof localStorage === 'undefined') return createMemoryStorage();\n return probe(localStorage) ? localStorage : createMemoryStorage();\n },\n});\n\nexport type { WrStorageEngine } from './interfaces';\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { isPlatformBrowser } from '@angular/common';\nimport { DestroyRef, Service, PLATFORM_ID, type Signal, type WritableSignal, inject, signal } from '@angular/core';\n\nimport { WR_STORAGE_CONFIG } from './storage-config';\nimport { WR_STORAGE_ENGINE } from './storage-engine';\n\n/** Envelope written when `json` mode is on. `e` is epoch-ms expiry. @internal */\ninterface Envelope<T> {\n readonly v: T;\n readonly e?: number;\n}\n\nfunction isEnvelope(x: unknown): x is Envelope<unknown> {\n return x !== null && typeof x === 'object' && 'v' in x;\n}\n\n/**\n * Reactive key/value storage on top of any `Storage`-compatible engine.\n *\n * - **Swap engines** through {@link WR_STORAGE_ENGINE} or\n * {@link provideWrStorage}. Default: `localStorage` with an in-memory\n * fallback for SSR / private mode.\n * - **Namespacing** via `prefix` (config) — every key is transparently\n * prefixed on read / write.\n * - **TTL** per-call or default — values past their expiry are removed\n * lazily on the next `get` / `watch` read.\n * - **Reactive watch** — `watch(key)` returns a `Signal` that updates on\n * local writes and cross-tab `storage` events.\n *\n * SSR-safe: the default engine factory returns an in-memory shim when\n * `localStorage` is unavailable, so reads always work.\n *\n * @example\n * ```ts\n * const store = inject(WrStorage);\n *\n * store.set('user', { name: 'Ada' });\n * store.get<{ name: string }>('user'); // { name: 'Ada' }\n *\n * store.set('cart', items, { ttl: 60_000 }); // expires in 60s\n *\n * const theme = store.watch<'light' | 'dark'>('theme', 'light');\n * effect(() => console.log('theme is', theme()));\n * ```\n *\n * @see https://ngwr.dev/reference/services/storage\n */\n@Service()\nexport class WrStorage {\n private readonly engine = inject(WR_STORAGE_ENGINE);\n private readonly config = inject(WR_STORAGE_CONFIG);\n private readonly destroyRef = inject(DestroyRef);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n\n /**\n * Per-key watchers. Shared so multiple `watch(k)` calls reuse one signal.\n *\n * The fallback is kept alongside the signal because every refresh has to read\n * the key the same way `watch` first did. Refreshing without it made `get` and\n * `watch` disagree about what an ABSENT key means: after a `remove()` the\n * signal went to `null` while `get(key, fallback)` still answered with the\n * default, so a consumer watching `'theme'` with a `'light'` fallback got no\n * theme at all rather than the light one.\n */\n private readonly watchers = new Map<string, { readonly sig: WritableSignal<unknown>; readonly fallback: unknown }>();\n private listenerInstalled = false;\n\n // Public API\n\n /** Is `key` present (regardless of value / expiry)? */\n has(key: string): boolean {\n return this.engine.getItem(this.fullKey(key)) !== null;\n }\n\n /**\n * Read `key`. Returns `fallback` (default `null`) when the key is\n * missing or expired. Expired values are also removed as a side effect.\n */\n get<T = unknown>(key: string, fallback: T | null = null): T | null {\n const fk = this.fullKey(key);\n const raw = this.engine.getItem(fk);\n if (raw === null) return fallback;\n\n if (!this.config.json) return raw as unknown as T;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n // Non-JSON value written by external code — return as-is.\n return raw as unknown as T;\n }\n\n if (!isEnvelope(parsed)) return parsed as T;\n\n if (parsed.e !== undefined && parsed.e < Date.now()) {\n this.remove(key);\n return fallback;\n }\n return parsed.v as T;\n }\n\n /**\n * Write `value` at `key`. Per-call `ttl` (ms) overrides the config\n * default. JSON-serializable values only when `json` is on (the default).\n */\n set<T = unknown>(key: string, value: T, opts?: { ttl?: number }): void {\n const fk = this.fullKey(key);\n let serialized: string;\n\n if (this.config.json) {\n const ttl = opts?.ttl ?? this.config.ttl;\n const env: Envelope<T> = ttl ? { v: value, e: Date.now() + ttl } : { v: value };\n try {\n serialized = JSON.stringify(env);\n } catch (err) {\n // eslint-disable-next-line no-console -- intentional diagnostic for unserialisable values\n console.warn('[ngwr/storage] value not JSON-serializable', err);\n return;\n }\n } else {\n serialized = String(value);\n }\n\n try {\n this.engine.setItem(fk, serialized);\n } catch (err) {\n // Quota exceeded / disabled / cleared mid-write — log + carry on.\n // eslint-disable-next-line no-console -- intentional diagnostic on storage write failure\n console.warn('[ngwr/storage] setItem failed', err);\n return;\n }\n this.notify(key);\n }\n\n /** Remove `key`. No-op when absent. */\n remove(key: string): void {\n this.engine.removeItem(this.fullKey(key));\n this.notify(key);\n }\n\n /**\n * Clear every key owned by this prefix. When `prefix` is empty this\n * defers to `engine.clear()` (clears everything — be careful with\n * shared storage).\n */\n clear(): void {\n const p = this.config.prefix;\n if (p) {\n for (const fk of this.rawKeys()) this.engine.removeItem(fk);\n } else {\n this.engine.clear();\n }\n // Refresh every active watcher — they may have just been cleared.\n for (const [k, entry] of this.watchers) entry.sig.set(this.get(k, entry.fallback));\n }\n\n /** All known keys under our prefix, with the prefix stripped. */\n keys(): readonly string[] {\n const p = this.config.prefix;\n return this.rawKeys().map(k => (p ? k.slice(p.length) : k));\n }\n\n /**\n * Reactive read of `key`. Updates when this instance writes to the key,\n * when `clear()` runs, and when another tab updates `localStorage`\n * under the same prefix. Returned signal is shared per key — calling\n * `watch(k)` twice returns the same signal.\n */\n watch<T = unknown>(key: string, fallback: T | null = null): Signal<T | null> {\n const existing = this.watchers.get(key);\n if (existing) return (existing.sig as WritableSignal<T | null>).asReadonly();\n\n const sig = signal<T | null>(this.get<T>(key, fallback));\n this.watchers.set(key, { sig: sig, fallback });\n this.installCrossTabListener();\n return sig.asReadonly();\n }\n\n // Internals\n\n private fullKey(key: string): string {\n return this.config.prefix + key;\n }\n\n private notify(key: string): void {\n const entry = this.watchers.get(key);\n if (entry) entry.sig.set(this.get(key, entry.fallback));\n }\n\n private rawKeys(): string[] {\n const p = this.config.prefix;\n const out: string[] = [];\n for (let i = 0; i < this.engine.length; i++) {\n const k = this.engine.key(i);\n if (k === null) continue;\n if (!p || k.startsWith(p)) out.push(k);\n }\n return out;\n }\n\n private installCrossTabListener(): void {\n if (!this.isBrowser || this.listenerInstalled) return;\n this.listenerInstalled = true;\n\n const handler = (event: StorageEvent): void => {\n // `storage` only fires for `localStorage` / `sessionStorage`, and\n // only for changes from OTHER tabs. Local writes are handled by\n // `notify()` in `set`/`remove`/`clear`.\n if (event.key === null) {\n // Storage cleared from another tab.\n for (const [k, entry] of this.watchers) entry.sig.set(this.get(k, entry.fallback));\n return;\n }\n const p = this.config.prefix;\n if (p && !event.key.startsWith(p)) return;\n this.notify(p ? event.key.slice(p.length) : event.key);\n };\n\n window.addEventListener('storage', handler);\n\n // The listener belongs to THIS injector. Root-provided it lives as long as\n // the page, but a route or component that lists `WrStorage` in its own\n // `providers` used to leave the handler on the window after its injector was\n // gone — still driving the watcher signals of a destroyed instance, and\n // holding the instance and every signal in it reachable for the life of the\n // page. Same bug `WrHotkey` already fixed once.\n this.destroyRef.onDestroy(() => {\n window.removeEventListener('storage', handler);\n this.listenerInstalled = false;\n });\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { type EnvironmentProviders, type Provider, makeEnvironmentProviders } from '@angular/core';\n\nimport {\n DEFAULT_WR_STORAGE_CONFIG,\n WR_STORAGE_CONFIG,\n type WrStorageConfig,\n type WrStorageConfigResolved,\n} from './storage-config';\nimport { WR_STORAGE_ENGINE, type WrStorageEngine } from './storage-engine';\n\n/**\n * Configure {@link WrStorage}. All fields optional — merged with defaults.\n *\n * @example Override the engine globally (e.g. session storage)\n * ```ts\n * provideWrStorage({ engine: sessionStorage })\n * ```\n *\n * @example Lazy engine factory (e.g. wrap localStorage with encryption)\n * ```ts\n * provideWrStorage({ engine: () => new EncryptedStorage(localStorage, key) })\n * ```\n *\n * @example Namespace + auto-expire\n * ```ts\n * provideWrStorage({ prefix: 'myapp:', ttl: 24 * 60 * 60 * 1000 })\n * ```\n */\nexport interface ProvideWrStorageOptions extends WrStorageConfig {\n /**\n * Storage engine. Either an instance (eager) or a factory (lazy —\n * called inside the injection context the first time `WR_STORAGE_ENGINE`\n * is read). Defaults to {@link WR_STORAGE_ENGINE}'s factory\n * (`localStorage` with in-memory fallback).\n */\n readonly engine?: WrStorageEngine | (() => WrStorageEngine);\n}\n\nexport function provideWrStorage(options: ProvideWrStorageOptions = {}): EnvironmentProviders {\n const { engine, ...config } = options;\n\n const merged: WrStorageConfigResolved = { ...DEFAULT_WR_STORAGE_CONFIG, ...config };\n\n const providers: Provider[] = [{ provide: WR_STORAGE_CONFIG, useValue: merged }];\n\n if (engine !== undefined) {\n providers.push(\n typeof engine === 'function'\n ? { provide: WR_STORAGE_ENGINE, useFactory: engine }\n : { provide: WR_STORAGE_ENGINE, useValue: engine }\n );\n }\n\n return makeEnvironmentProviders(providers);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngwr-storage.mjs","sources":["../../../projects/lib/storage/storage-config.ts","../../../projects/lib/storage/storage-engine.ts","../../../projects/lib/storage/storage.ts","../../../projects/lib/storage/provide-wr-storage.ts","../../../projects/lib/storage/ngwr-storage.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { InjectionToken } from '@angular/core';\n\nimport type { WrStorageConfigResolved } from './interfaces';\n\nexport const DEFAULT_WR_STORAGE_CONFIG: WrStorageConfigResolved = {\n prefix: '',\n json: true,\n ttl: 0,\n};\n\nexport const WR_STORAGE_CONFIG = new InjectionToken<WrStorageConfigResolved>('WR_STORAGE_CONFIG', {\n providedIn: 'root',\n factory: () => DEFAULT_WR_STORAGE_CONFIG,\n});\n\nexport type { WrStorageConfig, WrStorageConfigResolved } from './interfaces';\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { InjectionToken } from '@angular/core';\n\nimport type { WrStorageEngine } from './interfaces';\n\n/**\n * Probe a `Storage` candidate to confirm it's writable. Safari private\n * mode, disabled cookies, and storage-blocked iframes all throw on\n * `setItem` — fall back to memory in those cases.\n */\nfunction probe(engine: WrStorageEngine): boolean {\n try {\n const k = '__wr_storage_probe__';\n engine.setItem(k, '1');\n engine.removeItem(k);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * In-memory implementation of `Storage`. Used as the SSR / private-mode\n * fallback. Exported so consumers can opt into it explicitly for tests.\n */\nexport function createMemoryStorage(): WrStorageEngine {\n const map = new Map<string, string>();\n return {\n get length(): number {\n return map.size;\n },\n clear(): void {\n map.clear();\n },\n getItem(key: string): string | null {\n return map.has(key) ? map.get(key)! : null;\n },\n key(i: number): string | null {\n return Array.from(map.keys())[i] ?? null;\n },\n removeItem(key: string): void {\n map.delete(key);\n },\n setItem(key: string, value: string): void {\n map.set(key, value);\n },\n };\n}\n\n/**\n * Injection token for the active storage engine. Override at any\n * injector level to swap engines (e.g. a feature module uses\n * `sessionStorage`; the rest uses `localStorage`):\n *\n * ```ts\n * providers: [{ provide: WR_STORAGE_ENGINE, useValue: sessionStorage }]\n * ```\n *\n * The default factory returns `localStorage` in the browser when it's\n * actually writable, an in-memory map otherwise.\n */\nexport const WR_STORAGE_ENGINE = new InjectionToken<WrStorageEngine>('WR_STORAGE_ENGINE', {\n providedIn: 'root',\n factory: () => {\n if (typeof localStorage === 'undefined') return createMemoryStorage();\n return probe(localStorage) ? localStorage : createMemoryStorage();\n },\n});\n\nexport type { WrStorageEngine } from './interfaces';\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { isPlatformBrowser } from '@angular/common';\nimport { DestroyRef, Service, PLATFORM_ID, type Signal, type WritableSignal, inject, signal } from '@angular/core';\n\nimport type { WrStorageEnvelope } from './interfaces';\nimport { WR_STORAGE_CONFIG } from './storage-config';\nimport { WR_STORAGE_ENGINE } from './storage-engine';\n\nfunction isEnvelope(x: unknown): x is WrStorageEnvelope {\n return x !== null && typeof x === 'object' && 'v' in x;\n}\n\n/**\n * Reactive key/value storage on top of any `Storage`-compatible engine.\n *\n * - **Swap engines** through {@link WR_STORAGE_ENGINE} or\n * {@link provideWrStorage}. Default: `localStorage` with an in-memory\n * fallback for SSR / private mode.\n * - **Namespacing** via `prefix` (config) — every key is transparently\n * prefixed on read / write.\n * - **TTL** per-call or default — values past their expiry are removed\n * lazily on the next `get` / `watch` read.\n * - **Reactive watch** — `watch(key)` returns a `Signal` that updates on\n * local writes and cross-tab `storage` events.\n * - **On-disk format** — values are wrapped in a {@link WrStorageEnvelope}\n * (`{\"v\":…,\"e\":…}`) while `json` is on. Anything reading the same key from\n * outside Angular has to unwrap it.\n *\n * SSR-safe: the default engine factory returns an in-memory shim when\n * `localStorage` is unavailable, so reads always work.\n *\n * @example\n * ```ts\n * const store = inject(WrStorage);\n *\n * store.set('user', { name: 'Ada' });\n * store.get<{ name: string }>('user'); // { name: 'Ada' }\n *\n * store.set('cart', items, { ttl: 60_000 }); // expires in 60s\n *\n * const theme = store.watch<'light' | 'dark'>('theme', 'light');\n * effect(() => console.log('theme is', theme()));\n * ```\n *\n * @see https://ngwr.dev/reference/services/storage\n */\n@Service()\nexport class WrStorage {\n private readonly engine = inject(WR_STORAGE_ENGINE);\n private readonly config = inject(WR_STORAGE_CONFIG);\n private readonly destroyRef = inject(DestroyRef);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n\n /**\n * Per-key watchers. Shared so multiple `watch(k)` calls reuse one signal.\n *\n * The fallback is kept alongside the signal because every refresh has to read\n * the key the same way `watch` first did. Refreshing without it made `get` and\n * `watch` disagree about what an ABSENT key means: after a `remove()` the\n * signal went to `null` while `get(key, fallback)` still answered with the\n * default, so a consumer watching `'theme'` with a `'light'` fallback got no\n * theme at all rather than the light one.\n */\n private readonly watchers = new Map<string, { readonly sig: WritableSignal<unknown>; readonly fallback: unknown }>();\n private listenerInstalled = false;\n\n // Public API\n\n /** Is `key` present (regardless of value / expiry)? */\n has(key: string): boolean {\n return this.engine.getItem(this.fullKey(key)) !== null;\n }\n\n /**\n * Read `key`. Returns `fallback` (default `null`) when the key is\n * missing or expired. Expired values are also removed as a side effect.\n */\n get<T = unknown>(key: string, fallback: T | null = null): T | null {\n const fk = this.fullKey(key);\n const raw = this.engine.getItem(fk);\n if (raw === null) return fallback;\n\n if (!this.config.json) return raw as unknown as T;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n // Non-JSON value written by external code — return as-is.\n return raw as unknown as T;\n }\n\n if (!isEnvelope(parsed)) return parsed as T;\n\n if (parsed.e !== undefined && parsed.e < Date.now()) {\n this.remove(key);\n return fallback;\n }\n return parsed.v as T;\n }\n\n /**\n * Write `value` at `key`. Per-call `ttl` (ms) overrides the config\n * default. JSON-serializable values only when `json` is on (the default).\n *\n * What lands in the engine is a {@link WrStorageEnvelope} —\n * `{\"v\":<value>}`, plus `\"e\"` when a TTL applies — not the bare value. Code\n * outside Angular that reads the same key has to unwrap it; see the envelope's\n * own docs for the exact format.\n */\n set<T = unknown>(key: string, value: T, opts?: { ttl?: number }): void {\n const fk = this.fullKey(key);\n let serialized: string;\n\n if (this.config.json) {\n const ttl = opts?.ttl ?? this.config.ttl;\n const env: WrStorageEnvelope<T> = ttl ? { v: value, e: Date.now() + ttl } : { v: value };\n try {\n serialized = JSON.stringify(env);\n } catch (err) {\n // eslint-disable-next-line no-console -- intentional diagnostic for unserialisable values\n console.warn('[ngwr/storage] value not JSON-serializable', err);\n return;\n }\n } else {\n serialized = String(value);\n }\n\n try {\n this.engine.setItem(fk, serialized);\n } catch (err) {\n // Quota exceeded / disabled / cleared mid-write — log + carry on.\n // eslint-disable-next-line no-console -- intentional diagnostic on storage write failure\n console.warn('[ngwr/storage] setItem failed', err);\n return;\n }\n this.notify(key);\n }\n\n /** Remove `key`. No-op when absent. */\n remove(key: string): void {\n this.engine.removeItem(this.fullKey(key));\n this.notify(key);\n }\n\n /**\n * Clear every key owned by this prefix. When `prefix` is empty this\n * defers to `engine.clear()` (clears everything — be careful with\n * shared storage).\n */\n clear(): void {\n const p = this.config.prefix;\n if (p) {\n for (const fk of this.rawKeys()) this.engine.removeItem(fk);\n } else {\n this.engine.clear();\n }\n // Refresh every active watcher — they may have just been cleared.\n for (const [k, entry] of this.watchers) entry.sig.set(this.get(k, entry.fallback));\n }\n\n /** All known keys under our prefix, with the prefix stripped. */\n keys(): readonly string[] {\n const p = this.config.prefix;\n return this.rawKeys().map(k => (p ? k.slice(p.length) : k));\n }\n\n /**\n * Reactive read of `key`. Updates when this instance writes to the key,\n * when `clear()` runs, and when another tab updates `localStorage`\n * under the same prefix. Returned signal is shared per key — calling\n * `watch(k)` twice returns the same signal.\n */\n watch<T = unknown>(key: string, fallback: T | null = null): Signal<T | null> {\n const existing = this.watchers.get(key);\n if (existing) return (existing.sig as WritableSignal<T | null>).asReadonly();\n\n const sig = signal<T | null>(this.get<T>(key, fallback));\n this.watchers.set(key, { sig: sig, fallback });\n this.installCrossTabListener();\n return sig.asReadonly();\n }\n\n // Internals\n\n private fullKey(key: string): string {\n return this.config.prefix + key;\n }\n\n private notify(key: string): void {\n const entry = this.watchers.get(key);\n if (entry) entry.sig.set(this.get(key, entry.fallback));\n }\n\n private rawKeys(): string[] {\n const p = this.config.prefix;\n const out: string[] = [];\n for (let i = 0; i < this.engine.length; i++) {\n const k = this.engine.key(i);\n if (k === null) continue;\n if (!p || k.startsWith(p)) out.push(k);\n }\n return out;\n }\n\n private installCrossTabListener(): void {\n if (!this.isBrowser || this.listenerInstalled) return;\n this.listenerInstalled = true;\n\n const handler = (event: StorageEvent): void => {\n // `storage` only fires for `localStorage` / `sessionStorage`, and\n // only for changes from OTHER tabs. Local writes are handled by\n // `notify()` in `set`/`remove`/`clear`.\n if (event.key === null) {\n // Storage cleared from another tab.\n for (const [k, entry] of this.watchers) entry.sig.set(this.get(k, entry.fallback));\n return;\n }\n const p = this.config.prefix;\n if (p && !event.key.startsWith(p)) return;\n this.notify(p ? event.key.slice(p.length) : event.key);\n };\n\n window.addEventListener('storage', handler);\n\n // The listener belongs to THIS injector. Root-provided it lives as long as\n // the page, but a route or component that lists `WrStorage` in its own\n // `providers` used to leave the handler on the window after its injector was\n // gone — still driving the watcher signals of a destroyed instance, and\n // holding the instance and every signal in it reachable for the life of the\n // page. Same bug `WrHotkey` already fixed once.\n this.destroyRef.onDestroy(() => {\n window.removeEventListener('storage', handler);\n this.listenerInstalled = false;\n });\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { type EnvironmentProviders, type Provider, makeEnvironmentProviders } from '@angular/core';\n\nimport {\n DEFAULT_WR_STORAGE_CONFIG,\n WR_STORAGE_CONFIG,\n type WrStorageConfig,\n type WrStorageConfigResolved,\n} from './storage-config';\nimport { WR_STORAGE_ENGINE, type WrStorageEngine } from './storage-engine';\n\n/**\n * Configure {@link WrStorage}. All fields optional — merged with defaults.\n *\n * @example Override the engine globally (e.g. session storage)\n * ```ts\n * provideWrStorage({ engine: sessionStorage })\n * ```\n *\n * @example Lazy engine factory (e.g. wrap localStorage with encryption)\n * ```ts\n * provideWrStorage({ engine: () => new EncryptedStorage(localStorage, key) })\n * ```\n *\n * @example Namespace + auto-expire\n * ```ts\n * provideWrStorage({ prefix: 'myapp:', ttl: 24 * 60 * 60 * 1000 })\n * ```\n */\nexport interface ProvideWrStorageOptions extends WrStorageConfig {\n /**\n * Storage engine. Either an instance (eager) or a factory (lazy —\n * called inside the injection context the first time `WR_STORAGE_ENGINE`\n * is read). Defaults to {@link WR_STORAGE_ENGINE}'s factory\n * (`localStorage` with in-memory fallback).\n */\n readonly engine?: WrStorageEngine | (() => WrStorageEngine);\n}\n\nexport function provideWrStorage(options: ProvideWrStorageOptions = {}): EnvironmentProviders {\n const { engine, ...config } = options;\n\n const merged: WrStorageConfigResolved = { ...DEFAULT_WR_STORAGE_CONFIG, ...config };\n\n const providers: Provider[] = [{ provide: WR_STORAGE_CONFIG, useValue: merged }];\n\n if (engine !== undefined) {\n providers.push(\n typeof engine === 'function'\n ? { provide: WR_STORAGE_ENGINE, useFactory: engine }\n : { provide: WR_STORAGE_ENGINE, useValue: engine }\n );\n }\n\n return makeEnvironmentProviders(providers);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/fesm2022/ngwr-switch.mjs
CHANGED
|
@@ -94,10 +94,10 @@ class WrSwitch {
|
|
|
94
94
|
onInputBlur() {
|
|
95
95
|
this.touch.emit();
|
|
96
96
|
}
|
|
97
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
98
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.
|
|
97
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrSwitch, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
98
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.5", type: WrSwitch, isStandalone: true, selector: "wr-switch", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange", touch: "touch" }, host: { properties: { "class": "classes()", "attr.id": "null" } }, ngImport: i0, template: "<label class=\"wr-switch__label\" [for]=\"id()\">\n <input\n class=\"wr-switch__input\"\n type=\"checkbox\"\n role=\"switch\"\n [id]=\"id()\"\n [attr.aria-label]=\"ariaLabel()\"\n [checked]=\"checked()\"\n [disabled]=\"disabled()\"\n [attr.aria-readonly]=\"readonly() || null\"\n [attr.aria-invalid]=\"fieldAria.ariaInvalid()\"\n [attr.aria-describedby]=\"fieldAria.describedBy()\"\n (click)=\"onInputClick($event)\"\n (change)=\"onInputChange($event)\"\n (blur)=\"onInputBlur()\"\n />\n\n <span class=\"wr-switch__track\" aria-hidden=\"true\">\n <span class=\"wr-switch__thumb\"></span>\n </span>\n\n <span class=\"wr-switch__text\">\n <ng-content />\n </span>\n</label>\n", encapsulation: i0.ViewEncapsulation.None });
|
|
99
99
|
}
|
|
100
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
100
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: WrSwitch, decorators: [{
|
|
101
101
|
type: Component,
|
|
102
102
|
args: [{ selector: 'wr-switch', encapsulation: ViewEncapsulation.None, host: {
|
|
103
103
|
'[class]': 'classes()',
|