ngwr 14.5.0 → 14.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -3
- package/fesm2022/ngwr-i18n-en.mjs +16 -5
- package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
- package/fesm2022/ngwr-i18n.mjs +13 -0
- package/fesm2022/ngwr-i18n.mjs.map +1 -1
- package/fesm2022/ngwr-table.mjs +10 -2
- package/fesm2022/ngwr-table.mjs.map +1 -1
- package/fesm2022/ngwr-version.mjs +1 -1
- package/fesm2022/ngwr-version.mjs.map +1 -1
- package/llms-full.txt +1 -1
- package/llms.txt +12 -3
- package/mcp/providers.js +8 -2
- package/package.json +1 -1
- package/schematics/migrations/v14/index.js +90 -34
- package/schematics/migrations/v7/index.js +15 -4
- package/schematics/migrations/v8/index.js +13 -2
- package/schematics/migrations/v9/index.js +19 -10
- package/skills/ngwr/SKILL.md +9 -4
- package/skills/ngwr/references/setup.md +2 -2
- package/table/styles/_index.scss +39 -12
- package/types/ngwr-i18n-en.d.ts +16 -5
- package/types/ngwr-i18n.d.ts +13 -0
- package/types/ngwr-table.d.ts +8 -0
- package/types/ngwr-version.d.ts +1 -1
|
@@ -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
|
-
const NGWR_VERSION = '14.5.
|
|
19
|
+
const NGWR_VERSION = '14.5.1';
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* @license
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-version.mjs","sources":["../../../projects/lib/version/version.ts","../../../projects/lib/version/version.token.ts","../../../projects/lib/version/ngwr-version.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\n/**\n * The ngwr library version string, kept in sync with\n * `projects/lib/package.json` by `scripts/release-prepare.ts`.\n *\n * Prefer this over reading `package.json` at runtime — that requires a JSON\n * import or `require`, neither of which tree-shakes well in Angular builds.\n *\n * Distinct from `Version` exported by `@angular/core`, which reports the\n * loaded Angular runtime version (e.g. `'22.0.0'`), not ngwr's.\n */\nexport const NGWR_VERSION = '14.5.
|
|
1
|
+
{"version":3,"file":"ngwr-version.mjs","sources":["../../../projects/lib/version/version.ts","../../../projects/lib/version/version.token.ts","../../../projects/lib/version/ngwr-version.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\n/**\n * The ngwr library version string, kept in sync with\n * `projects/lib/package.json` by `scripts/release-prepare.ts`.\n *\n * Prefer this over reading `package.json` at runtime — that requires a JSON\n * import or `require`, neither of which tree-shakes well in Angular builds.\n *\n * Distinct from `Version` exported by `@angular/core`, which reports the\n * loaded Angular runtime version (e.g. `'22.0.0'`), not ngwr's.\n */\nexport const NGWR_VERSION = '14.5.1';\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { InjectionToken } from '@angular/core';\n\nimport { NGWR_VERSION } from './version';\n\n/**\n * Injection token holding the ngwr library version string.\n *\n * Default factory returns {@link NGWR_VERSION}. Override it in tests or in\n * apps that want to surface a custom build identifier.\n *\n * @example\n * ```ts\n * @Component({...})\n * export class FooterComponent {\n * readonly version = inject(NGWR_VERSION_TOKEN);\n * }\n * ```\n */\nexport const NGWR_VERSION_TOKEN = new InjectionToken<string>('NGWR_VERSION_TOKEN', {\n providedIn: 'root',\n factory: () => NGWR_VERSION,\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;AAAA;;;;;AAKG;AAEH;;;;;;;;;AASG;AACI,MAAM,YAAY,GAAG;;ACjB5B;;;;;AAKG;AAMH;;;;;;;;;;;;;AAaG;MACU,kBAAkB,GAAG,IAAI,cAAc,CAAS,oBAAoB,EAAE;AACjF,IAAA,UAAU,EAAE,MAAM;AAClB,IAAA,OAAO,EAAE,MAAM,YAAY;AAC5B,CAAA;;AC5BD;;AAEG;;;;"}
|
package/llms-full.txt
CHANGED
|
@@ -461,7 +461,7 @@
|
|
|
461
461
|
- import: `import { WrI18n } from 'ngwr/i18n'`
|
|
462
462
|
- selector: `[wrT]`
|
|
463
463
|
- exports: WrI18n, WrTPipe, WrTDirective, WR_I18N_CONFIG, DEFAULT_WR_I18N_CONFIG, WrI18nCatalog, WrI18nConfig, WrI18nConfigResolved, WrI18nParams, WrI18nMissingHandler, WR_I18N_LOADER, WrI18nLoader, WR_I18N_BASE_CATALOGS, WrI18nBaseCatalogs, WrI18nStaticLoader, WrI18nStaticCatalogs, WrI18nStaticScopedCatalogs, WrI18nHttpLoader, WrI18nHttpLoaderConfig, provideWrI18n, provideWrI18nBaseCatalogs, provideWrI18nStaticLoader, provideWrI18nHttpLoader, ProvideWrI18nOptions, useI18nText, readI18nText, useI18nFormatter
|
|
464
|
-
- Reactive i18n service. Active locale lives on a signal, catalogs load lazily through a swappable loader (HTTP or static), and double-brace placeholders interpolate at render time. Scopes let feature modules ship and load their own catalogs.
|
|
464
|
+
- Reactive i18n service. Active locale lives on a signal, catalogs load lazily through a swappable loader (HTTP or static), and double-brace placeholders interpolate at render time. Scopes let feature modules ship and load their own catalogs. Keep ngwr's own strings with `provideWrI18nBaseCatalogs` rather than spreading `wrEn` into your catalog: a spread is shallow, so any namespace you share with ngwr, e.g. `common`, `validation`, `table`, keeps only the side spread last, and the other side's keys stop resolving with nothing logged — ngwr's components fall back to English and a `wrT` read of a lost key renders the raw key.
|
|
465
465
|
|
|
466
466
|
## ngwr/i18n/ar
|
|
467
467
|
- import: `import { wrAr } from 'ngwr/i18n/ar'`
|
package/llms.txt
CHANGED
|
@@ -84,7 +84,12 @@ Add from their entry points as needed:
|
|
|
84
84
|
/ `select`, and `linkTarget` / `copyable` on `markdown`. There is deliberately no
|
|
85
85
|
`color` key — a bound `[color]="null"` means "no intent", which a default cannot
|
|
86
86
|
express without inventing a sentinel.
|
|
87
|
-
- `provideWrI18n(...)` + `
|
|
87
|
+
- `provideWrI18n(...)` + `provideWrI18nBaseCatalogs({ en: wrEn })` +
|
|
88
|
+
`provideWrI18nStaticLoader(...)` — localization. ngwr's catalogs go in as a
|
|
89
|
+
BASE, never spread into yours: a spread is shallow, so any namespace you share
|
|
90
|
+
with ngwr, e.g. `common`, `validation`, `table`, keeps only the side spread
|
|
91
|
+
last, and the other side's keys stop resolving with nothing logged — ngwr's
|
|
92
|
+
components fall back to English and a `wrT` read renders the raw key.
|
|
88
93
|
- `provideWrDateAdapter(...)` — calendar + date-picker (`ngwr/date/adapters/fns`
|
|
89
94
|
or `ngwr/date/adapters/luxon`).
|
|
90
95
|
|
|
@@ -106,8 +111,12 @@ one element at a time; a step whose target is missing is skipped, not floated.
|
|
|
106
111
|
|
|
107
112
|
## Upgrading to v14
|
|
108
113
|
|
|
109
|
-
Run `ng update ngwr@14
|
|
110
|
-
|
|
114
|
+
Run `ng update ngwr@14`, once, from whatever major the app is on — it runs every
|
|
115
|
+
migration between the installed version and 14, in order. Do not step through the
|
|
116
|
+
majors, and never target a 7.x, 8.x or 9.x release: their schematics die with
|
|
117
|
+
`exports is not defined in ES module scope`. It rewrites the renames and REPORTS
|
|
118
|
+
the rest — read its output, because the reported half is where the silent
|
|
119
|
+
failures are.
|
|
111
120
|
|
|
112
121
|
Rewritten for you (six renames, one word per concept):
|
|
113
122
|
|
package/mcp/providers.js
CHANGED
|
@@ -46,8 +46,14 @@ const REQUIRED_PROVIDERS = [
|
|
|
46
46
|
test: /^WrTPipe$|^WrTDirective$|^WrI18n/,
|
|
47
47
|
// Two entry points, and the comment has to say so: the catalog `wrEn` is
|
|
48
48
|
// `ngwr/i18n/en`, not `ngwr/i18n`, which exports neither catalog.
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
//
|
|
50
|
+
// `wrEn` goes in as a BASE and the loader carries only the app's keys. A
|
|
51
|
+
// loader serves only the catalog it is given, so the other way to keep both
|
|
52
|
+
// is a spread, and a spread is shallow: it silently drops one side of every
|
|
53
|
+
// namespace the two catalogs share. This line is what an agent pastes, so it
|
|
54
|
+
// has to be the form that survives the app adding its first `common` key.
|
|
55
|
+
provider: "provideWrI18n() + provideWrI18nBaseCatalogs({ en: wrEn }) + provideWrI18nStaticLoader({ en: { … } }) // from 'ngwr/i18n' + 'ngwr/i18n/en'",
|
|
56
|
+
why: "the pipe and directive read from a catalog you provide. Register ngwr's with `provideWrI18nBaseCatalogs`, never spread it into yours: a spread is shallow, so any namespace you share with ngwr, e.g. `common`, `validation`, `table`, keeps only the side spread last, and the other side's keys stop resolving with nothing logged — ngwr's components fall back to English and a `wrT` read of a lost key renders the raw key",
|
|
51
57
|
},
|
|
52
58
|
];
|
|
53
59
|
export { REQUIRED_PROVIDERS };
|
package/package.json
CHANGED
|
@@ -101,28 +101,57 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
101
101
|
* Both are now zero for an app that does not opt in.
|
|
102
102
|
*/
|
|
103
103
|
const IGNORE_DIRS = new Set(['node_modules', 'dist', '.git', '.cache', '.angular', 'coverage', '.next', '.nuxt']);
|
|
104
|
+
/**
|
|
105
|
+
* What an open tag may hold between its name and the attribute a rule is after:
|
|
106
|
+
* a quoted value, consumed only as a PAIR, or any one character that is neither
|
|
107
|
+
* a quote nor `>`. Every element-scoped rule and attribute detector in this file
|
|
108
|
+
* is built on it, and both halves of "only as a pair" were earned.
|
|
109
|
+
*
|
|
110
|
+
* Stepping OVER a quoted value is what a plain `[^>]*?` got wrong: a `>` inside a
|
|
111
|
+
* binding looks like the end of the tag, so
|
|
112
|
+
* `<wr-alert [type]="n > 0 ? 'a' : 'b'" closeable>` left `closeable` behind while
|
|
113
|
+
* the same attributes in the other order moved. The leftover is SILENT — a static
|
|
114
|
+
* `closeable` / `totalItems="42"` that matches no input is an ordinary DOM
|
|
115
|
+
* attribute and `strictTemplates` says nothing, so the alert quietly loses its
|
|
116
|
+
* dismiss button. (Bracketed forms are loud: NG8002.)
|
|
117
|
+
*
|
|
118
|
+
* Never consuming a LONE quote is what the first fix got wrong. It spelled the
|
|
119
|
+
* fallback `[^>]`, which matches a quote as well, so the engine could backtrack
|
|
120
|
+
* into a single-quoted span that STARTS at the apostrophe inside `title="it's"`
|
|
121
|
+
* and runs past `/>` into the following element: `<wr-alert title="it's" />`
|
|
122
|
+
* then `<app-panel [label]="'x'" closeable />` renamed the PANEL's attribute. The
|
|
123
|
+
* same overlap made a miss exponential — one `<wr-alert>` holding twenty-two
|
|
124
|
+
* quoted attributes and nothing to rename took sixteen seconds in the bare
|
|
125
|
+
* `closeable` rule alone, where this form takes under a millisecond. And a miss
|
|
126
|
+
* did not stay inside its tag: since a pair may contain `>`, a pairing that
|
|
127
|
+
* started at a CLOSING quote jumped over `/>` into later elements, so an
|
|
128
|
+
* ordinary element without the attribute sent the search across the rest of the
|
|
129
|
+
* file. On a 64-line template that never finished, and because `ng update`
|
|
130
|
+
* commits each migration's tree separately, v12 and v13 landed while this one
|
|
131
|
+
* wrote nothing. The spec's timing cases are sized to fail in seconds on that form.
|
|
132
|
+
*
|
|
133
|
+
* What it guarantees: a match cannot leave the open tag it started in, as long as
|
|
134
|
+
* every quote in that tag opens or closes an attribute value. The one markup that
|
|
135
|
+
* breaks the condition is an UNQUOTED value holding a quote (`title=it's`), and a
|
|
136
|
+
* tag like that is skipped rather than guessed at — which costs nothing real,
|
|
137
|
+
* because Angular's own template parser refuses it (`Opening tag "input" not
|
|
138
|
+
* terminated.`).
|
|
139
|
+
*/
|
|
140
|
+
const IN_TAG = String.raw `(?:"[^"]*"|'[^']*'|[^>"'])*?`;
|
|
104
141
|
/**
|
|
105
142
|
* An open tag, up to and including the whitespace before some attribute.
|
|
106
|
-
* `[^>]*?` cannot cross a `>`, so a rename can never escape the element it is
|
|
107
|
-
* scoped to, however the tag wraps across lines.
|
|
108
143
|
*
|
|
109
144
|
* The anchor is `(?![-\w])` and NOT `\b`: a word boundary still matches at the
|
|
110
145
|
* front of a longer element name, which is how a v9-shaped rule would have
|
|
111
146
|
* renamed an attribute on `<wr-table-filter>` while claiming to touch only
|
|
112
147
|
* `<wr-table>`. Every one of these four has such a neighbour — `wr-table-filter`
|
|
113
148
|
* and `wr-table-sort`, `wr-window-container` and `wr-window-taskbar` — or would
|
|
114
|
-
* acquire one the moment the catalog grows.
|
|
115
|
-
*
|
|
116
|
-
* Quoted values are stepped over rather than excluded, and that is the half a
|
|
117
|
-
* plain `[^>]*?` gets wrong: a `>` inside a binding expression looks like the end
|
|
118
|
-
* of the tag, so `<wr-alert [type]="n > 0 ? 'a' : 'b'" closeable>` left
|
|
119
|
-
* `closeable` behind while the same attributes in the other order moved. The
|
|
120
|
-
* leftover is SILENT — a static `closeable` / `totalItems="42"` that matches no
|
|
121
|
-
* input is an ordinary DOM attribute and `strictTemplates` says nothing, so the
|
|
122
|
-
* alert quietly loses its dismiss button. (Bracketed forms are loud: NG8002.)
|
|
123
|
-
* `migration-v9` carries the same anchoring and the same hole.
|
|
149
|
+
* acquire one the moment the catalog grows. `migration-v9` carries the same
|
|
150
|
+
* anchoring and the same pattern.
|
|
124
151
|
*/
|
|
125
|
-
const openTag = (name) => String.raw `<${name}(?![-\w])
|
|
152
|
+
const openTag = (name) => String.raw `<${name}(?![-\w])${IN_TAG}\s`;
|
|
153
|
+
/** The two elements `[wrInput]` applies to — its selector is `input[wrInput], textarea[wrInput]`. */
|
|
154
|
+
const FIELD = String.raw `<(?:input|textarea)(?![-\w])`;
|
|
126
155
|
const ALERT = openTag('wr-alert');
|
|
127
156
|
const TABLE = openTag('wr-table');
|
|
128
157
|
const PAGER = openTag('wr-pagination');
|
|
@@ -143,21 +172,15 @@ const HTML_TRANSFORMS = [
|
|
|
143
172
|
// native attribute, so rewriting one that was never ngwr's silently rebinds a
|
|
144
173
|
// character-width hint. The two orders are both real markup, hence two rules.
|
|
145
174
|
{
|
|
146
|
-
pattern:
|
|
175
|
+
pattern: new RegExp(String.raw `(${FIELD}${IN_TAG}\swrInput${IN_TAG}\s)\[wrSize\]`, 'g'),
|
|
147
176
|
replacement: '$1[size]',
|
|
148
177
|
},
|
|
178
|
+
{ pattern: new RegExp(String.raw `(${FIELD}${IN_TAG}\swrInput${IN_TAG}\s)wrSize=`, 'g'), replacement: '$1size=' },
|
|
149
179
|
{
|
|
150
|
-
pattern:
|
|
151
|
-
replacement: '$1size=',
|
|
152
|
-
},
|
|
153
|
-
{
|
|
154
|
-
pattern: /(<(?:input|textarea)(?![-\w])(?:"[^"]*"|'[^']*'|[^>])*?\s)\[wrSize\]((?:"[^"]*"|'[^']*'|[^>])*?\swrInput)/g,
|
|
180
|
+
pattern: new RegExp(String.raw `(${FIELD}${IN_TAG}\s)\[wrSize\](${IN_TAG}\swrInput)`, 'g'),
|
|
155
181
|
replacement: '$1[size]$2',
|
|
156
182
|
},
|
|
157
|
-
{
|
|
158
|
-
pattern: /(<(?:input|textarea)(?![-\w])(?:"[^"]*"|'[^']*'|[^>])*?\s)wrSize=((?:"[^"]*"|'[^']*'|[^>])*?\swrInput)/g,
|
|
159
|
-
replacement: '$1size=$2',
|
|
160
|
-
},
|
|
183
|
+
{ pattern: new RegExp(String.raw `(${FIELD}${IN_TAG}\s)wrSize=(${IN_TAG}\swrInput)`, 'g'), replacement: '$1size=$2' },
|
|
161
184
|
// <wr-table>, from [totalItems] to [total]
|
|
162
185
|
{ pattern: new RegExp(`(${TABLE})\\[totalItems\\]`, 'g'), replacement: '$1[total]' },
|
|
163
186
|
{ pattern: new RegExp(`(${TABLE})totalItems=`, 'g'), replacement: '$1total=' },
|
|
@@ -202,8 +225,12 @@ const GLOBAL_TRANSFORMS = [
|
|
|
202
225
|
// keyed on it stops matching with no error — CSS does not have one.
|
|
203
226
|
{ pattern: /\bwr-window--chrome-normal\b/g, replacement: 'wr-window--chrome-md' },
|
|
204
227
|
];
|
|
205
|
-
/**
|
|
206
|
-
|
|
228
|
+
/**
|
|
229
|
+
* `<wr-tab …>` carrying a `routerLink`, however the tag is wrapped across lines
|
|
230
|
+
* and whatever an earlier binding compares — the plain `[^>]*` this used to be
|
|
231
|
+
* read `[disabled]="n > 0"` as the end of the tag and reported nothing.
|
|
232
|
+
*/
|
|
233
|
+
const ROUTER_TAB = new RegExp(String.raw `<wr-tab(?![-\w])${IN_TAG}\brouterLink\b`);
|
|
207
234
|
const LOADING_BAR = /<wr-loading-bar\b/;
|
|
208
235
|
/** `provideWrDateAdapter(` with no `locale:` before the call closes. */
|
|
209
236
|
// `locale` as a key OR as shorthand, and the scan for it runs to the call's own
|
|
@@ -217,8 +244,20 @@ const DATE_ADAPTER_NO_LOCALE = /\bprovideWrDateAdapter\(\s*(?:\)|\{(?![\s\S]*?\b
|
|
|
217
244
|
/** `provideWrI18n(` with no `defaultLocale:` before the call closes. */
|
|
218
245
|
const I18N_NO_DEFAULT_LOCALE = /\bprovideWrI18n\(\s*(?:\)|\{(?![^})]*\bdefaultLocale\s*:))/;
|
|
219
246
|
const DEFAULT_CONFIG = /\bDEFAULT_WR_I18N_CONFIG\b/;
|
|
220
|
-
/** `ofLabel` on a pagination tag, bound (`[ofLabel]`) or static. */
|
|
221
|
-
const OF_LABEL =
|
|
247
|
+
/** `ofLabel` on a pagination tag, bound (`[ofLabel]`) or static, wherever it sits in the tag. */
|
|
248
|
+
const OF_LABEL = new RegExp(String.raw `${PAGER}\[?ofLabel\]?\s*=`);
|
|
249
|
+
/**
|
|
250
|
+
* `wrSize` still on a `[wrInput]` field AFTER the renames ran, in either
|
|
251
|
+
* attribute order and with any spacing around `=`. The renames read `wrSize=` and
|
|
252
|
+
* `[wrSize]` exactly, and whatever they do not move is silent: a static `wrSize`
|
|
253
|
+
* matches no input, lands on the field as a plain DOM attribute, and the control
|
|
254
|
+
* renders at its default size. So this is the one detector that reads the
|
|
255
|
+
* REWRITTEN text — its whole job is what the rules left behind.
|
|
256
|
+
*/
|
|
257
|
+
const LEFTOVER_WR_SIZE = [
|
|
258
|
+
new RegExp(String.raw `${FIELD}${IN_TAG}\swrInput${IN_TAG}\s\[?wrSize\]?\s*=`),
|
|
259
|
+
new RegExp(String.raw `${FIELD}${IN_TAG}\s\[?wrSize\]?\s*=${IN_TAG}\swrInput`),
|
|
260
|
+
];
|
|
222
261
|
// The half `OF_LABEL` cannot see. Apps that never bound the input still
|
|
223
262
|
// translated the key, and `pagination.of` is gone: the range is one
|
|
224
263
|
// `pagination.range` template now, so a catalog that defines the old key loses
|
|
@@ -285,6 +324,7 @@ function ngUpdateV14() {
|
|
|
285
324
|
const defaultConfigs = [];
|
|
286
325
|
const ofLabels = [];
|
|
287
326
|
const staleCatalogs = [];
|
|
327
|
+
const leftoverSizes = [];
|
|
288
328
|
let rewritten = 0;
|
|
289
329
|
visit(tree, '/', filePath => {
|
|
290
330
|
const lower = filePath.toLowerCase();
|
|
@@ -295,10 +335,11 @@ function ngUpdateV14() {
|
|
|
295
335
|
// reach stylesheets too, because one of them is a BEM class.
|
|
296
336
|
if (!isTs && !isHtml && !isStyle && !lower.endsWith('.json'))
|
|
297
337
|
return;
|
|
298
|
-
// Read ONCE. Every detector below
|
|
299
|
-
//
|
|
300
|
-
//
|
|
301
|
-
//
|
|
338
|
+
// Read ONCE. Every detector below but the leftover `wrSize` check then
|
|
339
|
+
// answers about the file the user wrote, not about the file a transform
|
|
340
|
+
// left behind — none of the six renames touches a token those detectors
|
|
341
|
+
// report today, and relying on that is exactly the coupling that breaks
|
|
342
|
+
// the next time one is added.
|
|
302
343
|
const content = tree.readText(filePath);
|
|
303
344
|
if (isTs || isHtml || isStyle) {
|
|
304
345
|
const next = apply(content, [
|
|
@@ -310,6 +351,11 @@ function ngUpdateV14() {
|
|
|
310
351
|
tree.overwrite(filePath, next);
|
|
311
352
|
rewritten += 1;
|
|
312
353
|
}
|
|
354
|
+
// The one detector that reads what the renames LEFT rather than what the
|
|
355
|
+
// user wrote: a `wrSize` surviving them is exactly what it exists to name.
|
|
356
|
+
if ((isTs || isHtml) && LEFTOVER_WR_SIZE.some(pattern => pattern.test(next))) {
|
|
357
|
+
leftoverSizes.push(filePath);
|
|
358
|
+
}
|
|
313
359
|
}
|
|
314
360
|
if (ROUTER_TAB.test(content))
|
|
315
361
|
routerTabs.push(filePath);
|
|
@@ -333,10 +379,19 @@ function ngUpdateV14() {
|
|
|
333
379
|
context.logger.info(`ngwr v14 migration: rewrote ${rewritten} file(s) for the renames: on <wr-alert> from ` +
|
|
334
380
|
'closeable to closable, on <wr-table> from totalItems to total, on <wr-pagination> from ' +
|
|
335
381
|
'currentPage to page (and from currentPageChange to pageChange), from isDisabledWhenLoading ' +
|
|
336
|
-
'to disabledWhenLoading,
|
|
337
|
-
'(class .wr-window--chrome-compact to --chrome-sm)
|
|
382
|
+
'to disabledWhenLoading, the window chromeSize scale from compact/normal to sm/md ' +
|
|
383
|
+
'(class .wr-window--chrome-compact to --chrome-sm), and on [wrInput] from wrSize to size ' +
|
|
384
|
+
'(and from [wrSize] to [size]).');
|
|
338
385
|
context.logger.info('Verify the result with `git diff` — a few edge cases may need manual touch-up.');
|
|
339
386
|
}
|
|
387
|
+
if (leftoverSizes.length > 0) {
|
|
388
|
+
context.logger.warn(`ngwr v14: \`wrSize\` is still on a [wrInput] field in ${leftoverSizes.length} file(s), in a spelling ` +
|
|
389
|
+
"the rename did not match. [wrInput]'s input has been `size` since v14, so a static wrSize is " +
|
|
390
|
+
'ignored — it lands as a plain DOM attribute and the field renders at its default size, with ' +
|
|
391
|
+
'nothing said — and a bound [wrSize] fails to compile (NG8002). Rename it to `size` by hand.');
|
|
392
|
+
for (const file of leftoverSizes)
|
|
393
|
+
context.logger.warn(` ${file}`);
|
|
394
|
+
}
|
|
340
395
|
if (staleCatalogs.length > 0) {
|
|
341
396
|
context.logger.warn(`ngwr v14: a translated \`pagination.of\` found in ${staleCatalogs.length} file(s). The range is ` +
|
|
342
397
|
'one template now — replace it with `pagination.range` ("{{from}}–{{to}} of {{total}}") and ' +
|
|
@@ -399,7 +454,8 @@ function ngUpdateV14() {
|
|
|
399
454
|
i18nProviders.length === 0 &&
|
|
400
455
|
defaultConfigs.length === 0 &&
|
|
401
456
|
ofLabels.length === 0 &&
|
|
402
|
-
staleCatalogs.length === 0
|
|
457
|
+
staleCatalogs.length === 0 &&
|
|
458
|
+
leftoverSizes.length === 0) {
|
|
403
459
|
context.logger.info('ngwr v14 migration: nothing to do — no affected usage found.');
|
|
404
460
|
}
|
|
405
461
|
return tree;
|
|
@@ -6,6 +6,17 @@
|
|
|
6
6
|
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
/**
|
|
10
|
+
* What an open tag may hold before the attribute a rule is after. A quoted value
|
|
11
|
+
* is consumed only as a PAIR: the plain `[^>]*?` this replaced read a `>` inside
|
|
12
|
+
* a binding as the end of the tag, so
|
|
13
|
+
* `<wr-select [placeholder]="n > 0 ? 'a' : 'b'" multi>` kept its `multi` while the
|
|
14
|
+
* same attributes in the other order moved — and a lone quote is never consumed,
|
|
15
|
+
* so a rule cannot slide through an apostrophe in one element's value into the
|
|
16
|
+
* next element. `migration-v14`'s `IN_TAG` carries the full account, including
|
|
17
|
+
* the one shape this skips: an UNQUOTED value holding a quote (`title=it's`).
|
|
18
|
+
*/
|
|
19
|
+
const IN_TAG = String.raw `(?:"[^"]*"|'[^']*'|[^>"'])*?`;
|
|
9
20
|
const HTML_TRANSFORMS = [
|
|
10
21
|
// wr-autocomplete → wr-select mode="search"
|
|
11
22
|
{ pattern: /<wr-autocomplete(\s|>|\/)/g, replacement: '<wr-select mode="search"$1' },
|
|
@@ -35,9 +46,9 @@ const HTML_TRANSFORMS = [
|
|
|
35
46
|
{ pattern: /<wr-count-up-text(\s|>|\/)/g, replacement: '<wr-count-up$1' },
|
|
36
47
|
{ pattern: /<\/wr-count-up-text>/g, replacement: '</wr-count-up>' },
|
|
37
48
|
// wr-select's deprecated [multi] alias → mode="multi"
|
|
38
|
-
{ pattern:
|
|
39
|
-
{ pattern:
|
|
40
|
-
{ pattern:
|
|
49
|
+
{ pattern: new RegExp(String.raw `(<wr-select\b${IN_TAG})\s\[multi\]="true"`, 'g'), replacement: '$1 mode="multi"' },
|
|
50
|
+
{ pattern: new RegExp(String.raw `(<wr-select\b${IN_TAG})\s\[multi\]="false"`, 'g'), replacement: '$1' },
|
|
51
|
+
{ pattern: new RegExp(String.raw `(<wr-select\b${IN_TAG})\smulti(?=[\s>/])`, 'g'), replacement: '$1 mode="multi"' },
|
|
41
52
|
// wr-image → wr-lightbox (rename — same surface)
|
|
42
53
|
{ pattern: /<wr-image(\s|>|\/)/g, replacement: '<wr-lightbox$1' },
|
|
43
54
|
{ pattern: /<\/wr-image>/g, replacement: '</wr-lightbox>' },
|
|
@@ -46,7 +57,7 @@ const HTML_TRANSFORMS = [
|
|
|
46
57
|
// attribute form (`<h1 wr-animated-text …>`) has no 1:1 target and is
|
|
47
58
|
// left for manual migration; a bound `[mode]` falls back to typewriter.
|
|
48
59
|
{
|
|
49
|
-
pattern:
|
|
60
|
+
pattern: new RegExp(String.raw `<wr-animated-text\b(${IN_TAG})\s*(\/>|>\s*<\/wr-animated-text>)`, 'g'),
|
|
50
61
|
replacement: (_match, attrs) => {
|
|
51
62
|
const mode = /\bmode\s*=\s*"(\w+)"/.exec(attrs)?.[1] ?? 'typewriter';
|
|
52
63
|
const tag = mode === 'split' ? 'wr-split-text' : mode === 'scramble' ? 'wr-decrypt-text' : 'wr-typewriter';
|
|
@@ -12,6 +12,17 @@ const DENSITY_MAP = [
|
|
|
12
12
|
['default', 'md'],
|
|
13
13
|
['comfortable', 'lg'],
|
|
14
14
|
];
|
|
15
|
+
/**
|
|
16
|
+
* What an open tag may hold before the attribute a rule is after. A quoted value
|
|
17
|
+
* is consumed only as a PAIR: the plain `[^>]*?` this replaced read a `>` inside
|
|
18
|
+
* a binding as the end of the tag, so `<wr-pagination [disabled]="n > 0" size="xs" />`
|
|
19
|
+
* kept its `xs` while the same attributes in the other order moved — and a lone
|
|
20
|
+
* quote is never consumed, so a rule cannot slide through an apostrophe in one
|
|
21
|
+
* element's value into the next element. `migration-v14`'s `IN_TAG` carries the
|
|
22
|
+
* full account, including the one shape this skips: an UNQUOTED value holding a
|
|
23
|
+
* quote (`title=it's`).
|
|
24
|
+
*/
|
|
25
|
+
const IN_TAG = String.raw `(?:"[^"]*"|'[^']*'|[^>"'])*?`;
|
|
15
26
|
const HTML_TRANSFORMS = [
|
|
16
27
|
// density — directive attribute, string form: wrDensity="compact" → "sm"
|
|
17
28
|
...DENSITY_MAP.map(([from, to]) => ({
|
|
@@ -29,8 +40,8 @@ const HTML_TRANSFORMS = [
|
|
|
29
40
|
replacement: `$1${to}$2`,
|
|
30
41
|
})),
|
|
31
42
|
// pagination size — scoped to the element so other `size="xs"` attrs are untouched
|
|
32
|
-
{ pattern:
|
|
33
|
-
{ pattern:
|
|
43
|
+
{ pattern: new RegExp(String.raw `(<wr-pagination\b${IN_TAG}\ssize=")xs(")`, 'g'), replacement: '$1sm$2' },
|
|
44
|
+
{ pattern: new RegExp(String.raw `(<wr-pagination\b${IN_TAG}\ssize=")xl(")`, 'g'), replacement: '$1lg$2' },
|
|
34
45
|
];
|
|
35
46
|
const TS_TRANSFORMS = [
|
|
36
47
|
// density — provideWrDensity({ defaultDensity: 'compact' }) → 'sm'
|
|
@@ -14,17 +14,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
14
14
|
* `FormValueControl`) and must be left alone — renaming it would break every
|
|
15
15
|
* bound group.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
* plain `[^>]*?` got wrong for two majors: a `>`
|
|
19
|
-
* looks like the end of the tag, so
|
|
20
|
-
* kept its `value` while the same
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
17
|
+
* A quoted value is consumed only as a PAIR, and both halves of that matter.
|
|
18
|
+
* Stepping OVER it is what a plain `[^>]*?` got wrong for two majors: a `>`
|
|
19
|
+
* inside a binding expression looks like the end of the tag, so
|
|
20
|
+
* `<wr-checkbox [disabled]="n > 0" value="a">` kept its `value` while the same
|
|
21
|
+
* attributes in the other order moved. The leftover is SILENT — a static
|
|
22
|
+
* `value="a"` that matches no input is an ordinary DOM attribute,
|
|
23
|
+
* `strictTemplates` says nothing, and every checkbox in the group keeps the
|
|
24
|
+
* default identity `null`, so they all toggle together. That is the exact defect
|
|
25
|
+
* this migration exists to prevent, reintroduced by the migration itself.
|
|
26
|
+
*
|
|
27
|
+
* Never consuming a LONE quote is the half the first fix missed. It spelled the
|
|
28
|
+
* fallback `[^>]`, which matches a quote too, so the engine could backtrack into
|
|
29
|
+
* a single-quoted span starting at the apostrophe of `label="it's"` and running
|
|
30
|
+
* past `/>` into the next element: `<wr-checkbox label="it's" />` followed by
|
|
31
|
+
* `<wr-select [x]="'y'" value="z" />` renamed the SELECT's form model. Now a rename
|
|
32
|
+
* stays inside one open tag whenever every quote in it opens or closes a value;
|
|
33
|
+
* an UNQUOTED value holding a quote (`title=it's`) breaks that, and is skipped.
|
|
34
|
+
* `migration-v14`'s `IN_TAG` carries the same pattern and the longer account.
|
|
26
35
|
*/
|
|
27
|
-
const CHECKBOX_TAG = String.raw `<wr-checkbox(?![-\w])(?:"[^"]*"|'[^']*'|[^>])*?\s`;
|
|
36
|
+
const CHECKBOX_TAG = String.raw `<wr-checkbox(?![-\w])(?:"[^"]*"|'[^']*'|[^>"'])*?\s`;
|
|
28
37
|
const HTML_TRANSFORMS = [
|
|
29
38
|
// <wr-checkbox … value="x"> → checkboxValue="x"
|
|
30
39
|
{ pattern: new RegExp(`(${CHECKBOX_TAG})value=`, 'g'), replacement: '$1checkboxValue=' },
|
package/skills/ngwr/SKILL.md
CHANGED
|
@@ -44,8 +44,13 @@ guess gets backwards.
|
|
|
44
44
|
- **There is no `ControlValueAccessor`.** Value components implement Signal
|
|
45
45
|
Forms' `FormValueControl` / `FormCheckboxControl`. Bind
|
|
46
46
|
`[formField]="form.x"`, or use the two-way model standalone —
|
|
47
|
-
`[(value)]`, `[(checked)]`. `[(ngModel)]` and reactive forms still
|
|
48
|
-
Angular
|
|
47
|
+
`[(value)]`, `[(checked)]`. `[(ngModel)]` and reactive forms still bind,
|
|
48
|
+
with no accessor created: Angular's `NgModel` / `FormControlDirective` drive
|
|
49
|
+
the `value` or `checked` model directly. That bridge does NOT apply template
|
|
50
|
+
validator directives — `required`, `minlength`, `maxlength`, `pattern` or
|
|
51
|
+
`email` on an ngwr control is silently ignored and the form submits — so put
|
|
52
|
+
validators on the `FormControl`. It also ignores `updateOn`, and a
|
|
53
|
+
`{ emitEvent: false }` write needs `markForCheck()`.
|
|
49
54
|
- **`<wr-checkbox>` group identity is `checkboxValue`, not `value`.**
|
|
50
55
|
`value` is reserved for the form value, so a leftover `value="x"` lands on the
|
|
51
56
|
host as a plain DOM attribute, every box in the group keeps the default
|
|
@@ -95,8 +100,8 @@ cause.
|
|
|
95
100
|
- `provideWrLoadingBarRouter() // from 'ngwr/loading-bar/router'`
|
|
96
101
|
— without it the bar never responds to navigation; it only moves for manual start() / complete()
|
|
97
102
|
— needed by: `WrLoadingBar`
|
|
98
|
-
- `provideWrI18n() +
|
|
99
|
-
— the pipe and directive read from a catalog you provide
|
|
103
|
+
- `provideWrI18n() + provideWrI18nBaseCatalogs({ en: wrEn }) + provideWrI18nStaticLoader({ en: { … } }) // from 'ngwr/i18n' + 'ngwr/i18n/en'`
|
|
104
|
+
— the pipe and directive read from a catalog you provide. Register ngwr's with `provideWrI18nBaseCatalogs`, never spread it into yours: a spread is shallow, so any namespace you share with ngwr, e.g. `common`, `validation`, `table`, keeps only the side spread last, and the other side's keys stop resolving with nothing logged — ngwr's components fall back to English and a `wrT` read of a lost key renders the raw key
|
|
100
105
|
— needed by: `WrTPipe`, `WrTDirective`, `WrI18n`
|
|
101
106
|
|
|
102
107
|
## Testing
|
|
@@ -60,9 +60,9 @@ Every date mode goes through an adapter; there is no built-in default. Needed by
|
|
|
60
60
|
|
|
61
61
|
Without it the bar never responds to navigation; it only moves for manual start() / complete(). Needed by `WrLoadingBar`.
|
|
62
62
|
|
|
63
|
-
### `provideWrI18n() +
|
|
63
|
+
### `provideWrI18n() + provideWrI18nBaseCatalogs({ en: wrEn }) + provideWrI18nStaticLoader({ en: { … } }) // from 'ngwr/i18n' + 'ngwr/i18n/en'`
|
|
64
64
|
|
|
65
|
-
The pipe and directive read from a catalog you provide. Needed by `WrTPipe`, `WrTDirective`, `WrI18n`.
|
|
65
|
+
The pipe and directive read from a catalog you provide. Register ngwr's with `provideWrI18nBaseCatalogs`, never spread it into yours: a spread is shallow, so any namespace you share with ngwr, e.g. `common`, `validation`, `table`, keeps only the side spread last, and the other side's keys stop resolving with nothing logged — ngwr's components fall back to English and a `wrT` read of a lost key renders the raw key. Needed by `WrTPipe`, `WrTDirective`, `WrI18n`.
|
|
66
66
|
|
|
67
67
|
## Optional, app-wide
|
|
68
68
|
|
package/table/styles/_index.scss
CHANGED
|
@@ -389,6 +389,14 @@
|
|
|
389
389
|
padding: 0;
|
|
390
390
|
cursor: pointer;
|
|
391
391
|
color: inherit;
|
|
392
|
+
// The indicator inside is a bare `.wr-icon__svg`, which is `1em`, and a
|
|
393
|
+
// `<button>` does not inherit its font-size: it takes the browser's control
|
|
394
|
+
// font (about 13.33px) unless the app resets it. So the same glyph measured
|
|
395
|
+
// 13.33px on a page with no reset and 12px under `ngwr/reset`, which sets
|
|
396
|
+
// `font: inherit`. Inheriting the size makes `1em` the header's own text in
|
|
397
|
+
// every app. `--wr-icon-size` cannot do this job — only a `<wr-icon>` host
|
|
398
|
+
// reads it, and the rule here used to set it for nothing.
|
|
399
|
+
font-size: inherit;
|
|
392
400
|
line-height: 0;
|
|
393
401
|
}
|
|
394
402
|
|
|
@@ -741,21 +749,35 @@
|
|
|
741
749
|
|
|
742
750
|
.wr-table-sort {
|
|
743
751
|
display: inline-flex;
|
|
744
|
-
|
|
752
|
+
// Unsorted is the flat line the template draws, at full strength in the muted
|
|
753
|
+
// role — the same ink as the filter funnel beside it. It used to be the sort
|
|
754
|
+
// ARROW at half opacity, which is how an unsorted column came to read as
|
|
755
|
+
// "sorted ascending, dimmed". The glyph carries the state now, so the opacity
|
|
756
|
+
// has no job left, and dropping it is what lifts the indicator over the 3:1 a
|
|
757
|
+
// graphic that identifies a control is held to. Measured on the header's own
|
|
758
|
+
// background in Chromium, after the colour transition settled: from 1.98:1 to
|
|
759
|
+
// 4.78:1 in light (`#5f6c7d` on `#eff2f6`) and from 2.74:1 to 7.04:1 in dark
|
|
760
|
+
// (`#9aa6b8` on `#131a2b`). An SVG stroke is invisible to axe, so re-measure
|
|
761
|
+
// by hand if this ink or the header fill ever moves.
|
|
745
762
|
color: var(--wr-color-on-surface-muted);
|
|
746
|
-
transition
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
763
|
+
// Only the colour eases back to unsorted. A transition is taken from the
|
|
764
|
+
// state being ENTERED, so leaving `--desc` for the base would otherwise spin
|
|
765
|
+
// the flat line from 180deg to 0 — motion with no direction to report. The
|
|
766
|
+
// turn between the two arrows still animates, since both modifiers carry it.
|
|
767
|
+
transition: color var(--wr-transition-base);
|
|
768
|
+
|
|
769
|
+
// The template swaps the glyph — a flat line while unsorted, an arrow here
|
|
770
|
+
// (table-sort.ts) — so the state reads from the shape, and the primary ink
|
|
771
|
+
// only says which column is the sorted one.
|
|
772
|
+
&--asc,
|
|
773
|
+
&--desc {
|
|
753
774
|
color: var(--wr-color-primary);
|
|
775
|
+
transition:
|
|
776
|
+
transform var(--wr-transition-base),
|
|
777
|
+
color var(--wr-transition-base);
|
|
754
778
|
}
|
|
755
779
|
|
|
756
780
|
&--desc {
|
|
757
|
-
opacity: 1;
|
|
758
|
-
color: var(--wr-color-primary);
|
|
759
781
|
transform: rotate(180deg);
|
|
760
782
|
}
|
|
761
783
|
}
|
|
@@ -781,7 +803,13 @@
|
|
|
781
803
|
padding: 0;
|
|
782
804
|
cursor: pointer;
|
|
783
805
|
color: inherit;
|
|
784
|
-
|
|
806
|
+
// The funnel is the same bare `1em` svg as the sort indicator beside it, in
|
|
807
|
+
// the same kind of `<button>`, so it inherits the header's font-size for the
|
|
808
|
+
// same reason (see `.wr-table__sort-btn`). The size only, not the `font`
|
|
809
|
+
// shorthand: that would also bring the header's 1.25rem line-height, and the
|
|
810
|
+
// count pill beside the funnel — 10px type with no line-height of its own —
|
|
811
|
+
// grows from 12px to 20px tall under it.
|
|
812
|
+
font-size: inherit;
|
|
785
813
|
}
|
|
786
814
|
|
|
787
815
|
&__count {
|
|
@@ -855,7 +883,6 @@
|
|
|
855
883
|
border-radius: var(--wr-border-radius-sm);
|
|
856
884
|
border: 1px solid var(--wr-color-outline);
|
|
857
885
|
color: transparent;
|
|
858
|
-
--wr-icon-size: 0.75rem;
|
|
859
886
|
transition: var(--wr-transition-base);
|
|
860
887
|
}
|
|
861
888
|
|
package/types/ngwr-i18n-en.d.ts
CHANGED
|
@@ -1,16 +1,27 @@
|
|
|
1
1
|
import { WrI18nCatalog } from 'ngwr/i18n';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Base English catalog for ngwr built-in component strings.
|
|
5
|
-
*
|
|
4
|
+
* Base English catalog for ngwr built-in component strings. Register it with
|
|
5
|
+
* `provideWrI18nBaseCatalogs` and keep only your own keys in the loader.
|
|
6
|
+
*
|
|
7
|
+
* Do not spread it into your own catalog. A spread is shallow, so any namespace
|
|
8
|
+
* you share with ngwr, e.g. `common`, `validation`, `table`, keeps only the keys
|
|
9
|
+
* of the side spread last, and the other side's keys stop resolving with nothing
|
|
10
|
+
* logged: ngwr's components fall back to their English defaults, and a `wrT`
|
|
11
|
+
* read of a lost key renders the raw key under the default missing handler. A
|
|
12
|
+
* base catalog is looked up key by key underneath yours, so both halves of a
|
|
13
|
+
* shared namespace resolve.
|
|
6
14
|
*
|
|
7
15
|
* @example
|
|
8
16
|
* ```ts
|
|
17
|
+
* import { provideWrI18n, provideWrI18nBaseCatalogs, provideWrI18nStaticLoader } from 'ngwr/i18n';
|
|
9
18
|
* import { wrEn } from 'ngwr/i18n/en';
|
|
10
19
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* })
|
|
20
|
+
* providers: [
|
|
21
|
+
* provideWrI18n(),
|
|
22
|
+
* provideWrI18nBaseCatalogs({ en: wrEn }),
|
|
23
|
+
* provideWrI18nStaticLoader({ en: { app: { title: 'My app' } } }),
|
|
24
|
+
* ]
|
|
14
25
|
* ```
|
|
15
26
|
*/
|
|
16
27
|
declare const wrEn: WrI18nCatalog;
|
package/types/ngwr-i18n.d.ts
CHANGED
|
@@ -403,6 +403,15 @@ declare function provideWrI18n(options?: ProvideWrI18nOptions): EnvironmentProvi
|
|
|
403
403
|
/**
|
|
404
404
|
* Provide a static loader — catalogs already in memory.
|
|
405
405
|
*
|
|
406
|
+
* A loader serves only the catalog you pass it, and ngwr registers none of its
|
|
407
|
+
* own. Pass only your own keys here and register ngwr's catalogs with
|
|
408
|
+
* {@link provideWrI18nBaseCatalogs} — not `{ ...wrRu, ...yours }`. A spread is
|
|
409
|
+
* shallow, so any namespace you share with ngwr, e.g. `common`, `validation`,
|
|
410
|
+
* `table`, keeps only the keys of the side spread last, and the other side's
|
|
411
|
+
* keys stop resolving with nothing logged: ngwr's components fall back to their
|
|
412
|
+
* English defaults, and a `wrT` read of a lost key renders the raw key under the
|
|
413
|
+
* default missing handler.
|
|
414
|
+
*
|
|
406
415
|
* @param catalogs Root catalogs keyed by locale.
|
|
407
416
|
* @param scopes Optional per-scope catalogs served to `registerScope(name)`.
|
|
408
417
|
*/
|
|
@@ -428,6 +437,10 @@ declare function provideWrI18nStaticLoader(catalogs: WrI18nStaticCatalogs, scope
|
|
|
428
437
|
*
|
|
429
438
|
* Pass only the locales you ship — the ones you leave out stay out of the
|
|
430
439
|
* bundle. Your own keys always win; this is a floor, not an override.
|
|
440
|
+
*
|
|
441
|
+
* Use it instead of spreading `wrRu` into your own catalog, too: the lookup
|
|
442
|
+
* walks these key by key after the loader's catalog misses, so a namespace both
|
|
443
|
+
* define keeps both halves, where a shallow spread keeps only one.
|
|
431
444
|
*/
|
|
432
445
|
declare function provideWrI18nBaseCatalogs(catalogs: WrI18nBaseCatalogs): Provider;
|
|
433
446
|
/** Provide an HTTP loader — catalogs fetched from URLs. Requires `provideHttpClient`. */
|
package/types/ngwr-table.d.ts
CHANGED
|
@@ -861,6 +861,14 @@ declare class WrTableGroupHeader {
|
|
|
861
861
|
/**
|
|
862
862
|
* Sort indicator rendered in a sortable column's header.
|
|
863
863
|
*
|
|
864
|
+
* Draws an ARROW for a sorted column — up for `asc`, the same arrow turned by
|
|
865
|
+
* the stylesheet for `desc` — and a flat LINE for a column that sorts but is
|
|
866
|
+
* not sorted. A different shape rather than a fainter arrow, on purpose: a
|
|
867
|
+
* dimmed up-arrow reads as "sorted ascending", which is the one thing an
|
|
868
|
+
* unsorted column must not say, and a state told apart by opacity and colour
|
|
869
|
+
* alone is lost to anyone who cannot see that difference. A line also has no
|
|
870
|
+
* direction to mirror under RTL.
|
|
871
|
+
*
|
|
864
872
|
* @internal — used internally by `<wr-table>`. Parent listens for clicks
|
|
865
873
|
* on the indicator to cycle direction.
|
|
866
874
|
*/
|
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.5.
|
|
19
|
+
declare const NGWR_VERSION = "14.5.1";
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* @license
|