ngwr 14.5.1 → 14.7.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/alert/styles/_index.scss +14 -3
- package/avatar/styles/_index.scss +90 -0
- package/cascader/styles/_rules.scss +0 -4
- package/collapse/styles/_index.scss +0 -1
- package/fesm2022/ngwr-avatar.mjs +76 -8
- package/fesm2022/ngwr-avatar.mjs.map +1 -1
- package/fesm2022/ngwr-cascader.mjs +2 -2
- package/fesm2022/ngwr-cascader.mjs.map +1 -1
- package/fesm2022/ngwr-image-cropper-testing.mjs +34 -3
- package/fesm2022/ngwr-image-cropper-testing.mjs.map +1 -1
- package/fesm2022/ngwr-image-cropper.mjs +245 -65
- package/fesm2022/ngwr-image-cropper.mjs.map +1 -1
- package/fesm2022/ngwr-lightbox.mjs +2 -2
- package/fesm2022/ngwr-lightbox.mjs.map +1 -1
- package/fesm2022/ngwr-pagination.mjs +1 -1
- package/fesm2022/ngwr-pagination.mjs.map +1 -1
- package/fesm2022/ngwr-schema-form.mjs +1 -1
- package/fesm2022/ngwr-schema-form.mjs.map +1 -1
- package/fesm2022/ngwr-select-testing.mjs +21 -2
- package/fesm2022/ngwr-select-testing.mjs.map +1 -1
- package/fesm2022/ngwr-select.mjs +299 -50
- package/fesm2022/ngwr-select.mjs.map +1 -1
- package/fesm2022/ngwr-version.mjs +1 -1
- package/fesm2022/ngwr-version.mjs.map +1 -1
- package/image-cropper/styles/_index.scss +7 -0
- package/input/styles/_index.scss +8 -2
- package/lightbox/styles/_rules.scss +7 -1
- package/llms-full.txt +4 -4
- package/package.json +1 -1
- package/schematics/use/symbol-map.json +1 -0
- package/select/styles/_index.scss +50 -4
- package/skills/ngwr/references/catalog.md +1 -1
- package/table/styles/_index.scss +55 -0
- package/toast/styles/_index.scss +9 -3
- package/tree/styles/_index.scss +0 -3
- package/types/ngwr-avatar.d.ts +51 -4
- package/types/ngwr-image-cropper-testing.d.ts +25 -3
- package/types/ngwr-image-cropper.d.ts +136 -2
- package/types/ngwr-select-testing.d.ts +18 -1
- package/types/ngwr-select.d.ts +238 -10
- 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.
|
|
19
|
+
const NGWR_VERSION = '14.7.0';
|
|
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.
|
|
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.7.0';\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;;;;"}
|
|
@@ -23,6 +23,13 @@
|
|
|
23
23
|
user-select: none;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
// A source the browser could not decode. The `<img>` stays in the DOM, since the
|
|
27
|
+
// next `src` goes through the same element, but some engines draw a broken-image
|
|
28
|
+
// glyph for it — and the failure is the host's to explain, not a stray icon's.
|
|
29
|
+
&--failed &__image {
|
|
30
|
+
display: none;
|
|
31
|
+
}
|
|
32
|
+
|
|
26
33
|
&__backdrop {
|
|
27
34
|
position: absolute;
|
|
28
35
|
inset: 0;
|
package/input/styles/_index.scss
CHANGED
|
@@ -199,8 +199,14 @@
|
|
|
199
199
|
color: var(--wr-input-group-affix);
|
|
200
200
|
cursor: pointer;
|
|
201
201
|
transition: color var(--wr-transition-base);
|
|
202
|
-
|
|
203
|
-
|
|
202
|
+
// The eye is a bare `.wr-icon__svg`, which is `1em`, and a `<button>` does
|
|
203
|
+
// not inherit its font-size — so it drew the browser's control font (about
|
|
204
|
+
// 13.33px) with no reset and the surrounding text's size under `ngwr/reset`.
|
|
205
|
+
// Inheriting the size makes `1em` the text around the field in every app.
|
|
206
|
+
// The size only, not the `font` shorthand, which would also hand the button
|
|
207
|
+
// the group's line-height. `--wr-icon-size` only drives `<wr-icon>` hosts, so
|
|
208
|
+
// the declaration that used to sit here drove nothing.
|
|
209
|
+
font-size: inherit;
|
|
204
210
|
|
|
205
211
|
&:hover:not(:disabled) {
|
|
206
212
|
color: var(--wr-color-primary);
|
|
@@ -132,7 +132,13 @@
|
|
|
132
132
|
touch-action: none;
|
|
133
133
|
|
|
134
134
|
&__close {
|
|
135
|
-
|
|
135
|
+
// A bare `.wr-icon__svg` in a `<button>`: `1em`, and a button inherits no
|
|
136
|
+
// font-size — so the ✕ came out at the browser's control font, about
|
|
137
|
+
// 13.33px, inside a 36px circle, and at the surrounding text's size under
|
|
138
|
+
// `ngwr/reset`. Inheriting the size gives the same glyph either way. The
|
|
139
|
+
// size only, not the `font` shorthand. `--wr-icon-size` was never going to
|
|
140
|
+
// do it: only a `<wr-icon>` host reads that hook.
|
|
141
|
+
font-size: inherit;
|
|
136
142
|
position: absolute;
|
|
137
143
|
top: 1rem;
|
|
138
144
|
inset-inline-end: 1rem;
|
package/llms-full.txt
CHANGED
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
- import: `import { WrAvatar } from 'ngwr/avatar'`
|
|
46
46
|
- selector: `wr-avatar`
|
|
47
47
|
- exports: WrAvatar, WrAvatarSize, WrAvatarShape
|
|
48
|
-
- Image avatar with a
|
|
48
|
+
- Image avatar with a square, rounded, circle or squircle shape. Projected initials stand in while the image loads and when it fails.
|
|
49
49
|
|
|
50
50
|
## ngwr/back-top
|
|
51
51
|
- import: `import { WrBackTop } from 'ngwr/back-top'`
|
|
@@ -568,7 +568,7 @@
|
|
|
568
568
|
## ngwr/image-cropper
|
|
569
569
|
- import: `import { WrImageCropper } from 'ngwr/image-cropper'`
|
|
570
570
|
- selector: `wr-image-cropper`
|
|
571
|
-
- exports: WrImageCropper, WrCropRect, WrCropHandle, WrImageOutputType
|
|
571
|
+
- exports: WrImageCropper, WrCropRect, WrCropHandle, WrImageCropperStatus, WrImageLoadError, WrImageOutputType
|
|
572
572
|
- DOM-based crop UI. Drag the box to move, drag any of the eight handles to resize. Optional `[aspectRatio]` locks the box shape. `(cropped)` fires with a `Blob` after each drag end — wire to upload or preview.
|
|
573
573
|
|
|
574
574
|
## ngwr/image-cropper/testing
|
|
@@ -840,8 +840,8 @@
|
|
|
840
840
|
|
|
841
841
|
## ngwr/select
|
|
842
842
|
- import: `import { WrSelect } from 'ngwr/select'`
|
|
843
|
-
- selector: `wr-option-group`, `wr-option`, `wr-select`
|
|
844
|
-
- exports: WrSelect, WrOption, WrOptionGroup, WR_SELECT, WrSelectContext, WrSelectMode, WrSelectSearchLoader, WrSelectTagValidator, WrSelectSize
|
|
843
|
+
- selector: `wr-option-group`, `ng-template[wrOptionLeading]`, `wr-option`, `wr-select`
|
|
844
|
+
- exports: WrSelect, WrOption, WrOptionGroup, WrOptionLeading, WR_SELECT, WrSelectContext, WrOptionLeadingContext, WrOptionLeadingPlacement, WrSelectMode, WrSelectSearchLoader, WrSelectTagValidator, WrSelectSize
|
|
845
845
|
- Native-like select built on CDK Overlay. A signal-forms native control — it implements `FormValueControl`, so `[formField]` binds straight to its `value` model. `[(value)]` works standalone, and `[(ngModel)]` / reactive forms keep working through [Angular 22's forms bridge](/guides/forms).
|
|
846
846
|
|
|
847
847
|
## ngwr/select/testing
|
package/package.json
CHANGED
|
@@ -120,8 +120,15 @@
|
|
|
120
120
|
color: var(--wr-color-text-muted);
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
+
// The selected option's leading visual on a single-mode button trigger. Never
|
|
124
|
+
// shrinks: the label beside it is the part that truncates.
|
|
125
|
+
&__value-leading {
|
|
126
|
+
display: inline-flex;
|
|
127
|
+
flex: none;
|
|
128
|
+
align-items: center;
|
|
129
|
+
}
|
|
130
|
+
|
|
123
131
|
&__chevron {
|
|
124
|
-
--wr-icon-size: 1rem;
|
|
125
132
|
flex: 0 0 auto;
|
|
126
133
|
color: var(--wr-color-on-surface-muted);
|
|
127
134
|
transition: transform var(--wr-transition-base);
|
|
@@ -171,6 +178,22 @@
|
|
|
171
178
|
}
|
|
172
179
|
}
|
|
173
180
|
|
|
181
|
+
// A leading visual inside a search trigger. The FIELD owns the leading
|
|
182
|
+
// padding here (see `--search` above), so the inset has to move with the
|
|
183
|
+
// visual — otherwise the avatar sits on the border. Only the trigger's own
|
|
184
|
+
// 0.5rem `gap` is then left between the two, which is the spacing the button
|
|
185
|
+
// trigger already has between `__value-leading` and `__value`.
|
|
186
|
+
&__trigger--search &__value-leading {
|
|
187
|
+
padding-inline-start: calc(var(--wr-select-padding-x) * var(--wr-density-x, 1));
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// …and the field drops the inset it just handed over. Keyed on the sibling
|
|
191
|
+
// rather than on a modifier class so the two can never be set apart: the
|
|
192
|
+
// padding moves exactly when the element it moved to exists.
|
|
193
|
+
&__value-leading + &__search-input {
|
|
194
|
+
padding-inline-start: 0;
|
|
195
|
+
}
|
|
196
|
+
|
|
174
197
|
&__search-input {
|
|
175
198
|
flex: 1 1 auto;
|
|
176
199
|
min-width: 0;
|
|
@@ -268,6 +291,17 @@
|
|
|
268
291
|
user-select: none;
|
|
269
292
|
}
|
|
270
293
|
|
|
294
|
+
// A selected option's leading visual — an avatar, an icon. Pulled toward the
|
|
295
|
+
// chip's start edge so a round avatar reads as the chip's cap rather than as a
|
|
296
|
+
// glyph floating in the padding, and spaced from the label by a little more
|
|
297
|
+
// than the chip's own gap.
|
|
298
|
+
&__chip-leading {
|
|
299
|
+
display: inline-flex;
|
|
300
|
+
flex: none;
|
|
301
|
+
align-items: center;
|
|
302
|
+
margin-inline: -0.25rem 0.125rem;
|
|
303
|
+
}
|
|
304
|
+
|
|
271
305
|
&__chip-label {
|
|
272
306
|
overflow: hidden;
|
|
273
307
|
text-overflow: ellipsis;
|
|
@@ -275,7 +309,6 @@
|
|
|
275
309
|
}
|
|
276
310
|
|
|
277
311
|
&__chip-remove {
|
|
278
|
-
--wr-icon-size: 0.875rem;
|
|
279
312
|
display: inline-flex;
|
|
280
313
|
align-items: center;
|
|
281
314
|
justify-content: center;
|
|
@@ -301,7 +334,6 @@
|
|
|
301
334
|
}
|
|
302
335
|
|
|
303
336
|
&__clear {
|
|
304
|
-
--wr-icon-size: 0.875rem;
|
|
305
337
|
// Never shrink: the chips box is allowed to grow into the whole row, so the
|
|
306
338
|
// × has to hold its own size against it.
|
|
307
339
|
flex: 0 0 auto;
|
|
@@ -424,6 +456,14 @@
|
|
|
424
456
|
}
|
|
425
457
|
}
|
|
426
458
|
|
|
459
|
+
// An option's leading visual — a sibling of the label inside the row's flex,
|
|
460
|
+
// so `--wr-option-inline-gap` spaces it like any projected icon.
|
|
461
|
+
&__leading {
|
|
462
|
+
display: inline-flex;
|
|
463
|
+
flex: none;
|
|
464
|
+
align-items: center;
|
|
465
|
+
}
|
|
466
|
+
|
|
427
467
|
// Search-mode filter — out-of-match options collapse but stay in the
|
|
428
468
|
// DOM so registration order survives the panel re-open.
|
|
429
469
|
&--hidden {
|
|
@@ -461,6 +501,13 @@
|
|
|
461
501
|
position: relative;
|
|
462
502
|
}
|
|
463
503
|
|
|
504
|
+
// A virtual row is a block, not a flex row (one line, so it can ellipsize),
|
|
505
|
+
// so the leading visual takes its spacing as a margin instead of the gap.
|
|
506
|
+
.wr-option__leading {
|
|
507
|
+
vertical-align: middle;
|
|
508
|
+
margin-inline-end: var(--wr-option-inline-gap, 0.5rem);
|
|
509
|
+
}
|
|
510
|
+
|
|
464
511
|
// Keyboard cursor highlight — the virtualized list is navigated by
|
|
465
512
|
// aria-activedescendant, so real focus never lands on the row and the tint
|
|
466
513
|
// is all there was. `--wr-color-hover` is translucent and lands within about
|
|
@@ -534,7 +581,6 @@
|
|
|
534
581
|
|
|
535
582
|
.wr-select__chip-remove,
|
|
536
583
|
.wr-select__clear {
|
|
537
|
-
--wr-icon-size: 1.125rem;
|
|
538
584
|
width: 2rem;
|
|
539
585
|
height: 2rem;
|
|
540
586
|
}
|
|
@@ -171,7 +171,7 @@ root barrel for components.
|
|
|
171
171
|
| `ngwr/scroll` | `import { WrScroll } from 'ngwr/scroll'` | — |
|
|
172
172
|
| `ngwr/segmented` | `import { WrSegmented } from 'ngwr/segmented'` | `wr-segmented` |
|
|
173
173
|
| `ngwr/segmented/testing` | `import { WrSegmentedHarness } from 'ngwr/segmented/testing'` | — |
|
|
174
|
-
| `ngwr/select` | `import { WrSelect } from 'ngwr/select'` | `wr-option-group` `wr-option` `wr-select` |
|
|
174
|
+
| `ngwr/select` | `import { WrSelect } from 'ngwr/select'` | `wr-option-group` `ng-template[wrOptionLeading]` `wr-option` `wr-select` |
|
|
175
175
|
| `ngwr/select/testing` | `import { WrOptionHarness } from 'ngwr/select/testing'` | — |
|
|
176
176
|
| `ngwr/shiny-text` | `import { WrShinyText } from 'ngwr/shiny-text'` | `[wrShimmer]` `wr-shiny-text` |
|
|
177
177
|
| `ngwr/shiny-text/testing` | `import { WrShinyTextHarness } from 'ngwr/shiny-text/testing'` | — |
|
package/table/styles/_index.scss
CHANGED
|
@@ -376,6 +376,28 @@
|
|
|
376
376
|
display: inline-flex;
|
|
377
377
|
align-items: center;
|
|
378
378
|
gap: 0.375rem;
|
|
379
|
+
|
|
380
|
+
// The spacing of the header's controls, and it moves for a COARSE pointer
|
|
381
|
+
// only. A column that is both `sortable` and `filterable` puts two 12px
|
|
382
|
+
// controls in this row 0.375rem apart, so their centres are 18px apart —
|
|
383
|
+
// while the touch halo each one grows below is 24px wide and centred on its
|
|
384
|
+
// control. Two 24px boxes with centres 18px apart OVERLAP by 6px, and the
|
|
385
|
+
// later one in the DOM (the filter) wins the hit test, so the sort button
|
|
386
|
+
// would hand over a strip of the slack it just gained. 0.75rem puts the
|
|
387
|
+
// centres 24px apart, which is the closest the two halos can come: at rest
|
|
388
|
+
// they abut exactly, and a filter showing a count pill is 32px wide, which
|
|
389
|
+
// only separates them further. A fine pointer keeps the 0.375rem this row
|
|
390
|
+
// has always drawn.
|
|
391
|
+
//
|
|
392
|
+
// This gap is also the whole of what a COARSE-pointer `target-size` run
|
|
393
|
+
// measures. axe never sees the halo — an `::after` enters no rect, so it
|
|
394
|
+
// reads 12x12 either way — but 24px between centres satisfies WCAG 2.5.8's
|
|
395
|
+
// spacing exception exactly, and the pair passes. Narrow this and a coarse
|
|
396
|
+
// run reports both nodes again; `table-header-target.spec.ts` pins the
|
|
397
|
+
// value here so a PR catches it without a browser.
|
|
398
|
+
@media (pointer: coarse) {
|
|
399
|
+
gap: 0.75rem;
|
|
400
|
+
}
|
|
379
401
|
}
|
|
380
402
|
|
|
381
403
|
&__title {
|
|
@@ -398,6 +420,24 @@
|
|
|
398
420
|
// reads it, and the rule here used to set it for nothing.
|
|
399
421
|
font-size: inherit;
|
|
400
422
|
line-height: 0;
|
|
423
|
+
// The pointer target, widened for a COARSE pointer and for nothing else.
|
|
424
|
+
// WCAG 2.5.8 asks 24x24 of every control, a mouse included, and this glyph
|
|
425
|
+
// is 12x12: a lone one passes on the criterion's spacing exception, and a
|
|
426
|
+
// column carrying both this button and a filter trigger 6px away does not.
|
|
427
|
+
// A real 24px box on every pointer is what satisfies the criterion outright,
|
|
428
|
+
// and it was written, measured and REFUSED — it moves the caret and the
|
|
429
|
+
// funnel apart on a mouse, and the maintainer chose to keep the geometry
|
|
430
|
+
// 14.6.0 draws. So the coarse half ships, the fine-pointer failure is a
|
|
431
|
+
// decided trade recorded in AGENTS.md and in `scripts/contrast-baseline.json`,
|
|
432
|
+
// and the table's docs page says so to the reader. Do not re-report it.
|
|
433
|
+
//
|
|
434
|
+
// 24px rather than the mixin's 44px default, which is a real constraint and
|
|
435
|
+
// not a preference: the halo is centred on the control, so 44 reaches 22px
|
|
436
|
+
// either side and swallows the filter trigger beside it — the mixin's own
|
|
437
|
+
// docblock warns off tightly-packed rows for exactly this. 24 is the
|
|
438
|
+
// criterion's number, and `__th-inner` opens its gap under the same media
|
|
439
|
+
// query so the two halos cannot overlap.
|
|
440
|
+
@include theme.touch-target($size: 24px);
|
|
401
441
|
}
|
|
402
442
|
|
|
403
443
|
&__tr {
|
|
@@ -810,6 +850,13 @@
|
|
|
810
850
|
// count pill beside the funnel — 10px type with no line-height of its own —
|
|
811
851
|
// grows from 12px to 20px tall under it.
|
|
812
852
|
font-size: inherit;
|
|
853
|
+
// The same coarse-pointer target as the sort button beside it, where the
|
|
854
|
+
// whole reasoning — why 24 and not 44, and why a fine pointer keeps the
|
|
855
|
+
// 12px glyph — is written out. It goes on the TRIGGER and never on the
|
|
856
|
+
// `<wr-table-filter>` host: the halo belongs to the element that owns the
|
|
857
|
+
// click, and a tap landing on the host's own pseudo-element would target
|
|
858
|
+
// the host and open nothing.
|
|
859
|
+
@include theme.touch-target($size: 24px);
|
|
813
860
|
}
|
|
814
861
|
|
|
815
862
|
&__count {
|
|
@@ -822,6 +869,14 @@
|
|
|
822
869
|
background: var(--wr-color-primary);
|
|
823
870
|
color: var(--wr-color-primary-contrast);
|
|
824
871
|
font-size: 0.625rem; // 10px — intentional micro-count badge, below --wr-text-xs
|
|
872
|
+
// The pill has no padding on the block axis, so its height IS its line box,
|
|
873
|
+
// and leaving that at `normal` handed the box to whatever the page
|
|
874
|
+
// inherited: 12px in an app with no reset, 20px under `ngwr/reset`, whose
|
|
875
|
+
// `font: inherit` on a `<button>` brings the header's 1.25rem down with the
|
|
876
|
+
// font-size. A ratio of its own makes it 12px in both — and a ratio rather
|
|
877
|
+
// than a length, so a consumer who enlarges the numeral gets a pill that
|
|
878
|
+
// grows with it.
|
|
879
|
+
line-height: 1.2;
|
|
825
880
|
font-weight: 600;
|
|
826
881
|
}
|
|
827
882
|
|
package/toast/styles/_index.scss
CHANGED
|
@@ -205,8 +205,15 @@ $toast-colors: (
|
|
|
205
205
|
transition:
|
|
206
206
|
color var(--wr-transition-base),
|
|
207
207
|
background var(--wr-transition-base);
|
|
208
|
-
|
|
209
|
-
|
|
208
|
+
// The glyph is a bare `.wr-icon__svg` — `1em` — and a `<button>` does not
|
|
209
|
+
// inherit its font-size, so it drew the browser's control font (about
|
|
210
|
+
// 13.33px) with no reset and the surrounding text's size under `ngwr/reset`.
|
|
211
|
+
// Inheriting the size makes `1em` the toast's own text in every app; only a
|
|
212
|
+
// `<wr-icon>` host reads `--wr-icon-size`, so the hook never applied here.
|
|
213
|
+
// The SIZE only, never the `font` shorthand: that would also bring the
|
|
214
|
+
// surrounding line-height, which is what stretched the table's filter count
|
|
215
|
+
// pill from 12px to 20px when it was tried there.
|
|
216
|
+
font-size: inherit;
|
|
210
217
|
|
|
211
218
|
&:hover {
|
|
212
219
|
color: var(--wr-color-on-surface);
|
|
@@ -323,7 +330,6 @@ $toast-colors: (
|
|
|
323
330
|
width: 2rem;
|
|
324
331
|
height: 2rem;
|
|
325
332
|
padding: 0;
|
|
326
|
-
--wr-icon-size: 1.125rem;
|
|
327
333
|
}
|
|
328
334
|
|
|
329
335
|
.wr-toast-host__close-all {
|
package/tree/styles/_index.scss
CHANGED
|
@@ -249,7 +249,6 @@
|
|
|
249
249
|
}
|
|
250
250
|
|
|
251
251
|
&__chevron {
|
|
252
|
-
--wr-icon-size: 1rem;
|
|
253
252
|
flex: 0 0 auto;
|
|
254
253
|
color: var(--wr-color-on-surface-muted);
|
|
255
254
|
transition: transform var(--wr-transition-base);
|
|
@@ -260,7 +259,6 @@
|
|
|
260
259
|
}
|
|
261
260
|
|
|
262
261
|
&__clear {
|
|
263
|
-
--wr-icon-size: 0.875rem;
|
|
264
262
|
display: inline-flex;
|
|
265
263
|
align-items: center;
|
|
266
264
|
justify-content: center;
|
|
@@ -329,7 +327,6 @@
|
|
|
329
327
|
}
|
|
330
328
|
|
|
331
329
|
&__chip-remove {
|
|
332
|
-
--wr-icon-size: 0.875rem;
|
|
333
330
|
display: inline-flex;
|
|
334
331
|
align-items: center;
|
|
335
332
|
justify-content: center;
|
package/types/ngwr-avatar.d.ts
CHANGED
|
@@ -40,19 +40,38 @@ type WrAvatarSize = number | `${number}` | `${number}px` | `${number}rem`;
|
|
|
40
40
|
/**
|
|
41
41
|
* Image avatar with configurable corner treatment.
|
|
42
42
|
*
|
|
43
|
-
*
|
|
43
|
+
* Projected content (typically initials) is the FALLBACK: it shows with no
|
|
44
|
+
* `url`, while the image loads and after it fails, and leaves the paint once the
|
|
45
|
+
* image has loaded. It is projected into a `.wr-avatar__content` wrapper, so a
|
|
46
|
+
* `wr-avatar > …` child selector no longer reaches it. While it is there, no
|
|
47
|
+
* spinner is drawn over it; with nothing projected, the spinner marks the
|
|
48
|
+
* loading state instead. See `alt` for what a screen reader hears.
|
|
49
|
+
*
|
|
50
|
+
* Projected initials take the text size around the avatar, capped at
|
|
51
|
+
* `--wr-avatar-initials-scale` (`0.375`) of the box, so they shrink only where
|
|
52
|
+
* they would not fit: a 16px avatar in a 14px chip draws 6px letters, while a
|
|
53
|
+
* `6rem` one keeps the surrounding size up to 36px and is capped only past it.
|
|
54
|
+
* Anything projected that is sized in `em` follows the cap too — a `<wr-icon>`
|
|
55
|
+
* at its default `1.2em` included — so pin a `px` or `rem` size on the projected
|
|
56
|
+
* element, or override the hook, to keep it. A `font-size` rule on the avatar
|
|
57
|
+
* itself still wins, unless it sits in a cascade layer (Tailwind v4's utilities
|
|
58
|
+
* do), which ngwr's unlayered stylesheet beats whatever the selector.
|
|
59
|
+
*
|
|
60
|
+
* The initials are inert: `pointer-events: none` hands a click on them to whatever
|
|
61
|
+
* holds the avatar, and `user-select: none` keeps them out of a text selection.
|
|
44
62
|
*
|
|
45
63
|
* @example
|
|
46
64
|
* ```html
|
|
47
65
|
* <wr-avatar url="/me.png" alt="Roman" size="3rem" shape="circle" />
|
|
48
|
-
* <wr-avatar url="
|
|
66
|
+
* <wr-avatar [url]="photo" alt="Roman Khegay" [size]="48">RK</wr-avatar>
|
|
49
67
|
* ```
|
|
50
68
|
*
|
|
51
69
|
* @see https://ngwr.dev/reference/components/avatar
|
|
52
70
|
*/
|
|
53
71
|
declare class WrAvatar {
|
|
54
72
|
/**
|
|
55
|
-
* Image URL.
|
|
73
|
+
* Image URL. Projected content (e.g. initials) shows while it is unset,
|
|
74
|
+
* loading or broken, and gives way once the image has loaded.
|
|
56
75
|
*
|
|
57
76
|
* @default null
|
|
58
77
|
*/
|
|
@@ -61,6 +80,11 @@ declare class WrAvatar {
|
|
|
61
80
|
* Alt text for the image. Falls back to `avatar.alt`, then `'Avatar'` — pass
|
|
62
81
|
* the person's name where you have it, since that is what a reader wants.
|
|
63
82
|
*
|
|
83
|
+
* With an `alt`, projected initials are hidden from assistive technology while
|
|
84
|
+
* an image is in play, so the name is announced once. Without one, the image
|
|
85
|
+
* carries only the generic name, so the initials stay announced beside it —
|
|
86
|
+
* visually hidden once it has loaded, never dropped.
|
|
87
|
+
*
|
|
64
88
|
* @default null
|
|
65
89
|
*/
|
|
66
90
|
readonly alt: _angular_core.InputSignal<string | null>;
|
|
@@ -73,7 +97,8 @@ declare class WrAvatar {
|
|
|
73
97
|
*/
|
|
74
98
|
readonly shape: _angular_core.InputSignal<WrAvatarShape>;
|
|
75
99
|
/**
|
|
76
|
-
* Box size. See {@link WrAvatarSize} for accepted values.
|
|
100
|
+
* Box size. See {@link WrAvatarSize} for accepted values. The resolved value is
|
|
101
|
+
* published on the host as `--wr-avatar-size`.
|
|
77
102
|
*
|
|
78
103
|
* @default '6rem'
|
|
79
104
|
*/
|
|
@@ -85,8 +110,30 @@ declare class WrAvatar {
|
|
|
85
110
|
* worth showing instead.
|
|
86
111
|
*/
|
|
87
112
|
protected readonly failed: _angular_core.WritableSignal<boolean>;
|
|
113
|
+
private readonly img;
|
|
88
114
|
constructor();
|
|
115
|
+
/**
|
|
116
|
+
* A prerendered `<img>` starts loading when the browser parses the HTML, and
|
|
117
|
+
* `(load)` / `(error)` are only attached at hydration — so on a slow bundle the
|
|
118
|
+
* image settles first, both events go nowhere, and the avatar sits on its
|
|
119
|
+
* fallback over a photo it already has (or names a broken image it never
|
|
120
|
+
* learns about). Only the FIRST render can race: every later `<img>` is
|
|
121
|
+
* created on the client with its listeners in place before `src` is set.
|
|
122
|
+
*/
|
|
123
|
+
private adoptSettledImage;
|
|
89
124
|
protected readonly resolved: _angular_core.Signal<ResolvedCssSize>;
|
|
125
|
+
/**
|
|
126
|
+
* Whether the projected fallback is `aria-hidden`: an `<img>` is in the DOM
|
|
127
|
+
* (loading or loaded) AND the consumer named it. Then the image's `alt` owns
|
|
128
|
+
* the name, announced once and unchanged at the moment the photo arrives.
|
|
129
|
+
* Without a real `alt` the image is only "Avatar", and hiding the initials
|
|
130
|
+
* would drop the one thing that says who this is.
|
|
131
|
+
*
|
|
132
|
+
* The stylesheet keys on the same attribute once `--loaded`: a hidden fallback
|
|
133
|
+
* leaves the paint through `visibility`, a named-by-initials one is clipped and
|
|
134
|
+
* stays in the accessibility tree. While loading it is painted either way.
|
|
135
|
+
*/
|
|
136
|
+
protected readonly fallbackHidden: _angular_core.Signal<boolean>;
|
|
90
137
|
protected readonly cssSize: _angular_core.Signal<string>;
|
|
91
138
|
protected readonly pxSize: _angular_core.Signal<number | null>;
|
|
92
139
|
protected readonly classes: _angular_core.Signal<string>;
|
|
@@ -72,9 +72,10 @@ interface WrCropWindowBox {
|
|
|
72
72
|
* arrives on the `(cropped)` output, which emits a `Blob` after each drag end or
|
|
73
73
|
* each run of arrow keys, and a consumer who wants a one-off read calls `toBlob()` /
|
|
74
74
|
* `toDataUrl()` — or `cropRect()` for the geometry — on the component through a
|
|
75
|
-
* `viewChild`.
|
|
76
|
-
*
|
|
77
|
-
* rather than
|
|
75
|
+
* `viewChild`. The same goes for `(loadError)` and `status()`, which is why
|
|
76
|
+
* {@link isFailed} reads the failure off the host class instead. Outputs and instance
|
|
77
|
+
* members are component API rather than DOM, so all of it is outside what a harness
|
|
78
|
+
* can reach at all, which is worth knowing rather than discovering.
|
|
78
79
|
*
|
|
79
80
|
* @example
|
|
80
81
|
* ```ts
|
|
@@ -127,6 +128,27 @@ declare class WrImageCropperHarness extends ComponentHarness {
|
|
|
127
128
|
* a zero-sized image.
|
|
128
129
|
*/
|
|
129
130
|
dispatchImageLoad(): Promise<void>;
|
|
131
|
+
/**
|
|
132
|
+
* Fire the image's `error` event — what a browser does with a source it cannot
|
|
133
|
+
* decode, and the only way to get one in a unit test, where nothing is decoded.
|
|
134
|
+
*
|
|
135
|
+
* Afterwards {@link isFailed} is `true` and the component has emitted
|
|
136
|
+
* `(loadError)`; a spec that wants the payload binds that output on its host.
|
|
137
|
+
*/
|
|
138
|
+
dispatchImageError(): Promise<void>;
|
|
139
|
+
/**
|
|
140
|
+
* Whether the browser failed to decode the current source.
|
|
141
|
+
*
|
|
142
|
+
* Read off the `wr-image-cropper--failed` host modifier — the part of the failure
|
|
143
|
+
* the DOM shows. It is a third answer beside {@link isEmpty} and {@link isReady},
|
|
144
|
+
* not a combination of them: a failed cropper has a `src` (so it is not empty) and
|
|
145
|
+
* no crop window (so it is not ready), which is also exactly what a cropper still
|
|
146
|
+
* LOADING looks like. Asking those two would call a broken image a slow one.
|
|
147
|
+
*
|
|
148
|
+
* The component renders no message for it, so there is no text to read here; the
|
|
149
|
+
* host's own message is the host's to assert.
|
|
150
|
+
*/
|
|
151
|
+
isFailed(): Promise<boolean>;
|
|
130
152
|
/**
|
|
131
153
|
* Where the crop window sits over the displayed image, in CSS pixels.
|
|
132
154
|
*
|