ngwr 7.3.0 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -4
- package/alert/styles/_index.scss +44 -17
- package/avatar/styles/_index.scss +2 -2
- package/badge/styles/_index.scss +11 -7
- package/badge/styles/_tag.scss +1 -1
- package/bar-chart/styles/_index.scss +1 -2
- package/breadcrumbs/styles/_index.scss +4 -2
- package/burger/styles/_index.scss +2 -2
- package/button/styles/_index.scss +30 -20
- package/calendar/styles/_index.scss +11 -9
- package/calendar-heatmap/styles/_index.scss +2 -0
- package/card/styles/_index.scss +1 -1
- package/carousel/styles/_index.scss +1 -1
- package/cascader/styles/_index.scss +54 -14
- package/checkbox/styles/_index.scss +21 -4
- package/collapse/styles/_index.scss +1 -1
- package/color-picker/styles/_index.scss +11 -12
- package/command-palette/styles/_index.scss +3 -3
- package/compare/styles/_index.scss +3 -3
- package/context-menu/styles/_index.scss +1 -1
- package/date-picker/styles/_index.scss +5 -6
- package/density/styles/_index.scss +3 -3
- package/dialog/styles/_index.scss +3 -3
- package/divider/styles/_index.scss +1 -1
- package/drawer/styles/_index.scss +11 -11
- package/dropdown/styles/_index.scss +2 -2
- package/fesm2022/ngwr-affix.mjs +3 -3
- package/fesm2022/ngwr-alert.mjs +22 -10
- package/fesm2022/ngwr-alert.mjs.map +1 -1
- package/fesm2022/ngwr-anchor.mjs +3 -3
- package/fesm2022/ngwr-aurora.mjs +3 -3
- package/fesm2022/ngwr-avatar.mjs +3 -3
- package/fesm2022/ngwr-back-top.mjs +3 -3
- package/fesm2022/ngwr-badge.mjs +6 -6
- package/fesm2022/ngwr-bar-chart.mjs +3 -3
- package/fesm2022/ngwr-blur-text.mjs +3 -3
- package/fesm2022/ngwr-border-glow.mjs +3 -3
- 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 +6 -6
- package/fesm2022/ngwr-calendar-heatmap.mjs +3 -3
- package/fesm2022/ngwr-calendar.mjs +4 -4
- package/fesm2022/ngwr-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-card.mjs +10 -10
- package/fesm2022/ngwr-card.mjs.map +1 -1
- package/fesm2022/ngwr-carousel.mjs +6 -6
- package/fesm2022/ngwr-cascader.mjs +12 -35
- package/fesm2022/ngwr-cascader.mjs.map +1 -1
- package/fesm2022/ngwr-checkbox.mjs +13 -30
- package/fesm2022/ngwr-checkbox.mjs.map +1 -1
- package/fesm2022/ngwr-circular-text.mjs +3 -3
- package/fesm2022/ngwr-click-spark.mjs +25 -6
- package/fesm2022/ngwr-click-spark.mjs.map +1 -1
- package/fesm2022/ngwr-clipboard.mjs +27 -6
- package/fesm2022/ngwr-clipboard.mjs.map +1 -1
- package/fesm2022/ngwr-collapse.mjs +9 -9
- package/fesm2022/ngwr-color-picker.mjs +7 -7
- package/fesm2022/ngwr-color-picker.mjs.map +1 -1
- package/fesm2022/ngwr-command-palette.mjs +3 -3
- package/fesm2022/ngwr-compare.mjs +3 -3
- package/fesm2022/ngwr-confetti.mjs +3 -3
- package/fesm2022/ngwr-context-menu.mjs +40 -88
- package/fesm2022/ngwr-context-menu.mjs.map +1 -1
- package/fesm2022/ngwr-cookie.mjs +3 -3
- package/fesm2022/ngwr-counter.mjs +12 -8
- package/fesm2022/ngwr-counter.mjs.map +1 -1
- package/fesm2022/ngwr-date-adapter-fns.mjs +3 -3
- package/fesm2022/ngwr-date-adapter-luxon.mjs +3 -3
- package/fesm2022/ngwr-date-adapter.mjs +3 -3
- package/fesm2022/ngwr-date-picker.mjs +25 -11
- package/fesm2022/ngwr-date-picker.mjs.map +1 -1
- package/fesm2022/ngwr-decrypt-text.mjs +3 -3
- package/fesm2022/ngwr-density.mjs +14 -14
- package/fesm2022/ngwr-density.mjs.map +1 -1
- package/fesm2022/ngwr-descriptions.mjs +6 -6
- package/fesm2022/ngwr-dialog.mjs +15 -15
- package/fesm2022/ngwr-directives.mjs +15 -87
- package/fesm2022/ngwr-directives.mjs.map +1 -1
- package/fesm2022/ngwr-divider.mjs +3 -3
- package/fesm2022/ngwr-donut-chart.mjs +10 -4
- package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
- package/fesm2022/ngwr-drag-drop.mjs +6 -6
- package/fesm2022/ngwr-drawer.mjs +15 -15
- package/fesm2022/ngwr-dropdown.mjs +9 -9
- package/fesm2022/ngwr-dropdown.mjs.map +1 -1
- package/fesm2022/ngwr-empty.mjs +3 -3
- package/fesm2022/ngwr-falling-text.mjs +3 -3
- package/fesm2022/ngwr-file-upload.mjs +3 -3
- package/fesm2022/ngwr-form.mjs +9 -9
- package/fesm2022/ngwr-fuzzy-text.mjs +8 -7
- package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -1
- package/fesm2022/ngwr-gauge.mjs +3 -3
- package/fesm2022/ngwr-glitch-text.mjs +15 -7
- package/fesm2022/ngwr-glitch-text.mjs.map +1 -1
- package/fesm2022/ngwr-gradient-text.mjs +3 -3
- package/fesm2022/ngwr-hotkey.mjs +6 -6
- package/fesm2022/ngwr-i18n.mjs +9 -9
- package/fesm2022/ngwr-icon.mjs +3 -3
- package/fesm2022/ngwr-image-cropper.mjs +3 -3
- package/fesm2022/ngwr-input-number.mjs +4 -4
- package/fesm2022/ngwr-input-number.mjs.map +1 -1
- package/fesm2022/ngwr-input-otp.mjs +10 -4
- package/fesm2022/ngwr-input-otp.mjs.map +1 -1
- package/fesm2022/ngwr-input.mjs +25 -16
- package/fesm2022/ngwr-input.mjs.map +1 -1
- package/fesm2022/ngwr-keyboard.mjs +3 -3
- package/fesm2022/ngwr-knob.mjs +3 -3
- package/fesm2022/ngwr-layout.mjs +15 -15
- package/fesm2022/ngwr-lightbox.mjs +17 -5
- 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.mjs +6 -6
- package/fesm2022/ngwr-marquee.mjs +3 -3
- package/fesm2022/ngwr-media.mjs +3 -3
- package/fesm2022/ngwr-mention.mjs +6 -6
- package/fesm2022/ngwr-meta.mjs +6 -6
- package/fesm2022/ngwr-meter-group.mjs +3 -3
- package/fesm2022/ngwr-overlay.mjs +3 -3
- package/fesm2022/ngwr-page-header.mjs +3 -3
- package/fesm2022/ngwr-pagination.mjs +5 -15
- package/fesm2022/ngwr-pagination.mjs.map +1 -1
- package/fesm2022/ngwr-pipes.mjs +21 -21
- package/fesm2022/ngwr-platform.mjs +3 -3
- package/fesm2022/ngwr-popconfirm.mjs +6 -6
- package/fesm2022/ngwr-popover.mjs +6 -6
- package/fesm2022/ngwr-progress.mjs +3 -3
- package/fesm2022/ngwr-qr.mjs +3 -3
- package/fesm2022/ngwr-radio.mjs +28 -26
- package/fesm2022/ngwr-radio.mjs.map +1 -1
- package/fesm2022/ngwr-rating.mjs +12 -23
- 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 +10 -22
- package/fesm2022/ngwr-segmented.mjs.map +1 -1
- package/fesm2022/ngwr-select.mjs +26 -13
- package/fesm2022/ngwr-select.mjs.map +1 -1
- package/fesm2022/ngwr-shiny-text.mjs +6 -6
- package/fesm2022/ngwr-sidebar.mjs +3 -3
- package/fesm2022/ngwr-skeleton.mjs +3 -3
- package/fesm2022/ngwr-slider.mjs +3 -3
- 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.mjs +3 -3
- package/fesm2022/ngwr-spotlight-card.mjs +8 -8
- package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
- package/fesm2022/ngwr-squircle.mjs +6 -6
- package/fesm2022/ngwr-star-border.mjs +3 -3
- package/fesm2022/ngwr-statistic.mjs +79 -10
- package/fesm2022/ngwr-statistic.mjs.map +1 -1
- package/fesm2022/ngwr-stepper.mjs +6 -6
- package/fesm2022/ngwr-storage.mjs +3 -3
- package/fesm2022/ngwr-switch.mjs +10 -14
- package/fesm2022/ngwr-switch.mjs.map +1 -1
- package/fesm2022/ngwr-table.mjs +12 -12
- package/fesm2022/ngwr-tabs.mjs +8 -6
- package/fesm2022/ngwr-tabs.mjs.map +1 -1
- package/fesm2022/ngwr-textarea.mjs +84 -25
- package/fesm2022/ngwr-textarea.mjs.map +1 -1
- package/fesm2022/ngwr-theme.mjs +3 -3
- package/fesm2022/ngwr-tilt-card.mjs +6 -6
- package/fesm2022/ngwr-timeline.mjs +6 -6
- package/fesm2022/ngwr-toast.mjs +46 -24
- package/fesm2022/ngwr-toast.mjs.map +1 -1
- package/fesm2022/ngwr-toolbar.mjs +3 -3
- package/fesm2022/ngwr-tree.mjs +3 -3
- package/fesm2022/ngwr-typewriter.mjs +3 -3
- package/fesm2022/ngwr-typography.mjs +3 -3
- package/fesm2022/ngwr-validators.mjs +41 -3
- package/fesm2022/ngwr-validators.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 +3 -3
- package/fesm2022/ngwr-window.mjs +12 -12
- package/file-upload/styles/_index.scss +3 -3
- package/form/styles/_index.scss +5 -5
- package/glitch-text/styles/_index.scss +3 -6
- package/image-cropper/styles/_index.scss +3 -3
- package/input/styles/_index.scss +26 -7
- package/input-otp/styles/_index.scss +23 -5
- package/keyboard/styles/_index.scss +6 -4
- package/knob/styles/_index.scss +1 -1
- package/lightbox/styles/_index.scss +29 -10
- package/list/styles/_index.scss +3 -3
- package/llms-full.txt +14 -19
- package/mention/styles/_index.scss +2 -2
- package/overlay/styles/_index.scss +1 -1
- package/package.json +1 -6
- package/pagination/styles/_index.scss +3 -26
- package/popconfirm/styles/_index.scss +1 -1
- package/popover/styles/_index.scss +2 -2
- package/radio/styles/_index.scss +20 -5
- package/rating/styles/_index.scss +12 -1
- package/schematics/migrations/v8/index.js +122 -0
- package/schematics/migrations.json +5 -0
- package/schematics/ng-add/index.js +3 -3
- package/schematics/ng-add/schema.json +6 -6
- package/schematics/provider/schema.json +1 -1
- package/schematics/use/symbol-map.json +11 -2
- package/segmented/styles/_index.scss +31 -8
- package/select/styles/_index.scss +73 -25
- package/sidebar/styles/_index.scss +3 -3
- package/slider/styles/_index.scss +2 -3
- package/speed-dial/styles/_index.scss +1 -0
- package/splitter/styles/_index.scss +4 -4
- package/spotlight-card/styles/_index.scss +8 -4
- package/stepper/styles/_index.scss +4 -4
- package/styles/_animations.scss +0 -23
- package/styles.scss +0 -1
- package/switch/styles/_index.scss +25 -6
- package/table/styles/_index.scss +9 -9
- package/tabs/styles/_index.scss +22 -3
- package/textarea/styles/_index.scss +59 -4
- package/theme/styles/_colors.scss +57 -0
- package/theme/styles/_dark.scss +22 -8
- package/theme/styles/_focus.scss +5 -0
- package/theme/styles/_variables.scss +24 -0
- package/timeline/styles/_index.scss +11 -2
- package/toast/styles/_index.scss +13 -5
- package/toolbar/styles/_index.scss +1 -1
- package/tree/styles/_index.scss +18 -17
- package/types/ngwr-alert.d.ts +16 -6
- package/types/ngwr-cascader.d.ts +5 -2
- package/types/ngwr-checkbox.d.ts +5 -2
- package/types/ngwr-click-spark.d.ts +13 -1
- package/types/ngwr-clipboard.d.ts +12 -1
- package/types/ngwr-context-menu.d.ts +20 -25
- package/types/ngwr-date-picker.d.ts +3 -0
- package/types/ngwr-density.d.ts +7 -7
- package/types/ngwr-directives.d.ts +17 -49
- package/types/ngwr-fuzzy-text.d.ts +1 -1
- package/types/ngwr-glitch-text.d.ts +9 -3
- package/types/ngwr-input-otp.d.ts +6 -2
- package/types/ngwr-input.d.ts +27 -13
- package/types/ngwr-lightbox.d.ts +9 -1
- package/types/ngwr-pagination.d.ts +3 -9
- package/types/ngwr-radio.d.ts +14 -3
- package/types/ngwr-rating.d.ts +5 -1
- package/types/ngwr-segmented.d.ts +5 -2
- package/types/ngwr-select.d.ts +6 -2
- package/types/ngwr-spotlight-card.d.ts +1 -1
- package/types/ngwr-statistic.d.ts +35 -1
- package/types/ngwr-switch.d.ts +5 -1
- package/types/ngwr-textarea.d.ts +25 -3
- package/types/ngwr-toast.d.ts +7 -1
- package/types/ngwr-validators.d.ts +3 -1
- package/types/ngwr-version.d.ts +1 -1
- package/window/styles/_index.scss +8 -8
- package/fesm2022/ngwr-scramble-text.mjs +0 -165
- package/fesm2022/ngwr-scramble-text.mjs.map +0 -1
- package/scramble-text/scramble-text.scss +0 -1
- package/scramble-text/styles/_index.scss +0 -8
- package/types/ngwr-scramble-text.d.ts +0 -49
|
@@ -4,15 +4,22 @@ import * as _angular_core from '@angular/core';
|
|
|
4
4
|
* KPI card — label + big number + optional prefix/suffix + delta. Pair
|
|
5
5
|
* with a layout grid for dashboards.
|
|
6
6
|
*
|
|
7
|
+
* When `value` is numeric the number counts up (eased) from its previous
|
|
8
|
+
* value to the new one on every change — see `animate`. String values and
|
|
9
|
+
* `prefers-reduced-motion` render instantly.
|
|
10
|
+
*
|
|
7
11
|
* @example
|
|
8
12
|
* ```html
|
|
9
13
|
* <wr-statistic label="Active users" [value]="12345" suffix="users" />
|
|
10
14
|
* <wr-statistic label="Revenue" [value]="9512" prefix="$" [delta]="12.4" />
|
|
15
|
+
* <wr-statistic label="Churn" [value]="1.8" suffix="%" [precision]="1" />
|
|
11
16
|
* ```
|
|
12
17
|
*
|
|
13
18
|
* @see https://ngwr.dev/components/statistic
|
|
14
19
|
*/
|
|
15
20
|
declare class WrStatistic {
|
|
21
|
+
private readonly platform;
|
|
22
|
+
private readonly locale;
|
|
16
23
|
readonly label: _angular_core.InputSignal<string>;
|
|
17
24
|
/** The number (or string) to display in the main slot. */
|
|
18
25
|
readonly value: _angular_core.InputSignal<string | number | null>;
|
|
@@ -20,6 +27,33 @@ declare class WrStatistic {
|
|
|
20
27
|
readonly prefix: _angular_core.InputSignal<string>;
|
|
21
28
|
/** Suffix glyph / unit (e.g. `'%'`, `'kg'`). */
|
|
22
29
|
readonly suffix: _angular_core.InputSignal<string>;
|
|
30
|
+
/** Fixed number of decimals applied to numeric values. @default 0 */
|
|
31
|
+
readonly precision: _angular_core.InputSignalWithTransform<number, unknown>;
|
|
32
|
+
/**
|
|
33
|
+
* Count up to a new numeric `value` instead of swapping instantly. Always
|
|
34
|
+
* off for string values or under `prefers-reduced-motion`. @default true
|
|
35
|
+
*/
|
|
36
|
+
readonly animate: _angular_core.InputSignalWithTransform<boolean, any>;
|
|
37
|
+
/** Count-up duration (ms). @default 700 */
|
|
38
|
+
readonly duration: _angular_core.InputSignalWithTransform<number, unknown>;
|
|
39
|
+
/**
|
|
40
|
+
* The current value coerced to a finite number, or `null` when `value` is
|
|
41
|
+
* a non-numeric string / empty / nullish (rendered as-is).
|
|
42
|
+
*/
|
|
43
|
+
protected readonly numericValue: _angular_core.Signal<number | null>;
|
|
44
|
+
/** Whether the value should count up (browser, numeric, opted-in, motion allowed). */
|
|
45
|
+
protected readonly animated: _angular_core.Signal<boolean>;
|
|
46
|
+
/** Animation start — the previously-rendered numeric value (0 on first paint). */
|
|
47
|
+
protected readonly animateFrom: _angular_core.WritableSignal<number>;
|
|
48
|
+
/** Bookkeeping: the last numeric value seen, fed back as the next `from`. */
|
|
49
|
+
private readonly lastNumeric;
|
|
50
|
+
constructor();
|
|
51
|
+
/**
|
|
52
|
+
* Static (non-animated) display string. Numeric values honour `precision`
|
|
53
|
+
* and locale grouping so they match the count-up output; everything else
|
|
54
|
+
* renders verbatim with an em-dash fallback.
|
|
55
|
+
*/
|
|
56
|
+
protected readonly displayValue: _angular_core.Signal<string>;
|
|
23
57
|
/**
|
|
24
58
|
* Optional delta vs previous period — shown as `+x.x%` (or `-x.x%`).
|
|
25
59
|
* Use `deltaSuffix` to change the trailing unit.
|
|
@@ -31,7 +65,7 @@ declare class WrStatistic {
|
|
|
31
65
|
protected readonly deltaDirection: _angular_core.Signal<"up" | "down" | "flat">;
|
|
32
66
|
protected readonly deltaText: _angular_core.Signal<string>;
|
|
33
67
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrStatistic, never>;
|
|
34
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrStatistic, "wr-statistic", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "prefix": { "alias": "prefix"; "required": false; "isSignal": true; }; "suffix": { "alias": "suffix"; "required": false; "isSignal": true; }; "delta": { "alias": "delta"; "required": false; "isSignal": true; }; "deltaSuffix": { "alias": "deltaSuffix"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
68
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrStatistic, "wr-statistic", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "prefix": { "alias": "prefix"; "required": false; "isSignal": true; }; "suffix": { "alias": "suffix"; "required": false; "isSignal": true; }; "precision": { "alias": "precision"; "required": false; "isSignal": true; }; "animate": { "alias": "animate"; "required": false; "isSignal": true; }; "duration": { "alias": "duration"; "required": false; "isSignal": true; }; "delta": { "alias": "delta"; "required": false; "isSignal": true; }; "deltaSuffix": { "alias": "deltaSuffix"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
35
69
|
}
|
|
36
70
|
|
|
37
71
|
/**
|
package/types/ngwr-switch.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { ControlValueAccessor } from '@angular/forms';
|
|
|
11
11
|
*
|
|
12
12
|
* @see https://ngwr.dev/components/switch
|
|
13
13
|
*/
|
|
14
|
+
type WrSwitchSize = 'sm' | 'md' | 'lg';
|
|
14
15
|
declare class WrSwitch implements ControlValueAccessor {
|
|
15
16
|
/** Stable id used to associate the native input with its label. */
|
|
16
17
|
readonly id: _angular_core.InputSignal<string>;
|
|
@@ -20,6 +21,8 @@ declare class WrSwitch implements ControlValueAccessor {
|
|
|
20
21
|
* @default false
|
|
21
22
|
*/
|
|
22
23
|
readonly disabled: _angular_core.InputSignalWithTransform<boolean, any>;
|
|
24
|
+
/** Control size — shares the `--wr-control-*` contract. @default 'md' */
|
|
25
|
+
readonly size: _angular_core.InputSignal<WrSwitchSize>;
|
|
23
26
|
protected readonly checked: _angular_core.WritableSignal<boolean>;
|
|
24
27
|
private readonly disabledFromCva;
|
|
25
28
|
protected readonly effectiveDisabled: _angular_core.Signal<boolean>;
|
|
@@ -33,7 +36,8 @@ declare class WrSwitch implements ControlValueAccessor {
|
|
|
33
36
|
protected onInputChange(event: Event): void;
|
|
34
37
|
protected onInputBlur(): void;
|
|
35
38
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrSwitch, never>;
|
|
36
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrSwitch, "wr-switch", never, { "id": { "alias": "id"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
39
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrSwitch, "wr-switch", never, { "id": { "alias": "id"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
export { WrSwitch };
|
|
43
|
+
export type { WrSwitchSize };
|
package/types/ngwr-textarea.d.ts
CHANGED
|
@@ -16,13 +16,19 @@ import { ControlValueAccessor } from '@angular/forms';
|
|
|
16
16
|
*
|
|
17
17
|
* @see https://ngwr.dev/components/textarea
|
|
18
18
|
*/
|
|
19
|
+
type WrTextareaSize = 'sm' | 'md' | 'lg';
|
|
20
|
+
type WrTextareaResize = 'none' | 'vertical' | 'horizontal' | 'both';
|
|
19
21
|
declare class WrTextarea implements ControlValueAccessor {
|
|
20
22
|
/** Native placeholder text. @default '' */
|
|
21
23
|
readonly placeholder: _angular_core.InputSignal<string>;
|
|
24
|
+
/** Control size — shares the `--wr-control-*` contract. @default 'md' */
|
|
25
|
+
readonly size: _angular_core.InputSignal<WrTextareaSize>;
|
|
22
26
|
/** Visible row count. @default 3 */
|
|
23
27
|
readonly rows: _angular_core.InputSignalWithTransform<number, unknown>;
|
|
24
|
-
/** Allow user resize via the
|
|
28
|
+
/** Allow user resize via the corner grip. @default true */
|
|
25
29
|
readonly resizable: _angular_core.InputSignalWithTransform<boolean, any>;
|
|
30
|
+
/** Resize direction of the corner grip (the grip icon adapts). @default 'vertical' */
|
|
31
|
+
readonly resize: _angular_core.InputSignal<WrTextareaResize>;
|
|
26
32
|
/** Read-only state. @default false */
|
|
27
33
|
readonly readonly: _angular_core.InputSignalWithTransform<boolean, any>;
|
|
28
34
|
/** Grow the textarea to fit its content. @default false */
|
|
@@ -40,11 +46,23 @@ declare class WrTextarea implements ControlValueAccessor {
|
|
|
40
46
|
protected readonly focused: _angular_core.WritableSignal<boolean>;
|
|
41
47
|
protected readonly effectiveDisabled: _angular_core.Signal<boolean>;
|
|
42
48
|
protected readonly native: _angular_core.Signal<ElementRef<HTMLTextAreaElement>>;
|
|
49
|
+
/** Resize direction, gated by `resizable` (false → 'none'). */
|
|
50
|
+
protected readonly effectiveResize: _angular_core.Signal<WrTextareaResize>;
|
|
43
51
|
protected readonly classes: _angular_core.Signal<string>;
|
|
52
|
+
/** Show the corner grip (hidden when direction is 'none' / autosize / disabled). */
|
|
53
|
+
protected readonly showHandle: _angular_core.Signal<boolean>;
|
|
44
54
|
private readonly platformId;
|
|
45
55
|
private readonly isBrowser;
|
|
56
|
+
private readonly hostEl;
|
|
46
57
|
private onChange;
|
|
47
58
|
private onTouched;
|
|
59
|
+
private resizing;
|
|
60
|
+
private resizeStartY;
|
|
61
|
+
private resizeStartX;
|
|
62
|
+
private resizeStartHeight;
|
|
63
|
+
private resizeStartWidth;
|
|
64
|
+
private resizeMinHeight;
|
|
65
|
+
private resizeMaxWidth;
|
|
48
66
|
constructor();
|
|
49
67
|
writeValue(value: string | null): void;
|
|
50
68
|
registerOnChange(fn: (value: string) => void): void;
|
|
@@ -52,9 +70,13 @@ declare class WrTextarea implements ControlValueAccessor {
|
|
|
52
70
|
setDisabledState(isDisabled: boolean): void;
|
|
53
71
|
protected onInput(event: Event): void;
|
|
54
72
|
protected onBlur(): void;
|
|
55
|
-
|
|
73
|
+
protected startResize(event: PointerEvent): void;
|
|
74
|
+
protected onResize(event: PointerEvent): void;
|
|
75
|
+
protected endResize(event: PointerEvent): void;
|
|
76
|
+
private autofit;
|
|
56
77
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrTextarea, never>;
|
|
57
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrTextarea, "wr-textarea", never, { "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "resizable": { "alias": "resizable"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "autosize": { "alias": "autosize"; "required": false; "isSignal": true; }; "maxRows": { "alias": "maxRows"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
78
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrTextarea, "wr-textarea", never, { "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "resizable": { "alias": "resizable"; "required": false; "isSignal": true; }; "resize": { "alias": "resize"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "autosize": { "alias": "autosize"; "required": false; "isSignal": true; }; "maxRows": { "alias": "maxRows"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
58
79
|
}
|
|
59
80
|
|
|
60
81
|
export { WrTextarea };
|
|
82
|
+
export type { WrTextareaResize, WrTextareaSize };
|
package/types/ngwr-toast.d.ts
CHANGED
|
@@ -147,7 +147,11 @@ declare class WrToast {
|
|
|
147
147
|
private currentPosition;
|
|
148
148
|
private currentMode;
|
|
149
149
|
private nextId;
|
|
150
|
+
/** Currently rendered toasts (capped at `config.maxStack`). */
|
|
150
151
|
private active;
|
|
152
|
+
/** Overflow waiting for a free slot — promoted FIFO as actives dismiss, so
|
|
153
|
+
* nothing is ever silently dropped. */
|
|
154
|
+
private queue;
|
|
151
155
|
/** Open a toast. Returns a handle you can `dismiss()` early. */
|
|
152
156
|
show(options: WrToastOptions): WrToastRef;
|
|
153
157
|
/** Dismiss a single toast by id. */
|
|
@@ -161,7 +165,9 @@ declare class WrToast {
|
|
|
161
165
|
private startTimer;
|
|
162
166
|
private pauseTimer;
|
|
163
167
|
private ensureHost;
|
|
164
|
-
|
|
168
|
+
/** Fill any free stack slots from the queue (FIFO), starting each promoted
|
|
169
|
+
* toast's auto-dismiss timer only as it becomes visible. */
|
|
170
|
+
private promoteFromQueue;
|
|
165
171
|
private pushToHost;
|
|
166
172
|
private disposeHost;
|
|
167
173
|
static ɵfac: i0.ɵɵFactoryDeclaration<WrToast, never>;
|
|
@@ -39,10 +39,12 @@ declare const WrValidators: {
|
|
|
39
39
|
hexColor: (control: AbstractControl) => ValidationErrors | null;
|
|
40
40
|
/**
|
|
41
41
|
* Valid URL. Accepts any scheme by default; pass `{ protocols: ['https'] }`
|
|
42
|
-
* to restrict.
|
|
42
|
+
* to restrict. A scheme is required by default; pass `{ requireProtocol: false }`
|
|
43
|
+
* to also accept bare domains (e.g. `ngwr.dev`), assuming `https`.
|
|
43
44
|
*/
|
|
44
45
|
url: (options?: {
|
|
45
46
|
readonly protocols?: readonly string[];
|
|
47
|
+
readonly requireProtocol?: boolean;
|
|
46
48
|
}) => ValidatorFn;
|
|
47
49
|
/** Credit card number — Luhn check + 13-19 digit length. Spaces and dashes are stripped first. */
|
|
48
50
|
cardNumber: (control: AbstractControl) => ValidationErrors | null;
|
package/types/ngwr-version.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ import { InjectionToken } from '@angular/core';
|
|
|
16
16
|
* Distinct from `Version` exported by `@angular/core`, which reports the
|
|
17
17
|
* loaded Angular runtime version (e.g. `'21.2.13'`), not ngwr's.
|
|
18
18
|
*/
|
|
19
|
-
declare const NGWR_VERSION = "
|
|
19
|
+
declare const NGWR_VERSION = "8.0.0";
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* @license
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
.wr-window {
|
|
4
4
|
--wr-window-bg: var(--wr-color-white);
|
|
5
5
|
--wr-window-border: var(--wr-color-light);
|
|
6
|
-
--wr-window-chrome-bg:
|
|
6
|
+
--wr-window-chrome-bg: var(--wr-color-hover);
|
|
7
7
|
--wr-window-chrome-color: var(--wr-color-dark);
|
|
8
8
|
--wr-window-radius: var(--wr-border-radius-base);
|
|
9
9
|
--wr-window-handle-size: 8px;
|
|
10
10
|
--wr-window-chrome-height: 2.25rem;
|
|
11
|
-
--wr-window-title-size:
|
|
11
|
+
--wr-window-title-size: var(--wr-text-sm);
|
|
12
12
|
--wr-window-action-size: 1.5rem;
|
|
13
13
|
--wr-window-anim-duration: 0.18s;
|
|
14
14
|
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
// pixel of vertical space matters.
|
|
46
46
|
&--chrome-compact {
|
|
47
47
|
--wr-window-chrome-height: 1.625rem;
|
|
48
|
-
--wr-window-title-size:
|
|
48
|
+
--wr-window-title-size: var(--wr-text-xs);
|
|
49
49
|
--wr-window-action-size: 1.125rem;
|
|
50
50
|
}
|
|
51
51
|
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
align-items: center;
|
|
95
95
|
gap: 0.375rem;
|
|
96
96
|
padding-right: 0.375rem;
|
|
97
|
-
font-size:
|
|
97
|
+
font-size: var(--wr-text-xs);
|
|
98
98
|
|
|
99
99
|
&:empty {
|
|
100
100
|
display: none;
|
|
@@ -157,7 +157,7 @@
|
|
|
157
157
|
width: 0.875rem; // 14px — bigger than the prior 12px to match native
|
|
158
158
|
height: 0.875rem;
|
|
159
159
|
border-radius: 50%;
|
|
160
|
-
color: rgba(
|
|
160
|
+
color: rgba(var(--wr-color-black-rgb), 0.55); // glyph color (revealed on hover)
|
|
161
161
|
|
|
162
162
|
&--close,
|
|
163
163
|
&--close:hover {
|
|
@@ -223,7 +223,7 @@
|
|
|
223
223
|
padding: 0.25rem 0.75rem;
|
|
224
224
|
border-top: 1px solid var(--wr-window-border);
|
|
225
225
|
background: rgba(var(--wr-color-light-rgb), 0.25);
|
|
226
|
-
font-size:
|
|
226
|
+
font-size: var(--wr-text-xs);
|
|
227
227
|
color: var(--wr-color-medium);
|
|
228
228
|
|
|
229
229
|
&:empty {
|
|
@@ -374,7 +374,7 @@
|
|
|
374
374
|
border-radius: var(--wr-border-radius-sm);
|
|
375
375
|
color: var(--wr-color-dark);
|
|
376
376
|
font-family: inherit;
|
|
377
|
-
font-size:
|
|
377
|
+
font-size: var(--wr-text-sm);
|
|
378
378
|
line-height: 1.25rem;
|
|
379
379
|
cursor: pointer;
|
|
380
380
|
max-width: 12rem;
|
|
@@ -387,7 +387,7 @@
|
|
|
387
387
|
}
|
|
388
388
|
|
|
389
389
|
&:focus-visible {
|
|
390
|
-
|
|
390
|
+
@include theme.focus-ring;
|
|
391
391
|
outline-offset: 2px;
|
|
392
392
|
}
|
|
393
393
|
}
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import { isPlatformBrowser } from '@angular/common';
|
|
2
|
-
import * as i0 from '@angular/core';
|
|
3
|
-
import { input, inject, ElementRef, DestroyRef, PLATFORM_ID, afterNextRender, ViewEncapsulation, Component } from '@angular/core';
|
|
4
|
-
import { WrPlatform } from 'ngwr/platform';
|
|
5
|
-
import { numAttr } from 'ngwr/utils';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @license
|
|
9
|
-
*
|
|
10
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
11
|
-
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
12
|
-
*
|
|
13
|
-
* Angular adaptation of the ScrambledText effect by David Haz / reactbits.dev.
|
|
14
|
-
* Original: https://www.reactbits.dev/text-animations/scrambled-text
|
|
15
|
-
*
|
|
16
|
-
* The reactbits version uses GSAP's paid SplitText + ScrambleTextPlugin.
|
|
17
|
-
* This port is dependency-free — splits via vanilla DOM, scrambles via a
|
|
18
|
-
* per-char `setInterval` loop, restores on settle.
|
|
19
|
-
*/
|
|
20
|
-
function pickRandom(pool, exclude) {
|
|
21
|
-
if (pool.length === 0)
|
|
22
|
-
return exclude;
|
|
23
|
-
if (pool.length === 1)
|
|
24
|
-
return pool;
|
|
25
|
-
// Avoid landing on the original mid-scramble — looks like nothing happened.
|
|
26
|
-
let pick = pool.charAt(Math.floor(Math.random() * pool.length));
|
|
27
|
-
for (let tries = 0; tries < 3 && pick === exclude; tries++) {
|
|
28
|
-
pick = pool.charAt(Math.floor(Math.random() * pool.length));
|
|
29
|
-
}
|
|
30
|
-
return pick;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Cursor-proximity scrambler. Each character inside the projected text
|
|
34
|
-
* scrambles through `scrambleChars` whenever the pointer moves within
|
|
35
|
-
* `radius` px of it, then settles back to the original. Closer pointer →
|
|
36
|
-
* longer scramble.
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* ```html
|
|
40
|
-
* <wr-scramble-text
|
|
41
|
-
* [radius]="120"
|
|
42
|
-
* [duration]="1.4"
|
|
43
|
-
* scrambleChars="!&%*"
|
|
44
|
-
* >
|
|
45
|
-
* Hover this paragraph to scramble characters near the cursor.
|
|
46
|
-
* </wr-scramble-text>
|
|
47
|
-
* ```
|
|
48
|
-
*
|
|
49
|
-
* @see https://www.reactbits.dev/text-animations/scrambled-text
|
|
50
|
-
*/
|
|
51
|
-
class WrScrambleText {
|
|
52
|
-
/** Proximity radius in pixels. @default 100 */
|
|
53
|
-
radius = input(100, { ...(ngDevMode ? { debugName: "radius" } : /* istanbul ignore next */ {}), transform: numAttr(100) });
|
|
54
|
-
/** Max scramble duration in seconds (scaled by proximity — closer = longer). @default 1.2 */
|
|
55
|
-
duration = input(1.2, { ...(ngDevMode ? { debugName: "duration" } : /* istanbul ignore next */ {}), transform: numAttr(1.2) });
|
|
56
|
-
/** Approximate seconds between random-char swaps. Lower = faster scramble. @default 0.05 */
|
|
57
|
-
speed = input(0.05, { ...(ngDevMode ? { debugName: "speed" } : /* istanbul ignore next */ {}), transform: numAttr(0.05) });
|
|
58
|
-
/** Pool of glyphs to scramble through. @default '.:' */
|
|
59
|
-
scrambleChars = input('.:', /* @ts-ignore */
|
|
60
|
-
...(ngDevMode ? [{ debugName: "scrambleChars" }] : /* istanbul ignore next */ []));
|
|
61
|
-
host = inject(ElementRef);
|
|
62
|
-
destroyRef = inject(DestroyRef);
|
|
63
|
-
isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
|
|
64
|
-
platform = inject(WrPlatform);
|
|
65
|
-
/** One entry per active scramble, keyed by char span. */
|
|
66
|
-
active = new Map();
|
|
67
|
-
/** Cached list of char spans. Re-computed after each render. */
|
|
68
|
-
chars = [];
|
|
69
|
-
constructor() {
|
|
70
|
-
if (!this.isBrowser)
|
|
71
|
-
return;
|
|
72
|
-
afterNextRender(() => this.split());
|
|
73
|
-
this.destroyRef.onDestroy(() => this.clearAll());
|
|
74
|
-
}
|
|
75
|
-
onPointerMove(event) {
|
|
76
|
-
if (this.chars.length === 0)
|
|
77
|
-
return;
|
|
78
|
-
// Reduced motion: pointer proximity stops scrambling — text stays put.
|
|
79
|
-
if (this.platform.prefersReducedMotion())
|
|
80
|
-
return;
|
|
81
|
-
const radius = this.radius();
|
|
82
|
-
const duration = this.duration() * 1000;
|
|
83
|
-
const swapInterval = Math.max(16, this.speed() * 1000);
|
|
84
|
-
const pool = this.scrambleChars();
|
|
85
|
-
for (const charEl of this.chars) {
|
|
86
|
-
const rect = charEl.getBoundingClientRect();
|
|
87
|
-
const dx = event.clientX - (rect.left + rect.width / 2);
|
|
88
|
-
const dy = event.clientY - (rect.top + rect.height / 2);
|
|
89
|
-
const dist = Math.hypot(dx, dy);
|
|
90
|
-
if (dist > radius)
|
|
91
|
-
continue;
|
|
92
|
-
// Cancel any in-flight scramble for this char — we're restarting.
|
|
93
|
-
this.cancelOne(charEl);
|
|
94
|
-
// Proximity factor: 0 at the edge, 1 at the centre.
|
|
95
|
-
const proximity = 1 - dist / radius;
|
|
96
|
-
const scrambleMs = duration * proximity;
|
|
97
|
-
const original = charEl.dataset['scrambleOriginal'] ?? '';
|
|
98
|
-
const swapId = setInterval(() => {
|
|
99
|
-
charEl.textContent = pickRandom(pool, original);
|
|
100
|
-
}, swapInterval);
|
|
101
|
-
const settleId = setTimeout(() => {
|
|
102
|
-
clearInterval(swapId);
|
|
103
|
-
charEl.textContent = original;
|
|
104
|
-
this.active.delete(charEl);
|
|
105
|
-
}, scrambleMs);
|
|
106
|
-
this.active.set(charEl, { swapId, settleId });
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
/** Walk the projected text and wrap each non-whitespace character in a span. */
|
|
110
|
-
split() {
|
|
111
|
-
const inner = this.host.nativeElement.querySelector('.wr-scramble-text__inner');
|
|
112
|
-
if (!inner)
|
|
113
|
-
return;
|
|
114
|
-
const raw = inner.textContent ?? '';
|
|
115
|
-
if (!raw)
|
|
116
|
-
return;
|
|
117
|
-
const frag = document.createDocumentFragment();
|
|
118
|
-
for (const ch of [...raw]) {
|
|
119
|
-
if (/\s/.test(ch)) {
|
|
120
|
-
frag.appendChild(document.createTextNode(ch));
|
|
121
|
-
}
|
|
122
|
-
else {
|
|
123
|
-
const span = document.createElement('span');
|
|
124
|
-
span.className = 'wr-scramble-text__char';
|
|
125
|
-
span.textContent = ch;
|
|
126
|
-
span.dataset['scrambleOriginal'] = ch;
|
|
127
|
-
frag.appendChild(span);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
inner.replaceChildren(frag);
|
|
131
|
-
this.chars = Array.from(inner.querySelectorAll('.wr-scramble-text__char'));
|
|
132
|
-
}
|
|
133
|
-
cancelOne(el) {
|
|
134
|
-
const entry = this.active.get(el);
|
|
135
|
-
if (!entry)
|
|
136
|
-
return;
|
|
137
|
-
clearInterval(entry.swapId);
|
|
138
|
-
clearTimeout(entry.settleId);
|
|
139
|
-
this.active.delete(el);
|
|
140
|
-
}
|
|
141
|
-
clearAll() {
|
|
142
|
-
for (const [el, entry] of this.active) {
|
|
143
|
-
clearInterval(entry.swapId);
|
|
144
|
-
clearTimeout(entry.settleId);
|
|
145
|
-
el.textContent = el.dataset['scrambleOriginal'] ?? '';
|
|
146
|
-
}
|
|
147
|
-
this.active.clear();
|
|
148
|
-
}
|
|
149
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrScrambleText, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
150
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.2", type: WrScrambleText, isStandalone: true, selector: "wr-scramble-text", inputs: { radius: { classPropertyName: "radius", publicName: "radius", isSignal: true, isRequired: false, transformFunction: null }, duration: { classPropertyName: "duration", publicName: "duration", isSignal: true, isRequired: false, transformFunction: null }, speed: { classPropertyName: "speed", publicName: "speed", isSignal: true, isRequired: false, transformFunction: null }, scrambleChars: { classPropertyName: "scrambleChars", publicName: "scrambleChars", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "pointermove": "onPointerMove($event)" }, classAttribute: "wr-scramble-text" }, ngImport: i0, template: '<span class="wr-scramble-text__inner" #inner><ng-content /></span>', isInline: true, styles: [".wr-scramble-text{display:block}.wr-scramble-text__char{display:inline-block;will-change:contents}\n"], encapsulation: i0.ViewEncapsulation.None });
|
|
151
|
-
}
|
|
152
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: WrScrambleText, decorators: [{
|
|
153
|
-
type: Component,
|
|
154
|
-
args: [{ selector: 'wr-scramble-text', template: '<span class="wr-scramble-text__inner" #inner><ng-content /></span>', encapsulation: ViewEncapsulation.None, host: {
|
|
155
|
-
class: 'wr-scramble-text',
|
|
156
|
-
'(pointermove)': 'onPointerMove($event)',
|
|
157
|
-
}, styles: [".wr-scramble-text{display:block}.wr-scramble-text__char{display:inline-block;will-change:contents}\n"] }]
|
|
158
|
-
}], ctorParameters: () => [], propDecorators: { radius: [{ type: i0.Input, args: [{ isSignal: true, alias: "radius", required: false }] }], duration: [{ type: i0.Input, args: [{ isSignal: true, alias: "duration", required: false }] }], speed: [{ type: i0.Input, args: [{ isSignal: true, alias: "speed", required: false }] }], scrambleChars: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrambleChars", required: false }] }] } });
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Generated bundle index. Do not edit.
|
|
162
|
-
*/
|
|
163
|
-
|
|
164
|
-
export { WrScrambleText };
|
|
165
|
-
//# sourceMappingURL=ngwr-scramble-text.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-scramble-text.mjs","sources":["../../../projects/lib/scramble-text/scramble-text.ts","../../../projects/lib/scramble-text/ngwr-scramble-text.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 * Angular adaptation of the ScrambledText effect by David Haz / reactbits.dev.\n * Original: https://www.reactbits.dev/text-animations/scrambled-text\n *\n * The reactbits version uses GSAP's paid SplitText + ScrambleTextPlugin.\n * This port is dependency-free — splits via vanilla DOM, scrambles via a\n * per-char `setInterval` loop, restores on settle.\n */\n\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n ElementRef,\n PLATFORM_ID,\n ViewEncapsulation,\n afterNextRender,\n inject,\n input,\n} from '@angular/core';\n\nimport { WrPlatform } from 'ngwr/platform';\nimport { numAttr } from 'ngwr/utils';\n\ninterface ActiveScramble {\n swapId: ReturnType<typeof setInterval>;\n settleId: ReturnType<typeof setTimeout>;\n}\n\nfunction pickRandom(pool: string, exclude: string): string {\n if (pool.length === 0) return exclude;\n if (pool.length === 1) return pool;\n // Avoid landing on the original mid-scramble — looks like nothing happened.\n let pick = pool.charAt(Math.floor(Math.random() * pool.length));\n for (let tries = 0; tries < 3 && pick === exclude; tries++) {\n pick = pool.charAt(Math.floor(Math.random() * pool.length));\n }\n return pick;\n}\n\n/**\n * Cursor-proximity scrambler. Each character inside the projected text\n * scrambles through `scrambleChars` whenever the pointer moves within\n * `radius` px of it, then settles back to the original. Closer pointer →\n * longer scramble.\n *\n * @example\n * ```html\n * <wr-scramble-text\n * [radius]=\"120\"\n * [duration]=\"1.4\"\n * scrambleChars=\"!&%*\"\n * >\n * Hover this paragraph to scramble characters near the cursor.\n * </wr-scramble-text>\n * ```\n *\n * @see https://www.reactbits.dev/text-animations/scrambled-text\n */\n@Component({\n selector: 'wr-scramble-text',\n template: '<span class=\"wr-scramble-text__inner\" #inner><ng-content /></span>',\n styleUrl: './scramble-text.scss',\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'wr-scramble-text',\n '(pointermove)': 'onPointerMove($event)',\n },\n})\nexport class WrScrambleText {\n /** Proximity radius in pixels. @default 100 */\n readonly radius = input(100, { transform: numAttr(100) });\n\n /** Max scramble duration in seconds (scaled by proximity — closer = longer). @default 1.2 */\n readonly duration = input(1.2, { transform: numAttr(1.2) });\n\n /** Approximate seconds between random-char swaps. Lower = faster scramble. @default 0.05 */\n readonly speed = input(0.05, { transform: numAttr(0.05) });\n\n /** Pool of glyphs to scramble through. @default '.:' */\n readonly scrambleChars = input('.:');\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly destroyRef = inject(DestroyRef);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly platform = inject(WrPlatform);\n\n /** One entry per active scramble, keyed by char span. */\n private readonly active = new Map<HTMLElement, ActiveScramble>();\n\n /** Cached list of char spans. Re-computed after each render. */\n private chars: readonly HTMLElement[] = [];\n\n constructor() {\n if (!this.isBrowser) return;\n afterNextRender(() => this.split());\n this.destroyRef.onDestroy(() => this.clearAll());\n }\n\n protected onPointerMove(event: PointerEvent): void {\n if (this.chars.length === 0) return;\n // Reduced motion: pointer proximity stops scrambling — text stays put.\n if (this.platform.prefersReducedMotion()) return;\n const radius = this.radius();\n const duration = this.duration() * 1000;\n const swapInterval = Math.max(16, this.speed() * 1000);\n const pool = this.scrambleChars();\n\n for (const charEl of this.chars) {\n const rect = charEl.getBoundingClientRect();\n const dx = event.clientX - (rect.left + rect.width / 2);\n const dy = event.clientY - (rect.top + rect.height / 2);\n const dist = Math.hypot(dx, dy);\n if (dist > radius) continue;\n\n // Cancel any in-flight scramble for this char — we're restarting.\n this.cancelOne(charEl);\n\n // Proximity factor: 0 at the edge, 1 at the centre.\n const proximity = 1 - dist / radius;\n const scrambleMs = duration * proximity;\n const original = charEl.dataset['scrambleOriginal'] ?? '';\n\n const swapId = setInterval(() => {\n charEl.textContent = pickRandom(pool, original);\n }, swapInterval);\n\n const settleId = setTimeout(() => {\n clearInterval(swapId);\n charEl.textContent = original;\n this.active.delete(charEl);\n }, scrambleMs);\n\n this.active.set(charEl, { swapId, settleId });\n }\n }\n\n /** Walk the projected text and wrap each non-whitespace character in a span. */\n private split(): void {\n const inner = this.host.nativeElement.querySelector<HTMLElement>('.wr-scramble-text__inner');\n if (!inner) return;\n const raw = inner.textContent ?? '';\n if (!raw) return;\n\n const frag = document.createDocumentFragment();\n for (const ch of [...raw]) {\n if (/\\s/.test(ch)) {\n frag.appendChild(document.createTextNode(ch));\n } else {\n const span = document.createElement('span');\n span.className = 'wr-scramble-text__char';\n span.textContent = ch;\n span.dataset['scrambleOriginal'] = ch;\n frag.appendChild(span);\n }\n }\n inner.replaceChildren(frag);\n this.chars = Array.from(inner.querySelectorAll<HTMLElement>('.wr-scramble-text__char'));\n }\n\n private cancelOne(el: HTMLElement): void {\n const entry = this.active.get(el);\n if (!entry) return;\n clearInterval(entry.swapId);\n clearTimeout(entry.settleId);\n this.active.delete(el);\n }\n\n private clearAll(): void {\n for (const [el, entry] of this.active) {\n clearInterval(entry.swapId);\n clearTimeout(entry.settleId);\n el.textContent = el.dataset['scrambleOriginal'] ?? '';\n }\n this.active.clear();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
@forward './styles';
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import * as _angular_core from '@angular/core';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Cursor-proximity scrambler. Each character inside the projected text
|
|
5
|
-
* scrambles through `scrambleChars` whenever the pointer moves within
|
|
6
|
-
* `radius` px of it, then settles back to the original. Closer pointer →
|
|
7
|
-
* longer scramble.
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* ```html
|
|
11
|
-
* <wr-scramble-text
|
|
12
|
-
* [radius]="120"
|
|
13
|
-
* [duration]="1.4"
|
|
14
|
-
* scrambleChars="!&%*"
|
|
15
|
-
* >
|
|
16
|
-
* Hover this paragraph to scramble characters near the cursor.
|
|
17
|
-
* </wr-scramble-text>
|
|
18
|
-
* ```
|
|
19
|
-
*
|
|
20
|
-
* @see https://www.reactbits.dev/text-animations/scrambled-text
|
|
21
|
-
*/
|
|
22
|
-
declare class WrScrambleText {
|
|
23
|
-
/** Proximity radius in pixels. @default 100 */
|
|
24
|
-
readonly radius: _angular_core.InputSignalWithTransform<number, unknown>;
|
|
25
|
-
/** Max scramble duration in seconds (scaled by proximity — closer = longer). @default 1.2 */
|
|
26
|
-
readonly duration: _angular_core.InputSignalWithTransform<number, unknown>;
|
|
27
|
-
/** Approximate seconds between random-char swaps. Lower = faster scramble. @default 0.05 */
|
|
28
|
-
readonly speed: _angular_core.InputSignalWithTransform<number, unknown>;
|
|
29
|
-
/** Pool of glyphs to scramble through. @default '.:' */
|
|
30
|
-
readonly scrambleChars: _angular_core.InputSignal<string>;
|
|
31
|
-
private readonly host;
|
|
32
|
-
private readonly destroyRef;
|
|
33
|
-
private readonly isBrowser;
|
|
34
|
-
private readonly platform;
|
|
35
|
-
/** One entry per active scramble, keyed by char span. */
|
|
36
|
-
private readonly active;
|
|
37
|
-
/** Cached list of char spans. Re-computed after each render. */
|
|
38
|
-
private chars;
|
|
39
|
-
constructor();
|
|
40
|
-
protected onPointerMove(event: PointerEvent): void;
|
|
41
|
-
/** Walk the projected text and wrap each non-whitespace character in a span. */
|
|
42
|
-
private split;
|
|
43
|
-
private cancelOne;
|
|
44
|
-
private clearAll;
|
|
45
|
-
static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrScrambleText, never>;
|
|
46
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrScrambleText, "wr-scramble-text", never, { "radius": { "alias": "radius"; "required": false; "isSignal": true; }; "duration": { "alias": "duration"; "required": false; "isSignal": true; }; "speed": { "alias": "speed"; "required": false; "isSignal": true; }; "scrambleChars": { "alias": "scrambleChars"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export { WrScrambleText };
|