ngwr 14.1.0 → 14.3.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 +23 -22
- package/command-palette/styles/_index.scss +17 -0
- package/fesm2022/ngwr-breadcrumbs.mjs +2 -2
- package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
- package/fesm2022/ngwr-calendar.mjs +4 -2
- package/fesm2022/ngwr-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-cascader.mjs +2 -2
- package/fesm2022/ngwr-cascader.mjs.map +1 -1
- package/fesm2022/ngwr-command-palette.mjs +2 -2
- package/fesm2022/ngwr-command-palette.mjs.map +1 -1
- package/fesm2022/ngwr-drag-drop.mjs +2 -2
- package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
- package/fesm2022/ngwr-event-calendar.mjs +17 -5
- package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-form.mjs +30 -1
- package/fesm2022/ngwr-form.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ar.mjs +429 -0
- package/fesm2022/ngwr-i18n-ar.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-cs.mjs +399 -0
- package/fesm2022/ngwr-i18n-cs.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-de.mjs +418 -0
- package/fesm2022/ngwr-i18n-de.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-en.mjs +23 -0
- package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-es.mjs +399 -0
- package/fesm2022/ngwr-i18n-es.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-fr.mjs +423 -0
- package/fesm2022/ngwr-i18n-fr.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-he.mjs +422 -0
- package/fesm2022/ngwr-i18n-he.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-hi.mjs +399 -0
- package/fesm2022/ngwr-i18n-hi.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-id.mjs +399 -0
- package/fesm2022/ngwr-i18n-id.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-it.mjs +418 -0
- package/fesm2022/ngwr-i18n-it.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-ja.mjs +403 -0
- package/fesm2022/ngwr-i18n-ja.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-ko.mjs +411 -0
- package/fesm2022/ngwr-i18n-ko.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-nl.mjs +415 -0
- package/fesm2022/ngwr-i18n-nl.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-pl.mjs +425 -0
- package/fesm2022/ngwr-i18n-pl.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-pt.mjs +408 -0
- package/fesm2022/ngwr-i18n-pt.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-ru.mjs +11 -0
- package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-sv.mjs +399 -0
- package/fesm2022/ngwr-i18n-sv.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-tr.mjs +423 -0
- package/fesm2022/ngwr-i18n-tr.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-uk.mjs +420 -0
- package/fesm2022/ngwr-i18n-uk.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-vi.mjs +416 -0
- package/fesm2022/ngwr-i18n-vi.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-zh-TW.mjs +407 -0
- package/fesm2022/ngwr-i18n-zh-TW.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-zh.mjs +398 -0
- package/fesm2022/ngwr-i18n-zh.mjs.map +1 -0
- package/fesm2022/ngwr-lightbox.mjs +2 -2
- package/fesm2022/ngwr-lightbox.mjs.map +1 -1
- package/fesm2022/ngwr-line-chart.mjs +24 -4
- 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-pipes.mjs +75 -10
- package/fesm2022/ngwr-pipes.mjs.map +1 -1
- package/fesm2022/ngwr-schema-form.mjs +185 -0
- package/fesm2022/ngwr-schema-form.mjs.map +1 -0
- package/fesm2022/ngwr-select.mjs +2 -2
- package/fesm2022/ngwr-select.mjs.map +1 -1
- package/fesm2022/ngwr-validators.mjs +8 -1
- package/fesm2022/ngwr-validators.mjs.map +1 -1
- package/fesm2022/ngwr-version.mjs +1 -1
- package/fesm2022/ngwr-version.mjs.map +1 -1
- package/i18n/ar.json +389 -0
- package/i18n/cs.json +389 -0
- package/i18n/de.json +389 -0
- package/i18n/en.json +10 -2
- package/i18n/es.json +389 -0
- package/i18n/fr.json +389 -0
- package/i18n/he.json +389 -0
- package/i18n/hi.json +389 -0
- package/i18n/id.json +389 -0
- package/i18n/it.json +389 -0
- package/i18n/ja.json +389 -0
- package/i18n/ko.json +389 -0
- package/i18n/nl.json +389 -0
- package/i18n/pl.json +389 -0
- package/i18n/pt.json +389 -0
- package/i18n/ru.json +10 -2
- package/i18n/sv.json +389 -0
- package/i18n/tr.json +389 -0
- package/i18n/uk.json +389 -0
- package/i18n/vi.json +389 -0
- package/i18n/zh-TW.json +389 -0
- package/i18n/zh.json +389 -0
- package/llms-full.txt +87 -1
- package/llms.txt +1 -1
- package/package.json +89 -7
- package/schema-form/styles/_index.scss +15 -0
- package/schematics/migrations/v9/index.js +11 -3
- package/schematics/use/symbol-map.json +1 -0
- package/skills/ngwr/SKILL.md +1 -1
- package/skills/ngwr/references/catalog.md +21 -0
- package/styles.scss +1 -0
- package/theme/styles/_focus.scss +23 -2
- package/types/ngwr-calendar.d.ts +2 -0
- package/types/ngwr-command-palette.d.ts +1 -1
- package/types/ngwr-event-calendar.d.ts +5 -0
- package/types/ngwr-form.d.ts +88 -2
- package/types/ngwr-i18n-ar.d.ts +6 -0
- package/types/ngwr-i18n-cs.d.ts +6 -0
- package/types/ngwr-i18n-de.d.ts +6 -0
- package/types/ngwr-i18n-es.d.ts +6 -0
- package/types/ngwr-i18n-fr.d.ts +6 -0
- package/types/ngwr-i18n-he.d.ts +6 -0
- package/types/ngwr-i18n-hi.d.ts +6 -0
- package/types/ngwr-i18n-id.d.ts +6 -0
- package/types/ngwr-i18n-it.d.ts +6 -0
- package/types/ngwr-i18n-ja.d.ts +6 -0
- package/types/ngwr-i18n-ko.d.ts +6 -0
- package/types/ngwr-i18n-nl.d.ts +6 -0
- package/types/ngwr-i18n-pl.d.ts +6 -0
- package/types/ngwr-i18n-pt.d.ts +6 -0
- package/types/ngwr-i18n-sv.d.ts +6 -0
- package/types/ngwr-i18n-tr.d.ts +6 -0
- package/types/ngwr-i18n-uk.d.ts +6 -0
- package/types/ngwr-i18n-vi.d.ts +6 -0
- package/types/ngwr-i18n-zh-TW.d.ts +6 -0
- package/types/ngwr-i18n-zh.d.ts +6 -0
- package/types/ngwr-line-chart.d.ts +15 -0
- package/types/ngwr-pipes.d.ts +45 -4
- package/types/ngwr-schema-form.d.ts +90 -0
- package/types/ngwr-version.d.ts +1 -1
|
@@ -8,15 +8,23 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
/**
|
|
10
10
|
* Match `value` / `[value]` / `[(value)]` inside a `<wr-checkbox …>` open tag.
|
|
11
|
-
* `[^>]*?` stays inside the tag (it can't cross `>`), so the rename never
|
|
12
|
-
* escapes the element it's scoped to.
|
|
13
11
|
*
|
|
14
12
|
* The tag anchor is `(?![-\w])`, NOT `\b`: a word boundary still matches at
|
|
15
13
|
* `<wr-checkbox-group`, whose own `value` IS its form model (it is the group's
|
|
16
14
|
* `FormValueControl`) and must be left alone — renaming it would break every
|
|
17
15
|
* bound group.
|
|
16
|
+
*
|
|
17
|
+
* Quoted values are STEPPED OVER rather than excluded, and that is the half a
|
|
18
|
+
* plain `[^>]*?` got wrong for two majors: a `>` inside a binding expression
|
|
19
|
+
* looks like the end of the tag, so `<wr-checkbox [disabled]="n > 0" value="a">`
|
|
20
|
+
* kept its `value` while the same attributes in the other order moved. The
|
|
21
|
+
* leftover is SILENT — a static `value="a"` that matches no input is an ordinary
|
|
22
|
+
* DOM attribute, `strictTemplates` says nothing, and every checkbox in the group
|
|
23
|
+
* keeps the default identity `null`, so they all toggle together. That is the
|
|
24
|
+
* exact defect this migration exists to prevent, reintroduced by the migration
|
|
25
|
+
* itself. `migration-v14` fixed the same anchoring; this is that fix, ported.
|
|
18
26
|
*/
|
|
19
|
-
const CHECKBOX_TAG = String.raw `<wr-checkbox(?![-\w])[^>]*?\s`;
|
|
27
|
+
const CHECKBOX_TAG = String.raw `<wr-checkbox(?![-\w])(?:"[^"]*"|'[^']*'|[^>])*?\s`;
|
|
20
28
|
const HTML_TRANSFORMS = [
|
|
21
29
|
// <wr-checkbox … value="x"> → checkboxValue="x"
|
|
22
30
|
{ pattern: new RegExp(`(${CHECKBOX_TAG})value=`, 'g'), replacement: '$1checkboxValue=' },
|
package/skills/ngwr/SKILL.md
CHANGED
|
@@ -5,7 +5,7 @@ description: Build Angular UIs with the ngwr component library (standalone, sign
|
|
|
5
5
|
|
|
6
6
|
# ngwr
|
|
7
7
|
|
|
8
|
-
An Angular 22 UI library:
|
|
8
|
+
An Angular 22 UI library: 225 tree-shakable entry points, 112 of them shipping a selector.
|
|
9
9
|
Standalone, signals-first, zoneless, `ViewEncapsulation.None`. One runtime
|
|
10
10
|
dependency (`tslib`).
|
|
11
11
|
|
|
@@ -91,8 +91,28 @@ root barrel for components.
|
|
|
91
91
|
| `ngwr/gradient-text/testing` | `import { WrGradientTextHarness } from 'ngwr/gradient-text/testing'` | — |
|
|
92
92
|
| `ngwr/hotkey` | `import { WrHotkey } from 'ngwr/hotkey'` | `[wrHotkey]` |
|
|
93
93
|
| `ngwr/i18n` | `import { WrI18n } from 'ngwr/i18n'` | `[wrT]` |
|
|
94
|
+
| `ngwr/i18n/ar` | `import { wrAr } from 'ngwr/i18n/ar'` | — |
|
|
95
|
+
| `ngwr/i18n/cs` | `import { wrCs } from 'ngwr/i18n/cs'` | — |
|
|
96
|
+
| `ngwr/i18n/de` | `import { wrDe } from 'ngwr/i18n/de'` | — |
|
|
94
97
|
| `ngwr/i18n/en` | `import { wrEn } from 'ngwr/i18n/en'` | — |
|
|
98
|
+
| `ngwr/i18n/es` | `import { wrEs } from 'ngwr/i18n/es'` | — |
|
|
99
|
+
| `ngwr/i18n/fr` | `import { wrFr } from 'ngwr/i18n/fr'` | — |
|
|
100
|
+
| `ngwr/i18n/he` | `import { wrHe } from 'ngwr/i18n/he'` | — |
|
|
101
|
+
| `ngwr/i18n/hi` | `import { wrHi } from 'ngwr/i18n/hi'` | — |
|
|
102
|
+
| `ngwr/i18n/id` | `import { wrId } from 'ngwr/i18n/id'` | — |
|
|
103
|
+
| `ngwr/i18n/it` | `import { wrIt } from 'ngwr/i18n/it'` | — |
|
|
104
|
+
| `ngwr/i18n/ja` | `import { wrJa } from 'ngwr/i18n/ja'` | — |
|
|
105
|
+
| `ngwr/i18n/ko` | `import { wrKo } from 'ngwr/i18n/ko'` | — |
|
|
106
|
+
| `ngwr/i18n/nl` | `import { wrNl } from 'ngwr/i18n/nl'` | — |
|
|
107
|
+
| `ngwr/i18n/pl` | `import { wrPl } from 'ngwr/i18n/pl'` | — |
|
|
108
|
+
| `ngwr/i18n/pt` | `import { wrPt } from 'ngwr/i18n/pt'` | — |
|
|
95
109
|
| `ngwr/i18n/ru` | `import { wrRu } from 'ngwr/i18n/ru'` | — |
|
|
110
|
+
| `ngwr/i18n/sv` | `import { wrSv } from 'ngwr/i18n/sv'` | — |
|
|
111
|
+
| `ngwr/i18n/tr` | `import { wrTr } from 'ngwr/i18n/tr'` | — |
|
|
112
|
+
| `ngwr/i18n/uk` | `import { wrUk } from 'ngwr/i18n/uk'` | — |
|
|
113
|
+
| `ngwr/i18n/vi` | `import { wrVi } from 'ngwr/i18n/vi'` | — |
|
|
114
|
+
| `ngwr/i18n/zh` | `import { wrZh } from 'ngwr/i18n/zh'` | — |
|
|
115
|
+
| `ngwr/i18n/zh-TW` | `import { wrZhTw } from 'ngwr/i18n/zh-TW'` | — |
|
|
96
116
|
| `ngwr/icon` | `import { WrIcon } from 'ngwr/icon'` | `wr-icon` |
|
|
97
117
|
| `ngwr/icon/adapters/feather` | `import { feather } from 'ngwr/icon/adapters/feather'` | — |
|
|
98
118
|
| `ngwr/icon/adapters/lucide` | `import { lucide } from 'ngwr/icon/adapters/lucide'` | — |
|
|
@@ -145,6 +165,7 @@ root barrel for components.
|
|
|
145
165
|
| `ngwr/result` | `import { WrResult } from 'ngwr/result'` | `wr-result-404` `wr-result-403` `wr-result-500` `wr-result` |
|
|
146
166
|
| `ngwr/rotating-text` | `import { WrRotatingText } from 'ngwr/rotating-text'` | `wr-rotating-text` |
|
|
147
167
|
| `ngwr/rotating-text/testing` | `import { WrRotatingTextHarness } from 'ngwr/rotating-text/testing'` | — |
|
|
168
|
+
| `ngwr/schema-form` | `import { WrSchemaForm } from 'ngwr/schema-form'` | `wr-schema-form` |
|
|
148
169
|
| `ngwr/scroll` | `import { WrScroll } from 'ngwr/scroll'` | — |
|
|
149
170
|
| `ngwr/segmented` | `import { WrSegmented } from 'ngwr/segmented'` | `wr-segmented` |
|
|
150
171
|
| `ngwr/segmented/testing` | `import { WrSegmentedHarness } from 'ngwr/segmented/testing'` | — |
|
package/styles.scss
CHANGED
package/theme/styles/_focus.scss
CHANGED
|
@@ -83,11 +83,32 @@
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
// Command palette options
|
|
86
|
-
.wr-command-palette__option:focus-visible
|
|
87
|
-
.wr-command-palette__panel input:focus-visible {
|
|
86
|
+
.wr-command-palette__option:focus-visible {
|
|
88
87
|
@include focus-ring;
|
|
89
88
|
}
|
|
90
89
|
|
|
90
|
+
// The palette's search field gets NO ring, and this is the one place in the
|
|
91
|
+
// library that withholds one deliberately. The rule everywhere else — a
|
|
92
|
+
// component may inset the ring but must not cancel it — was written about
|
|
93
|
+
// `dropdown`, where focus ROVES between items and the ring is the only thing
|
|
94
|
+
// saying which one you are on. Nothing roves here.
|
|
95
|
+
//
|
|
96
|
+
// The palette autofocuses this field on open and focus never leaves it: the
|
|
97
|
+
// arrows move a highlight through `aria-activedescendant`, so the DOM's focused
|
|
98
|
+
// element is the input from the first frame to the last. An indicator that is
|
|
99
|
+
// on before the user has done anything, and that never moves afterwards,
|
|
100
|
+
// reports no state — it is a permanent blue box that reads as an error.
|
|
101
|
+
//
|
|
102
|
+
// What identifies focus here instead: the caret, which a text field draws on
|
|
103
|
+
// its own and which 2.4.7 accepts; the panel, which is modal and traps focus;
|
|
104
|
+
// and the placeholder plus the search icon, which say what the field is. Insetting
|
|
105
|
+
// was tried first and does not help — an outline on a full-bleed field traces
|
|
106
|
+
// the same rectangle two pixels in.
|
|
107
|
+
//
|
|
108
|
+
// If a future palette ever moves real focus between rows, that variant needs the
|
|
109
|
+
// ring back, and it should be scoped to the roving element rather than reinstated
|
|
110
|
+
// here.
|
|
111
|
+
|
|
91
112
|
// Mention option rows
|
|
92
113
|
.wr-mention-panel__option:focus-visible {
|
|
93
114
|
@include focus-ring;
|
package/types/ngwr-calendar.d.ts
CHANGED
|
@@ -91,6 +91,8 @@ declare class WrCalendar {
|
|
|
91
91
|
private readonly rovedChip;
|
|
92
92
|
private readonly prevMonthLabel;
|
|
93
93
|
private readonly nextMonthLabel;
|
|
94
|
+
protected readonly monthListLabel: _angular_core.Signal<string>;
|
|
95
|
+
protected readonly yearListLabel: _angular_core.Signal<string>;
|
|
94
96
|
private readonly prevYearLabel;
|
|
95
97
|
private readonly nextYearLabel;
|
|
96
98
|
private readonly prevYearsLabel;
|
|
@@ -215,7 +215,7 @@ declare class WrCommandPalette {
|
|
|
215
215
|
private revealActive;
|
|
216
216
|
private commit;
|
|
217
217
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrCommandPalette, never>;
|
|
218
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrCommandPalette, "wr-command-palette", never, { "paletteLabel": { "alias": "paletteLabel"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": false; "isSignal": true; }; "open": { "alias": "open"; "required": false; "isSignal": true; }; "trigger": { "alias": "trigger"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "emptyText": { "alias": "emptyText"; "required": false; "isSignal": true; }; "loadingText": { "alias": "loadingText"; "required": false; "isSignal": true; }; "closeOnPick": { "alias": "closeOnPick"; "required": false; "isSignal": true; }; "responsive": { "alias": "responsive"; "required": false; "isSignal": true; }; "query": { "alias": "query"; "required": false; "isSignal": true; }; "serverSearch": { "alias": "serverSearch"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "debounceMs": { "alias": "debounceMs"; "required": false; "isSignal": true; }; }, { "open": "openChange"; "picked": "picked"; "query": "queryChange"; "searchChange": "searchChange"; }, never,
|
|
218
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrCommandPalette, "wr-command-palette", never, { "paletteLabel": { "alias": "paletteLabel"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": false; "isSignal": true; }; "open": { "alias": "open"; "required": false; "isSignal": true; }; "trigger": { "alias": "trigger"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "emptyText": { "alias": "emptyText"; "required": false; "isSignal": true; }; "loadingText": { "alias": "loadingText"; "required": false; "isSignal": true; }; "closeOnPick": { "alias": "closeOnPick"; "required": false; "isSignal": true; }; "responsive": { "alias": "responsive"; "required": false; "isSignal": true; }; "query": { "alias": "query"; "required": false; "isSignal": true; }; "serverSearch": { "alias": "serverSearch"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "debounceMs": { "alias": "debounceMs"; "required": false; "isSignal": true; }; }, { "open": "openChange"; "picked": "picked"; "query": "queryChange"; "searchChange": "searchChange"; }, never, ["[wrCommandPaletteFooter]"], true, never>;
|
|
219
219
|
}
|
|
220
220
|
|
|
221
221
|
export { WrCommandPalette };
|
|
@@ -232,6 +232,11 @@ declare class WrEventCalendar {
|
|
|
232
232
|
protected readonly allDayLabel: _angular_core.Signal<string>;
|
|
233
233
|
protected readonly timeLabel: _angular_core.Signal<string>;
|
|
234
234
|
protected readonly moreLabel: (params?: ngwr_i18n.WrI18nParams) => string;
|
|
235
|
+
private readonly headerText;
|
|
236
|
+
private readonly rangeText;
|
|
237
|
+
private readonly chipLabelText;
|
|
238
|
+
private readonly slotLabelText;
|
|
239
|
+
private readonly allDayCellText;
|
|
235
240
|
private readonly monthLabel;
|
|
236
241
|
private readonly weekLabel;
|
|
237
242
|
private readonly dayLabel;
|
package/types/ngwr-form.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import * as _angular_core from '@angular/core';
|
|
|
2
2
|
import { InjectionToken, Signal, EnvironmentProviders } from '@angular/core';
|
|
3
3
|
import * as _angular_forms from '@angular/forms';
|
|
4
4
|
import { NgControl } from '@angular/forms';
|
|
5
|
+
import * as _angular_forms_signals from '@angular/forms/signals';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Wraps a label + control + error message into a single field row.
|
|
@@ -359,5 +360,90 @@ declare function provideWrFormErrors(messages?: WrFormErrorMessages): Environmen
|
|
|
359
360
|
*/
|
|
360
361
|
declare const WR_FORM_ERROR_FALLBACKS: WrFormErrorMessages;
|
|
361
362
|
|
|
362
|
-
|
|
363
|
-
|
|
363
|
+
/**
|
|
364
|
+
* @license
|
|
365
|
+
*
|
|
366
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
367
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
368
|
+
*/
|
|
369
|
+
/**
|
|
370
|
+
* How a field is DRAWN, attached to the same Signal Forms schema that already
|
|
371
|
+
* says how it is validated.
|
|
372
|
+
*
|
|
373
|
+
* The alternative was a second schema — one for rules, one for presentation —
|
|
374
|
+
* and it was rejected before it was written: two descriptions of one form drift
|
|
375
|
+
* the moment someone renames a field in one of them, and nothing would report
|
|
376
|
+
* it. Angular's `metadata()` takes a typed key and a `LogicFn`, so the
|
|
377
|
+
* presentation rides on the schema the validators are already in, and it is
|
|
378
|
+
* REACTIVE for free: a label, a set of options or a placeholder may depend on
|
|
379
|
+
* the value of another field.
|
|
380
|
+
*
|
|
381
|
+
* What this deliberately does NOT carry: `required`, `disabled`, `readonly`,
|
|
382
|
+
* `hidden`, `min`, `max`, and every validation rule. Those are Angular's own
|
|
383
|
+
* schema functions, they already drive the control through `[formField]`, and
|
|
384
|
+
* duplicating them here would create a second source of truth for state the form
|
|
385
|
+
* already owns. That is not only a judgement call — Angular REFUSES a `[min]` or
|
|
386
|
+
* `[required]` binding on a field-bound control (NG8022), so the second source
|
|
387
|
+
* of truth is a compile error rather than a drift.
|
|
388
|
+
*/
|
|
389
|
+
type WrFieldKind = 'input' | 'textarea' | 'number' | 'select' | 'checkbox' | 'switch' | 'radio' | 'date' | 'slider';
|
|
390
|
+
/** One choice, for the kinds that offer a list. */
|
|
391
|
+
interface WrFieldOption {
|
|
392
|
+
readonly value: unknown;
|
|
393
|
+
readonly label: string;
|
|
394
|
+
readonly disabled?: boolean;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* The presentation of one field.
|
|
398
|
+
*
|
|
399
|
+
* `kind` is the only required member: everything else has a sane default, and a
|
|
400
|
+
* schema that says no more than `{ kind: 'input' }` still renders a labelled,
|
|
401
|
+
* error-bound control — the label falls back to the field's own name.
|
|
402
|
+
*/
|
|
403
|
+
interface WrFieldSpec {
|
|
404
|
+
readonly kind: WrFieldKind;
|
|
405
|
+
/** Defaults to the field's key, de-camel-cased — `workEmail` becomes "Work email". */
|
|
406
|
+
readonly label?: string;
|
|
407
|
+
readonly placeholder?: string;
|
|
408
|
+
/** Help text under the control. Errors replace it while the field is invalid. */
|
|
409
|
+
readonly hint?: string;
|
|
410
|
+
/** For `select` and `radio`. Ignored by every other kind. */
|
|
411
|
+
readonly options?: readonly WrFieldOption[];
|
|
412
|
+
/** Native `type` for `kind: 'input'` — `email`, `password`, `url`, `tel`. */
|
|
413
|
+
readonly type?: string;
|
|
414
|
+
/**
|
|
415
|
+
* Granularity for `number` and `slider`. The BOUNDS are deliberately absent:
|
|
416
|
+
* Angular refuses a `[min]` or `[max]` binding on a `[formField]`-bound
|
|
417
|
+
* control outright (NG8022), because the field owns them — write `min(path.x,
|
|
418
|
+
* 18)` in the schema and the control picks it up. `step` is presentation, has
|
|
419
|
+
* no schema function, and stays here.
|
|
420
|
+
*/
|
|
421
|
+
readonly step?: number;
|
|
422
|
+
/**
|
|
423
|
+
* Columns this field spans in `<wr-schema-form>`'s grid. Clamped to the form's
|
|
424
|
+
* own `columns`, and 1 by default — a field is one cell unless it asks to be
|
|
425
|
+
* wider.
|
|
426
|
+
*/
|
|
427
|
+
readonly span?: number;
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* The metadata key `<wr-schema-form>` reads.
|
|
431
|
+
*
|
|
432
|
+
* ```ts
|
|
433
|
+
* const userSchema = schema<User>(path => {
|
|
434
|
+
* required(path.email);
|
|
435
|
+
* email(path.email);
|
|
436
|
+
* metadata(path.email, WR_FIELD, () => ({ kind: 'input', type: 'email', label: 'Work email' }));
|
|
437
|
+
* metadata(path.role, WR_FIELD, () => ({ kind: 'select', options: ROLES }));
|
|
438
|
+
* });
|
|
439
|
+
* ```
|
|
440
|
+
*
|
|
441
|
+
* A field with no `WR_FIELD` metadata is not an error and is not guessed at —
|
|
442
|
+
* `<wr-schema-form>` skips it, so a schema can describe more than one screen shows.
|
|
443
|
+
*/
|
|
444
|
+
declare const WR_FIELD: _angular_forms_signals.MetadataKey<_angular_core.Signal<WrFieldSpec | undefined>, WrFieldSpec, WrFieldSpec | undefined>;
|
|
445
|
+
/** `workEmail` -> `Work email`. The fallback label, and only ever a fallback. */
|
|
446
|
+
declare function wrFieldLabel(key: string): string;
|
|
447
|
+
|
|
448
|
+
export { WR_FIELD, WR_FORM_ERRORS, WR_FORM_ERROR_FALLBACKS, WR_FORM_FIELD, WrFormError, WrFormField, WrFormItem, provideWrFormErrors, useFormFieldAria, wrFieldLabel };
|
|
449
|
+
export type { WrFieldKind, WrFieldOption, WrFieldSpec, WrFormErrorContext, WrFormErrorMessage, WrFormErrorMessages, WrFormFieldAria, WrFormFieldContext };
|
|
@@ -32,6 +32,8 @@ declare class WrLineChart {
|
|
|
32
32
|
*/
|
|
33
33
|
readonly ariaLabel: _angular_core.InputSignal<string | null>;
|
|
34
34
|
protected readonly resolvedAriaLabel: _angular_core.Signal<string>;
|
|
35
|
+
private readonly locale;
|
|
36
|
+
private readonly thousandsText;
|
|
35
37
|
/** Labels for the X axis (one per data point). */
|
|
36
38
|
readonly xLabels: _angular_core.InputSignal<readonly string[]>;
|
|
37
39
|
/** Chart pixel height. @default 240 */
|
|
@@ -103,6 +105,19 @@ declare class WrLineChart {
|
|
|
103
105
|
protected readonly hoverLabel: _angular_core.Signal<string>;
|
|
104
106
|
protected onPointerMove(event: PointerEvent): void;
|
|
105
107
|
protected onPointerLeave(): void;
|
|
108
|
+
/**
|
|
109
|
+
* A Y-axis tick, in the reader's own language.
|
|
110
|
+
*
|
|
111
|
+
* Two halves and both were English. The `k` was a hardcoded Latin
|
|
112
|
+
* abbreviation — `тыс.` in Russian — so it goes through the catalog like every
|
|
113
|
+
* other word the library paints. The digits went through `toFixed`, which
|
|
114
|
+
* always writes a full stop, so a German axis read `1.5` where the rest of the
|
|
115
|
+
* page read `1,5`; they go through `Intl` now, the way `wrNumber`, `wrDate`
|
|
116
|
+
* and `wrPlural` already did.
|
|
117
|
+
*
|
|
118
|
+
* Grouping is OFF deliberately: a tick is a short axis label, and `5,000k`
|
|
119
|
+
* would be both wider and a change to what every existing chart draws.
|
|
120
|
+
*/
|
|
106
121
|
protected formatTick(v: number): string;
|
|
107
122
|
protected readonly viewBox: _angular_core.Signal<string>;
|
|
108
123
|
protected readonly hostEl: HTMLElement;
|
package/types/ngwr-pipes.d.ts
CHANGED
|
@@ -4,17 +4,58 @@ import { WrDateFormat } from 'ngwr/date';
|
|
|
4
4
|
import { SafeHtml } from '@angular/platform-browser';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Humanise a byte count using binary (1024-based) units.
|
|
7
|
+
* Humanise a byte count using binary (1024-based) units, in the reader's locale.
|
|
8
8
|
*
|
|
9
9
|
* @example
|
|
10
10
|
* ```html
|
|
11
|
-
* {{ 1234 | wrBytes }} <!-- "1.2
|
|
12
|
-
* {{ 1234567 | wrBytes: 0 }} <!-- "1 MB" -->
|
|
13
|
-
* {{ 0 | wrBytes }} <!-- "0 B" -->
|
|
11
|
+
* {{ 1234 | wrBytes }} <!-- en: "1.2 kB" de: "1,2 kB" ru: "1,2 кБ" -->
|
|
12
|
+
* {{ 1234567 | wrBytes: 0 }} <!-- en: "1 MB" fr: "1 Mo" -->
|
|
13
|
+
* {{ 0 | wrBytes }} <!-- en: "0 B" ru: "0 Б" -->
|
|
14
14
|
* ```
|
|
15
|
+
*
|
|
16
|
+
* **Both halves come from `Intl`, and the unit table is not the catalog's.** The
|
|
17
|
+
* number always did need `LOCALE_ID` — it went through `toFixed`, which writes a
|
|
18
|
+
* full stop in every language, so a German page read `1.2 KB` beside its own
|
|
19
|
+
* `1,2` everywhere else — and the three formatting pipes beside this one
|
|
20
|
+
* (`wrDate`, `wrNumber`, `wrPlural`) had injected it since they shipped.
|
|
21
|
+
*
|
|
22
|
+
* The unit could not follow them into `ngwr/i18n`, and the reason is the pipe
|
|
23
|
+
* rather than the strings: a PURE pipe is re-invoked only when its argument
|
|
24
|
+
* changes, so a catalog that lands after the first render — which is every
|
|
25
|
+
* `provideWrI18nHttpLoader` app — would never reach it, and the pipe would be
|
|
26
|
+
* correct under the static loader and silently English under the other one.
|
|
27
|
+
* `LOCALE_ID` is a constant, so `Intl` has no such failure mode, and it knows
|
|
28
|
+
* every locale ICU ships rather than the twenty-two this package translates.
|
|
29
|
+
*
|
|
30
|
+
* One visible change in English and it is the only one: `KB` became `kB`, which
|
|
31
|
+
* is what CLDR calls that unit. `B`, the space before it and every other
|
|
32
|
+
* magnitude read exactly as they did — see `format` for the part of that which
|
|
33
|
+
* is not free.
|
|
34
|
+
*
|
|
35
|
+
* The other consequence, kept here so nobody rediscovers it as a bug:
|
|
36
|
+
* `<wr-file-upload>` prints its own sizes from `fileUpload.unitKb` and friends,
|
|
37
|
+
* which are public catalog keys a consumer may have overridden, so it renders
|
|
38
|
+
* `KB` where this pipe renders `kB`. Retiring those keys would silently break
|
|
39
|
+
* every override that had been translating them, which is a major-version move.
|
|
15
40
|
*/
|
|
16
41
|
declare class WrBytes implements PipeTransform {
|
|
42
|
+
private readonly locale;
|
|
17
43
|
transform(value: number | string | null | undefined, decimals?: number): string;
|
|
44
|
+
/**
|
|
45
|
+
* `Intl`'s NARROW unit, with one space put back between it and the number.
|
|
46
|
+
*
|
|
47
|
+
* Neither display mode is right on its own. `short` spells the smallest unit
|
|
48
|
+
* as a word — "512 byte", "0 byte" in English, "0 Byte" in German — which is
|
|
49
|
+
* both worse copy than the `B` this pipe has always rendered and a bigger
|
|
50
|
+
* change than the fix is worth. `narrow` gives `B` / `Б` / `o` correctly and
|
|
51
|
+
* then closes the gap: "1.2kB".
|
|
52
|
+
*
|
|
53
|
+
* So the parts are reassembled rather than the string. Going through
|
|
54
|
+
* `formatToParts` is what keeps the ORDER the locale's own — Hebrew puts the
|
|
55
|
+
* unit first, and hand-joining `${n} ${unit}` would silently straighten every
|
|
56
|
+
* such locale into English order.
|
|
57
|
+
*/
|
|
58
|
+
private format;
|
|
18
59
|
static ɵfac: i0.ɵɵFactoryDeclaration<WrBytes, never>;
|
|
19
60
|
static ɵpipe: i0.ɵɵPipeDeclaration<WrBytes, "wrBytes", true>;
|
|
20
61
|
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
import { FieldTree, Field } from '@angular/forms/signals';
|
|
3
|
+
import { WrFieldSpec } from 'ngwr/form';
|
|
4
|
+
|
|
5
|
+
/** One field the template draws, resolved once per schema change. */
|
|
6
|
+
interface WrRenderedField {
|
|
7
|
+
readonly key: string;
|
|
8
|
+
readonly field: Field<never>;
|
|
9
|
+
readonly spec: WrFieldSpec;
|
|
10
|
+
/** `spec.label`, or the key de-camel-cased. */
|
|
11
|
+
readonly label: string;
|
|
12
|
+
/**
|
|
13
|
+
* The same text, or `''` for the two kinds that carry their own label inside
|
|
14
|
+
* the control. Resolved here rather than in the template: a method call in a
|
|
15
|
+
* template is re-run on every pass, and this is decided once per schema.
|
|
16
|
+
*/
|
|
17
|
+
readonly labelAbove: string;
|
|
18
|
+
/** `grid-column`, already clamped to the form's own `columns`. */
|
|
19
|
+
readonly column: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A form drawn from a Signal Forms schema — one `<wr-form-field>`, one control
|
|
23
|
+
* and one set of error messages per described field, laid out on a grid.
|
|
24
|
+
*
|
|
25
|
+
* The presentation rides on the SAME schema as the validation, through the
|
|
26
|
+
* `WR_FIELD` metadata key from `ngwr/form`:
|
|
27
|
+
*
|
|
28
|
+
* ```ts
|
|
29
|
+
* const profile = form(model, path => {
|
|
30
|
+
* required(path.email);
|
|
31
|
+
* email(path.email);
|
|
32
|
+
* metadata(path.email, WR_FIELD, () => ({ kind: 'input', type: 'email' }));
|
|
33
|
+
* metadata(path.role, WR_FIELD, () => ({ kind: 'select', options: ROLES }));
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
* ```html
|
|
37
|
+
* <wr-schema-form [field]="profile" [columns]="2" />
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* **A field with no `WR_FIELD` metadata is skipped**, silently and on purpose: a
|
|
41
|
+
* schema may describe more than one screen renders, and guessing a control from
|
|
42
|
+
* a field's type would draw a `wr-switch` for every boolean flag in the model.
|
|
43
|
+
* Order is the model's own key order.
|
|
44
|
+
*
|
|
45
|
+
* **`required`, `disabled`, `readonly` and `hidden` are NOT in the spec.** They
|
|
46
|
+
* are Angular's own schema functions, `[formField]` already applies the first
|
|
47
|
+
* three to the control, and this component reads `hidden()` to decide whether to
|
|
48
|
+
* draw the field at all — which Angular's docs say a template has to do itself.
|
|
49
|
+
* Re-declaring any of them here would be a second source of truth for state the
|
|
50
|
+
* form already owns.
|
|
51
|
+
*
|
|
52
|
+
* **Why its own entry point rather than `ngwr/form`.** Drawing nine kinds means
|
|
53
|
+
* depending on nine controls, and `ngwr/form` is the layout primitive every
|
|
54
|
+
* form imports — folding this in would put a date picker and a slider into the
|
|
55
|
+
* bundle of an app that only wanted `<wr-form-field>`.
|
|
56
|
+
*
|
|
57
|
+
* @see https://ngwr.dev/reference/components/schema-form
|
|
58
|
+
*/
|
|
59
|
+
declare class WrSchemaForm<T extends object> {
|
|
60
|
+
/**
|
|
61
|
+
* The form to draw — the value `form()` returned, or any object-valued field
|
|
62
|
+
* inside one.
|
|
63
|
+
*/
|
|
64
|
+
readonly field: _angular_core.InputSignal<FieldTree<T>>;
|
|
65
|
+
/**
|
|
66
|
+
* Grid columns. A field spans one of them unless its spec says otherwise.
|
|
67
|
+
* @default 1
|
|
68
|
+
*/
|
|
69
|
+
readonly columns: _angular_core.InputSignalWithTransform<number, unknown>;
|
|
70
|
+
/**
|
|
71
|
+
* The track list, written as a style rather than published as a
|
|
72
|
+
* `--wr-schema-form-columns` hook: `columns` always has a value, so the
|
|
73
|
+
* inline style would win over any declaration a consumer wrote and the hook
|
|
74
|
+
* would be one nobody could use.
|
|
75
|
+
*/
|
|
76
|
+
protected readonly template: _angular_core.Signal<string>;
|
|
77
|
+
/**
|
|
78
|
+
* The described fields, in the model's key order.
|
|
79
|
+
*
|
|
80
|
+
* A field tree over an object is iterable as `[key, field]` pairs, which is
|
|
81
|
+
* the whole reason this component needs no field list of its own. `isFieldTree`
|
|
82
|
+
* guards the pair: a model carrying a method or a non-field property would
|
|
83
|
+
* otherwise be read as a field and answer `undefined` to everything.
|
|
84
|
+
*/
|
|
85
|
+
protected readonly fields: _angular_core.Signal<readonly WrRenderedField[]>;
|
|
86
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<WrSchemaForm<any>, never>;
|
|
87
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<WrSchemaForm<any>, "wr-schema-form", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "columns": { "alias": "columns"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export { WrSchemaForm };
|
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. `'22.0.0'`), not ngwr's.
|
|
18
18
|
*/
|
|
19
|
-
declare const NGWR_VERSION = "14.
|
|
19
|
+
declare const NGWR_VERSION = "14.3.0";
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* @license
|