forty-cdk 0.23.0 → 0.24.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/context-menu/README.md +1 -1
- package/dialog/README.md +11 -1
- package/drag-drop/README.md +3 -2
- package/drawer/README.md +10 -0
- package/dropdown-menu/README.md +1 -1
- package/fesm2022/forty-cdk-avatar.mjs.map +1 -1
- package/fesm2022/forty-cdk-carousel.mjs.map +1 -1
- package/fesm2022/forty-cdk-combobox.mjs +0 -15
- package/fesm2022/forty-cdk-combobox.mjs.map +1 -1
- package/fesm2022/forty-cdk-context-menu.mjs +0 -15
- package/fesm2022/forty-cdk-context-menu.mjs.map +1 -1
- package/fesm2022/forty-cdk-core-overlay.mjs +6 -22
- package/fesm2022/forty-cdk-core-overlay.mjs.map +1 -1
- package/fesm2022/forty-cdk-core.mjs +0 -15
- package/fesm2022/forty-cdk-core.mjs.map +1 -1
- package/fesm2022/forty-cdk-date-field.mjs.map +1 -1
- package/fesm2022/forty-cdk-date-picker.mjs +0 -8
- package/fesm2022/forty-cdk-date-picker.mjs.map +1 -1
- package/fesm2022/forty-cdk-drag-drop.mjs.map +1 -1
- package/fesm2022/forty-cdk-hover-card.mjs +13 -3
- package/fesm2022/forty-cdk-hover-card.mjs.map +1 -1
- package/fesm2022/forty-cdk-listbox.mjs +97 -10
- package/fesm2022/forty-cdk-listbox.mjs.map +1 -1
- package/fesm2022/forty-cdk-menu.mjs +0 -5
- package/fesm2022/forty-cdk-menu.mjs.map +1 -1
- package/fesm2022/forty-cdk-menubar.mjs +0 -3
- package/fesm2022/forty-cdk-menubar.mjs.map +1 -1
- package/fesm2022/forty-cdk-meter.mjs.map +1 -1
- package/fesm2022/forty-cdk-navigation-menu.mjs +6 -9
- package/fesm2022/forty-cdk-navigation-menu.mjs.map +1 -1
- package/fesm2022/forty-cdk-number-input.mjs.map +1 -1
- package/fesm2022/forty-cdk-popover.mjs +13 -9
- package/fesm2022/forty-cdk-popover.mjs.map +1 -1
- package/fesm2022/forty-cdk-radio-group.mjs.map +1 -1
- package/fesm2022/forty-cdk-scroll-area.mjs.map +1 -1
- package/fesm2022/forty-cdk-select.mjs +80 -21
- package/fesm2022/forty-cdk-select.mjs.map +1 -1
- package/fesm2022/forty-cdk-table.mjs +1 -15
- package/fesm2022/forty-cdk-table.mjs.map +1 -1
- package/fesm2022/forty-cdk-tabs.mjs +4 -5
- package/fesm2022/forty-cdk-tabs.mjs.map +1 -1
- package/fesm2022/forty-cdk-time-field.mjs.map +1 -1
- package/fesm2022/forty-cdk-time-picker.mjs +85 -12
- package/fesm2022/forty-cdk-time-picker.mjs.map +1 -1
- package/fesm2022/forty-cdk-toast.mjs +0 -1
- package/fesm2022/forty-cdk-toast.mjs.map +1 -1
- package/fesm2022/forty-cdk-tooltip.mjs +13 -4
- package/fesm2022/forty-cdk-tooltip.mjs.map +1 -1
- package/fesm2022/forty-cdk-tree.mjs +0 -5
- package/fesm2022/forty-cdk-tree.mjs.map +1 -1
- package/hover-card/README.md +2 -0
- package/listbox/README.md +20 -7
- package/menu/README.md +1 -2
- package/menubar/README.md +7 -7
- package/navigation-menu/README.md +1 -1
- package/package.json +1 -1
- package/popover/README.md +3 -1
- package/select/README.md +20 -5
- package/shared/README.md +61 -0
- package/stepper/README.md +12 -0
- package/table/README.md +12 -0
- package/tabs/README.md +12 -1
- package/time-picker/README.md +13 -1
- package/tooltip/README.md +2 -0
- package/types/forty-cdk-avatar.d.ts +2 -1
- package/types/forty-cdk-carousel.d.ts +1 -1
- package/types/forty-cdk-combobox.d.ts +23 -35
- package/types/forty-cdk-context-menu.d.ts +22 -37
- package/types/forty-cdk-core-overlay.d.ts +36 -54
- package/types/forty-cdk-core.d.ts +12 -27
- package/types/forty-cdk-date-field.d.ts +8 -8
- package/types/forty-cdk-date-picker.d.ts +23 -31
- package/types/forty-cdk-drag-drop.d.ts +3 -3
- package/types/forty-cdk-hover-card.d.ts +26 -6
- package/types/forty-cdk-listbox.d.ts +43 -14
- package/types/forty-cdk-menu.d.ts +7 -11
- package/types/forty-cdk-menubar.d.ts +0 -2
- package/types/forty-cdk-meter.d.ts +1 -0
- package/types/forty-cdk-navigation-menu.d.ts +7 -9
- package/types/forty-cdk-number-input.d.ts +1 -1
- package/types/forty-cdk-popover.d.ts +27 -18
- package/types/forty-cdk-radio-group.d.ts +1 -1
- package/types/forty-cdk-scroll-area.d.ts +2 -1
- package/types/forty-cdk-select.d.ts +81 -41
- package/types/forty-cdk-table.d.ts +39 -53
- package/types/forty-cdk-tabs.d.ts +12 -13
- package/types/forty-cdk-time-field.d.ts +4 -4
- package/types/forty-cdk-time-picker.d.ts +90 -8
- package/types/forty-cdk-toast.d.ts +4 -5
- package/types/forty-cdk-tooltip.d.ts +22 -7
- package/types/forty-cdk-tree.d.ts +9 -14
- package/virtual-reorder/README.md +0 -1
package/context-menu/README.md
CHANGED
|
@@ -140,7 +140,7 @@ Both triggers carry `[menuPositioning]`, a partial `{ side, align, sideOffset, a
|
|
|
140
140
|
|
|
141
141
|
Same vetoable dismiss API as DropdownMenu. Call `preventDefault()` on the emitted veto to suppress the directive's default action; the original DOM event, when present, is on `.event`.
|
|
142
142
|
|
|
143
|
-
`(autoFocusOnOpen)` / `(autoFocusOnClose)` are output-shape because ContextMenu always routes close transitions through `[(open)]` (via the implicit `openChange` emitter).
|
|
143
|
+
`(autoFocusOnOpen)` / `(autoFocusOnClose)` are output-shape because ContextMenu always routes close transitions through `[(open)]` (via the implicit `openChange` emitter). Dialog and Drawer take callback-shape inputs for the same pair instead: either can be closed by a direct `open.set(false)` that bypasses the `(dismiss)` output entirely, so their close hook has to be a stored function reference that still runs during teardown.
|
|
144
144
|
|
|
145
145
|
### Data attributes
|
|
146
146
|
|
package/dialog/README.md
CHANGED
|
@@ -249,7 +249,7 @@ Keep `dismissible: true` (the default) so Escape still closes, and veto only the
|
|
|
249
249
|
|
|
250
250
|
### Inputs — focus callbacks
|
|
251
251
|
|
|
252
|
-
The auto-focus pair is bound as **function references** (input callbacks), not as event listeners. Each callback receives a `VetoableEvent` whose `preventDefault()` suppresses the directive's default focus action. This shape mirrors `ForDialogManager`'s `config.autoFocusOn*` callbacks and guarantees the `autoFocusOnClose` callback fires reliably on every close path — including a direct `open.set(false)` that bypasses the `(dismiss)` output.
|
|
252
|
+
The auto-focus pair is bound as **function references** (input callbacks), not as event listeners. Each callback receives a `VetoableEvent` whose `preventDefault()` suppresses the directive's default focus action. This shape mirrors `ForDialogManager`'s `config.autoFocusOn*` callbacks and guarantees the `autoFocusOnClose` callback fires reliably on every close path — including a direct `open.set(false)` that bypasses the `(dismiss)` output. The trigger-anchored overlays (Popover, DropdownMenu, Select, …) expose the same pair as **outputs** instead, because every close transition there runs through their own `[(open)]` model, so no path can bypass the emitter.
|
|
253
253
|
|
|
254
254
|
| Property | Type | Description |
|
|
255
255
|
| ------------------ | -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -349,6 +349,16 @@ Implements the [WAI-ARIA Modal Dialog pattern](https://www.w3.org/WAI/ARIA/apg/p
|
|
|
349
349
|
- `alert: true` interrupts assistive tech aggressively — only for genuine alerts (lost connection, unsaved changes warning), not for general confirms.
|
|
350
350
|
- Don't put interactive overlays (popovers, menus) outside the focus trap while a modal dialog is open — they won't be reachable. For a non-modal floating surface anchored to a trigger, use `[forPopover]` instead.
|
|
351
351
|
|
|
352
|
+
## Known limitations
|
|
353
|
+
|
|
354
|
+
Two shapes are correct by design and still break something a consumer can only discover by hitting it. Both live in markup a design system produces routinely, and neither shows up in devtools: every role and `aria-*` stays correct, so the symptom is a keyboard or screen-reader one. The library-wide statement, with the same detail for every primitive, is [Shadow DOM](../shared/README.md#shadow-dom) in `forty-cdk/shared`.
|
|
355
|
+
|
|
356
|
+
**A shadow host that renders a focusable after its `<slot>` breaks the trap's `Tab` cycle.** The trap resolves its first / last pair by walking the surface's composed tree, and that walk visits slotted content after the host's whole shadow tree, whereas the browser sequences it at the `<slot>`'s position. Initial focus can land on a control that is not the visually first one, and a `Tab` at the dialog's real last control is not recognised as the cycle's end — focus leaves the surface (with the page `inert`, usually onto the browser's own UI) and the next `Tab` is pulled back to whichever control the walk thinks is first. That is the configuration you are in whenever you wrap a third-party web component, or your own `ViewEncapsulation.ShadowDom` component, inside the dialog. **Workaround:** render a host's own focusables before its `<slot>`, or project them instead of shadowing them; `initialFocus="container"` fixes the initial-focus half only, since the cycle's edges are re-resolved on every `Tab` press. Details and markup: [Focusable order](../shared/README.md#focusable-order-is-composed-only-for-a-host-that-renders-no-slot).
|
|
357
|
+
|
|
358
|
+
**A `keydown` handler inside the dialog that calls `stopPropagation()` swallows Escape.** The dismissible-layer stack observes `Escape` on `document` in the bubble phase — a deliberate trade-off recorded on `DismissibleLayerStack` — so an event stopped inside the surface never arrives, and `Escape` silently stops dismissing while the backdrop click and `[forDialogClose]` keep working. **Workaround:** narrow the `stopPropagation()` to the keys you actually handle. Keeping the dialog open on `Escape` is the separate, supported job of the vetoable `(escapeKeyDown)` output. Details: [Escape is observed on the bubble phase](../shared/README.md#escape-is-observed-on-the-bubble-phase).
|
|
359
|
+
|
|
360
|
+
A third known limit does not apply to this primitive but is easy to hit inside one: a [Tabs](../tabs) or [Stepper](../stepper) panel rendered in a dialog cannot re-measure its focusable content across a shadow boundary, so its own tab stop can go stale — see [that entry](../shared/README.md#a-panels-focusable-content-measurement-does-not-re-measure-across-a-boundary).
|
|
361
|
+
|
|
352
362
|
## Styling
|
|
353
363
|
|
|
354
364
|
forty-cdk ships no styles. Add your own class to each piece — the `for*` selectors are the behavior API, not a styling contract (see [Styling forty-cdk](../../../docs/styling.md)). Key your CSS off the reflected `data-*` attributes listed per piece in the [API](#api) section.
|
package/drag-drop/README.md
CHANGED
|
@@ -369,8 +369,9 @@ A custom integration that cannot use either companion must supply the same three
|
|
|
369
369
|
mechanisms itself: map window-relative to absolute indices with the reusable
|
|
370
370
|
`translateWindowReorder` helper (`forty-cdk/core`), keep the lifted row mounted
|
|
371
371
|
for the duration of the drag, and step the keyboard target over the true total
|
|
372
|
-
count.
|
|
373
|
-
|
|
372
|
+
count. Miss any one of the three and the failure is silent — an index that
|
|
373
|
+
addresses the wrong row, a lifted row recycled mid-drag, or a keyboard move that
|
|
374
|
+
stops at the window edge.
|
|
374
375
|
|
|
375
376
|
## Data attributes
|
|
376
377
|
|
package/drawer/README.md
CHANGED
|
@@ -581,6 +581,16 @@ Implements the [WAI-ARIA Modal Dialog pattern](https://www.w3.org/WAI/ARIA/apg/p
|
|
|
581
581
|
|
|
582
582
|
Keyboard: **Escape** closes the topmost drawer when `dismissible`; **Tab / Shift+Tab** cycles focus inside the drawer when `modal`; **Click** on `[forDrawerBackdrop]` closes when `dismissible`.
|
|
583
583
|
|
|
584
|
+
## Known limitations
|
|
585
|
+
|
|
586
|
+
Two shapes are correct by design and still break something a consumer can only discover by hitting it. Both live in markup a design system produces routinely, and neither shows up in devtools: every role and `aria-*` stays correct, so the symptom is a keyboard or screen-reader one. The library-wide statement, with the same detail for every primitive, is [Shadow DOM](../shared/README.md#shadow-dom) in `forty-cdk/shared`.
|
|
587
|
+
|
|
588
|
+
**A shadow host that renders a focusable after its `<slot>` breaks the trap's `Tab` cycle.** The trap resolves its first / last pair by walking the surface's composed tree, and that walk visits slotted content after the host's whole shadow tree, whereas the browser sequences it at the `<slot>`'s position. Initial focus can land on a control that is not the visually first one, and a `Tab` at the drawer's real last control is not recognised as the cycle's end — focus leaves the surface (with the page `inert`, usually onto the browser's own UI) and the next `Tab` is pulled back to whichever control the walk thinks is first. That is the configuration you are in whenever you wrap a third-party web component, or your own `ViewEncapsulation.ShadowDom` component, inside the drawer. **Workaround:** render a host's own focusables before its `<slot>`, or project them instead of shadowing them; `initialFocus="container"` fixes the initial-focus half only, since the cycle's edges are re-resolved on every `Tab` press. Details and markup: [Focusable order](../shared/README.md#focusable-order-is-composed-only-for-a-host-that-renders-no-slot).
|
|
589
|
+
|
|
590
|
+
**A `keydown` handler inside the drawer that calls `stopPropagation()` swallows Escape.** The dismissible-layer stack observes `Escape` on `document` in the bubble phase — a deliberate trade-off recorded on `DismissibleLayerStack` — so an event stopped inside the surface never arrives, and `Escape` silently stops dismissing while swipe-to-dismiss, the backdrop click and `[forDrawerClose]` keep working. Only the topmost drawer's `Escape` is affected; see [Nested drawers](#nested-drawers) for the stacking contract. **Workaround:** narrow the `stopPropagation()` to the keys you actually handle. Keeping the drawer open on `Escape` is the separate, supported job of the vetoable `(escapeKeyDown)` output. Details: [Escape is observed on the bubble phase](../shared/README.md#escape-is-observed-on-the-bubble-phase).
|
|
591
|
+
|
|
592
|
+
A third known limit does not apply to this primitive but is easy to hit inside one: a [Tabs](../tabs) or [Stepper](../stepper) panel rendered in a drawer cannot re-measure its focusable content across a shadow boundary, so its own tab stop can go stale — see [that entry](../shared/README.md#a-panels-focusable-content-measurement-does-not-re-measure-across-a-boundary).
|
|
593
|
+
|
|
584
594
|
## Styling
|
|
585
595
|
|
|
586
596
|
forty-cdk ships no styles. Add your own class to each piece — the `for*` selectors are the behavior API, not a styling contract (see [Styling forty-cdk](../../../docs/styling.md)). Key your CSS off the reflected `data-*` attributes listed per piece in the [API](#api) section.
|
package/dropdown-menu/README.md
CHANGED
|
@@ -156,7 +156,7 @@ Angular resolves `ng-template` DI at the template's **declaration** site, not wh
|
|
|
156
156
|
|
|
157
157
|
Every output above is vetoable — each handler receives a `VetoableEvent` (or `VetoableNativeEvent<E>` when there is a native DOM event). Call `preventDefault()` on the emitted veto to suppress the directive's default action; the original DOM event, when present, is on `.event`.
|
|
158
158
|
|
|
159
|
-
`(autoFocusOnOpen)` / `(autoFocusOnClose)` are output-shape because DropdownMenu always routes close transitions through `[(open)]` (via the implicit `openChange` emitter).
|
|
159
|
+
`(autoFocusOnOpen)` / `(autoFocusOnClose)` are output-shape because DropdownMenu always routes close transitions through `[(open)]` (via the implicit `openChange` emitter). Dialog and Drawer take callback-shape inputs for the same pair instead: either can be closed by a direct `open.set(false)` that bypasses the `(dismiss)` output entirely, so their close hook has to be a stored function reference that still runs during teardown.
|
|
160
160
|
|
|
161
161
|
### Data attributes
|
|
162
162
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forty-cdk-avatar.mjs","sources":["../../../projects/forty-cdk/avatar/src/avatar-context.ts","../../../projects/forty-cdk/avatar/src/avatar-defaults.ts","../../../projects/forty-cdk/avatar/src/avatar.ts","../../../projects/forty-cdk/avatar/src/avatar-image.ts","../../../projects/forty-cdk/avatar/src/avatar-fallback.ts","../../../projects/forty-cdk/avatar/src/forty-cdk-avatar.ts"],"sourcesContent":["import { inject, InjectionToken, type Signal } from '@angular/core';\n\nimport { assertRootContext, orphanContextError } from 'forty-cdk/core';\n\n/**\n * Lifecycle stages of the avatar's image:\n * - `idle`: no `src` set yet.\n * - `loading`: `src` set, waiting for the network.\n * - `loaded`: image rendered successfully.\n * - `error`: image failed to load.\n */\nexport type ForAvatarStatus = 'idle' | 'loading' | 'loaded' | 'error';\n\nexport interface ForAvatarContext {\n /** Current status of the avatar's image. */\n readonly status: Signal<ForAvatarStatus>;\n /**\n * `true` when the consumer should render the fallback. Drives `@if` in\n * the consumer's template. Honors `fallbackDelayMs` for `idle` / `loading`\n * states; `error` flips it to `true` immediately.\n */\n readonly shouldShowFallback: Signal<boolean>;\n}\n\n/**\n * The avatar's piece-coordination surface: the one call `[forAvatarImage]`\n * makes so the root can transition its state machine.\n *\n * Deliberately **not** part of {@link ForAvatarContext} and never exported from\n * `public-api.ts` — a consumer drives the status by binding `[src]`, never by\n * reporting a transition into the root.\n */\nexport interface AvatarPieceContext {\n /** Reported by `[forAvatarImage]` so the root can transition its state machine. */\n reportStatus(status: ForAvatarStatus): void;\n}\n\n/**\n * The avatar's internal coordination surface: everything\n * {@link ForAvatarContext} publishes plus the {@link AvatarPieceContext} call.\n *\n * Never exported from `public-api.ts`. It is the type the pieces read\n * {@link FOR_AVATAR_CONTEXT} at, so a consumer who injects that token gets the\n * read surface while `[forAvatarImage]` gets the transition channel. `ForAvatar`\n * declares `reportStatus` TS-`private`, which keeps it out of the emitted\n * `.d.ts` while `useExisting` still satisfies this contract at runtime.\n */\nexport interface AvatarContext extends ForAvatarContext, AvatarPieceContext {}\n\n/**\n * DI token for the avatar's coordination surface, provided by `[forAvatar]`.\n *\n * Publicly typed as the read surface {@link ForAvatarContext}, which is the whole of\n * what the token promises a consumer. `[forAvatarImage]` reads the same token at an\n * internal type that adds the status-report channel, so a wrapper re-providing it must\n * alias it to the root: `{ provide: FOR_AVATAR_CONTEXT, useExisting: MyAvatar }`, where\n * `MyAvatar` extends `ForAvatar`. A value that merely satisfies the declared type\n * resolves too, and is rejected in dev mode by the first piece to reach the channel.\n */\nexport const FOR_AVATAR_CONTEXT = new InjectionToken<ForAvatarContext>('FOR_AVATAR_CONTEXT');\n\n/**\n * The constant half of both resolvers' {@link assertRootContext} calls, so the\n * fallback and the image state the same requirement.\n */\nconst ROOT_ASSERTION = {\n entryPoint: 'avatar',\n token: 'FOR_AVATAR_CONTEXT',\n root: '[forAvatar]',\n};\n\n/**\n * Injects the nearest {@link ForAvatarContext}, throwing a descriptive error\n * when used outside a `[forAvatar]` element.\n *\n * @param piece Name of the calling directive, used in the error message.\n */\nexport function injectAvatarContext(piece: string): AvatarContext {\n const ctx = inject(FOR_AVATAR_CONTEXT, { optional: true });\n if (!ctx) {\n throw orphanContextError({\n code: 'FORCDK-AVATAR-001',\n piece,\n root: '[forAvatar]',\n token: 'FOR_AVATAR_CONTEXT',\n });\n }\n const widened = ctx as AvatarContext;\n assertRootContext({\n ...ROOT_ASSERTION,\n piece,\n probe: () => widened.reportStatus,\n });\n return widened;\n}\n\n/**\n * `[forAvatarImage]`'s own resolver. It reports a distinct failure from the rest\n * of the anatomy — the image is the piece that drives the state machine, so an\n * orphaned one silently never transitions — and therefore carries its own code\n * rather than routing through {@link injectAvatarContext}.\n */\nexport function injectAvatarImageContext(): AvatarContext {\n const ctx = inject(FOR_AVATAR_CONTEXT, { optional: true });\n if (!ctx) {\n throw orphanContextError({\n code: 'FORCDK-AVATAR-002',\n piece: 'ForAvatarImage',\n root: '[forAvatar]',\n token: 'FOR_AVATAR_CONTEXT',\n });\n }\n const widened = ctx as AvatarContext;\n assertRootContext({\n ...ROOT_ASSERTION,\n piece: 'ForAvatarImage',\n probe: () => widened.reportStatus,\n });\n return widened;\n}\n","import { type Provider } from '@angular/core';\n\nimport { createDefaults } from 'forty-cdk/core';\n\n/**\n * Defaults inherited by descendant avatars in the surrounding injector\n * scope. Configure with `provideForAvatarDefaults` either at the\n * application root or in any component's `providers` array; partial\n * overrides merge with the parent scope.\n */\nexport interface ForAvatarDefaults {\n /**\n * Milliseconds to defer the fallback for fast loads, avoiding a brief\n * \"initials → image\" flicker. Set to `0` to show immediately during\n * `idle` / `loading`, or to e.g. `500` to skip rendering during quick\n * cached loads. `error` always shows the fallback immediately.\n */\n fallbackDelayMs: number;\n}\n\n/**\n * Library fallback for avatar defaults, read at the root injector when no\n * consumer has called `provideForAvatarDefaults`. Exported for the shared defaults\n * contract spec; not re-exported from the primitive's public entry.\n */\nexport const FOR_AVATAR_FALLBACK_DEFAULTS: ForAvatarDefaults = {\n fallbackDelayMs: 0,\n};\n\nconst { token, provideDefaults } = createDefaults<ForAvatarDefaults>(\n 'FOR_AVATAR_DEFAULTS',\n FOR_AVATAR_FALLBACK_DEFAULTS,\n);\n\n/** Token holding the resolved avatar defaults for the current scope. */\nexport const FOR_AVATAR_DEFAULTS = token;\n\n/**\n * Configures forty-cdk avatar defaults for this injector scope. Partial\n * overrides inherit unspecified keys from the parent scope (or library\n * defaults at the root).\n */\nexport function provideForAvatarDefaults(defaults: Partial<ForAvatarDefaults> = {}): Provider[] {\n return provideDefaults(defaults);\n}\n","import { isPlatformBrowser } from '@angular/common';\nimport {\n computed,\n DestroyRef,\n Directive,\n effect,\n inject,\n input,\n linkedSignal,\n numberAttribute,\n PLATFORM_ID,\n signal,\n} from '@angular/core';\n\nimport { FOR_AVATAR_CONTEXT, type ForAvatarContext, type ForAvatarStatus } from './avatar-context';\nimport { FOR_AVATAR_DEFAULTS } from './avatar-defaults';\n\n/**\n * Headless avatar root. Tracks the load lifecycle of an inner\n * `[forAvatarImage]` and exposes `status` + `shouldShowFallback` so the\n * consumer can swap the image for fallback content (initials, generic icon)\n * via `@if`.\n *\n * No ARIA role is imposed — avatars are typically presentational. If the\n * surrounding component conveys identity (a person's name in the header,\n * a chat bubble), the consumer should provide an `aria-label` on the\n * relevant ancestor or pair the avatar with visible text.\n *\n * @example\n * ```html\n * <span forAvatar #a=\"forAvatar\" fallbackDelayMs=\"500\">\n * <img forAvatarImage [src]=\"user.avatarUrl\" [alt]=\"user.name\" />\n * @if (a.shouldShowFallback()) {\n * <span forAvatarFallback>{{ user.initials }}</span>\n * }\n * </span>\n * ```\n */\n@Directive({\n selector: '[forAvatar]',\n exportAs: 'forAvatar',\n host: {\n '[attr.data-status]': 'status()',\n },\n providers: [{ provide: FOR_AVATAR_CONTEXT, useExisting: ForAvatar }],\n})\nexport class ForAvatar implements ForAvatarContext {\n readonly #defaults = inject(FOR_AVATAR_DEFAULTS);\n\n /**\n * Milliseconds to defer the fallback for fast loads, avoiding a brief\n * \"initials → image\" flicker. Set to `0` (default) to show immediately\n * during `idle` / `loading`, or to e.g. `500` to skip rendering during\n * quick cached loads. `error` always shows the fallback immediately.\n * The default is read from `provideForAvatarDefaults` for the\n * surrounding scope.\n */\n readonly fallbackDelayMs = input(this.#defaults.fallbackDelayMs, {\n transform: (value: unknown) => {\n const parsed = numberAttribute(value);\n return Number.isFinite(parsed) ? parsed : this.#defaults.fallbackDelayMs;\n },\n });\n\n readonly #status = signal<ForAvatarStatus>('idle');\n readonly status = this.#status.asReadonly();\n\n // Whether the deferred-fallback timer has fired for the current status/delay.\n // `linkedSignal` resets it to `false` whenever the source changes (the\n // canonical replacement for resetting state inside an effect); the timer\n // callback in the constructor flips it to `true`.\n readonly #timerElapsed = linkedSignal<{ status: ForAvatarStatus; delay: number }, boolean>({\n source: () => ({ status: this.#status(), delay: this.fallbackDelayMs() }),\n computation: () => false,\n });\n #timer: ReturnType<typeof setTimeout> | null = null;\n readonly #isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n\n readonly shouldShowFallback = computed(() => {\n const status = this.#status();\n if (status === 'loaded') return false;\n if (status === 'error') return true;\n // idle | loading: an immediate (delay <= 0) gate shows the fallback right\n // away; a deferred gate waits for the timer armed in the effect below.\n if (this.fallbackDelayMs() <= 0) return true;\n return this.#timerElapsed();\n });\n\n private reportStatus(status: ForAvatarStatus): void {\n this.#status.set(status);\n }\n\n constructor() {\n // Imperative timer integration: the effect's only job is to (re)arm a\n // setTimeout for the deferred-fallback case (idle | loading with a positive\n // delay). The synchronous branches (loaded / error / delay <= 0) are pure\n // derivations and live in `shouldShowFallback`. The signal write happens\n // inside the timer callback, which runs outside the effect's reactive\n // scope, so this does NOT create a self-cycle in the reactive graph.\n effect(() => {\n const status = this.#status();\n const delay = this.fallbackDelayMs();\n this.#cancelTimer();\n if (this.#isBrowser && (status === 'idle' || status === 'loading') && delay > 0) {\n this.#timer = setTimeout(() => {\n this.#timer = null;\n this.#timerElapsed.set(true);\n }, delay);\n }\n });\n\n inject(DestroyRef).onDestroy(() => this.#cancelTimer());\n }\n\n #cancelTimer(): void {\n if (this.#timer !== null) {\n clearTimeout(this.#timer);\n this.#timer = null;\n }\n }\n}\n","import { isPlatformBrowser } from '@angular/common';\nimport {\n afterNextRender,\n DestroyRef,\n Directive,\n ElementRef,\n inject,\n output,\n PLATFORM_ID,\n} from '@angular/core';\n\nimport { type ForAvatarStatus, injectAvatarImageContext } from './avatar-context';\n\n/**\n * Wraps an `<img>` and reports its load lifecycle to the surrounding\n * `[forAvatar]`. The native `src` / `alt` bindings are owned by the\n * consumer — this directive only observes.\n *\n * Reflects `data-status` on the image element so the consumer can hide it\n * via CSS while loading or after an error (e.g. `img[data-status=\"error\"]\n * { display: none }`).\n */\n@Directive({\n selector: 'img[forAvatarImage]',\n exportAs: 'forAvatarImage',\n host: {\n '[attr.data-status]': 'status()',\n '(load)': 'onLoad()',\n '(error)': 'onError()',\n },\n})\nexport class ForAvatarImage {\n readonly #host = inject<ElementRef<HTMLImageElement>>(ElementRef).nativeElement;\n readonly #parent = injectAvatarImageContext();\n\n /**\n * Emits whenever the image lifecycle transitions to a new state. Useful\n * if the consumer wants to log analytics, swap to a different src on\n * error, etc.\n */\n readonly loadStatusChange = output<ForAvatarStatus>();\n\n constructor() {\n const parent = this.#parent;\n const host = this.#host;\n\n let destroyed = false;\n inject(DestroyRef).onDestroy(() => (destroyed = true));\n\n afterNextRender(() => {\n this.#syncFromAttr();\n });\n\n if (isPlatformBrowser(inject(PLATFORM_ID)) && typeof MutationObserver !== 'undefined') {\n const observer = new MutationObserver(() => {\n this.#syncFromAttr();\n });\n observer.observe(host, { attributes: true, attributeFilter: ['src'] });\n inject(DestroyRef).onDestroy(() => observer.disconnect());\n }\n\n // Re-emit upstream whenever the parent's status changes due to our writes.\n // De-dupe on the (request, status) pair rather than status alone: a new\n // `src` opens a fresh request token, so an identical status (e.g. a second\n // image that also `loaded`) still re-reports for the new request, while a\n // repeated status within the same request is suppressed.\n let last: ForAvatarStatus | null = null;\n let lastReportedToken = -1;\n const emit = (status: ForAvatarStatus): void => {\n if (destroyed) return;\n if (last === status && lastReportedToken === this.#requestToken) return;\n last = status;\n lastReportedToken = this.#requestToken;\n parent.reportStatus(status);\n this.loadStatusChange.emit(status);\n };\n this.#emit = emit;\n }\n\n protected status(): ForAvatarStatus {\n return this.#parent.status();\n }\n\n protected onLoad(): void {\n // Ignore a `load` that fires for a request the host has already moved past\n // (the native event can arrive after `src` was reassigned).\n if (!this.#isCurrentRequest()) return;\n if (!this.#host.complete) return;\n this.#emit('loaded');\n }\n\n protected onError(): void {\n if (!this.#isCurrentRequest()) return;\n if (!this.#host.complete) return;\n this.#emit('error');\n }\n\n /**\n * Cheap string-identity fast-path: true when the `src` the host currently\n * carries is the one the latest `#syncFromAttr` observed, so a native\n * load/error event has not drifted away from the in-flight request. This\n * proves src-attribute stability only; request *completeness* (a late event\n * from a superseded resource that happens to share the current src) is\n * verified separately in onLoad/onError via `this.#host.complete`.\n */\n #isCurrentRequest(): boolean {\n return this.#host.getAttribute('src') === this.#requestSrc;\n }\n\n #syncFromAttr(): void {\n const src = this.#host.getAttribute('src');\n this.#requestToken++;\n this.#requestSrc = src;\n if (!src) {\n this.#emit('idle');\n return;\n }\n if (this.#host.complete) {\n // Cached image: load/error events may not fire — derive from naturalWidth.\n if (this.#host.naturalWidth > 0) {\n this.#emit('loaded');\n return;\n }\n // A complete image with zero intrinsic width is ambiguous: it may be a\n // broken image OR a valid SVG with no intrinsic dimensions. Don't\n // pessimistically flag `error` and hide a valid image — verify with\n // `decode()`, which resolves for a decodable (even zero-size) image and\n // rejects for a broken one. Stay `loading` until it settles.\n this.#emit('loading');\n this.#verifyCachedZeroSize(src);\n return;\n }\n this.#emit('loading');\n }\n\n #verifyCachedZeroSize(src: string): void {\n const decode = this.#host.decode?.bind(this.#host);\n if (!decode) {\n // No `decode()` (older engines / jsdom): keep the legacy heuristic.\n this.#emit('error');\n return;\n }\n decode().then(\n () => {\n if (this.#host.getAttribute('src') === src) {\n this.#emit('loaded');\n }\n },\n () => {\n if (this.#host.getAttribute('src') === src) {\n this.#emit('error');\n }\n },\n );\n }\n\n // Initialized in constructor.\n #emit!: (status: ForAvatarStatus) => void;\n\n /** Monotonic id bumped on every `src` change so stale events are ignored. */\n #requestToken = 0;\n /** The `src` the latest `#syncFromAttr` observed, used to match native events. */\n #requestSrc: string | null = null;\n}\n","import { Directive } from '@angular/core';\n\nimport { injectAvatarContext } from './avatar-context';\n\n/**\n * Marker for the avatar's fallback content (initials, generic icon, …).\n * Reflects `data-status` from the parent `[forAvatar]` so the consumer can\n * style for the `error` state separately from `idle` / `loading` if needed.\n *\n * The decision of *whether* to render the fallback lives on the root —\n * drive `@if` with `forAvatar.shouldShowFallback()`.\n */\n@Directive({\n selector: '[forAvatarFallback]',\n exportAs: 'forAvatarFallback',\n host: {\n '[attr.data-status]': 'parent.status()',\n },\n})\nexport class ForAvatarFallback {\n protected readonly parent = injectAvatarContext('ForAvatarFallback');\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"forty-cdk-avatar.mjs","sources":["../../../projects/forty-cdk/avatar/src/avatar-context.ts","../../../projects/forty-cdk/avatar/src/avatar-defaults.ts","../../../projects/forty-cdk/avatar/src/avatar.ts","../../../projects/forty-cdk/avatar/src/avatar-image.ts","../../../projects/forty-cdk/avatar/src/avatar-fallback.ts","../../../projects/forty-cdk/avatar/src/forty-cdk-avatar.ts"],"sourcesContent":["import { inject, InjectionToken, type Signal } from '@angular/core';\n\nimport { assertRootContext, orphanContextError } from 'forty-cdk/core';\n\n/**\n * Lifecycle stages of the avatar's image:\n * - `idle`: no `src` set yet.\n * - `loading`: `src` set, waiting for the network.\n * - `loaded`: image rendered successfully.\n * - `error`: image failed to load.\n */\nexport type ForAvatarStatus = 'idle' | 'loading' | 'loaded' | 'error';\n\n/** Read surface `[forAvatar]` publishes through {@link FOR_AVATAR_CONTEXT}. */\nexport interface ForAvatarContext {\n /** Current status of the avatar's image. */\n readonly status: Signal<ForAvatarStatus>;\n /**\n * `true` when the consumer should render the fallback. Drives `@if` in\n * the consumer's template. Honors `fallbackDelayMs` for `idle` / `loading`\n * states; `error` flips it to `true` immediately.\n */\n readonly shouldShowFallback: Signal<boolean>;\n}\n\n/**\n * The avatar's piece-coordination surface: the one call `[forAvatarImage]`\n * makes so the root can transition its state machine.\n *\n * **Not** part of {@link ForAvatarContext} and never exported from\n * `public-api.ts` — a consumer drives the status by binding `[src]`, never by\n * reporting a transition into the root.\n */\nexport interface AvatarPieceContext {\n /** Reported by `[forAvatarImage]` so the root can transition its state machine. */\n reportStatus(status: ForAvatarStatus): void;\n}\n\n/**\n * The avatar's internal coordination surface: everything\n * {@link ForAvatarContext} publishes plus the {@link AvatarPieceContext} call.\n *\n * Never exported from `public-api.ts`. It is the type the pieces read\n * {@link FOR_AVATAR_CONTEXT} at, so a consumer who injects that token gets the\n * read surface while `[forAvatarImage]` gets the transition channel. `ForAvatar`\n * declares `reportStatus` TS-`private`, which keeps it out of the emitted\n * `.d.ts` while `useExisting` still satisfies this contract at runtime.\n */\nexport interface AvatarContext extends ForAvatarContext, AvatarPieceContext {}\n\n/**\n * DI token for the avatar's coordination surface, provided by `[forAvatar]`.\n *\n * Publicly typed as the read surface {@link ForAvatarContext}, which is the whole of\n * what the token promises a consumer. `[forAvatarImage]` reads the same token at an\n * internal type that adds the status-report channel, so a wrapper re-providing it must\n * alias it to the root: `{ provide: FOR_AVATAR_CONTEXT, useExisting: MyAvatar }`, where\n * `MyAvatar` extends `ForAvatar`. A value that merely satisfies the declared type\n * resolves too, and is rejected in dev mode by the first piece to reach the channel.\n */\nexport const FOR_AVATAR_CONTEXT = new InjectionToken<ForAvatarContext>('FOR_AVATAR_CONTEXT');\n\n/**\n * The constant half of both resolvers' {@link assertRootContext} calls, so the\n * fallback and the image state the same requirement.\n */\nconst ROOT_ASSERTION = {\n entryPoint: 'avatar',\n token: 'FOR_AVATAR_CONTEXT',\n root: '[forAvatar]',\n};\n\n/**\n * Injects the nearest {@link ForAvatarContext}, throwing a descriptive error\n * when used outside a `[forAvatar]` element.\n *\n * @param piece Name of the calling directive, used in the error message.\n */\nexport function injectAvatarContext(piece: string): AvatarContext {\n const ctx = inject(FOR_AVATAR_CONTEXT, { optional: true });\n if (!ctx) {\n throw orphanContextError({\n code: 'FORCDK-AVATAR-001',\n piece,\n root: '[forAvatar]',\n token: 'FOR_AVATAR_CONTEXT',\n });\n }\n const widened = ctx as AvatarContext;\n assertRootContext({\n ...ROOT_ASSERTION,\n piece,\n probe: () => widened.reportStatus,\n });\n return widened;\n}\n\n/**\n * `[forAvatarImage]`'s own resolver. It reports a distinct failure from the rest\n * of the anatomy — the image is the piece that drives the state machine, so an\n * orphaned one silently never transitions — and therefore carries its own code\n * rather than routing through {@link injectAvatarContext}.\n */\nexport function injectAvatarImageContext(): AvatarContext {\n const ctx = inject(FOR_AVATAR_CONTEXT, { optional: true });\n if (!ctx) {\n throw orphanContextError({\n code: 'FORCDK-AVATAR-002',\n piece: 'ForAvatarImage',\n root: '[forAvatar]',\n token: 'FOR_AVATAR_CONTEXT',\n });\n }\n const widened = ctx as AvatarContext;\n assertRootContext({\n ...ROOT_ASSERTION,\n piece: 'ForAvatarImage',\n probe: () => widened.reportStatus,\n });\n return widened;\n}\n","import { type Provider } from '@angular/core';\n\nimport { createDefaults } from 'forty-cdk/core';\n\n/**\n * Defaults inherited by descendant avatars in the surrounding injector\n * scope. Configure with `provideForAvatarDefaults` either at the\n * application root or in any component's `providers` array; partial\n * overrides merge with the parent scope.\n */\nexport interface ForAvatarDefaults {\n /**\n * Milliseconds to defer the fallback for fast loads, avoiding a brief\n * \"initials → image\" flicker. Set to `0` to show immediately during\n * `idle` / `loading`, or to e.g. `500` to skip rendering during quick\n * cached loads. `error` always shows the fallback immediately.\n */\n fallbackDelayMs: number;\n}\n\n/**\n * Library fallback for avatar defaults, read at the root injector when no\n * consumer has called `provideForAvatarDefaults`. Exported for the shared defaults\n * contract spec; not re-exported from the primitive's public entry.\n */\nexport const FOR_AVATAR_FALLBACK_DEFAULTS: ForAvatarDefaults = {\n fallbackDelayMs: 0,\n};\n\nconst { token, provideDefaults } = createDefaults<ForAvatarDefaults>(\n 'FOR_AVATAR_DEFAULTS',\n FOR_AVATAR_FALLBACK_DEFAULTS,\n);\n\n/** Token holding the resolved avatar defaults for the current scope. */\nexport const FOR_AVATAR_DEFAULTS = token;\n\n/**\n * Configures forty-cdk avatar defaults for this injector scope. Partial\n * overrides inherit unspecified keys from the parent scope (or library\n * defaults at the root).\n */\nexport function provideForAvatarDefaults(defaults: Partial<ForAvatarDefaults> = {}): Provider[] {\n return provideDefaults(defaults);\n}\n","import { isPlatformBrowser } from '@angular/common';\nimport {\n computed,\n DestroyRef,\n Directive,\n effect,\n inject,\n input,\n linkedSignal,\n numberAttribute,\n PLATFORM_ID,\n signal,\n} from '@angular/core';\n\nimport { FOR_AVATAR_CONTEXT, type ForAvatarContext, type ForAvatarStatus } from './avatar-context';\nimport { FOR_AVATAR_DEFAULTS } from './avatar-defaults';\n\n/**\n * Headless avatar root. Tracks the load lifecycle of an inner\n * `[forAvatarImage]` and exposes `status` + `shouldShowFallback` so the\n * consumer can swap the image for fallback content (initials, generic icon)\n * via `@if`.\n *\n * No ARIA role is imposed — avatars are typically presentational. If the\n * surrounding component conveys identity (a person's name in the header,\n * a chat bubble), the consumer should provide an `aria-label` on the\n * relevant ancestor or pair the avatar with visible text.\n *\n * @example\n * ```html\n * <span forAvatar #a=\"forAvatar\" fallbackDelayMs=\"500\">\n * <img forAvatarImage [src]=\"user.avatarUrl\" [alt]=\"user.name\" />\n * @if (a.shouldShowFallback()) {\n * <span forAvatarFallback>{{ user.initials }}</span>\n * }\n * </span>\n * ```\n */\n@Directive({\n selector: '[forAvatar]',\n exportAs: 'forAvatar',\n host: {\n '[attr.data-status]': 'status()',\n },\n providers: [{ provide: FOR_AVATAR_CONTEXT, useExisting: ForAvatar }],\n})\nexport class ForAvatar implements ForAvatarContext {\n readonly #defaults = inject(FOR_AVATAR_DEFAULTS);\n\n /**\n * Milliseconds to defer the fallback for fast loads, avoiding a brief\n * \"initials → image\" flicker. Set to `0` (default) to show immediately\n * during `idle` / `loading`, or to e.g. `500` to skip rendering during\n * quick cached loads. `error` always shows the fallback immediately.\n * The default is read from `provideForAvatarDefaults` for the\n * surrounding scope.\n */\n readonly fallbackDelayMs = input(this.#defaults.fallbackDelayMs, {\n transform: (value: unknown) => {\n const parsed = numberAttribute(value);\n return Number.isFinite(parsed) ? parsed : this.#defaults.fallbackDelayMs;\n },\n });\n\n readonly #status = signal<ForAvatarStatus>('idle');\n readonly status = this.#status.asReadonly();\n\n // Whether the deferred-fallback timer has fired for the current status/delay.\n // `linkedSignal` resets it to `false` whenever the source changes (the\n // canonical replacement for resetting state inside an effect); the timer\n // callback in the constructor flips it to `true`.\n readonly #timerElapsed = linkedSignal<{ status: ForAvatarStatus; delay: number }, boolean>({\n source: () => ({ status: this.#status(), delay: this.fallbackDelayMs() }),\n computation: () => false,\n });\n #timer: ReturnType<typeof setTimeout> | null = null;\n readonly #isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n\n readonly shouldShowFallback = computed(() => {\n const status = this.#status();\n if (status === 'loaded') return false;\n if (status === 'error') return true;\n // idle | loading: an immediate (delay <= 0) gate shows the fallback right\n // away; a deferred gate waits for the timer armed in the effect below.\n if (this.fallbackDelayMs() <= 0) return true;\n return this.#timerElapsed();\n });\n\n private reportStatus(status: ForAvatarStatus): void {\n this.#status.set(status);\n }\n\n constructor() {\n // Imperative timer integration: the effect's only job is to (re)arm a\n // setTimeout for the deferred-fallback case (idle | loading with a positive\n // delay). The synchronous branches (loaded / error / delay <= 0) are pure\n // derivations and live in `shouldShowFallback`. The signal write happens\n // inside the timer callback, which runs outside the effect's reactive\n // scope, so this does NOT create a self-cycle in the reactive graph.\n effect(() => {\n const status = this.#status();\n const delay = this.fallbackDelayMs();\n this.#cancelTimer();\n if (this.#isBrowser && (status === 'idle' || status === 'loading') && delay > 0) {\n this.#timer = setTimeout(() => {\n this.#timer = null;\n this.#timerElapsed.set(true);\n }, delay);\n }\n });\n\n inject(DestroyRef).onDestroy(() => this.#cancelTimer());\n }\n\n #cancelTimer(): void {\n if (this.#timer !== null) {\n clearTimeout(this.#timer);\n this.#timer = null;\n }\n }\n}\n","import { isPlatformBrowser } from '@angular/common';\nimport {\n afterNextRender,\n DestroyRef,\n Directive,\n ElementRef,\n inject,\n output,\n PLATFORM_ID,\n} from '@angular/core';\n\nimport { type ForAvatarStatus, injectAvatarImageContext } from './avatar-context';\n\n/**\n * Wraps an `<img>` and reports its load lifecycle to the surrounding\n * `[forAvatar]`. The native `src` / `alt` bindings are owned by the\n * consumer — this directive only observes.\n *\n * Reflects `data-status` on the image element so the consumer can hide it\n * via CSS while loading or after an error (e.g. `img[data-status=\"error\"]\n * { display: none }`).\n */\n@Directive({\n selector: 'img[forAvatarImage]',\n exportAs: 'forAvatarImage',\n host: {\n '[attr.data-status]': 'status()',\n '(load)': 'onLoad()',\n '(error)': 'onError()',\n },\n})\nexport class ForAvatarImage {\n readonly #host = inject<ElementRef<HTMLImageElement>>(ElementRef).nativeElement;\n readonly #parent = injectAvatarImageContext();\n\n /**\n * Emits whenever the image lifecycle transitions to a new state. Useful\n * if the consumer wants to log analytics, swap to a different src on\n * error, etc.\n */\n readonly loadStatusChange = output<ForAvatarStatus>();\n\n constructor() {\n const parent = this.#parent;\n const host = this.#host;\n\n let destroyed = false;\n inject(DestroyRef).onDestroy(() => (destroyed = true));\n\n afterNextRender(() => {\n this.#syncFromAttr();\n });\n\n if (isPlatformBrowser(inject(PLATFORM_ID)) && typeof MutationObserver !== 'undefined') {\n const observer = new MutationObserver(() => {\n this.#syncFromAttr();\n });\n observer.observe(host, { attributes: true, attributeFilter: ['src'] });\n inject(DestroyRef).onDestroy(() => observer.disconnect());\n }\n\n // Re-emit upstream whenever the parent's status changes due to our writes.\n // De-dupe on the (request, status) pair rather than status alone: a new\n // `src` opens a fresh request token, so an identical status (e.g. a second\n // image that also `loaded`) still re-reports for the new request, while a\n // repeated status within the same request is suppressed.\n let last: ForAvatarStatus | null = null;\n let lastReportedToken = -1;\n const emit = (status: ForAvatarStatus): void => {\n if (destroyed) return;\n if (last === status && lastReportedToken === this.#requestToken) return;\n last = status;\n lastReportedToken = this.#requestToken;\n parent.reportStatus(status);\n this.loadStatusChange.emit(status);\n };\n this.#emit = emit;\n }\n\n protected status(): ForAvatarStatus {\n return this.#parent.status();\n }\n\n protected onLoad(): void {\n // Ignore a `load` that fires for a request the host has already moved past\n // (the native event can arrive after `src` was reassigned).\n if (!this.#isCurrentRequest()) return;\n if (!this.#host.complete) return;\n this.#emit('loaded');\n }\n\n protected onError(): void {\n if (!this.#isCurrentRequest()) return;\n if (!this.#host.complete) return;\n this.#emit('error');\n }\n\n /**\n * Cheap string-identity fast-path: true when the `src` the host currently\n * carries is the one the latest `#syncFromAttr` observed, so a native\n * load/error event has not drifted away from the in-flight request. This\n * proves src-attribute stability only; request *completeness* (a late event\n * from a superseded resource that happens to share the current src) is\n * verified separately in onLoad/onError via `this.#host.complete`.\n */\n #isCurrentRequest(): boolean {\n return this.#host.getAttribute('src') === this.#requestSrc;\n }\n\n #syncFromAttr(): void {\n const src = this.#host.getAttribute('src');\n this.#requestToken++;\n this.#requestSrc = src;\n if (!src) {\n this.#emit('idle');\n return;\n }\n if (this.#host.complete) {\n // Cached image: load/error events may not fire — derive from naturalWidth.\n if (this.#host.naturalWidth > 0) {\n this.#emit('loaded');\n return;\n }\n // A complete image with zero intrinsic width is ambiguous: it may be a\n // broken image OR a valid SVG with no intrinsic dimensions. Don't\n // pessimistically flag `error` and hide a valid image — verify with\n // `decode()`, which resolves for a decodable (even zero-size) image and\n // rejects for a broken one. Stay `loading` until it settles.\n this.#emit('loading');\n this.#verifyCachedZeroSize(src);\n return;\n }\n this.#emit('loading');\n }\n\n #verifyCachedZeroSize(src: string): void {\n const decode = this.#host.decode?.bind(this.#host);\n if (!decode) {\n // No `decode()` (older engines / jsdom): keep the legacy heuristic.\n this.#emit('error');\n return;\n }\n decode().then(\n () => {\n if (this.#host.getAttribute('src') === src) {\n this.#emit('loaded');\n }\n },\n () => {\n if (this.#host.getAttribute('src') === src) {\n this.#emit('error');\n }\n },\n );\n }\n\n // Initialized in constructor.\n #emit!: (status: ForAvatarStatus) => void;\n\n /** Monotonic id bumped on every `src` change so stale events are ignored. */\n #requestToken = 0;\n /** The `src` the latest `#syncFromAttr` observed, used to match native events. */\n #requestSrc: string | null = null;\n}\n","import { Directive } from '@angular/core';\n\nimport { injectAvatarContext } from './avatar-context';\n\n/**\n * Marker for the avatar's fallback content (initials, generic icon, …).\n * Reflects `data-status` from the parent `[forAvatar]` so the consumer can\n * style for the `error` state separately from `idle` / `loading` if needed.\n *\n * The decision of *whether* to render the fallback lives on the root —\n * drive `@if` with `forAvatar.shouldShowFallback()`.\n */\n@Directive({\n selector: '[forAvatarFallback]',\n exportAs: 'forAvatarFallback',\n host: {\n '[attr.data-status]': 'parent.status()',\n },\n})\nexport class ForAvatarFallback {\n protected readonly parent = injectAvatarContext('ForAvatarFallback');\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|