ngwr 10.0.0 → 10.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -8
- package/action-sheet/styles/_index.scss +6 -1
- package/badge/styles/_index.scss +1 -1
- package/badge/styles/_tag.scss +2 -2
- package/border-glow/styles/_index.scss +5 -0
- package/button/styles/_index.scss +6 -6
- package/calendar/styles/_index.scss +9 -1
- package/circular-text/styles/_index.scss +6 -1
- package/density/styles/_index.scss +3 -1
- package/dialog/styles/_index.scss +1 -2
- package/drag-drop/styles/_index.scss +20 -7
- package/event-calendar/styles/_index.scss +284 -0
- package/falling-text/styles/_index.scss +5 -0
- package/fesm2022/ngwr-alert.mjs +8 -3
- package/fesm2022/ngwr-alert.mjs.map +1 -1
- package/fesm2022/ngwr-back-top.mjs +6 -4
- package/fesm2022/ngwr-back-top.mjs.map +1 -1
- package/fesm2022/ngwr-border-glow.mjs +12 -9
- package/fesm2022/ngwr-border-glow.mjs.map +1 -1
- package/fesm2022/ngwr-breadcrumbs.mjs +2 -2
- package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
- package/fesm2022/ngwr-calendar.mjs +5 -3
- package/fesm2022/ngwr-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-card.mjs +2 -2
- package/fesm2022/ngwr-card.mjs.map +1 -1
- package/fesm2022/ngwr-carousel.mjs +17 -4
- package/fesm2022/ngwr-carousel.mjs.map +1 -1
- package/fesm2022/ngwr-cascader.mjs +31 -4
- package/fesm2022/ngwr-cascader.mjs.map +1 -1
- package/fesm2022/ngwr-checkbox.mjs +12 -3
- package/fesm2022/ngwr-checkbox.mjs.map +1 -1
- package/fesm2022/ngwr-circular-text.mjs +2 -2
- package/fesm2022/ngwr-circular-text.mjs.map +1 -1
- package/fesm2022/ngwr-command-palette.mjs +7 -3
- package/fesm2022/ngwr-command-palette.mjs.map +1 -1
- package/fesm2022/ngwr-counter.mjs +9 -1
- package/fesm2022/ngwr-counter.mjs.map +1 -1
- package/fesm2022/ngwr-date-picker.mjs +23 -6
- package/fesm2022/ngwr-date-picker.mjs.map +1 -1
- package/fesm2022/ngwr-descriptions.mjs +5 -4
- package/fesm2022/ngwr-descriptions.mjs.map +1 -1
- package/fesm2022/ngwr-drag-drop.mjs +2 -2
- package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
- package/fesm2022/ngwr-dropdown.mjs +4 -0
- package/fesm2022/ngwr-dropdown.mjs.map +1 -1
- package/fesm2022/ngwr-event-calendar.mjs +723 -0
- package/fesm2022/ngwr-event-calendar.mjs.map +1 -0
- package/fesm2022/ngwr-falling-text.mjs +2 -2
- package/fesm2022/ngwr-falling-text.mjs.map +1 -1
- package/fesm2022/ngwr-file-upload.mjs +2 -2
- package/fesm2022/ngwr-file-upload.mjs.map +1 -1
- package/fesm2022/ngwr-form.mjs +258 -42
- package/fesm2022/ngwr-form.mjs.map +1 -1
- package/fesm2022/ngwr-fuzzy-text.mjs +15 -1
- package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -1
- package/fesm2022/ngwr-gauge.mjs +8 -3
- package/fesm2022/ngwr-gauge.mjs.map +1 -1
- package/fesm2022/ngwr-glitch-text.mjs +2 -2
- package/fesm2022/ngwr-glitch-text.mjs.map +1 -1
- package/fesm2022/ngwr-gradient-text.mjs +2 -2
- package/fesm2022/ngwr-gradient-text.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-en.mjs +73 -5
- package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ru.mjs +73 -5
- package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
- package/fesm2022/ngwr-i18n.mjs +20 -2
- package/fesm2022/ngwr-i18n.mjs.map +1 -1
- package/fesm2022/ngwr-icon.mjs +5 -0
- package/fesm2022/ngwr-icon.mjs.map +1 -1
- package/fesm2022/ngwr-input-number.mjs +19 -3
- package/fesm2022/ngwr-input-number.mjs.map +1 -1
- package/fesm2022/ngwr-input.mjs +48 -6
- package/fesm2022/ngwr-input.mjs.map +1 -1
- package/fesm2022/ngwr-knob.mjs +8 -3
- package/fesm2022/ngwr-knob.mjs.map +1 -1
- package/fesm2022/ngwr-lightbox.mjs +32 -3
- package/fesm2022/ngwr-lightbox.mjs.map +1 -1
- package/fesm2022/ngwr-line-chart.mjs +3 -3
- package/fesm2022/ngwr-line-chart.mjs.map +1 -1
- package/fesm2022/ngwr-list.mjs +2 -2
- package/fesm2022/ngwr-list.mjs.map +1 -1
- package/fesm2022/ngwr-loading-bar.mjs +2 -2
- package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
- package/fesm2022/ngwr-marquee.mjs +2 -2
- package/fesm2022/ngwr-marquee.mjs.map +1 -1
- package/fesm2022/ngwr-media.mjs +3 -0
- package/fesm2022/ngwr-media.mjs.map +1 -1
- package/fesm2022/ngwr-meter-group.mjs +14 -3
- package/fesm2022/ngwr-meter-group.mjs.map +1 -1
- package/fesm2022/ngwr-page-header.mjs +2 -2
- package/fesm2022/ngwr-page-header.mjs.map +1 -1
- package/fesm2022/ngwr-pagination.mjs +1 -1
- package/fesm2022/ngwr-pagination.mjs.map +1 -1
- package/fesm2022/ngwr-progress.mjs +8 -2
- package/fesm2022/ngwr-progress.mjs.map +1 -1
- package/fesm2022/ngwr-qr.mjs.map +1 -1
- package/fesm2022/ngwr-rating.mjs +6 -4
- package/fesm2022/ngwr-rating.mjs.map +1 -1
- package/fesm2022/ngwr-result.mjs +19 -12
- package/fesm2022/ngwr-result.mjs.map +1 -1
- package/fesm2022/ngwr-segmented.mjs +2 -2
- package/fesm2022/ngwr-segmented.mjs.map +1 -1
- package/fesm2022/ngwr-select.mjs +28 -8
- package/fesm2022/ngwr-select.mjs.map +1 -1
- package/fesm2022/ngwr-shiny-text.mjs +4 -6
- package/fesm2022/ngwr-shiny-text.mjs.map +1 -1
- package/fesm2022/ngwr-speed-dial.mjs +11 -3
- package/fesm2022/ngwr-speed-dial.mjs.map +1 -1
- package/fesm2022/ngwr-spotlight-card.mjs +2 -2
- package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
- package/fesm2022/ngwr-squircle.mjs +1 -1
- package/fesm2022/ngwr-squircle.mjs.map +1 -1
- package/fesm2022/ngwr-star-border.mjs +2 -2
- package/fesm2022/ngwr-star-border.mjs.map +1 -1
- package/fesm2022/ngwr-switch.mjs +10 -3
- package/fesm2022/ngwr-switch.mjs.map +1 -1
- package/fesm2022/ngwr-table.mjs +233 -19
- package/fesm2022/ngwr-table.mjs.map +1 -1
- package/fesm2022/ngwr-tabs.mjs +21 -4
- package/fesm2022/ngwr-tabs.mjs.map +1 -1
- package/fesm2022/ngwr-textarea.mjs +20 -4
- package/fesm2022/ngwr-textarea.mjs.map +1 -1
- package/fesm2022/ngwr-tilt-card.mjs +2 -2
- package/fesm2022/ngwr-tilt-card.mjs.map +1 -1
- package/fesm2022/ngwr-toolbar.mjs +2 -2
- package/fesm2022/ngwr-toolbar.mjs.map +1 -1
- package/fesm2022/ngwr-tour.mjs +264 -0
- package/fesm2022/ngwr-tour.mjs.map +1 -0
- package/fesm2022/ngwr-transfer.mjs +184 -0
- package/fesm2022/ngwr-transfer.mjs.map +1 -0
- package/fesm2022/ngwr-tree.mjs +23 -6
- package/fesm2022/ngwr-tree.mjs.map +1 -1
- package/fesm2022/ngwr-typewriter.mjs +2 -2
- package/fesm2022/ngwr-typewriter.mjs.map +1 -1
- package/fesm2022/ngwr-validators.mjs +118 -2
- package/fesm2022/ngwr-validators.mjs.map +1 -1
- package/fesm2022/ngwr-version.mjs +2 -2
- package/fesm2022/ngwr-version.mjs.map +1 -1
- package/fesm2022/ngwr-virtual-scroll.mjs +2 -2
- package/fesm2022/ngwr-virtual-scroll.mjs.map +1 -1
- package/fesm2022/ngwr-waves.mjs +2 -2
- package/fesm2022/ngwr-waves.mjs.map +1 -1
- package/form/styles/_index.scss +8 -4
- package/glitch-text/styles/_index.scss +5 -0
- package/gradient-text/styles/_index.scss +5 -0
- package/i18n/en.json +74 -6
- package/i18n/ru.json +74 -6
- package/icon/styles/_index.scss +5 -0
- package/keyboard/styles/_index.scss +5 -0
- package/llms-full.txt +123 -62
- package/llms.txt +29 -8
- package/loading-bar/styles/_index.scss +5 -0
- package/marquee/styles/_index.scss +7 -2
- package/overlay/styles/_index.scss +5 -0
- package/package.json +13 -1
- package/popover/styles/_index.scss +48 -12
- package/pull-to-refresh/styles/_index.scss +5 -0
- package/result/styles/_index.scss +3 -3
- package/schematics/icon-set/index.js +80 -34
- package/schematics/icon-set/schema.json +8 -3
- package/schematics/ng-add/index.js +5 -2
- package/schematics/page/templates.js +17 -21
- package/schematics/provider/index.js +31 -13
- package/schematics/provider/schema.json +40 -24
- package/schematics/use/index.js +5 -1
- package/schematics/use/schema.json +8 -3
- package/schematics/use/symbol-map.json +6 -177
- package/segmented/styles/_index.scss +1 -1
- package/select/styles/_index.scss +7 -3
- package/shiny-text/styles/_index.scss +5 -0
- package/speed-dial/styles/_index.scss +12 -1
- package/spotlight-card/styles/_index.scss +5 -0
- package/squircle/styles/_index.scss +5 -0
- package/star-border/styles/_index.scss +5 -0
- package/statistic/styles/_index.scss +2 -2
- package/styles/_animations.scss +6 -0
- package/styles.scss +3 -0
- package/table/styles/_index.scss +100 -2
- package/theme/styles/_colors.scss +43 -1
- package/theme/styles/_dark.scss +18 -6
- package/theme/styles/_focus.scss +2 -8
- package/tilt-card/styles/_index.scss +5 -0
- package/toast/styles/_index.scss +6 -3
- package/tour/styles/_index.scss +63 -0
- package/transfer/styles/_index.scss +105 -0
- package/types/ngwr-alert.d.ts +4 -1
- package/types/ngwr-avatar.d.ts +1 -1
- package/types/ngwr-back-top.d.ts +3 -2
- package/types/ngwr-badge.d.ts +1 -1
- package/types/ngwr-border-glow.d.ts +0 -1
- package/types/ngwr-carousel.d.ts +10 -1
- package/types/ngwr-cascader.d.ts +12 -1
- package/types/ngwr-checkbox.d.ts +9 -1
- package/types/ngwr-command-palette.d.ts +4 -1
- package/types/ngwr-date-picker.d.ts +9 -1
- package/types/ngwr-density.d.ts +1 -1
- package/types/ngwr-divider.d.ts +1 -1
- package/types/ngwr-event-calendar.d.ts +358 -0
- package/types/ngwr-form.d.ts +177 -20
- package/types/ngwr-fuzzy-text.d.ts +8 -0
- package/types/ngwr-gauge.d.ts +4 -1
- package/types/ngwr-i18n.d.ts +15 -0
- package/types/ngwr-input-number.d.ts +8 -1
- package/types/ngwr-input.d.ts +50 -20
- package/types/ngwr-knob.d.ts +4 -1
- package/types/ngwr-lightbox.d.ts +7 -1
- package/types/ngwr-line-chart.d.ts +1 -1
- package/types/ngwr-media.d.ts +1 -1
- package/types/ngwr-meter-group.d.ts +9 -1
- package/types/ngwr-page-header.d.ts +2 -2
- package/types/ngwr-pagination.d.ts +1 -1
- package/types/ngwr-progress.d.ts +4 -1
- package/types/ngwr-rating.d.ts +3 -2
- package/types/ngwr-result.d.ts +12 -6
- package/types/ngwr-segmented.d.ts +6 -0
- package/types/ngwr-select.d.ts +13 -7
- package/types/ngwr-shiny-text.d.ts +2 -4
- package/types/ngwr-speed-dial.d.ts +7 -1
- package/types/ngwr-squircle.d.ts +1 -1
- package/types/ngwr-switch.d.ts +7 -1
- package/types/ngwr-table.d.ts +126 -6
- package/types/ngwr-tabs.d.ts +1 -4
- package/types/ngwr-textarea.d.ts +8 -1
- package/types/ngwr-toolbar.d.ts +2 -2
- package/types/ngwr-tour.d.ts +132 -0
- package/types/ngwr-transfer.d.ts +118 -0
- package/types/ngwr-tree.d.ts +10 -2
- package/types/ngwr-validators.d.ts +62 -2
- package/types/ngwr-version.d.ts +2 -2
- package/typewriter/styles/_index.scss +5 -0
- package/typography/styles/_index.scss +3 -3
- package/virtual-scroll/styles/_index.scss +6 -1
- package/waves/styles/_index.scss +5 -0
|
@@ -99,6 +99,14 @@ declare class WrDatePicker implements FormValueControl<Date | null> {
|
|
|
99
99
|
private readonly labelDate;
|
|
100
100
|
private readonly labelTime;
|
|
101
101
|
private readonly labelDateTime;
|
|
102
|
+
/**
|
|
103
|
+
* Accessible name of the text field. Falls back to the placeholder, then to
|
|
104
|
+
* the same catalog string the calendar button uses — the field is a
|
|
105
|
+
* `role="combobox"`, and with an empty placeholder it had no name at all.
|
|
106
|
+
*/
|
|
107
|
+
readonly ariaLabel: _angular_core.InputSignal<string | null>;
|
|
108
|
+
private readonly fieldLabel;
|
|
109
|
+
protected readonly resolvedAriaLabel: _angular_core.Signal<string>;
|
|
102
110
|
protected readonly triggerLabel: _angular_core.Signal<string>;
|
|
103
111
|
protected readonly classes: _angular_core.Signal<string>;
|
|
104
112
|
private overlayRef;
|
|
@@ -128,7 +136,7 @@ declare class WrDatePicker implements FormValueControl<Date | null> {
|
|
|
128
136
|
private isOutOfBounds;
|
|
129
137
|
private sameDate;
|
|
130
138
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrDatePicker, never>;
|
|
131
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrDatePicker, "wr-date-picker", never, { "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "format": { "alias": "format"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "dateFilter": { "alias": "dateFilter"; "required": false; "isSignal": true; }; "timeFormat": { "alias": "timeFormat"; "required": false; "isSignal": true; }; "showSeconds": { "alias": "showSeconds"; "required": false; "isSignal": true; }; "step": { "alias": "step"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touch": "touch"; }, never, never, true, never>;
|
|
139
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrDatePicker, "wr-date-picker", never, { "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "format": { "alias": "format"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "dateFilter": { "alias": "dateFilter"; "required": false; "isSignal": true; }; "timeFormat": { "alias": "timeFormat"; "required": false; "isSignal": true; }; "showSeconds": { "alias": "showSeconds"; "required": false; "isSignal": true; }; "step": { "alias": "step"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touch": "touch"; }, never, never, true, never>;
|
|
132
140
|
}
|
|
133
141
|
|
|
134
142
|
/**
|
package/types/ngwr-density.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { InjectionToken, Signal, EnvironmentProviders } from '@angular/core';
|
|
|
3
3
|
|
|
4
4
|
/** Density scale. Components multiply their paddings by the matching multiplier. */
|
|
5
5
|
type WrDensityValue = 'sm' | 'md' | 'lg' | 'touch';
|
|
6
|
-
/** Configuration for {@link
|
|
6
|
+
/** Configuration for {@link WrDensity}. */
|
|
7
7
|
interface WrDensityConfig {
|
|
8
8
|
/** Initial density used when no persisted value is present. @default 'md' */
|
|
9
9
|
readonly defaultDensity: WrDensityValue;
|
package/types/ngwr-divider.d.ts
CHANGED
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import * as ngwr_i18n from 'ngwr/i18n';
|
|
2
|
+
import * as _angular_core from '@angular/core';
|
|
3
|
+
import { TemplateRef } from '@angular/core';
|
|
4
|
+
import { WrColor } from 'ngwr/theme';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @license
|
|
8
|
+
*
|
|
9
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
10
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** Which span of time the calendar is showing. */
|
|
14
|
+
type WrCalendarView = 'month' | 'week' | 'day';
|
|
15
|
+
/**
|
|
16
|
+
* One entry on the calendar.
|
|
17
|
+
*
|
|
18
|
+
* `end` is EXCLUSIVE — an event from 09:00 to 10:00 does not overlap one that
|
|
19
|
+
* starts at 10:00, and an all-day event on a single day ends at 00:00 the next
|
|
20
|
+
* day. Exclusive ends are what make adjacency and overlap the same comparison
|
|
21
|
+
* in every view, instead of a per-view off-by-one.
|
|
22
|
+
*/
|
|
23
|
+
interface WrCalendarEvent {
|
|
24
|
+
/** Stable identity. Used for tracking and echoed back on every output. */
|
|
25
|
+
readonly id: string | number;
|
|
26
|
+
/** Text shown on the chip and read out as the button's accessible name. */
|
|
27
|
+
readonly title: string;
|
|
28
|
+
/** Start instant, inclusive. */
|
|
29
|
+
readonly start: Date;
|
|
30
|
+
/** End instant, exclusive. */
|
|
31
|
+
readonly end: Date;
|
|
32
|
+
/**
|
|
33
|
+
* Show in the all-day band rather than against the time grid. Month view
|
|
34
|
+
* renders every event as a band regardless.
|
|
35
|
+
*/
|
|
36
|
+
readonly allDay?: boolean;
|
|
37
|
+
/** Intent color for the chip. Falls back to `primary`. */
|
|
38
|
+
readonly color?: WrColor | null;
|
|
39
|
+
/**
|
|
40
|
+
* Per-event override of the calendar's `editable` input — `false` pins an
|
|
41
|
+
* event that would otherwise be draggable.
|
|
42
|
+
*/
|
|
43
|
+
readonly editable?: boolean;
|
|
44
|
+
/** Anything the host wants to carry along; the calendar never reads it. */
|
|
45
|
+
readonly data?: unknown;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* A move or a resize, emitted before anything is applied. `events` is an input,
|
|
49
|
+
* so the calendar cannot mutate it: apply the change in your own state and the
|
|
50
|
+
* new position renders on the next pass. Ignoring the output cancels the drag.
|
|
51
|
+
*/
|
|
52
|
+
interface WrCalendarEventChange {
|
|
53
|
+
/** The event as it was, untouched. */
|
|
54
|
+
readonly event: WrCalendarEvent;
|
|
55
|
+
/** Where it would start. */
|
|
56
|
+
readonly start: Date;
|
|
57
|
+
/** Where it would end, exclusive. */
|
|
58
|
+
readonly end: Date;
|
|
59
|
+
/** Whether the pointer changed the duration (`resize`) or only slid it. */
|
|
60
|
+
readonly kind: 'move' | 'resize';
|
|
61
|
+
}
|
|
62
|
+
/** An empty stretch of the calendar the user activated. */
|
|
63
|
+
interface WrCalendarSlot {
|
|
64
|
+
/** Start of the slot — midnight in month view, the slot's own time otherwise. */
|
|
65
|
+
readonly start: Date;
|
|
66
|
+
/** End of the slot, exclusive. */
|
|
67
|
+
readonly end: Date;
|
|
68
|
+
/** `true` in month view and in the all-day band. */
|
|
69
|
+
readonly allDay: boolean;
|
|
70
|
+
}
|
|
71
|
+
/** Implicit context of the `wrCalendarEvent` template. */
|
|
72
|
+
interface WrCalendarEventContext {
|
|
73
|
+
readonly $implicit: WrCalendarEvent;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* A chip that spans whole days — every month-view event, and the all-day band
|
|
78
|
+
* of the time views. It lives in the cell where its segment STARTS and reaches
|
|
79
|
+
* right with a `calc()` width, so it stays inside one `role="gridcell"` however
|
|
80
|
+
* far it spans.
|
|
81
|
+
*/
|
|
82
|
+
interface BandChip {
|
|
83
|
+
readonly key: string;
|
|
84
|
+
readonly event: WrCalendarEvent;
|
|
85
|
+
/** Index of the day it starts on, within the row it was laid out against. */
|
|
86
|
+
readonly column: number;
|
|
87
|
+
readonly span: number;
|
|
88
|
+
readonly lane: number;
|
|
89
|
+
readonly continuesBefore: boolean;
|
|
90
|
+
readonly continuesAfter: boolean;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* A chip positioned against the time grid. Same rule — it belongs to the cell
|
|
94
|
+
* holding its start — but sized in percentages OF THAT CELL, which works only
|
|
95
|
+
* because every slot row is the same height.
|
|
96
|
+
*/
|
|
97
|
+
interface TimeChip {
|
|
98
|
+
readonly key: string;
|
|
99
|
+
readonly event: WrCalendarEvent;
|
|
100
|
+
/** Offset into the start cell, 0–100. */
|
|
101
|
+
readonly top: number;
|
|
102
|
+
/** Height as a multiple of the cell, ×100. */
|
|
103
|
+
readonly height: number;
|
|
104
|
+
/** Horizontal share of the column, both 0–100. */
|
|
105
|
+
readonly left: number;
|
|
106
|
+
readonly width: number;
|
|
107
|
+
readonly continuesBefore: boolean;
|
|
108
|
+
readonly continuesAfter: boolean;
|
|
109
|
+
}
|
|
110
|
+
interface DayCell {
|
|
111
|
+
readonly date: Date;
|
|
112
|
+
readonly key: string;
|
|
113
|
+
readonly day: string;
|
|
114
|
+
readonly label: string;
|
|
115
|
+
readonly inMonth: boolean;
|
|
116
|
+
readonly isToday: boolean;
|
|
117
|
+
readonly bands: readonly BandChip[];
|
|
118
|
+
readonly hidden: number;
|
|
119
|
+
}
|
|
120
|
+
interface MonthWeek {
|
|
121
|
+
readonly key: string;
|
|
122
|
+
readonly days: readonly DayCell[];
|
|
123
|
+
}
|
|
124
|
+
interface TimeCell {
|
|
125
|
+
readonly key: string;
|
|
126
|
+
readonly date: Date;
|
|
127
|
+
readonly label: string;
|
|
128
|
+
readonly chips: readonly TimeChip[];
|
|
129
|
+
}
|
|
130
|
+
interface TimeRow {
|
|
131
|
+
readonly key: string;
|
|
132
|
+
readonly label: string;
|
|
133
|
+
/** Minutes from midnight — also what the drag target reads off the cell. */
|
|
134
|
+
readonly minutes: number;
|
|
135
|
+
readonly major: boolean;
|
|
136
|
+
readonly cells: readonly TimeCell[];
|
|
137
|
+
}
|
|
138
|
+
interface ColumnHeader {
|
|
139
|
+
readonly key: string;
|
|
140
|
+
readonly date: Date;
|
|
141
|
+
readonly weekday: string;
|
|
142
|
+
readonly day: string;
|
|
143
|
+
readonly label: string;
|
|
144
|
+
readonly isToday: boolean;
|
|
145
|
+
}
|
|
146
|
+
/** Live drag state. `null` whenever the pointer is not down on a chip. */
|
|
147
|
+
interface DragState {
|
|
148
|
+
readonly event: WrCalendarEvent;
|
|
149
|
+
readonly kind: 'move' | 'resize';
|
|
150
|
+
readonly originDate: Date;
|
|
151
|
+
readonly originMinutes: number;
|
|
152
|
+
readonly pointerId: number;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Month / week / day event calendar with drag to move and resize.
|
|
156
|
+
*
|
|
157
|
+
* `events` is an INPUT, never mutated: a drag emits `eventChange` describing
|
|
158
|
+
* where the event would land and stops there. Apply it to your own state and
|
|
159
|
+
* the calendar re-renders — so an unhandled output is a cancelled drag, an
|
|
160
|
+
* optimistic update is one `set`, and a rejected server write needs no rollback
|
|
161
|
+
* path inside the component.
|
|
162
|
+
*
|
|
163
|
+
* Every chip lives inside the `role="gridcell"` where it starts and reaches out
|
|
164
|
+
* with `calc()` widths or percentage heights. That is what keeps the ARIA grid
|
|
165
|
+
* valid — an events layer floating over the grid would leave rows owning
|
|
166
|
+
* something other than cells — and it means no pixel measurement anywhere.
|
|
167
|
+
*
|
|
168
|
+
* **Keyboard.** The grid is one tab stop with a roving cursor: arrows move by
|
|
169
|
+
* day (left / right) and by week or slot (up / down), `Home` / `End` jump to
|
|
170
|
+
* the ends of the row, `Enter` on an empty cell emits `slotClick`, and `Enter`
|
|
171
|
+
* on a cell holding events focuses the first chip (`Escape` returns). On a
|
|
172
|
+
* focused chip, `Alt` + arrows move the event — the keyboard equivalent of the
|
|
173
|
+
* drag, emitting the same `eventChange`.
|
|
174
|
+
*
|
|
175
|
+
* Date math and formatting go through {@link WrDateAdapter}; register one with
|
|
176
|
+
* `provideWrDateAdapter(...)` at bootstrap.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```html
|
|
180
|
+
* <wr-event-calendar
|
|
181
|
+
* editable
|
|
182
|
+
* [events]="events()"
|
|
183
|
+
* [(view)]="view"
|
|
184
|
+
* [(date)]="anchor"
|
|
185
|
+
* (eventChange)="apply($event)"
|
|
186
|
+
* (slotClick)="compose($event)"
|
|
187
|
+
* />
|
|
188
|
+
* ```
|
|
189
|
+
*
|
|
190
|
+
* @see https://ngwr.dev/reference/components/event-calendar
|
|
191
|
+
*/
|
|
192
|
+
declare class WrEventCalendar {
|
|
193
|
+
/** Everything to render. Never mutated — see `eventChange`. */
|
|
194
|
+
readonly events: _angular_core.InputSignal<readonly WrCalendarEvent[]>;
|
|
195
|
+
/** Which span is shown. Two-way bindable. @default 'month' */
|
|
196
|
+
readonly view: _angular_core.ModelSignal<WrCalendarView>;
|
|
197
|
+
/** Any date inside the shown span. Two-way bindable. */
|
|
198
|
+
readonly date: _angular_core.ModelSignal<Date>;
|
|
199
|
+
/** Which buttons the view switcher offers. Empty hides it. */
|
|
200
|
+
readonly views: _angular_core.InputSignal<readonly WrCalendarView[]>;
|
|
201
|
+
/** Allow dragging chips to move and resize them. @default false */
|
|
202
|
+
readonly editable: _angular_core.InputSignalWithTransform<boolean, any>;
|
|
203
|
+
/** Minutes per row in the time views — also the drag snap. @default 30 */
|
|
204
|
+
readonly slotMinutes: _angular_core.InputSignalWithTransform<number, unknown>;
|
|
205
|
+
/** First hour the time views show. @default 0 */
|
|
206
|
+
readonly dayStartHour: _angular_core.InputSignalWithTransform<number, unknown>;
|
|
207
|
+
/** First hour they do NOT show, exclusive. @default 24 */
|
|
208
|
+
readonly dayEndHour: _angular_core.InputSignalWithTransform<number, unknown>;
|
|
209
|
+
/** Lanes a month cell shows before collapsing the rest into “+N more”. @default 3 */
|
|
210
|
+
readonly maxLanes: _angular_core.InputSignalWithTransform<number, unknown>;
|
|
211
|
+
/** Hide the built-in header — supply your own navigation instead. @default false */
|
|
212
|
+
readonly hideHeader: _angular_core.InputSignalWithTransform<boolean, any>;
|
|
213
|
+
/** A chip was activated. */
|
|
214
|
+
readonly eventClick: _angular_core.OutputEmitterRef<WrCalendarEvent>;
|
|
215
|
+
/** Empty space was activated — the slot the user pointed at. */
|
|
216
|
+
readonly slotClick: _angular_core.OutputEmitterRef<WrCalendarSlot>;
|
|
217
|
+
/** A drag or an `Alt` + arrow finished. Apply it yourself; nothing moves until you do. */
|
|
218
|
+
readonly eventChange: _angular_core.OutputEmitterRef<WrCalendarEventChange>;
|
|
219
|
+
private readonly adapter;
|
|
220
|
+
private readonly document;
|
|
221
|
+
private readonly chipTpl;
|
|
222
|
+
protected readonly todayLabel: string;
|
|
223
|
+
protected readonly previousLabel: string;
|
|
224
|
+
protected readonly nextLabel: string;
|
|
225
|
+
protected readonly allDayLabel: string;
|
|
226
|
+
protected readonly timeLabel: string;
|
|
227
|
+
protected readonly moreLabel: (params?: ngwr_i18n.WrI18nParams) => string;
|
|
228
|
+
protected readonly viewLabels: Record<WrCalendarView, string>;
|
|
229
|
+
/** Accessible name of the grid; overridable for a page with several. */
|
|
230
|
+
readonly ariaLabel: _angular_core.InputSignal<string | null>;
|
|
231
|
+
protected readonly resolvedAriaLabel: _angular_core.Signal<string>;
|
|
232
|
+
/**
|
|
233
|
+
* `[day, minutes]` of the roving cursor — `minutes === -1` means a month cell
|
|
234
|
+
* or the all-day band. Raw, so it survives a view switch; read
|
|
235
|
+
* {@link cursorCell}, which clamps it to what the current view actually has.
|
|
236
|
+
*/
|
|
237
|
+
private readonly cursor;
|
|
238
|
+
/**
|
|
239
|
+
* The cursor as the current view can honour it. Exactly one cell may carry
|
|
240
|
+
* `tabindex="0"`, so a stale coordinate — the 09:30 row after switching to
|
|
241
|
+
* month, day 34 after switching to week — must fall back to a real cell
|
|
242
|
+
* rather than leave the grid with no tab stop at all.
|
|
243
|
+
*/
|
|
244
|
+
protected readonly cursorCell: _angular_core.Signal<readonly [number, number]>;
|
|
245
|
+
/** Non-null only while a pointer is down on a chip. @internal */
|
|
246
|
+
protected readonly drag: _angular_core.WritableSignal<DragState | null>;
|
|
247
|
+
protected readonly dragging: _angular_core.Signal<string | number | null>;
|
|
248
|
+
protected readonly chipTemplate: _angular_core.Signal<TemplateRef<WrCalendarEventContext> | null>;
|
|
249
|
+
protected readonly classes: _angular_core.Signal<string>;
|
|
250
|
+
/** Inclusive-exclusive window the current view covers. */
|
|
251
|
+
private readonly range;
|
|
252
|
+
/** Every day the view shows, left to right. */
|
|
253
|
+
private readonly days;
|
|
254
|
+
/** Only what overlaps the window — everything downstream works off this. */
|
|
255
|
+
private readonly visible;
|
|
256
|
+
protected readonly title: _angular_core.Signal<string>;
|
|
257
|
+
protected readonly weekdayNames: _angular_core.Signal<string[]>;
|
|
258
|
+
protected readonly switcher: _angular_core.Signal<{
|
|
259
|
+
view: WrCalendarView;
|
|
260
|
+
label: string;
|
|
261
|
+
}[]>;
|
|
262
|
+
protected readonly weeks: _angular_core.Signal<readonly MonthWeek[]>;
|
|
263
|
+
protected readonly columns: _angular_core.Signal<readonly ColumnHeader[]>;
|
|
264
|
+
/** The all-day band above the time grid — same layout as a month week. */
|
|
265
|
+
protected readonly allDayBands: _angular_core.Signal<readonly BandChip[]>;
|
|
266
|
+
protected readonly allDayCells: _angular_core.Signal<readonly {
|
|
267
|
+
key: string;
|
|
268
|
+
date: Date;
|
|
269
|
+
label: string;
|
|
270
|
+
bands: readonly BandChip[];
|
|
271
|
+
}[]>;
|
|
272
|
+
protected readonly hasAllDay: _angular_core.Signal<boolean>;
|
|
273
|
+
protected readonly rows: _angular_core.Signal<readonly TimeRow[]>;
|
|
274
|
+
protected step(direction: -1 | 1): void;
|
|
275
|
+
protected goToday(): void;
|
|
276
|
+
protected setView(view: WrCalendarView): void;
|
|
277
|
+
/** “+N more” opens that day — the overflow is only ever a month-view problem. */
|
|
278
|
+
protected openDay(date: Date): void;
|
|
279
|
+
protected onChipPointerDown(event: PointerEvent, chipEvent: WrCalendarEvent, kind: 'move' | 'resize'): void;
|
|
280
|
+
protected onPointerUp(event: PointerEvent): void;
|
|
281
|
+
protected onChipClick(event: WrCalendarEvent): void;
|
|
282
|
+
protected onCellClick(date: Date, minutes: number): void;
|
|
283
|
+
protected onChipKeyDown(event: KeyboardEvent, chipEvent: WrCalendarEvent): void;
|
|
284
|
+
protected onGridKeyDown(event: KeyboardEvent): void;
|
|
285
|
+
protected isCursor(day: number, minutes: number): boolean;
|
|
286
|
+
/**
|
|
287
|
+
* Greedy lane packing for day-spanning chips. Sorted by start then by length,
|
|
288
|
+
* each segment takes the first lane its columns are free in — the classic
|
|
289
|
+
* interval-graph colouring, and the reason a long event keeps one lane across
|
|
290
|
+
* the whole week instead of stair-stepping.
|
|
291
|
+
*
|
|
292
|
+
* `limit` caps the visible lanes; anything past it is reported per column so
|
|
293
|
+
* the cell can say how much it is hiding.
|
|
294
|
+
*/
|
|
295
|
+
private bandLayout;
|
|
296
|
+
/**
|
|
297
|
+
* Column layout inside one day: events that overlap in time share the width.
|
|
298
|
+
* Clusters are built by a running high-water mark — a new cluster starts the
|
|
299
|
+
* moment an event begins after everything before it has ended.
|
|
300
|
+
*/
|
|
301
|
+
private timeLayout;
|
|
302
|
+
protected chipLabel(event: WrCalendarEvent): string;
|
|
303
|
+
protected chipTime(event: WrCalendarEvent): string;
|
|
304
|
+
protected canDrag(event: WrCalendarEvent): boolean;
|
|
305
|
+
private slotAt;
|
|
306
|
+
/** The `[data-cell]` under the pointer, or `null` outside the grid. */
|
|
307
|
+
private cellUnder;
|
|
308
|
+
/** Value of a cell's `data-cell-date`. @internal */
|
|
309
|
+
protected stamp(date: Date): number;
|
|
310
|
+
private focusCursor;
|
|
311
|
+
private focusCell;
|
|
312
|
+
/**
|
|
313
|
+
* Move one time row, treating the all-day band as the row above the first —
|
|
314
|
+
* otherwise the band is mouse-only, which is the kind of gap that makes a
|
|
315
|
+
* keyboard user give up on the whole grid.
|
|
316
|
+
*/
|
|
317
|
+
private stepRow;
|
|
318
|
+
private shift;
|
|
319
|
+
private startOfDay;
|
|
320
|
+
private startOfWeek;
|
|
321
|
+
/** Whole days apart — computed on the day floor, so DST cannot round it off. */
|
|
322
|
+
private daysBetween;
|
|
323
|
+
private spansWholeDay;
|
|
324
|
+
private clock;
|
|
325
|
+
private iso;
|
|
326
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrEventCalendar, never>;
|
|
327
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrEventCalendar, "wr-event-calendar", never, { "events": { "alias": "events"; "required": false; "isSignal": true; }; "view": { "alias": "view"; "required": false; "isSignal": true; }; "date": { "alias": "date"; "required": false; "isSignal": true; }; "views": { "alias": "views"; "required": false; "isSignal": true; }; "editable": { "alias": "editable"; "required": false; "isSignal": true; }; "slotMinutes": { "alias": "slotMinutes"; "required": false; "isSignal": true; }; "dayStartHour": { "alias": "dayStartHour"; "required": false; "isSignal": true; }; "dayEndHour": { "alias": "dayEndHour"; "required": false; "isSignal": true; }; "maxLanes": { "alias": "maxLanes"; "required": false; "isSignal": true; }; "hideHeader": { "alias": "hideHeader"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "view": "viewChange"; "date": "dateChange"; "eventClick": "eventClick"; "slotClick": "slotClick"; "eventChange": "eventChange"; }, ["chipTpl"], never, true, never>;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* @license
|
|
332
|
+
*
|
|
333
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
334
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
335
|
+
*/
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Replace the chip's contents. The event is the implicit context; the chip
|
|
339
|
+
* itself — its button, its position and its drag handling — stays with the
|
|
340
|
+
* calendar, so a custom template cannot break the geometry.
|
|
341
|
+
*
|
|
342
|
+
* @example
|
|
343
|
+
* ```html
|
|
344
|
+
* <wr-event-calendar [events]="events">
|
|
345
|
+
* <ng-template wrCalendarEvent let-event>
|
|
346
|
+
* <strong>{{ event.title }}</strong> — {{ event.data.room }}
|
|
347
|
+
* </ng-template>
|
|
348
|
+
* </wr-event-calendar>
|
|
349
|
+
* ```
|
|
350
|
+
*/
|
|
351
|
+
declare class WrCalendarEventTemplate {
|
|
352
|
+
readonly template: TemplateRef<WrCalendarEventContext>;
|
|
353
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrCalendarEventTemplate, never>;
|
|
354
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<WrCalendarEventTemplate, "ng-template[wrCalendarEvent]", never, {}, {}, never, never, true, never>;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export { WrCalendarEventTemplate, WrEventCalendar };
|
|
358
|
+
export type { WrCalendarEvent, WrCalendarEventChange, WrCalendarEventContext, WrCalendarSlot, WrCalendarView };
|
package/types/ngwr-form.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as _angular_core from '@angular/core';
|
|
2
|
+
import { InjectionToken, Signal, EnvironmentProviders } from '@angular/core';
|
|
2
3
|
import * as _angular_forms from '@angular/forms';
|
|
3
4
|
import { NgControl } from '@angular/forms';
|
|
4
5
|
|
|
@@ -12,7 +13,7 @@ import { NgControl } from '@angular/forms';
|
|
|
12
13
|
* ```html
|
|
13
14
|
* <wr-form-item [hasError]="form.controls.email.invalid">
|
|
14
15
|
* <label>Email</label>
|
|
15
|
-
* <
|
|
16
|
+
* <input wrInput formControlName="email" />
|
|
16
17
|
* <wr-form-error>Invalid email</wr-form-error>
|
|
17
18
|
* </wr-form-item>
|
|
18
19
|
* ```
|
|
@@ -31,6 +32,71 @@ declare class WrFormItem {
|
|
|
31
32
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrFormItem, "wr-form-item", never, { "hasError": { "alias": "hasError"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
/**
|
|
36
|
+
* @license
|
|
37
|
+
*
|
|
38
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
39
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* What a projected control can read from its surrounding `<wr-form-field>`.
|
|
44
|
+
*
|
|
45
|
+
* The field renders `<label [for]>` before it can see what was projected into
|
|
46
|
+
* it, so the id has to travel the other way: the control adopts the id the
|
|
47
|
+
* label already points at. Doing it through DI keeps it a render-time binding,
|
|
48
|
+
* which is what SSR needs — stamping the id from `afterNextRender` would leave
|
|
49
|
+
* every prerendered page with a label pointing at nothing.
|
|
50
|
+
*/
|
|
51
|
+
interface WrFormFieldContext {
|
|
52
|
+
/** Id the field's `<label for>` points at. */
|
|
53
|
+
readonly controlId: Signal<string>;
|
|
54
|
+
/**
|
|
55
|
+
* Validator keys currently in error, once the control is touched or dirty.
|
|
56
|
+
* Empty when the field is valid or has not been interacted with.
|
|
57
|
+
*/
|
|
58
|
+
readonly errorKeys: Signal<readonly string[]>;
|
|
59
|
+
/** Id of the element listing the visible messages, or `null` when there are none. */
|
|
60
|
+
readonly describedBy: Signal<string | null>;
|
|
61
|
+
}
|
|
62
|
+
/** Present only inside a `<wr-form-field>`; inject with `{ optional: true }`. */
|
|
63
|
+
declare const WR_FORM_FIELD: InjectionToken<WrFormFieldContext>;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* One error message tied to a validator key. Renders only when the parent
|
|
67
|
+
* form-field has a matching error in `control.errors`, and only once the
|
|
68
|
+
* control is touched or dirty.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```html
|
|
72
|
+
* <wr-form-error key="required">This field is required.</wr-form-error>
|
|
73
|
+
* <wr-form-error key="email">That doesn't look right.</wr-form-error>
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
declare class WrFormError {
|
|
77
|
+
/**
|
|
78
|
+
* Validator key this message corresponds to (e.g. `'required'`).
|
|
79
|
+
* Optional — without a key the message always renders, which is the
|
|
80
|
+
* plain inline-error usage inside `<wr-form-item>`.
|
|
81
|
+
*/
|
|
82
|
+
readonly key: _angular_core.InputSignal<string | undefined>;
|
|
83
|
+
private readonly field;
|
|
84
|
+
/**
|
|
85
|
+
* Whether this message is the one the current error calls for.
|
|
86
|
+
*
|
|
87
|
+
* The parent projects every `<wr-form-error>` through a single
|
|
88
|
+
* `<ng-content select>`, which cannot filter — so each message decides for
|
|
89
|
+
* itself. Without this, one invalid control rendered "Email is required."
|
|
90
|
+
* and "That isn't a valid email." side by side, which is what the docs have
|
|
91
|
+
* always described as gated behaviour.
|
|
92
|
+
*
|
|
93
|
+
* A keyless message always shows: that is the plain inline-error usage inside
|
|
94
|
+
* `<wr-form-item>`, which has no error discovery at all.
|
|
95
|
+
*/
|
|
96
|
+
protected readonly visible: _angular_core.Signal<boolean>;
|
|
97
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrFormError, never>;
|
|
98
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrFormError, "wr-form-error", never, { "key": { "alias": "key"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
99
|
+
}
|
|
34
100
|
/**
|
|
35
101
|
* Wraps a label + control + hint + error messages into a single block —
|
|
36
102
|
* the layout primitive every form ends up reinventing.
|
|
@@ -52,7 +118,7 @@ declare class WrFormItem {
|
|
|
52
118
|
*
|
|
53
119
|
* @see https://ngwr.dev/reference/components/form-field
|
|
54
120
|
*/
|
|
55
|
-
declare class WrFormField {
|
|
121
|
+
declare class WrFormField implements WrFormFieldContext {
|
|
56
122
|
/** Label text shown above the control. */
|
|
57
123
|
readonly label: _angular_core.InputSignal<string>;
|
|
58
124
|
/** Hint text shown below the control. Hidden when an error is visible. */
|
|
@@ -61,35 +127,126 @@ declare class WrFormField {
|
|
|
61
127
|
readonly required: _angular_core.InputSignalWithTransform<boolean, any>;
|
|
62
128
|
/** Show `(optional)` next to the label. Mutually exclusive with `required`. @default false */
|
|
63
129
|
readonly optional: _angular_core.InputSignalWithTransform<boolean, any>;
|
|
64
|
-
/**
|
|
130
|
+
/**
|
|
131
|
+
* Force a specific id on the label's `for` attribute. Auto-generated
|
|
132
|
+
* otherwise, and adopted by the projected `wrInput` unless that element
|
|
133
|
+
* already carries an `id` of its own.
|
|
134
|
+
*/
|
|
65
135
|
readonly controlId: _angular_core.InputSignal<string>;
|
|
66
|
-
/**
|
|
136
|
+
/**
|
|
137
|
+
* Projected `NgControl` — used to read touched / dirty / errors.
|
|
138
|
+
*
|
|
139
|
+
* This catches `[formField]` too: Angular's Signal Forms directive provides
|
|
140
|
+
* `NgControl` via its interop shim, so both forms flavours land here.
|
|
141
|
+
*/
|
|
67
142
|
protected readonly ngControl: _angular_core.Signal<NgControl | undefined>;
|
|
143
|
+
/**
|
|
144
|
+
* Bumped on every event the projected control emits.
|
|
145
|
+
*
|
|
146
|
+
* `AbstractControl`'s `touched` / `dirty` / `errors` accessors are NOT
|
|
147
|
+
* reactive under classic forms — Angular reads them inside `untracked()`, and
|
|
148
|
+
* `errors` is a plain assigned field. A `computed` over them therefore caches
|
|
149
|
+
* its first value and never recomputes, which in a zoneless app means the
|
|
150
|
+
* error block never appears at all. `control.events` is the reactive source
|
|
151
|
+
* Angular does expose, so the computed depends on this counter instead.
|
|
152
|
+
* Signal Forms needs none of this — its interop getters read live signals —
|
|
153
|
+
* and harmlessly contributes no events.
|
|
154
|
+
*/
|
|
155
|
+
private readonly revision;
|
|
156
|
+
constructor();
|
|
68
157
|
protected readonly errors: _angular_core.Signal<_angular_forms.ValidationErrors | null>;
|
|
69
158
|
protected readonly hasError: _angular_core.Signal<boolean>;
|
|
159
|
+
/** @internal Read by the projected `<wr-form-error>` children to decide which of them renders. */
|
|
160
|
+
readonly errorKeys: _angular_core.Signal<readonly string[]>;
|
|
161
|
+
/** @internal Read by the projected control so a screen reader is pointed at the message. */
|
|
162
|
+
readonly describedBy: _angular_core.Signal<string | null>;
|
|
163
|
+
/**
|
|
164
|
+
* Render a catalog message for any error the markup does not already answer.
|
|
165
|
+
*
|
|
166
|
+
* On by default: a field with no `<wr-form-error>` at all is the common case,
|
|
167
|
+
* and an empty error block helps nobody. Turn it off for a field whose copy is
|
|
168
|
+
* entirely hand-written. @default true
|
|
169
|
+
*/
|
|
170
|
+
readonly autoErrors: _angular_core.InputSignalWithTransform<boolean, any>;
|
|
171
|
+
private readonly projectedErrors;
|
|
172
|
+
private readonly appMessages;
|
|
173
|
+
private readonly i18n;
|
|
174
|
+
/**
|
|
175
|
+
* Errors with no projected `<wr-form-error key>` to answer them, resolved to
|
|
176
|
+
* text: the app catalog first, then the `validation.*` i18n keys, then a
|
|
177
|
+
* built-in English sentence. Per-field markup always wins — it is the most
|
|
178
|
+
* specific thing the author wrote.
|
|
179
|
+
*/
|
|
180
|
+
protected readonly autoMessages: _angular_core.Signal<readonly {
|
|
181
|
+
key: string;
|
|
182
|
+
text: string;
|
|
183
|
+
}[]>;
|
|
184
|
+
private resolve;
|
|
70
185
|
protected readonly classes: _angular_core.Signal<string>;
|
|
71
186
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrFormField, never>;
|
|
72
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrFormField, "wr-form-field", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "optional": { "alias": "optional"; "required": false; "isSignal": true; }; "controlId": { "alias": "controlId"; "required": false; "isSignal": true; }; }, {}, ["ngControl"], ["*", "wr-form-error"], true, never>;
|
|
187
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrFormField, "wr-form-field", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "optional": { "alias": "optional"; "required": false; "isSignal": true; }; "controlId": { "alias": "controlId"; "required": false; "isSignal": true; }; "autoErrors": { "alias": "autoErrors"; "required": false; "isSignal": true; }; }, {}, ["ngControl", "projectedErrors"], ["*", "wr-form-error"], true, never>;
|
|
73
188
|
}
|
|
189
|
+
|
|
74
190
|
/**
|
|
75
|
-
*
|
|
76
|
-
* parent form-field has a matching error in `control.errors`.
|
|
191
|
+
* @license
|
|
77
192
|
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* <wr-form-error key="required">This field is required.</wr-form-error>
|
|
81
|
-
* <wr-form-error key="email">That doesn't look right.</wr-form-error>
|
|
82
|
-
* ```
|
|
193
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
194
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
83
195
|
*/
|
|
84
|
-
|
|
196
|
+
|
|
197
|
+
/** What a message function is handed to build its sentence. */
|
|
198
|
+
interface WrFormErrorContext {
|
|
199
|
+
/** Validator key (classic forms) or Signal Forms `kind` that produced the error. */
|
|
200
|
+
readonly key: string;
|
|
85
201
|
/**
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
202
|
+
* The validator's own payload — `{ requiredLength, actualLength }` for
|
|
203
|
+
* `minlength`, `{ min }` for `wrMinDate`, and so on. `true` for the
|
|
204
|
+
* flag-shaped validators, which carry nothing.
|
|
89
205
|
*/
|
|
90
|
-
readonly
|
|
91
|
-
|
|
92
|
-
|
|
206
|
+
readonly error: unknown;
|
|
207
|
+
/** The surrounding field's `label`, so a message can name the field. */
|
|
208
|
+
readonly label: string;
|
|
93
209
|
}
|
|
210
|
+
/** A message, or a function that builds one from the validator's payload. */
|
|
211
|
+
type WrFormErrorMessage = string | ((ctx: WrFormErrorContext) => string);
|
|
212
|
+
/** Validator key → message. Keys are matched exactly against `control.errors`. */
|
|
213
|
+
type WrFormErrorMessages = Readonly<Record<string, WrFormErrorMessage>>;
|
|
214
|
+
/**
|
|
215
|
+
* App-wide validation copy. Empty by default; `<wr-form-field>` falls through
|
|
216
|
+
* to the `ngwr/i18n` catalog and then to a built-in English sentence, so a
|
|
217
|
+
* form shows a usable message with no configuration at all.
|
|
218
|
+
*/
|
|
219
|
+
declare const WR_FORM_ERRORS: InjectionToken<Readonly<Record<string, WrFormErrorMessage>>>;
|
|
220
|
+
/**
|
|
221
|
+
* Register validation messages for the whole app.
|
|
222
|
+
*
|
|
223
|
+
* Only the keys you name are overridden — everything else keeps resolving
|
|
224
|
+
* through the i18n catalog, so this composes with `provideWrI18n()` rather than
|
|
225
|
+
* replacing it. A projected `<wr-form-error key="…">` still wins over both:
|
|
226
|
+
* per-field copy beats app-wide copy.
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* ```ts
|
|
230
|
+
* bootstrapApplication(App, {
|
|
231
|
+
* providers: [
|
|
232
|
+
* provideWrFormErrors({
|
|
233
|
+
* required: 'Please fill this in.',
|
|
234
|
+
* minlength: ({ error }) => `At least ${(error as { requiredLength: number }).requiredLength} characters.`,
|
|
235
|
+
* }),
|
|
236
|
+
* ],
|
|
237
|
+
* });
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
240
|
+
declare function provideWrFormErrors(messages?: WrFormErrorMessages): EnvironmentProviders;
|
|
241
|
+
/**
|
|
242
|
+
* Last-resort English, used when no app catalog and no i18n catalog answer.
|
|
243
|
+
*
|
|
244
|
+
* These exist so that a form with zero configuration still says something true
|
|
245
|
+
* rather than rendering an empty error block. Every key here also ships as a
|
|
246
|
+
* `validation.*` entry in `ngwr/i18n/{en,ru}`, which is what a localized app
|
|
247
|
+
* actually reads.
|
|
248
|
+
*/
|
|
249
|
+
declare const WR_FORM_ERROR_FALLBACKS: WrFormErrorMessages;
|
|
94
250
|
|
|
95
|
-
export { WrFormError, WrFormField, WrFormItem };
|
|
251
|
+
export { WR_FORM_ERRORS, WR_FORM_ERROR_FALLBACKS, WR_FORM_FIELD, WrFormError, WrFormField, WrFormItem, provideWrFormErrors };
|
|
252
|
+
export type { WrFormErrorContext, WrFormErrorMessage, WrFormErrorMessages, WrFormFieldContext };
|
|
@@ -64,6 +64,14 @@ declare class WrFuzzyText {
|
|
|
64
64
|
private readonly isBrowser;
|
|
65
65
|
private readonly platform;
|
|
66
66
|
private teardown;
|
|
67
|
+
/**
|
|
68
|
+
* `init()` suspends on font loading, so the component can be destroyed while
|
|
69
|
+
* it is awaiting. At that moment `teardown` is still undefined, so the
|
|
70
|
+
* destroy hook has nothing to call — and everything the rest of `init()`
|
|
71
|
+
* starts (the rAF loop, the glitch timers, canvas listeners) would run for
|
|
72
|
+
* the life of the page. This flag lets the continuation bail out.
|
|
73
|
+
*/
|
|
74
|
+
private destroyed;
|
|
67
75
|
constructor();
|
|
68
76
|
private init;
|
|
69
77
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrFuzzyText, never>;
|