@flyos/design-system 1.7.0 → 1.8.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.
@@ -1779,8 +1779,11 @@ declare class I18nService {
1779
1779
  * is a safe default that an integrator can override without coordination.
1780
1780
  *
1781
1781
  * Scope: only the keys the **shippable** DS components reference today
1782
- * (`common.*` toolbar/link/emoji-picker labels + `agent.lookup.*` + `select.*` + `typeahead.*` + `cron.*` + `gantt.*` + `form.*` + `captcha.*` + `comment.*` + `canvas_board.*` + `moderation.*` + `people_picker.*` + `pagination.*` + `tree_nav.*`). When a new DS component
1783
- * starts using `| translate`, add its keys here so it stays self-sufficient.
1782
+ * (`common.*` toolbar/link/emoji-picker labels + `agent.lookup.*` + `select.*` + `typeahead.*` + `cron.*` + `gantt.*` + `form.*` + `captcha.*` + `comment.*` + `canvas_board.*` + `moderation.*` + `people_picker.*` + `currency_selector.*` + `pagination.*` + `tree_nav.*` + `magic_actions.*`). When a new DS component
1783
+ * starts using `| translate` **or `I18nService.t()`**, add its keys here so it stays
1784
+ * self-sufficient — `fly-magic-actions` shipped resolving three keys that existed only in the
1785
+ * shell bundle, so an External App rendering it got the raw key string as every disabled
1786
+ * tooltip and every radio-menu trigger's accessible name (S1-review F5).
1784
1787
  * Values are copied verbatim from the shell's `public/locale/*.json` — keep
1785
1788
  * them in sync if either side changes.
1786
1789
  */
@@ -4407,6 +4410,18 @@ interface ContextMenuItem {
4407
4410
  * further children, each rendered as another nested `fly-context-menu` instance.
4408
4411
  */
4409
4412
  children?: ContextMenuItem[];
4413
+ /**
4414
+ * Set on EVERY item of a mutually-exclusive group (e.g. a Status/Sort radio menu) to opt
4415
+ * that whole group into radio semantics: `undefined` (default, omitted) renders the plain
4416
+ * `role="menuitem"` row this component always has; a `boolean` here renders
4417
+ * `role="menuitemradio"` with `aria-checked` and the selected row's 600-weight + accent-
4418
+ * check treatment (skill §6 "selected --w08 + 600 + accent check"). Additive — a caller
4419
+ * that never sets this sees no change. The row's own `icon` is untouched and keeps
4420
+ * rendering as today; the accent check this adds is a SEPARATE trailing indicator, so a
4421
+ * caller mid-migration (still passing `icon: 'pi-check'` on the selected row) does not get
4422
+ * a doubled glyph in the leading position — only a second, dedicated one at the row's end.
4423
+ */
4424
+ selected?: boolean;
4410
4425
  }
4411
4426
  interface ContextMenuSection {
4412
4427
  label?: string;
@@ -4470,7 +4485,7 @@ declare class ContextMenuComponent implements AfterViewInit, OnDestroy {
4470
4485
  align: _angular_core.InputSignal<ContextMenuAlign>;
4471
4486
  /** See {@link ContextMenuPlacement}. Ignored without an `[anchor]`. */
4472
4487
  placement: _angular_core.InputSignal<ContextMenuPlacement>;
4473
- sections: _angular_core.InputSignal<ContextMenuSection[]>;
4488
+ sections: _angular_core.InputSignal<readonly ContextMenuSection[]>;
4474
4489
  /**
4475
4490
  * Optional containing rect (viewport coords, e.g. from
4476
4491
  * `el.getBoundingClientRect()`) to keep the menu inside — for menus opened
@@ -5072,6 +5087,16 @@ type FlyDrawerSize = 'sm' | 'md' | 'lg' | 'xl';
5072
5087
  type FlyDrawerSide = 'end' | 'start';
5073
5088
  /** Standard body padding tier. `none` = full-bleed (consumer draws its own). */
5074
5089
  type FlyDrawerBodyPadding = 'none' | 'sm' | 'md' | 'lg';
5090
+ /**
5091
+ * `'side'` (default) — the classic edge-pinned panel, sliding in along the inline axis
5092
+ * (see {@link FlyDrawerSide}). `'sheet'` — a bottom-anchored panel spanning the full
5093
+ * inline size, sliding up from the block-end edge with rounded top corners; `side` is
5094
+ * ignored in this mode (there is no edge to pick — a sheet always anchors to the
5095
+ * bottom). Stage 5 of the UX-refresh program converts every `side` drawer to a `sheet`
5096
+ * on mobile; this variant is the primitive that makes that conversion a per-consumer
5097
+ * `variant` flip rather than a second component.
5098
+ */
5099
+ type FlyDrawerVariant = 'side' | 'sheet';
5075
5100
  /**
5076
5101
  * Where the drawer is anchored.
5077
5102
  * - `absolute` (default) — clipped to the nearest positioned ancestor, i.e. the
@@ -5123,8 +5148,10 @@ declare class FlyDrawerComponent {
5123
5148
  readonly size: _angular_core.InputSignal<FlyDrawerSize>;
5124
5149
  /** Convenience title shown in the default header (ignored if `[flyDrawerHeader]` is projected). Treated as an i18n key. */
5125
5150
  readonly heading: _angular_core.InputSignal<string | null>;
5126
- /** Edge to pin to. `end` (default) slides from inline-end; RTL flips it. */
5151
+ /** Edge to pin to. `end` (default) slides from inline-end; RTL flips it. Ignored when `variant` is `sheet`. */
5127
5152
  readonly side: _angular_core.InputSignal<FlyDrawerSide>;
5153
+ /** `side` (default, edge-pinned) or `sheet` (bottom-anchored, full-width). See {@link FlyDrawerVariant}. */
5154
+ readonly variant: _angular_core.InputSignal<FlyDrawerVariant>;
5128
5155
  /** Close when the scrim is clicked. */
5129
5156
  readonly dismissOnScrim: _angular_core.InputSignal<boolean>;
5130
5157
  /** Close on Escape. */
@@ -5158,9 +5185,10 @@ declare class FlyDrawerComponent {
5158
5185
  * which can race the leaving toggle and stutter the animation). */
5159
5186
  readonly panelClass: _angular_core.Signal<{
5160
5187
  [x: string]: boolean;
5188
+ 'fly-drawer__panel--sheet': boolean;
5161
5189
  }>;
5162
- /** Name of the exit keyframe — used to ignore bubbled child animationend events. */
5163
- private static readonly EXIT_ANIM;
5190
+ /** Exit keyframe names one per variant — used to ignore bubbled child animationend events. */
5191
+ private static readonly EXIT_ANIMS;
5164
5192
  /** Element focused before the drawer opened, restored on close. */
5165
5193
  private previouslyFocused;
5166
5194
  /** Parent element whose overflow we lock while open. */
@@ -5181,7 +5209,7 @@ declare class FlyDrawerComponent {
5181
5209
  private releaseScrollLock;
5182
5210
  private restoreFocus;
5183
5211
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<FlyDrawerComponent, never>;
5184
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlyDrawerComponent, "fly-drawer", never, { "open": { "alias": "open"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "heading": { "alias": "heading"; "required": false; "isSignal": true; }; "side": { "alias": "side"; "required": false; "isSignal": true; }; "dismissOnScrim": { "alias": "dismissOnScrim"; "required": false; "isSignal": true; }; "dismissOnEscape": { "alias": "dismissOnEscape"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "hideCloseButton": { "alias": "hideCloseButton"; "required": false; "isSignal": true; }; "bodyPadding": { "alias": "bodyPadding"; "required": false; "isSignal": true; }; "position": { "alias": "position"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; "isSignal": true; }; }, { "closed": "closed"; "openChange": "openChange"; }, never, ["[flyDrawerHeader]", "*", "[flyDrawerFooter]"], true, never>;
5212
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlyDrawerComponent, "fly-drawer", never, { "open": { "alias": "open"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "heading": { "alias": "heading"; "required": false; "isSignal": true; }; "side": { "alias": "side"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "dismissOnScrim": { "alias": "dismissOnScrim"; "required": false; "isSignal": true; }; "dismissOnEscape": { "alias": "dismissOnEscape"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "hideCloseButton": { "alias": "hideCloseButton"; "required": false; "isSignal": true; }; "bodyPadding": { "alias": "bodyPadding"; "required": false; "isSignal": true; }; "position": { "alias": "position"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; "isSignal": true; }; }, { "closed": "closed"; "openChange": "openChange"; }, never, ["[flyDrawerHeader]", "*", "[flyDrawerFooter]"], true, never>;
5185
5213
  }
5186
5214
 
5187
5215
  /**
@@ -5363,6 +5391,16 @@ interface FlySelectRenderGroup {
5363
5391
  key: string | null;
5364
5392
  options: FlySelectOption[];
5365
5393
  }
5394
+ /** Resolved fixed-position geometry for the portaled panel. */
5395
+ interface FlySelectPanelPosition {
5396
+ readonly top: number | null;
5397
+ readonly bottom: number | null;
5398
+ readonly left: number | null;
5399
+ readonly right: number | null;
5400
+ readonly minWidth: number;
5401
+ readonly maxHeight: number;
5402
+ readonly flipAbove: boolean;
5403
+ }
5366
5404
  /**
5367
5405
  * **`fly-select`** — the design-system searchable select / combobox.
5368
5406
  *
@@ -5378,12 +5416,29 @@ interface FlySelectRenderGroup {
5378
5416
  * each input defaults to the `select.*` key in `DS_BASELINE_LOCALES` (en/ar/fr/ur), and passing the
5379
5417
  * input still wins. It used to default to a hardcoded English literal that every consumer had to
5380
5418
  * remember to override — none did, so a searchable select read "Search…" under ar/fr/ur.
5381
- * Styling uses DS theme tokens (`--surface-card`,
5382
- * `--surface-border`, `--text-color`, `--primary-color`, …) with light-neutral fallbacks so it stays
5383
- * readable in consumers that haven't mapped the tokens.
5384
- *
5385
- * Pattern mirrors {@link EntityLookupComponent}: an absolutely-positioned panel (no CDK Overlay),
5386
- * signal-driven `activeIndex` keyboard nav, and a `document:mousedown` click-outside guard.
5419
+ * Styling composes the Nova token language (`--w*` ramp, `--accent`, `nova-glass.popover`) — see
5420
+ * `skills/desktop-design-language.md` §3.2 and `.workflow/plans/ux-refresh/notes/S1.7-form-family.md`.
5421
+ *
5422
+ * **Positioning (S1.7 — Nova):** the panel is `position: fixed`, measured from the trigger, and
5423
+ * **portaled to `<body>`** the same way {@link ContextMenuComponent} escapes a clipping/glass
5424
+ * ancestor — see that file's `ngAfterViewInit` for the precedent. Two DS-1.x findings this fixes:
5425
+ * the panel used to be `position: absolute` against a `position: relative` host, which is immune to
5426
+ * the transformed-ancestor trap but vulnerable to an `overflow: hidden` ancestor (a drawer body, an
5427
+ * app-window panel) clipping it; and `nova-glass.popover` puts `backdrop-filter` on the listbox,
5428
+ * and a `backdrop-filter` ancestor (e.g. a glass drawer) turns into a *backdrop root* — a nested
5429
+ * `backdrop-filter` then samples the ancestor's own painted content instead of the wallpaper and
5430
+ * reads as flat mud. Body-parenting resolves BOTH at once: once the panel is a direct child of
5431
+ * `<body>` it is no longer a descendant of any clipping or glass ancestor, so it escapes the clip
5432
+ * *and* is never "nested" glass — no `$nested: true` needed, the full translucent recipe renders
5433
+ * correctly every time. The panel flips above the trigger when fewer than 180px of room remains
5434
+ * below it, clamps its `max-height` into 120–242px, and closes (not repositions — D2 §3.2) on any
5435
+ * outside pointerdown (capture phase, so it isn't defeated by an inner `stopPropagation`), any
5436
+ * ancestor scroll (capture phase — scroll doesn't bubble, and a select routinely sits inside a
5437
+ * scrolling drawer body), or a window resize. Mirrors {@link FlyTooltipDirective}'s scroll/resize
5438
+ * dismiss idiom.
5439
+ *
5440
+ * Pattern mirrors {@link EntityLookupComponent}: no CDK Overlay, signal-driven `activeIndex`
5441
+ * keyboard nav.
5387
5442
  */
5388
5443
  declare class FlySelectComponent implements ControlValueAccessor {
5389
5444
  private readonly host;
@@ -5434,9 +5489,37 @@ declare class FlySelectComponent implements ControlValueAccessor {
5434
5489
  private _touched;
5435
5490
  private readonly searchEl?;
5436
5491
  private readonly triggerEl?;
5492
+ /** Signal query (not a decorator): the panel is created/destroyed by the template's `@if`, and the
5493
+ * portal effect below needs to react every time a NEW instance mounts, not just once at init. */
5494
+ private readonly panelEl;
5495
+ private readonly document;
5496
+ private readonly destroyRef;
5497
+ /** Trigger geometry sampled at open time (and cleared on close) — the only input the fixed
5498
+ * position math needs. Re-sampled on open, never on scroll/resize: those close the panel
5499
+ * instead of repositioning it (D2 §3.2), so there is nothing to keep in sync while it's up. */
5500
+ private readonly _triggerRect;
5501
+ private readonly _triggerRtl;
5437
5502
  private _onChange;
5438
5503
  private _onTouched;
5504
+ private readonly _onOutsidePointerDown;
5505
+ private readonly _onOutsideScroll;
5506
+ private readonly _onWindowResize;
5507
+ constructor();
5508
+ /** Registered only while open (mirrors {@link FlyTooltipDirective}'s show/hide discipline) —
5509
+ * a page can carry many selects, and there is no reason for a closed one to keep three
5510
+ * window-level listeners live. */
5511
+ private _attachDismissListeners;
5512
+ private _detachDismissListeners;
5439
5513
  readonly effectiveDisabled: _angular_core.Signal<boolean>;
5514
+ /**
5515
+ * Fixed-position geometry for the panel, computed purely from the trigger rect sampled at open
5516
+ * time — no post-render measurement pass. Flips above the trigger under 180px of room below (and
5517
+ * only when there's MORE room above), clamps `max-height` into 120–242px, and anchors the panel's
5518
+ * reading-start edge to the trigger's reading-start edge (RTL-aware), growing toward reading-end —
5519
+ * the same anchor behaviour the CSS `inset-inline: 0 auto` gave it before it needed a physical
5520
+ * `position: fixed` value to escape its ancestor.
5521
+ */
5522
+ readonly panelPosition: _angular_core.Signal<FlySelectPanelPosition | null>;
5440
5523
  readonly placeholderText: _angular_core.Signal<string>;
5441
5524
  readonly searchPlaceholderText: _angular_core.Signal<string>;
5442
5525
  readonly noResultsText: _angular_core.Signal<string>;
@@ -5469,6 +5552,8 @@ declare class FlySelectComponent implements ControlValueAccessor {
5469
5552
  toggleOpen(): void;
5470
5553
  open(): void;
5471
5554
  close(refocusTrigger?: boolean): void;
5555
+ /** Sampled once per open — see the `_triggerRect` field doc for why this never re-samples while open. */
5556
+ private _sampleTriggerRect;
5472
5557
  onTriggerKeydown(ev: KeyboardEvent): void;
5473
5558
  onPanelKeydown(ev: KeyboardEvent): void;
5474
5559
  private _selectActive;
@@ -5480,7 +5565,6 @@ declare class FlySelectComponent implements ControlValueAccessor {
5480
5565
  /** Clear the whole selection from the trigger ✕. Stops propagation so it never opens the panel. */
5481
5566
  clear(ev?: Event): void;
5482
5567
  onSearchInput(value: string): void;
5483
- onDocumentMouseDown(ev: MouseEvent): void;
5484
5568
  private _normalizedValue;
5485
5569
  private _emit;
5486
5570
  private _markTouched;
@@ -7136,6 +7220,1031 @@ declare class AgentFlightAnimator {
7136
7220
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<AgentFlightAnimator>;
7137
7221
  }
7138
7222
 
7223
+ /**
7224
+ * Magic-bar contribution contract (UX v2 "Nova", D5 §4).
7225
+ *
7226
+ * The magic bar is the shell's top-bar toolbar pill. Unlike the fixed right
7227
+ * cluster (Help / Tasks / Notifications / assistant orb — shell-owned, an app can
7228
+ * never remove it), the pill's contents belong to **whatever view the user is
7229
+ * looking at**, and the design's reference implementation re-publishes the whole
7230
+ * set on every selection, tab and save (`pubTabActions`). Two consequences shape
7231
+ * every type below:
7232
+ *
7233
+ * 1. **A contribution is a full replace, never a patch.** There is no "add one
7234
+ * action" call, because the publisher never knows what the previous view left
7235
+ * behind. That also collapses D5's `search: null` ("suppress") vs `search`
7236
+ * absent distinction — under full replace both simply mean "this view offers
7237
+ * no search".
7238
+ * 2. **Render data and behaviour are separated in the type system.** Each family
7239
+ * has a `*Spec` base carrying ONLY the fields that affect what is painted;
7240
+ * the publisher-facing type extends it with callbacks, and the shell-facing
7241
+ * `*View` type extends it with bound invokers. The base IS the equality
7242
+ * surface {@link MagicBarRegistry} dedupes on — a re-publish whose specs are
7243
+ * unchanged must not disturb the shell, even though its closures are brand
7244
+ * new objects every time (an arrow function in a component method never
7245
+ * compares equal to its predecessor). See `magic-bar-projection.ts`.
7246
+ *
7247
+ * **Strings are i18n keys, never resolved text** — same rule as
7248
+ * {@link AgentCommandRegistration} (`labelKey` / `descriptionKey` / `hintKey`),
7249
+ * for the same two reasons: a contribution outlives a locale switch (a resolved
7250
+ * label would silently go stale until the publisher happened to re-publish), and
7251
+ * keys are locale-invariant so the dedupe fingerprint doesn't churn when the user
7252
+ * changes language. Keys resolve in the OWNING app's bundle.
7253
+ *
7254
+ * **Every `*Key` has an optional `*Params` sibling** ({@link MagicBarTextParams}),
7255
+ * fed straight to `I18nService.t(key, params)`. Without it a count-carrying string
7256
+ * ("Search 1,204 tasks…") forces the publisher to pass pre-formatted TEXT as the
7257
+ * key: it renders correctly in `en`, renders identically untranslated in ar/fr/ur,
7258
+ * and no locale tool can see it. Params participate in the dedupe fingerprint, so
7259
+ * a changing count re-paints.
7260
+ *
7261
+ * Which of D5 §4's "dynamics the shell must honor" live where:
7262
+ *
7263
+ * | # | Dynamic | Owner |
7264
+ * |---|---|---|
7265
+ * | 1 | Live re-publication, idempotent replace | {@link MagicBarRegistry} (here) |
7266
+ * | 2 | Disabled ≠ hidden, auto disabled-tooltip | contract keeps `disabled` rows; `fly-magic-actions` renders + suffixes |
7267
+ * | 3 | `toolbarPopIn` 40 ms stagger | renderer — it tracks on {@link MagicBarActionSpec.id}, which is why ids are unique across the WHOLE contribution |
7268
+ * | 4 | i18n on every label/tip | contract (keys + params, above) |
7269
+ * | 5 | Fixed right cluster is not contributable | contract — no slot exists for it |
7270
+ * | 6 | Mobile renders the same contribution | contract carries no form-factor branch; `openWidth` is a desktop hint mobile ignores |
7271
+ * | 7 | `shortcut` reserved (design has no shortcut affordance yet) | contract — carried, unrendered |
7272
+ *
7273
+ * On dynamic 3 specifically: the registry's dedupe does NOT stop the stagger
7274
+ * replaying, and believing it does would produce a renderer that re-animates on
7275
+ * every click. Dedupe fires only when *nothing painted* changed, and the dominant
7276
+ * case — `disabled: !hasSelection` — changes the fingerprint on every selection.
7277
+ * What holds the DOM still is the renderer's `@for (…; track item.id)`.
7278
+ */
7279
+ /** How an action paints. `'text'` is the labelled-pill form (calendar's "Today"). */
7280
+ type MagicBarActionKind = 'icon' | 'text' | 'toggle';
7281
+ /**
7282
+ * Semantic colour of an action. `'danger'` is the red Delete treatment (red glyph
7283
+ * + red 18 % hover tint, D7); `'success'` is the green "Mark as complete" pressed
7284
+ * state (D5 §1.4 + §4 prop table: "pressed bg tint-sel / green for complete").
7285
+ *
7286
+ * A union rather than the boolean `danger` this started as: the design already
7287
+ * demands a second colour, and widening a shipped `danger?: boolean` into a union
7288
+ * later would mean REMOVING an interface member — MAJOR under `tools/ds-compat`
7289
+ * (rule 7), which forks the federation singleton for every remote.
7290
+ */
7291
+ type MagicBarTone = 'default' | 'danger' | 'success';
7292
+ /**
7293
+ * Interpolation params for one i18n key — the `params` argument of
7294
+ * `I18nService.t(key, params)`, substituting `{{name}}` placeholders.
7295
+ *
7296
+ * Values are `string | number` only: the fingerprint has to encode them, and the
7297
+ * renderer resolves them through `t()`, which stringifies. A `Date` or a nested
7298
+ * object would fingerprint as `{}` and paint as `[object Object]`.
7299
+ */
7300
+ type MagicBarTextParams = Readonly<Record<string, string | number>>;
7301
+ /**
7302
+ * Identity of a contribution's publisher, and the arbitration key the shell uses
7303
+ * to pick which contribution the bar renders.
7304
+ *
7305
+ * `windowId` is optional but strongly preferred: two windows of the same app can
7306
+ * be open on different selections, and keying on `appId` alone would let the
7307
+ * background one paint the focused one's toolbar. It is optional only because a
7308
+ * federated remote that predates per-window plumbing can still contribute —
7309
+ * {@link MagicBarRegistry} resolves an `appId`-keyed slot as a fallback.
7310
+ *
7311
+ * It only has to be unique **within the publishing app** (the shell passes its own
7312
+ * `win-<appId>-<timestamp>` window id; a tab index or a route-derived id is equally
7313
+ * valid) — {@link magicBarOwnerKey} scopes it by `appId`, so a value another app
7314
+ * also uses can never cross over.
7315
+ */
7316
+ interface MagicBarOwnerRef {
7317
+ readonly appId: string;
7318
+ readonly windowId?: string;
7319
+ }
7320
+ /**
7321
+ * Storage/arbitration key for an owner. Exported because the shell computes it
7322
+ * on the janitor path (`clear` after a window closes) without holding the
7323
+ * publisher.
7324
+ *
7325
+ * **Both fields key the slot**, even though the shell's own ids
7326
+ * (`win-<appId>-<timestamp>`) are already unique. `windowId` is publisher-supplied
7327
+ * DATA that crosses the federation boundary, and the field is documented only as
7328
+ * "two windows of the same app" — nothing stops a remote passing a tab index or a
7329
+ * route-derived id. Keyed on `windowId` alone, two apps that both call their first
7330
+ * window `"1"` would share a slot: one silently paints the other's chrome, and the
7331
+ * shell's janitor `clear()` wipes the wrong one.
7332
+ */
7333
+ declare function magicBarOwnerKey(owner: MagicBarOwnerRef): string;
7334
+ /** One `menuitemradio` row. `value` is the publisher's own vocabulary. */
7335
+ interface MagicBarRadioOption {
7336
+ readonly value: string;
7337
+ readonly labelKey: string;
7338
+ /** Params for {@link labelKey} — the count-badged option ("All statuses ({{count}})"). */
7339
+ readonly labelParams?: MagicBarTextParams;
7340
+ }
7341
+ /** Render surface of a radio menu — the dedupe key for {@link MagicBarRadioMenu}. */
7342
+ interface MagicBarRadioMenuSpec {
7343
+ /** Eyebrow above the options ("Filter by status" / "Sort by"). */
7344
+ readonly titleKey: string;
7345
+ /** Params for {@link titleKey}. */
7346
+ readonly titleParams?: MagicBarTextParams;
7347
+ readonly options: readonly MagicBarRadioOption[];
7348
+ /** Current selection — check glyph + 600 weight on the matching row. */
7349
+ readonly value: string;
7350
+ /** The unfiltered/unsorted baseline; the trigger shows its accent dot iff `value !== defaultValue`. */
7351
+ readonly defaultValue: string;
7352
+ }
7353
+ /** What a publisher supplies for a radio menu. */
7354
+ interface MagicBarRadioMenu extends MagicBarRadioMenuSpec {
7355
+ readonly onSelect?: (value: string) => void;
7356
+ }
7357
+ /** What the shell renders. `select` always exists; it no-ops when the publisher supplied no handler. */
7358
+ interface MagicBarRadioMenuView extends MagicBarRadioMenuSpec {
7359
+ select(value: string): void;
7360
+ }
7361
+ /**
7362
+ * Render surface of an action — the dedupe key for {@link MagicBarAction}.
7363
+ *
7364
+ * `id` must be unique across the WHOLE contribution (every group, plus `primary`
7365
+ * and `overflow`), not merely within its group: it is the address the shell's
7366
+ * invoker resolves against the publisher's latest handlers.
7367
+ */
7368
+ interface MagicBarActionSpec {
7369
+ readonly id: string;
7370
+ /** i18n key — the `aria-label` and the default tooltip. */
7371
+ readonly labelKey: string;
7372
+ /** Params for {@link labelKey}, e.g. `{ count: 3 }` for "Delete {{count}} items". */
7373
+ readonly labelParams?: MagicBarTextParams;
7374
+ /**
7375
+ * Inner-SVG geometry for a 24×24 glyph (`stroke-width: 1.8`, round caps) —
7376
+ * the design's icon transport. Reference {@link FLY_MAGIC_BAR_ICONS} by name
7377
+ * rather than hand-authoring; a publisher MAY author its own, subject to the
7378
+ * contract below.
7379
+ *
7380
+ * **This value is not trusted.** The renderer parses it against a closed
7381
+ * allowlist — self-closing `path`/`circle`/`rect`/`ellipse`/`line`/`polyline`/
7382
+ * `polygon` elements carrying geometry attributes only (`d`, `cx`, `points`,
7383
+ * …) — and binds the result as real attributes. It is never assigned as HTML.
7384
+ * Anything else (a container element, an `on*` handler, `style`, `href`,
7385
+ * `fill="url(…)"`, a stray text node) rejects the WHOLE fragment: the button
7386
+ * renders with no glyph and logs. See `magic-actions-icon.ts`.
7387
+ *
7388
+ * The type stays `string` deliberately. Narrowing it to a branded/opaque type
7389
+ * would be a ds-compat MAJOR, and it would not buy anything the renderer's own
7390
+ * validation does not already guarantee — a nominal type describes where a
7391
+ * value came from, not what it contains.
7392
+ */
7393
+ readonly iconPath?: string;
7394
+ /** Default `'icon'`. */
7395
+ readonly kind?: MagicBarActionKind;
7396
+ /** Dimmed (`opacity .38`), NEVER hidden — a vanishing action teaches the user nothing. */
7397
+ readonly disabled?: boolean;
7398
+ /**
7399
+ * Tooltip override while disabled. Absent is the normal case: the renderer
7400
+ * auto-suffixes the resolved label ("… — select an item first"). Resolution
7401
+ * and the connector phrasing are the renderer's job precisely because they are
7402
+ * locale work, and this store holds keys rather than text.
7403
+ */
7404
+ readonly disabledTipKey?: string;
7405
+ /** Params for {@link disabledTipKey}. */
7406
+ readonly disabledTipParams?: MagicBarTextParams;
7407
+ /** Tooltip override while enabled. Absent → the renderer uses `labelKey`. */
7408
+ readonly tipKey?: string;
7409
+ /** Params for {@link tipKey}. */
7410
+ readonly tipParams?: MagicBarTextParams;
7411
+ /**
7412
+ * Semantic colour. Default `'default'`; `'danger'` is the ONLY thing that makes
7413
+ * an icon red (D7), `'success'` the green completed-toggle treatment.
7414
+ */
7415
+ readonly tone?: MagicBarTone;
7416
+ /** `aria-pressed` for `kind: 'toggle'`. */
7417
+ readonly pressed?: boolean;
7418
+ /** Small accent dot — a non-default filter/sort is active. */
7419
+ readonly badgeDot?: boolean;
7420
+ /**
7421
+ * Reserved (D5 §4 item 7). The designs carry no keyboard-shortcut affordance
7422
+ * anywhere; the field exists so adding one later is a renderer change rather
7423
+ * than a contract break. Nothing renders it today.
7424
+ */
7425
+ readonly shortcut?: string;
7426
+ }
7427
+ /** What a publisher supplies for one action. */
7428
+ interface MagicBarAction extends MagicBarActionSpec {
7429
+ readonly menu?: MagicBarRadioMenu;
7430
+ readonly onSelect?: () => void;
7431
+ }
7432
+ /**
7433
+ * What the shell renders. `run()` always exists and always dispatches to the
7434
+ * publisher's LATEST handler for this id — including after a re-publish the
7435
+ * registry deliberately did not propagate (see `magic-bar-projection.ts`).
7436
+ */
7437
+ interface MagicBarActionView extends MagicBarActionSpec {
7438
+ readonly menu: MagicBarRadioMenuView | null;
7439
+ run(): void;
7440
+ }
7441
+ /** Render surface of a group — the dedupe key for {@link MagicBarGroup}. */
7442
+ interface MagicBarGroupSpec {
7443
+ readonly id: string;
7444
+ /** i18n key for the `role="group"` aria-label ("Signal actions"). */
7445
+ readonly labelKey: string;
7446
+ /** Framed variant: 2 px gaps + a trailing separator. Plain (default) uses 8 px gaps. */
7447
+ readonly framed?: boolean;
7448
+ }
7449
+ interface MagicBarGroup extends MagicBarGroupSpec {
7450
+ readonly items: readonly MagicBarAction[];
7451
+ }
7452
+ interface MagicBarGroupView extends MagicBarGroupSpec {
7453
+ readonly items: readonly MagicBarActionView[];
7454
+ }
7455
+ /**
7456
+ * Render surface of the expanding search field — the dedupe key for
7457
+ * {@link MagicBarSearch}.
7458
+ *
7459
+ * This is a per-page typeahead, NOT a command palette: neither design package
7460
+ * has a global ⌘K surface, and the only "command" affordance is the Ask-AI menu.
7461
+ */
7462
+ interface MagicBarSearchSpec {
7463
+ /** Context-aware placeholder key ("Search tasks…", "Search events…"). */
7464
+ readonly placeholderKey: string;
7465
+ /** Params for {@link placeholderKey}, e.g. `{ count: 1204 }` for "Search {{count}} tasks…". */
7466
+ readonly placeholderParams?: MagicBarTextParams;
7467
+ /**
7468
+ * The text the search field should SHOW — literal text, not an i18n key, because
7469
+ * it is the user's own query rather than a caption.
7470
+ *
7471
+ * Exists because a view can arrive **already filtered**: a deep link carrying
7472
+ * `?q=…`, a restored session, a filter applied from a detail pane. Without it the
7473
+ * box renders empty over a visibly filtered list, and the user is looking at a
7474
+ * contradiction the chrome cannot explain.
7475
+ *
7476
+ * ## Why it is not called `query`
7477
+ * {@link MagicBarSearchView} — which extends this interface — already declares
7478
+ * `query(text: string): void`, the late-bound invoker. A `query?: string` here
7479
+ * would make that view an illegal extension (TS2430: `(text: string) => void` is
7480
+ * not assignable to `string | undefined`), and the only other way out — renaming
7481
+ * the invoker — removes a member of a shipped exported interface, which is a
7482
+ * ds-compat MAJOR (rule 7) and forks the federation singleton for every remote.
7483
+ * So the field takes the name that pairs with the invoker instead of colliding
7484
+ * with it: `queryText` is the text, `query()` submits it.
7485
+ *
7486
+ * ## Precedence — this is a SEED, not a controlled value
7487
+ * The field's live text is owned by the **shell**, because the user types into
7488
+ * it. This field is the publisher's chance to move it, and the shell adopts the
7489
+ * published value exactly three times:
7490
+ *
7491
+ * 1. the first time it binds this view,
7492
+ * 2. when {@link MagicBarContribution.viewKey} changes (reset-on-navigate — the
7493
+ * previous view's query must not survive into the next one), and
7494
+ * 3. when the published value **itself changes** from the one previously
7495
+ * published.
7496
+ *
7497
+ * A re-publish carrying an UNCHANGED `queryText` never touches what the user has
7498
+ * typed. That third clause is the whole rule: the dominant re-publish is
7499
+ * `disabled: !hasSelection` flipping on a selection change, and a shell that
7500
+ * re-read `queryText` on every emitted view would revert a keystroke every time
7501
+ * the user selected a row mid-search — the classic controlled-input bug. The rule
7502
+ * is authored once, as {@link magicBarSearchText}, so no renderer re-derives it.
7503
+ *
7504
+ * `undefined` and `''` are **different** and the difference is load-bearing:
7505
+ * absent means "this view does not manage the field" (nothing is ever forced),
7506
+ * `''` means "clear it". Both the fingerprint and the seed comparison distinguish
7507
+ * them.
7508
+ *
7509
+ * ## Do not echo the user's keystrokes back through this field
7510
+ * A publisher that mirrors its `onQuery` argument straight back into `queryText`
7511
+ * is harmless (the seed changes to text the field already shows). A publisher
7512
+ * that mirrors it back **debounced** is not: typing "abc" then publishing
7513
+ * `queryText: 'a'` 300 ms later is, by rule 3, a genuine publisher-initiated
7514
+ * change, and the field snaps back to "a". Publish here only for state the view
7515
+ * owns independently of the field.
7516
+ */
7517
+ readonly queryText?: string;
7518
+ /**
7519
+ * Expanded width in px — a **desktop layout hint**, carried verbatim.
7520
+ *
7521
+ * The design's range is 140–420 (default 230), but this store deliberately does
7522
+ * NOT validate or clamp it: enforcing a paint range here would reject a whole
7523
+ * contribution over a cosmetic hint (leaving the previous view's actions in the
7524
+ * chrome), and mobile ignores the field entirely, so there is no single range to
7525
+ * enforce. `fly-magic-actions` clamps to the design range at paint time and is
7526
+ * the only place that decides what an out-of-range or non-finite value means.
7527
+ */
7528
+ readonly openWidth?: number;
7529
+ /** Accent dot on the Filters button — a non-default filter is applied. */
7530
+ readonly filtersActive?: boolean;
7531
+ }
7532
+ interface MagicBarSearch extends MagicBarSearchSpec {
7533
+ readonly onQuery?: (query: string) => void;
7534
+ /**
7535
+ * Opens the view's own Advanced-search overlay. Presence of this handler is
7536
+ * what makes the Filters button exist — the DS deliberately does not model the
7537
+ * dialog itself. Its fields are app schema (Circles' PESTLE/horizon grid), and
7538
+ * a descriptor for them would be business logic the design system cannot
7539
+ * validate or render honestly.
7540
+ */
7541
+ readonly onOpenFilters?: () => void;
7542
+ }
7543
+ interface MagicBarSearchView extends MagicBarSearchSpec {
7544
+ /** True iff the publisher can open an advanced-search overlay. */
7545
+ readonly hasFilters: boolean;
7546
+ /**
7547
+ * Submit the field's current text to the publisher's newest `onQuery`. The
7548
+ * inbound half — what the field should SHOW — is
7549
+ * {@link MagicBarSearchSpec.queryText}, and that asymmetry in naming is forced:
7550
+ * this member shipped first, and renaming it would be a ds-compat MAJOR.
7551
+ */
7552
+ query(text: string): void;
7553
+ openFilters(): void;
7554
+ }
7555
+ /**
7556
+ * One view's complete claim on the magic bar.
7557
+ *
7558
+ * Identity (`appId` / `windowId`) is deliberately absent: it belongs to the
7559
+ * {@link MagicBarPublisher} that was minted for this owner, so a later publish
7560
+ * cannot re-target another app's slot.
7561
+ */
7562
+ interface MagicBarContribution {
7563
+ /**
7564
+ * What the publisher is showing, e.g. `'tasks:detail'`. A change here is
7565
+ * reset-on-navigate: the registry replaces the slot wholesale rather than
7566
+ * reconciling, so nothing from the previous view can survive.
7567
+ */
7568
+ readonly viewKey: string;
7569
+ readonly search?: MagicBarSearch | null;
7570
+ /** Ordered clusters, separator-joined. */
7571
+ readonly groups?: readonly MagicBarGroup[];
7572
+ /** The accent-filled CTA ("New task", "Add signal"). */
7573
+ readonly primary?: MagicBarAction | null;
7574
+ /**
7575
+ * Ids of {@link AgentCommand}s this view considers most relevant, most-relevant
7576
+ * first — the Ask-AI menu's per-view sets.
7577
+ *
7578
+ * Ids, not command objects: the platform already models commands (manifest
7579
+ * `commands[]` → `AgentCommandRegistry`), and D5 §6 item 9 is explicit that
7580
+ * production must source these from manifests instead of the mock's hardcoded
7581
+ * `{ title, note, prompt }` triples. Duplicating that model here would fork the
7582
+ * palette and reintroduce hardcoded prompt text. Unknown ids are dropped by the
7583
+ * resolver; an empty list leaves the shell's affinity ranking in charge.
7584
+ */
7585
+ readonly quickCommandIds?: readonly string[];
7586
+ /** The "…" overflow set. Reserved design intent (D5 §6 item 8) — Print / Export / Settings. */
7587
+ readonly overflow?: readonly MagicBarAction[];
7588
+ }
7589
+ /** The shell-facing projection of a contribution. See `magic-bar-projection.ts`. */
7590
+ interface MagicBarView {
7591
+ readonly appId: string;
7592
+ readonly windowId?: string;
7593
+ /** {@link magicBarOwnerKey} of the publisher. */
7594
+ readonly ownerKey: string;
7595
+ readonly viewKey: string;
7596
+ readonly search: MagicBarSearchView | null;
7597
+ readonly groups: readonly MagicBarGroupView[];
7598
+ readonly primary: MagicBarActionView | null;
7599
+ readonly quickCommandIds: readonly string[];
7600
+ readonly overflow: readonly MagicBarActionView[];
7601
+ }
7602
+ /**
7603
+ * A view's handle on its magic-bar slot. Minted once per publisher (not per
7604
+ * publish) because the publish rate is the whole point of this surface: the
7605
+ * sibling registries hand back a handle per `register()` and expect a handful of
7606
+ * calls per app lifetime, whereas a magic-bar publisher re-emits on every
7607
+ * selection change. Handing out a fresh handle each time would leave the caller
7608
+ * holding a dead one and force it to reassign on every keystroke.
7609
+ */
7610
+ interface MagicBarPublisher {
7611
+ readonly owner: MagicBarOwnerRef;
7612
+ /**
7613
+ * Replace this owner's contribution. No-op after {@link dispose}, and no-op
7614
+ * after the shell has {@link MagicBarRegistry.clear}ed this owner key.
7615
+ *
7616
+ * **Publish is last-writer-wins and eviction is not** — a deliberate asymmetry.
7617
+ * A stale publisher (one that has been replaced on this key by a newer one)
7618
+ * cannot `dispose()` the newer one out of the slot, but it *can* still take the
7619
+ * slot back by publishing. Symmetry would need a "newest publisher wins" rule
7620
+ * enforced on write, which would make the first publish of a replacement
7621
+ * publisher silently drop whenever two live views briefly share a key. The
7622
+ * exposure is bounded: two live publishers on one owner key only happen while a
7623
+ * view is being replaced in place, and the loser re-publishes on its next
7624
+ * selection change. The unbounded case — a publisher that outlives its window —
7625
+ * is closed by `clear()`'s tombstone, not by write ordering.
7626
+ */
7627
+ publish(contribution: MagicBarContribution): void;
7628
+ /**
7629
+ * Release the slot. Idempotent, and a no-op if another publisher has since
7630
+ * taken this owner key — the same stale-handle rule the sibling registries use.
7631
+ */
7632
+ dispose(): void;
7633
+ }
7634
+
7635
+ /**
7636
+ * Cross-bundle store key + sync event.
7637
+ *
7638
+ * Exported for the same reason {@link FLY_REMOTE_CONTEXT_STORE_KEY} is — test
7639
+ * isolation and devtools — but NOT as a hand-writable integration path the way
7640
+ * that one is. Slots hold live functions, so a caller writing the slot directly
7641
+ * would have to reproduce the projection, the fingerprint and the session
7642
+ * bookkeeping. The DS API is the only supported writer.
7643
+ */
7644
+ declare const FLY_MAGIC_BAR_STORE_KEY = "__flyMagicBar__";
7645
+ declare const FLY_MAGIC_BAR_EVENT = "fly:magic-bar";
7646
+ /**
7647
+ * The magic bar's contribution store: apps publish what the top-bar pill should
7648
+ * offer for the view they are showing, the shell renders whichever contribution
7649
+ * belongs to the window the user is in.
7650
+ *
7651
+ * Why the state lives on `globalThis`
7652
+ * -----------------------------------
7653
+ * Same reasoning as {@link FlyRemoteContextService}, and the same direction of
7654
+ * travel (remote → shell chrome). This service is `providedIn: 'root'`, but a
7655
+ * root instance is not *reliably* shared across the federation boundary: the
7656
+ * shell builds the design system from workspace source while remotes consume the
7657
+ * published package, and Native Federation collapses those into one runtime
7658
+ * instance only when version negotiation succeeds. That negotiation has silently
7659
+ * split before. A split here would be invisible at build time and would present
7660
+ * as an empty toolbar for federated apps only — exactly the class of bug
7661
+ * `fly-federation-singleton-guard` exists to shout about. Keeping the state on
7662
+ * the one substrate every bundle shares makes THIS store fork-proof — which
7663
+ * contribution is published, which one is active, and the handlers behind it all
7664
+ * survive a split — and behaves identically to a plain signal store when there
7665
+ * isn't one. Each instance mirrors the store into signals and re-reads on the sync
7666
+ * event, so reactivity works whichever copy published.
7667
+ *
7668
+ * **What this does NOT harden: the Ask-AI menu.** A contribution's
7669
+ * `quickCommandIds` resolve against `AgentCommandRegistry`, a plain
7670
+ * `providedIn: 'root'` singleton with no `globalThis` backing. Under a fork the
7671
+ * toolbar therefore paints correctly while the quick-command menu comes back
7672
+ * empty — for federated apps only. S2.3 owns that decision (resolve fork-safely,
7673
+ * or accept the degradation deliberately); see the S1.5 note.
7674
+ *
7675
+ * Idempotent re-publication
7676
+ * -------------------------
7677
+ * A view re-publishes its whole contribution on every selection change. Only a
7678
+ * change to the *painted* fields propagates; the handlers behind an unchanged
7679
+ * projection are still swapped for the newest ones. `magic-bar-projection.ts`
7680
+ * carries that argument in full — it is the single most load-bearing property of
7681
+ * this store, and the reason `active()` can be held across dozens of publishes
7682
+ * without re-rendering and without ever firing a stale closure.
7683
+ *
7684
+ * What this service does NOT own
7685
+ * ------------------------------
7686
+ * **Window arbitration.** The registry stores every owner's contribution and
7687
+ * renders whichever one {@link setActiveOwner} names; deciding *which* window is
7688
+ * active is the shell's job (focus, minimize, close — none of which the DS can
7689
+ * see). Until the shell names one, {@link active} is `null`: an empty bar is a
7690
+ * loud, trivially-diagnosed failure, whereas a last-publisher-wins default would
7691
+ * paint a BACKGROUND window's Delete button into the chrome of the focused one.
7692
+ * S2.2 wires this from the shell's focused-window signal, alongside the existing
7693
+ * `WINDOW_ROUTE` per-window plumbing.
7694
+ */
7695
+ declare class MagicBarRegistry {
7696
+ private readonly _views;
7697
+ private readonly _activeOwner;
7698
+ private _syncedStore;
7699
+ private _syncedRevision;
7700
+ /**
7701
+ * Owner key → the last publish fault already reported for it. Instance-local, not
7702
+ * store-level: the thing being rate-limited is a throw into ONE app's
7703
+ * `ErrorHandler`, so each realm is entitled to its own single shout.
7704
+ */
7705
+ private readonly _lastFault;
7706
+ /** Every published contribution, keyed by {@link magicBarOwnerKey}. */
7707
+ readonly all: Signal<ReadonlyMap<string, MagicBarView>>;
7708
+ /** Owner the shell has nominated, or `null` when it has nominated none. */
7709
+ readonly activeOwner: Signal<MagicBarOwnerRef | null>;
7710
+ /**
7711
+ * The contribution the shell should render.
7712
+ *
7713
+ * Falls back from the window-keyed slot to an `appId`-keyed one so a remote
7714
+ * that publishes without a `windowId` still reaches the bar, then asserts the
7715
+ * resolved view belongs to the nominated app — see {@link resolveView}, which
7716
+ * {@link viewFor} shares so the two can never answer differently. Identity is
7717
+ * stable while the active view's painted content is unchanged, including across
7718
+ * publishes by OTHER windows.
7719
+ */
7720
+ readonly active: Signal<MagicBarView | null>;
7721
+ constructor();
7722
+ /**
7723
+ * Mint a publisher for one owner. Call once per view host (component
7724
+ * constructor), keep the result, `publish()` as often as the view changes, and
7725
+ * `dispose()` on teardown — a `DestroyRef.onDestroy` is the intended shape.
7726
+ *
7727
+ * The slot is claimed on the FIRST publish, not here, so a publisher that is
7728
+ * created and destroyed without ever publishing cannot evict whoever currently
7729
+ * owns the key.
7730
+ */
7731
+ publisher(owner: MagicBarOwnerRef): MagicBarPublisher;
7732
+ /**
7733
+ * Force-clear an owner's slot regardless of who published it. The shell's
7734
+ * janitor path: a window closing, or a remote that tore down without disposing,
7735
+ * must not leave its actions painted in the chrome.
7736
+ *
7737
+ * Two properties the janitor depends on, both learned the hard way:
7738
+ *
7739
+ * 1. **It clears the `appId` fallback slot too** when a `windowId` is given. The
7740
+ * janitor only ever knows the closing window (`{ appId, windowId }`), while a
7741
+ * remote that published WITHOUT a window id — precisely the case
7742
+ * {@link active}'s fallback exists to serve — sits in `a:<appId>`. Clearing
7743
+ * only the window slot would strand that one on `globalThis`, holding
7744
+ * `onSelect` closures that retain a destroyed component tree, and the shell
7745
+ * would paint the dead window's toolbar the next time the app opened.
7746
+ * The cost is deliberate, and PERMANENT for publishers minted before this
7747
+ * call: with two windows of one app open and only the windowId-less fallback
7748
+ * published, closing either revokes the fallback key at the current session
7749
+ * watermark — which the survivor's session is necessarily under — so the
7750
+ * survivor's future publishes are dropped too, for the rest of its life, not
7751
+ * merely until its next publish. That is not fixable with a smarter
7752
+ * watermark: two publishers sharing the fallback key are indistinguishable
7753
+ * at clear time (the janitor knows which WINDOW closed, not which SESSION
7754
+ * was publishing on the shared key), so any cutoff that reliably kills the
7755
+ * closing window's zombie can also kill the survivor. An empty bar is the
7756
+ * safe state (see {@link active}); recovery needs a publisher minted AFTER
7757
+ * the clear — a reopened window, or `publisherFor` called fresh. The real
7758
+ * lesson: a multi-window app should pass `windowId` and get its own slots.
7759
+ * 2. **It is a tombstone, not a delete.** `WindowManagerService.closeWindow`
7760
+ * marks the window `isClosing` and removes it 250 ms later, so the component
7761
+ * — and the `effect()` that publishes for it — outlives the janitor. A plain
7762
+ * delete leaves the publisher's own `disposed` flag false, so its next run
7763
+ * re-claims the key and a zombie contribution survives until `DestroyRef`
7764
+ * fires. Every publisher minted before this call is revoked permanently; one
7765
+ * minted after (a reopened window) owns the key normally.
7766
+ */
7767
+ clear(owner: MagicBarOwnerRef): void;
7768
+ /**
7769
+ * Nominate the owner whose contribution {@link active} resolves to. `null`
7770
+ * hands the bar back to the shell's own default (search only).
7771
+ */
7772
+ setActiveOwner(owner: MagicBarOwnerRef | null): void;
7773
+ /**
7774
+ * Direct, non-reactive read of one owner's contribution — the split-proof
7775
+ * escape hatch for callers outside an injection/reactive context. Applies the
7776
+ * SAME resolution as {@link active}, fallback included.
7777
+ */
7778
+ viewFor(owner: MagicBarOwnerRef): MagicBarView | null;
7779
+ private write;
7780
+ /**
7781
+ * Surface a publish fault LOUDLY on its first occurrence for an owner, then stay
7782
+ * quiet until the fault changes or a good publish lands.
7783
+ *
7784
+ * The sibling precedent (`AgentCommandRegistry.registerAll`) throws on a
7785
+ * once-per-boot path, so throwing outright is proportionate there. Here the
7786
+ * intended wiring is `effect(() => this.bar.publish(this.contribution()))`, so a
7787
+ * single duplicate action id would otherwise throw on EVERY selection change
7788
+ * forever — an unbounded stream of `ErrorHandler` toasts that buries the one
7789
+ * report the developer needed. Rethrowing the first occurrence keeps the loudest
7790
+ * possible signal (a real stack, through the app's own `ErrorHandler`); the
7791
+ * repeats are dropped, not the bug. A different fault message, or a recurrence
7792
+ * after a good publish, is loud again.
7793
+ */
7794
+ private reportFaultOnce;
7795
+ private drop;
7796
+ /**
7797
+ * Late binding of invokers to the newest publish. Closes over the owner key
7798
+ * only — never over a slot — so it survives every replacement, including one
7799
+ * written by another federated copy of this service.
7800
+ */
7801
+ private handlerSource;
7802
+ /**
7803
+ * Re-read the shared store. Cheap no-op unless a real mutation landed.
7804
+ *
7805
+ * The memo keys on store IDENTITY as well as revision: the revision counter
7806
+ * alone cannot distinguish "nothing changed" from "the `globalThis` slot now
7807
+ * holds a brand-new store that happens to be at the same revision". That is not
7808
+ * hypothetical — every spec's `beforeEach` replaces the store, and instances
7809
+ * from earlier tests are still subscribed (a `providedIn: 'root'` service has no
7810
+ * teardown hook for its `globalThis` listener, matching `FlyRemoteContextService`).
7811
+ */
7812
+ private sync;
7813
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MagicBarRegistry, never>;
7814
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<MagicBarRegistry>;
7815
+ }
7816
+
7817
+ /**
7818
+ * The precedence rule for {@link MagicBarSearchSpec.queryText}, authored once.
7819
+ *
7820
+ * ## The problem
7821
+ * The magic bar's search field has two writers. The **user** types into it, and the
7822
+ * **publisher** can move it — a deep link arriving with `?q=…`, a restored session,
7823
+ * a filter applied from a detail pane. Neither can be made subordinate to the other
7824
+ * by fiat:
7825
+ *
7826
+ * - Make the publisher's value authoritative on every emitted view and you get the
7827
+ * classic controlled-input bug. The dominant re-publish in this contract is
7828
+ * `disabled: !hasSelection` flipping on a selection change, which changes the
7829
+ * fingerprint and therefore emits a new view carrying the SAME `queryText`. A
7830
+ * renderer that re-read it would revert the user's keystroke every time they
7831
+ * clicked a row mid-search.
7832
+ * - Make the field authoritative once the user has touched it and a legitimate
7833
+ * publisher-initiated change — the deep link this field exists for — silently
7834
+ * fails to land.
7835
+ *
7836
+ * ## The rule
7837
+ * `queryText` is a **seed, not a controlled value**. The field adopts it exactly
7838
+ * three times: on first bind, on a `viewKey` change (reset-on-navigate), and when
7839
+ * the published value itself changes from the previously published one. Everything
7840
+ * else leaves the field alone.
7841
+ *
7842
+ * That is what {@link magicBarSearchText} computes. It is a pure function of
7843
+ * (previous publisher state, next publisher state) — deliberately NOT a function of
7844
+ * the field's current text, because whether to adopt must not depend on what the
7845
+ * user happens to have typed. A publisher re-publishing `queryText: 'open'` must
7846
+ * re-assert it identically whether the field currently reads `'open'`, `'opened'`
7847
+ * or `''`.
7848
+ *
7849
+ * ## Why this lives in the design system rather than in the shell
7850
+ * Same reasoning as `clampMagicBarSearchWidth`: the DS does not ship the magic-bar
7851
+ * search-field renderer (the shell composes `fly-search-input` itself, and D5 §4
7852
+ * dynamic 6 has a mobile bar rendering the same contribution), but the rule is part
7853
+ * of the CONTRACT, not of any one renderer. Documented-but-unimplemented precedence
7854
+ * would be re-derived per renderer, and the two would disagree on exactly the case
7855
+ * that is hard to notice.
7856
+ */
7857
+ /**
7858
+ * The publisher-side inputs the field's text is seeded from — the two fields
7859
+ * {@link magicBarSearchText} compares, lifted out of {@link MagicBarView} so a
7860
+ * renderer can retain them without retaining a whole view (and with it every
7861
+ * `run()` closure behind it).
7862
+ */
7863
+ interface MagicBarSearchSeed {
7864
+ /** {@link MagicBarContribution.viewKey} of the contribution being rendered. */
7865
+ readonly viewKey: string;
7866
+ /**
7867
+ * {@link MagicBarSearchSpec.queryText}. `undefined` (the view does not manage the
7868
+ * field) and `''` (clear it) are different values and must be passed through as
7869
+ * such — do not normalise one into the other before calling.
7870
+ */
7871
+ readonly queryText?: string;
7872
+ }
7873
+ /**
7874
+ * The text the field must be forced to, or `null` to leave whatever the user has
7875
+ * typed in place.
7876
+ *
7877
+ * `previous` is the seed from the last publish the renderer saw — `null` on first
7878
+ * bind. Store `next` as the new `previous` on every call, whether or not this
7879
+ * returned a string: the comparison is against the last value the PUBLISHER sent,
7880
+ * not against the last value the field adopted, and conflating the two makes an
7881
+ * A → B → A publish sequence stop re-asserting A.
7882
+ *
7883
+ * A view with no search at all never reaches here — the renderer has nothing to
7884
+ * seed. A view whose search omits `queryText` still seeds `''` on navigate, which
7885
+ * is the reset-on-navigate behaviour the contract already required.
7886
+ *
7887
+ * Within an unchanged view, the three transitions behave differently on purpose
7888
+ * (S2 review finding 1 — the model doc is the contract, and it says absent means
7889
+ * "this view does not manage the field; nothing is ever forced"):
7890
+ *
7891
+ * `'a' → 'b'` force `'b'` — the publisher changed a value it manages
7892
+ * `undefined → ''` force `''` — the publisher STARTED managing, asking for a clear
7893
+ * `'a' → undefined` leave alone — the publisher STOPPED managing; forcing `''`
7894
+ * here is the controlled-input revert bug: a view
7895
+ * that seeds from `?q=` and naturally omits the
7896
+ * field when no query param exists would wipe the
7897
+ * user's typed text on its next disabled-flip
7898
+ * re-publish
7899
+ */
7900
+ declare function magicBarSearchText(previous: MagicBarSearchSeed | null, next: MagicBarSearchSeed): string | null;
7901
+
7902
+ /**
7903
+ * Allowlist parser for {@link MagicBarActionSpec.iconPath} — the geometry-only
7904
+ * gate between a publisher-supplied glyph fragment and the DOM.
7905
+ *
7906
+ * ## Why this exists rather than a sanitizer call
7907
+ *
7908
+ * `iconPath` is inner-SVG markup (see `magic-actions-icons.ts`), and it used to
7909
+ * reach the DOM through `[innerHTML]` + `DomSanitizer.bypassSecurityTrustHtml()`.
7910
+ * Two facts make that untenable:
7911
+ *
7912
+ * 1. An `<svg>` fragment is not a closed world. `<foreignObject>` is an HTML
7913
+ * integration point, so `<foreignObject><img src=x onerror=…>` executes;
7914
+ * `<a xlink:href="javascript:…">` wrapping the glyph is live under a click
7915
+ * the user is being invited to make; `on*` handlers and `<style>` need no
7916
+ * integration point at all.
7917
+ * 2. `DomSanitizer.sanitize(SecurityContext.HTML, …)` is not the answer either:
7918
+ * Angular's HTML element allowlist contains no SVG shape elements, so it
7919
+ * strips `<path>`/`<circle>`/`<rect>` along with the attack — every glyph in
7920
+ * the curated table would render empty. Sanitizing HTML is the wrong tool for
7921
+ * an SVG payload.
7922
+ *
7923
+ * Making `iconPath` the bare `d` attribute its name suggests was considered and
7924
+ * rejected: 11 of the 22 curated entries are multi-element (`<circle>+<path>`,
7925
+ * `<rect>+<path>…`), several ported byte-verbatim from the UX drop, so a single
7926
+ * `d` cannot express them without re-authoring geometry — and narrowing a public
7927
+ * `string` field's meaning is exactly the ds-compat MAJOR that 1.8.0 freezes.
7928
+ *
7929
+ * So the field keeps its type and its markup transport, and the RENDERER stops
7930
+ * trusting it: this module parses the fragment against a closed element/
7931
+ * attribute/value allowlist and hands the component structured nodes, which the
7932
+ * template binds as real Angular attributes. No `innerHTML`, no sanitizer
7933
+ * bypass, no HTML parser anywhere in the path — an attribute binding cannot
7934
+ * introduce an element or a handler, so injection is structurally impossible
7935
+ * rather than filtered.
7936
+ *
7937
+ * ## Reject, never strip
7938
+ *
7939
+ * Any violation drops the ENTIRE fragment. This mirrors `Fly.Sdk.Svg`'s
7940
+ * server-side reject-on-violation policy, and it is the safer failure mode for a
7941
+ * toolbar: a half-rendered glyph looks like it worked, so nobody investigates. A
7942
+ * rejected glyph renders as an empty 16px box on a button whose accessible name
7943
+ * and behaviour are untouched, and logs once.
7944
+ */
7945
+ /** Elements a glyph may contain — pure geometry, no containers, no references. */
7946
+ declare const FLY_MAGIC_BAR_ICON_ELEMENTS: readonly ["path", "circle", "rect", "ellipse", "line", "polyline", "polygon"];
7947
+ type FlyMagicBarIconElement = (typeof FLY_MAGIC_BAR_ICON_ELEMENTS)[number];
7948
+ /** One allowlisted element and its allowlisted attributes, ready to bind. */
7949
+ interface FlyMagicBarIconNode {
7950
+ readonly tag: FlyMagicBarIconElement;
7951
+ readonly attrs: Readonly<Record<string, string>>;
7952
+ }
7953
+
7954
+ /** Design range for {@link MagicBarSearchSpec.openWidth} (D2 §3.1) — see {@link clampMagicBarSearchWidth}. */
7955
+ declare const MAGIC_BAR_SEARCH_WIDTH_MIN = 140;
7956
+ declare const MAGIC_BAR_SEARCH_WIDTH_MAX = 420;
7957
+ declare const MAGIC_BAR_SEARCH_WIDTH_DEFAULT = 230;
7958
+ /**
7959
+ * Clamp a {@link MagicBarSearchSpec.openWidth} hint to the design's documented
7960
+ * range. `magic-bar.model.ts` deliberately does not validate this field itself
7961
+ * (rejecting a whole contribution over a cosmetic hint would be worse than a
7962
+ * clamp) and names `fly-magic-actions` as "the only place that decides what an
7963
+ * out-of-range or non-finite value means".
7964
+ *
7965
+ * `fly-magic-actions` does not render the search field itself — search is a
7966
+ * separate DS component (D2 §3.1's `SearchField`, not yet ported) — but until
7967
+ * that renderer ships, this is the one place the clamp rule is authored, so a
7968
+ * future consumer imports it instead of re-deriving the 140–420/230 constants.
7969
+ */
7970
+ declare function clampMagicBarSearchWidth(width: number | undefined): number;
7971
+ /**
7972
+ * `<fly-magic-actions>` — renders the magic bar's dynamic action cluster: an
7973
+ * ordered set of {@link MagicBarGroupView}s (framed tab-actions, plain
7974
+ * record-actions, separator-joined), each action icon-only/text/toggle, with the
7975
+ * Status/Sort `menuitemradio` pattern where an action carries a `menu`, plus the
7976
+ * optional accent `primary` CTA.
7977
+ *
7978
+ * ## Why `primary` lives here (reversing half the S1.4 ruling)
7979
+ * This component originally rendered `groups` only, on the reasoning that the
7980
+ * accent CTA is a visually distinct, separately-composed element. First contact
7981
+ * with a real consumer (`features/desktop/magic-bar/magic-bar-pill`) showed that
7982
+ * reasoning costs more than it saves, because {@link parseMagicBarIcon} — the
7983
+ * closed-allowlist parser that makes a publisher's `iconPath` safe to render — is
7984
+ * internal to this component. A composer outside it has no way to draw a
7985
+ * contributed glyph at all, so `primary` had to be smuggled back in as a
7986
+ * synthetic one-item group: an invented group id, an invented group `labelKey`,
7987
+ * and a spurious `role="group"` wrapped around a single button, announced to a
7988
+ * screen-reader user as a group of one. Every place a CONTRIBUTED glyph is
7989
+ * painted now lives in the component that owns the parser.
7990
+ *
7991
+ * ## What is still NOT rendered here, and why
7992
+ * - **The search field** — a separate DS component (D2 §3.1's `SearchField`); this
7993
+ * file owns only its width rule, {@link clampMagicBarSearchWidth}.
7994
+ * - **The Ask-AI orb** — shell chrome keyed on `quickCommandIds`, no glyph of the
7995
+ * publisher's.
7996
+ * - **The `overflow` kebab** — and this one is a deliberate *deferral*, not a
7997
+ * boundary. Its rows would render through `fly-context-menu`, whose
7998
+ * `ContextMenuItem` carries `icon` as a PrimeIcons CLASS NAME and has no
7999
+ * `disabled`; so an overflow action's `iconPath` cannot be painted and a
8000
+ * disabled overflow row cannot be shown as disabled, wherever the kebab is
8001
+ * composed. Moving it here would relocate that limitation rather than remove
8002
+ * it, while making this component own a "More actions" string it cannot ship
8003
+ * into the shell bundle on its own. The prerequisite is two optional fields on
8004
+ * `ContextMenuItem`; see the S2.13 note.
8005
+ *
8006
+ * ## What this component must never do (S1.5 contract, `MagicBarRegistry`)
8007
+ * - **Never cache `run()`/`select()`.** They are late-bound invokers — read fresh
8008
+ * off the `MagicBarActionView`/`MagicBarRadioMenuView` on every call, never
8009
+ * captured into a local variable that outlives the click.
8010
+ * - **Never reach for a publisher's `onSelect`.** Only the projected view's
8011
+ * `run()`/`menu.select()` exist on the types this component accepts.
8012
+ *
8013
+ * ## The stagger guard
8014
+ * `toolbarPopIn` (40 ms/action) is a static `animation:` on `.fma-btn`, replayed
8015
+ * only when the browser creates a NEW element — never on a property-only
8016
+ * re-render of a persisted one. `@for (…; track action.id)` is what makes that
8017
+ * true: `action.id` is unique across the WHOLE contribution — `primary` included
8018
+ * (the model's own invariant) — so a re-publish that only flips
8019
+ * `disabled`/`pressed`/`badgeDot` on existing ids reuses the same DOM nodes and
8020
+ * the finished animation is left alone. A re-publish whose group genuinely
8021
+ * gains/loses ids creates/destroys the corresponding elements, and only THOSE
8022
+ * replay. Do not `track $index` — that defeats this and re-pops the whole group
8023
+ * on every selection change.
8024
+ *
8025
+ * `primary` sits in its own single-child wrapper rather than directly in the row,
8026
+ * so `nova-stagger`'s `:nth-child` arithmetic gives it a fixed delay instead of
8027
+ * one that shifts with how many framed groups (and therefore separators) happen
8028
+ * to precede it.
8029
+ */
8030
+ declare class FlyMagicActionsComponent {
8031
+ protected readonly i18n: I18nService;
8032
+ /** Ordered clusters — framed tab-actions before plain record-actions (D2 §2.3). */
8033
+ readonly groups: _angular_core.InputSignal<readonly MagicBarGroupView[]>;
8034
+ /**
8035
+ * The accent-filled CTA ("New task", "Add signal"), or `null`. Optional: a view
8036
+ * that offers no primary action passes nothing, and no accent disc is painted.
8037
+ */
8038
+ readonly primary: _angular_core.InputSignal<MagicBarActionView | null>;
8039
+ /** Id of the action whose radio menu is open, or `null`. Only one open at a time. */
8040
+ protected readonly openMenuActionId: _angular_core.WritableSignal<string | null>;
8041
+ private readonly menuAnchor;
8042
+ protected readonly menuAnchorEl: _angular_core.Signal<HTMLElement | null>;
8043
+ /** The scrolling group row — the box {@link measure} interrogates. Absent while `groups` is empty. */
8044
+ private readonly rowRef;
8045
+ /**
8046
+ * The action whose radio menu is open, resolved against the CURRENT projection
8047
+ * rather than captured when the menu opened — so a re-publish that
8048
+ * changes the menu's `value`/`options` while it is open renders the new state,
8049
+ * and one that drops the action entirely closes the menu instead of leaving an
8050
+ * orphan bound to a stale view.
8051
+ *
8052
+ * Exists because the menu is rendered once, outside the group loops (S1-review
8053
+ * F9): a `<fly-context-menu>` inserted beside its button would shift every
8054
+ * later `.fma-btn`'s `:nth-child` index and with it its stagger delay.
8055
+ */
8056
+ protected readonly openAction: _angular_core.Signal<MagicBarActionView | null>;
8057
+ /**
8058
+ * When the open action leaves the projection, ACTUALLY close — do not merely
8059
+ * stop rendering (S2 review finding 4). Left set, `openMenuActionId` +
8060
+ * `menuAnchor` are a re-open trap: a later publish that re-adds the same id
8061
+ * would resurrect the menu with no user action, anchored to an element the
8062
+ * `@for (…; track action.id)` has since destroyed — undefined placement plus
8063
+ * a retained DOM node. The effect fires on the same projection change that
8064
+ * un-rendered the menu, so there is no frame in between to observe.
8065
+ */
8066
+ private readonly closeWhenActionLeaves;
8067
+ /**
8068
+ * True once the GROUP row's content no longer fits its container. Drives the
8069
+ * fade-mask + horizontal-scroll treatment (house style: "icon-only toolbars
8070
+ * with horizontal-ellipsis overflow, never a second row" — skill §9 rule 6).
8071
+ * Buttons stay reachable by scroll/Tab rather than being clipped-and-hidden.
8072
+ *
8073
+ * Only the groups scroll. `primary` sits outside `.fma` precisely so the fade
8074
+ * can never reach it: a call to action that dissolves into a gradient, or that
8075
+ * has to be scrolled to, is the opposite of an overflow affordance.
8076
+ */
8077
+ protected readonly isOverflowing: _angular_core.WritableSignal<boolean>;
8078
+ constructor();
8079
+ /**
8080
+ * Identity function that types the `#actionButton` template's context.
8081
+ *
8082
+ * `NgTemplateOutlet` gives a template no context type — `let-projected` is
8083
+ * `any` — and Angular has no declarative way to annotate one. Passing it through
8084
+ * here and binding the result with `@let` makes every read inside that block
8085
+ * (`.kind`, `.disabled`, `.menu`) type-checked again. The alternative was
8086
+ * duplicating the block per call site, which trades a checked template for an
8087
+ * unchecked copy of the security-critical glyph binding.
8088
+ */
8089
+ protected asAction(action: MagicBarActionView): MagicBarActionView;
8090
+ /** `i18n.t(labelKey, labelParams)` — the resolved, interpolated label text. */
8091
+ protected resolvedLabel(action: MagicBarActionView): string;
8092
+ /**
8093
+ * The tooltip text. Disabled ⇒ `disabledTipKey` verbatim, or the auto-suffixed
8094
+ * `"{label} — {reason}"` — the connector + default reason are the renderer's
8095
+ * job precisely because the store only holds i18n keys (never resolved text,
8096
+ * never a locale decision baked in). Enabled ⇒ `tipKey` override, else the
8097
+ * label itself.
8098
+ */
8099
+ protected tooltipFor(action: MagicBarActionView): string;
8100
+ /**
8101
+ * Accessible name for a radio-menu trigger — richer than the plain label so a
8102
+ * screen-reader user hears the current value without opening the menu
8103
+ * ("Sort by: Newest first"), matching the visual badge-dot affordance.
8104
+ */
8105
+ protected triggerAriaLabel(action: MagicBarActionView): string;
8106
+ /**
8107
+ * The glyph's allowlisted geometry nodes, which the template binds as real
8108
+ * attributes on real `<svg:*>` elements.
8109
+ *
8110
+ * `iconPath` is publisher-supplied markup and is NOT trusted: this used to be
8111
+ * `bypassSecurityTrustHtml()` into `[innerHTML]`, which made an SVG fragment's
8112
+ * escape hatches (`<foreignObject>` → HTML integration point, `<a
8113
+ * xlink:href="javascript:…">`, `on*` handlers, `<style>`) live inside the
8114
+ * shell's own chrome. See `magic-actions-icon.ts` for why sanitizing the HTML
8115
+ * was not an option (Angular's HTML allowlist has no SVG shapes, so it strips
8116
+ * every glyph) and why `iconPath` could not become a bare `d`.
8117
+ *
8118
+ * `parseMagicBarIcon` memoizes, so this is safe to call from the template on
8119
+ * every change-detection pass AND returns a stable array identity, which is
8120
+ * what stops `@for (…; track $index)` rebuilding the glyph each time.
8121
+ */
8122
+ protected iconNodes(action: MagicBarActionView): readonly FlyMagicBarIconNode[];
8123
+ /** `null` (not `'default'`) so `[attr.data-tone]` omits the attribute entirely for the common case. */
8124
+ protected toneAttr(action: MagicBarActionView): string | null;
8125
+ /**
8126
+ * A radio-menu trigger derives its badge from the menu spec itself
8127
+ * (`value !== defaultValue`) rather than trusting a separately-set
8128
+ * `badgeDot` — the menu already carries both fields precisely for this
8129
+ * comparison, and deriving it here can't drift out of sync with a publisher
8130
+ * that forgets to keep the two in step. An action with no menu falls back to
8131
+ * the authored `badgeDot` verbatim.
8132
+ */
8133
+ protected hasBadge(action: MagicBarActionView): boolean;
8134
+ /** `aria-pressed` for `kind: 'toggle'` only — omitted (not `false`) for every other kind. */
8135
+ protected pressedAttr(action: MagicBarActionView): boolean | null;
8136
+ protected menuSections(action: MagicBarActionView): ContextMenuSection[];
8137
+ protected activate(action: MagicBarActionView, event: Event): void;
8138
+ protected onMenuAction(action: MagicBarActionView, value: string): void;
8139
+ protected closeMenu(): void;
8140
+ private toggleMenu;
8141
+ /**
8142
+ * Toggle {@link isOverflowing} when `.fma`'s content stops fitting. CSS alone
8143
+ * can't express "is this scrollable" as a selector, and a fixed always-on fade
8144
+ * would mislead when the row already fits — so the check has to run in JS.
8145
+ *
8146
+ * ## What this measures, and what it used to measure
8147
+ * The scroll box is `.fma`, NOT the host. The host is a plain flex container
8148
+ * whose in-flow children are `.fma` (which clips its OWN overflow) and the
8149
+ * primary wrapper — so the host's scrollable overflow area is exactly its
8150
+ * content box and `scrollWidth - clientWidth` is structurally always 0. It was
8151
+ * measured on the host before this change, where the fade mask could never
8152
+ * engage no matter how badly the row overflowed. Nothing failed: the feature was
8153
+ * simply inert, and jsdom performs no layout so no unit test could see it.
8154
+ *
8155
+ * ## Two passes, both needed
8156
+ * `ResizeObserver` catches the box changing under fixed content (window resize,
8157
+ * the pill sharing space with a longer search field). It does NOT fire when the
8158
+ * CONTENT changes inside a box that is already clamped at its maximum — a
8159
+ * re-publish that adds an action to a row that exactly fitted. That is what the
8160
+ * `afterRenderEffect` covers, and it must be an after-RENDER pass: the `effect`
8161
+ * below re-targets the observer as `.fma` mounts, but it runs before the browser
8162
+ * has laid the new content out, so a measurement there reads the previous frame.
8163
+ * Same split, same reasoning as `board-editor-chrome-metrics.ts`.
8164
+ *
8165
+ * `ResizeObserver` is optional — absent (Node/jsdom) the after-render pass still
8166
+ * runs and reads 0s, which reports "not overflowing" rather than throwing.
8167
+ */
8168
+ private watchOverflow;
8169
+ private measure;
8170
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FlyMagicActionsComponent, never>;
8171
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlyMagicActionsComponent, "fly-magic-actions", never, { "groups": { "alias": "groups"; "required": true; "isSignal": true; }; "primary": { "alias": "primary"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
8172
+ }
8173
+
8174
+ /**
8175
+ * Curated stroke-icon table for magic-bar actions (D2 §2, D5 §1.6/§1.9).
8176
+ *
8177
+ * A value is **inner SVG markup only** — one or more `<path>`/`<circle>`/`<rect>`
8178
+ * fragments with no wrapping `<svg>` tag. `fly-magic-actions` supplies the shell
8179
+ * (`viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"
8180
+ * stroke-linecap="round" stroke-linejoin="round"`) — matches
8181
+ * `ToolbarActions.dc.html`'s own transport ("raw SVG inner markup rendered into a
8182
+ * 24×24 viewBox … svg").
8183
+ *
8184
+ * `MagicBarActionSpec.iconPath` accepts ANY string — a publisher is free to author
8185
+ * its own glyph — but without a shared table, every app hand-authors `M4 4h16…`
8186
+ * literals with inconsistent stroke widths and no dedupe. This is that table.
8187
+ * Reference by name: `iconPath: FLY_MAGIC_BAR_ICONS.trash`.
8188
+ *
8189
+ * Provenance is marked per group below. The first group is ported verbatim (byte-
8190
+ * identical geometry) from the UX drop so real shipped surfaces keep their exact
8191
+ * look; the second is original, same-convention artwork for named actions the drop
8192
+ * doesn't expose as a standalone path. Swap an "original" entry for a sourced one
8193
+ * if a verbatim path turns up later — this table is additive, not frozen.
8194
+ */
8195
+ /**
8196
+ * The full curated table. Publishers reference it by name
8197
+ * (`iconPath: FLY_MAGIC_BAR_ICONS.trash`); nothing stops passing an arbitrary
8198
+ * string instead — {@link MagicBarActionSpec.iconPath} stays `string`.
8199
+ */
8200
+ declare const FLY_MAGIC_BAR_ICONS: {
8201
+ /** Signal-detail "View trace" — no standalone path in the drop; an activity/pulse line. */
8202
+ readonly viewTrace: "<path d=\"M3 12h4l2-7 4 14 2-7h6\"/>";
8203
+ /** Signal-detail "Archive". */
8204
+ readonly archive: "<rect x=\"3\" y=\"4\" width=\"18\" height=\"4\" rx=\"1\"/><path d=\"M5 8v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8\"/><path d=\"M10 13h4\"/>";
8205
+ /** Task-list "Sort by" trigger. */
8206
+ readonly sort: "<path d=\"M7 4v16\"/><path d=\"M3 8l4-4 4 4\"/><path d=\"M17 20V4\"/><path d=\"M13 16l4 4 4-4\"/>";
8207
+ /** Task-detail "Add audience". */
8208
+ readonly addAudience: "<circle cx=\"9\" cy=\"7\" r=\"3.2\"/><path d=\"M2.5 19.4a6.5 6.5 0 0 1 13 0\"/><path d=\"M16 10.5a3 3 0 1 0 0-5.8\"/><path d=\"M18.5 19.4a5.6 5.6 0 0 0-3-5\"/>";
8209
+ /** Task-detail "Add tag". */
8210
+ readonly addTag: "<path d=\"M20 13.5 12.5 21a2 2 0 0 1-2.8 0L4 15.3a2 2 0 0 1 0-2.8L11.5 5H18a2 2 0 0 1 2 2v6.5Z\"/><circle cx=\"15\" cy=\"9\" r=\"1.4\"/>";
8211
+ /** Task-detail "Assign robot". */
8212
+ readonly assignRobot: "<rect x=\"4\" y=\"8\" width=\"16\" height=\"11\" rx=\"3\"/><path d=\"M12 8V4\"/><circle cx=\"12\" cy=\"3\" r=\"1.2\"/><path d=\"M8 13v2M16 13v2\"/>";
8213
+ /** Task-detail "Add subtask". */
8214
+ readonly addSubtask: "<path d=\"M9 6h11M9 12h11M9 18h7\"/><path d=\"M4 6h.01M4 12h.01\"/><path d=\"M4.5 16h3M6 14.5v3\"/>";
8215
+ /** `UX/FlyOS Desktop-app/MainContent.dc.html:927` (`pubTabActions`'s local `P` table). */
8216
+ readonly addEvidence: "<path d=\"M10.5 13.5a4 4 0 0 0 5.7 0l2-2a4 4 0 0 0-5.7-5.7l-.6.6\"/><path d=\"M13.5 10.5a4 4 0 0 0-5.7 0l-2 2a4 4 0 0 0 4.2 6.5\"/><path d=\"M17.5 15.5v5M15 18h5\"/>";
8217
+ /** `MainContent.dc.html:928`. Reused for every "Edit …" action (evidence, link, task). */
8218
+ readonly edit: "<path d=\"M4 20h4.2L19 9.2a2 2 0 0 0 0-2.8l-1.4-1.4a2 2 0 0 0-2.8 0L4 15.8V20z\"/><path d=\"M13.5 6.5l4 4\"/>";
8219
+ /** `MainContent.dc.html:929`. Circle-minus — "Remove evidence", distinct from the full-trash `delete`. */
8220
+ readonly remove: "<circle cx=\"12\" cy=\"12\" r=\"8.6\"/><path d=\"M8.2 12h7.6\"/>";
8221
+ /** `MainContent.dc.html:930`. */
8222
+ readonly unlink: "<path d=\"M9.6 14.4l-1.4 1.4a3.8 3.8 0 0 1-5.4-5.4l1.9-1.9\"/><path d=\"M14.4 9.6l1.4-1.4a3.8 3.8 0 0 1 5.4 5.4l-1.9 1.9\"/><path d=\"M4.8 4.8l14.4 14.4\"/>";
8223
+ /** `MainContent.dc.html:931`. */
8224
+ readonly link: "<path d=\"M10.5 13.5a4 4 0 0 0 5.7 0l2.6-2.6a4 4 0 0 0-5.7-5.7l-1 1\"/><path d=\"M13.5 10.5a4 4 0 0 0-5.7 0l-2.6 2.6a4 4 0 0 0 5.7 5.7l1-1\"/>";
8225
+ /** `Home.dc.html:619` — the `+` glyph ("Add signal" / "Add trend" / New-task CTA). */
8226
+ readonly add: "<path d=\"M12 5v14M5 12h14\"/>";
8227
+ /** `Home.dc.html:445`. */
8228
+ readonly filter: "<path d=\"M4 6h16M7 12h10M10 18h4\"/>";
8229
+ /** `Home.dc.html:613`. */
8230
+ readonly export: "<path d=\"M12 16V7M8 11l4-4 4 4\"/><path d=\"M4 15v3a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-3\"/>";
8231
+ /** `Home.dc.html:616`. */
8232
+ readonly import: "<path d=\"M12 4v9M8 9l4 4 4-4\"/><path d=\"M4 15v3a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-3\"/>";
8233
+ /** `Home.dc.html:547` — "Mark as complete". */
8234
+ readonly check: "<circle cx=\"12\" cy=\"12\" r=\"8.6\"/><path d=\"M8.4 12.3l2.6 2.6 4.6-5\"/>";
8235
+ /** `Home.dc.html:550` — "Watch task". */
8236
+ readonly watch: "<path d=\"M2.5 12S6 5.8 12 5.8 21.5 12 21.5 12 18 18.2 12 18.2 2.5 12 2.5 12z\"/><circle cx=\"12\" cy=\"12\" r=\"2.8\"/>";
8237
+ /** `Home.dc.html:553` — the full trash-can; the danger "Delete" family. */
8238
+ readonly trash: "<path d=\"M4.5 7h15\"/><path d=\"M9.5 7V5.2h5V7\"/><path d=\"M6.5 7l.8 12a1.8 1.8 0 0 0 1.8 1.7h5.8a1.8 1.8 0 0 0 1.8-1.7L17.5 7\"/><path d=\"M10.5 11v6M13.5 11v6\"/>";
8239
+ /** `Home.dc.html:969`. */
8240
+ readonly close: "<path d=\"M6 6l12 12M18 6L6 18\"/>";
8241
+ /** `Home.dc.html:1090` — calendar's settings-gear `pageActions` entry. */
8242
+ readonly settings: "<circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M19.4 13a7.4 7.4 0 0 0 0-2l2-1.5-2-3.5-2.4.7a7.4 7.4 0 0 0-1.7-1L15 3h-4l-.3 2.7a7.4 7.4 0 0 0-1.7 1l-2.4-.7-2 3.5L6.6 11a7.4 7.4 0 0 0 0 2l-2 1.5 2 3.5 2.4-.7a7.4 7.4 0 0 0 1.7 1L11 21h4l.3-2.7a7.4 7.4 0 0 0 1.7-1l2.4.7 2-3.5-2-1.5z\"/>";
8243
+ /** `Home.dc.html:1151` — calendar-with-check, the "Today" text action's glyph. */
8244
+ readonly today: "<path d=\"M3.5 8.5h17M7 3.2v3.4M17 3.2v3.4\"/><rect x=\"3.5\" y=\"5.5\" width=\"17\" height=\"15\" rx=\"2.6\"/><path d=\"M8 13l2.2 2.2L14 11\"/>";
8245
+ };
8246
+ type FlyMagicBarIconName = keyof typeof FLY_MAGIC_BAR_ICONS;
8247
+
7139
8248
  /**
7140
8249
  * Single canonical way to declare a drag source for the agent input.
7141
8250
  *
@@ -7345,13 +8454,36 @@ type FlyTooltipPlacement = 'top' | 'bottom' | 'left' | 'right';
7345
8454
  * is `pointer-events: none` so it never eats a click or intercepts the hover.
7346
8455
  *
7347
8456
  * ## Theming + RTL
7348
- * The surface is styled from desktop-shell tokens that carry BOTH light and dark
7349
- * values (`--glass-bg-elevated`, `--surface-border`/`--separator`, `--text-color`/
7350
- * `--label-primary`), with a self-consistent dark-surface + light-text fallback for
7351
- * bare standalone usage where the DS theme layer isn't present. Placement is mirrored
8457
+ * The surface is Nova's `--mat-tip-a`/`-b` material (skill §4) a two-stop gradient
8458
+ * that carries BOTH light and dark values (`_nova-tokens.scss`, `html.light-theme` /
8459
+ * `html.dark-theme`), with a self-consistent dark-plate + white-text literal fallback
8460
+ * for bare standalone usage where no DS theme layer is present. Placement is mirrored
7352
8461
  * under `dir="rtl"` (a requested `left` lands on the reading-end side) and text aligns
7353
8462
  * to the logical start. Honours `prefers-reduced-motion`.
7354
8463
  *
8464
+ * ## Why this stays opaque, no `backdrop-filter` (read before adding blur)
8465
+ * A body-parented tooltip can land over ANY backdrop — a light app surface, a dark
8466
+ * canvas, the wallpaper — and it used to inherit `--glass-bg-elevated`, a TRANSLUCENT,
8467
+ * wallpaper-adaptive fill the shell recomputes at `:root` from the current wallpaper's
8468
+ * luminance, independent of `<html>`'s own light/dark theme class. Under a dark
8469
+ * wallpaper it became a ~54%-alpha dark plate even while the page was `light-theme`;
8470
+ * composited over a light surface (~rgb(143,141,140)) the paired white ink landed at
8471
+ * ~2.8:1 — "tooltips are white-on-white in the light theme" (commit 7aa921690, 2026-08-
8472
+ * 04). The directive's OWN doc comment at the time claimed a fallback existed; it
8473
+ * didn't — the `var()`s carried none, so the failure was silent until measured live.
8474
+ *
8475
+ * `--mat-tip-a`/`-b` do not reproduce that failure class: they are keyed on
8476
+ * `html.light-theme` / `html.dark-theme` directly (fixed per THEME), never recomputed
8477
+ * from the wallpaper at runtime, so the plate always matches the theme the page is
8478
+ * actually in. The residual risk — a light plate over a coincidentally dark LOCAL
8479
+ * backdrop (not the wallpaper) — only softens the plate/backdrop edge; the near-opaque
8480
+ * alpha (80–86%, D3 §1.6) keeps the ink-on-plate contrast itself unaffected, unlike the
8481
+ * ~2.8:1 failure above where the FILL's own colour was wrong. This is also why no
8482
+ * `backdrop-filter` is added here even though the material recipe allows it elsewhere:
8483
+ * the ratified design spec forces tooltips opaque and suppresses blur outright (D1 §7
8484
+ * item 10 / D3 §"Tooltips: ... fixed near-opaque fills"), so this file matches that
8485
+ * intentionally rather than reaching for a `glass.popover()`-style thin blur tier.
8486
+ *
7355
8487
  * The tip text is caller-supplied and assumed already-localized — no baseline i18n
7356
8488
  * strings are shipped.
7357
8489
  */
@@ -8095,6 +9227,204 @@ declare class FlyPeoplePickerComponent {
8095
9227
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlyPeoplePickerComponent, "fly-people-picker", never, { "searchFn": { "alias": "searchFn"; "required": true; "isSignal": true; }; "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "excludeIds": { "alias": "excludeIds"; "required": false; "isSignal": true; }; "initialSelection": { "alias": "initialSelection"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; }, { "selectionChange": "selectionChange"; }, never, never, true, never>;
8096
9228
  }
8097
9229
 
9230
+ /**
9231
+ * One ISO 4217 currency as the selector renders it.
9232
+ *
9233
+ * `code` is the identity: it is what {@link FlyCurrencySelectorComponent} emits and
9234
+ * what a record should persist — never the row's database id, which is an
9235
+ * implementation detail of whichever service served it.
9236
+ */
9237
+ interface FlyCurrency {
9238
+ /** ISO 4217 alpha-3 code (`AED`, `USD`, `XOF`). Unique. */
9239
+ readonly code: string;
9240
+ /** Display name, already resolved to the caller's locale by the server. */
9241
+ readonly name: string;
9242
+ /** Display symbol (`$`, `€`, `د.إ`). NOT unique — several currencies share `$`, which is exactly why every row also shows its code. */
9243
+ readonly symbol: string;
9244
+ /**
9245
+ * ISO 4217 minor-unit exponent: 0 (JPY, KRW, the CFA francs), 2 (most), or 3
9246
+ * (BHD, IQD, JOD, KWD, LYD, OMR, TND). Carried through so a host formatting the
9247
+ * amount next to the picked currency doesn't have to assume 2 and misprice a dinar.
9248
+ */
9249
+ readonly decimalDigits: number;
9250
+ /**
9251
+ * Issuing country's flag emoji, or null/absent for the multi-country union
9252
+ * currencies (XAF/XOF/XPF/XCD). The component degrades to a code tile either way —
9253
+ * see {@link FlyCurrencySelectorComponent} on why the emoji alone is not enough.
9254
+ */
9255
+ readonly flag?: string | null;
9256
+ /** Optional ISO 3166 alpha-2 codes of the countries using it, when the host fetched the richer `/api/currencies` shape. Purely informational. */
9257
+ readonly countryCodes?: readonly string[];
9258
+ }
9259
+ /** Single pick (replaces the selection, value is `string | null`) vs multi pick (chips accumulate, value is `string[]`). */
9260
+ type FlyCurrencySelectorMode = 'single' | 'multi';
9261
+ /**
9262
+ * Host-supplied loader, for a consumer that must not hit `/api/currencies/brief`
9263
+ * directly — an offline surface, a fixture-driven test, or an app that proxies
9264
+ * reference data through its own gateway route.
9265
+ */
9266
+ type FlyCurrencyFetchFn = () => Observable<readonly FlyCurrency[]>;
9267
+ /** The control's value: the picked code in single mode, the picked codes in multi mode. */
9268
+ type FlyCurrencySelectorValue = string | readonly string[] | null;
9269
+
9270
+ /**
9271
+ * **`fly-currency-selector`** — pick one currency or several from the platform's ISO 4217
9272
+ * catalogue, showing each with its flag, code, symbol and localized name.
9273
+ *
9274
+ * Pre-canned for the Controller's `GET /api/currencies/brief` (`CurrencyBriefDto`): with no
9275
+ * data inputs it loads that endpoint itself through the host's `HttpClient`, so the gateway
9276
+ * routing and auth interceptor apply and a consuming app writes one tag and nothing else.
9277
+ * A host that must not reach the platform directly supplies `[currencies]` (static rows) or
9278
+ * `[fetchFn]` (its own loader) instead — the same transport-agnostic escape hatch
9279
+ * `fly-entity-lookup` and `fly-people-picker` offer.
9280
+ *
9281
+ * Implements `ControlValueAccessor`, so it drops into reactive forms like `fly-select`. The
9282
+ * value is the ISO 4217 **code** (`string | null` single, `string[]` multi) — never the row
9283
+ * id, which belongs to whichever service served the list.
9284
+ *
9285
+ * ## Why every row shows a code, not just a flag
9286
+ * Two independent reasons, both of which the picker must survive:
9287
+ * 1. Windows renders flag emoji as two letters (no glyphs in Segoe UI Emoji). The component
9288
+ * measures this once and falls back to a styled code tile — deliberate-looking, not broken.
9289
+ * 2. Four currencies (XAF/XOF/XPF/XCD) serve many countries and have NO representative flag,
9290
+ * so `flag` is legitimately null. Picking one member state's would be wrong, not imprecise.
9291
+ *
9292
+ * Search matches word-wise AND across code, name and symbol — the same semantics as the
9293
+ * backend's `?search=`, so filtering client-side over the bounded catalogue cannot disagree
9294
+ * with what a server-side filter would have returned.
9295
+ *
9296
+ * i18n is self-sufficient through the `currency_selector.*` keys in `DS_BASELINE_LOCALES`
9297
+ * (en/ar/fr/ur); RTL works via logical CSS.
9298
+ *
9299
+ * @example
9300
+ * ```html
9301
+ * <!-- Loads /api/currencies/brief itself: -->
9302
+ * <fly-currency-selector [(ngModel)]="invoiceCurrency" [pinnedCodes]="['AED','USD','EUR']" />
9303
+ *
9304
+ * <!-- Multi-select, restricted to what the tenant trades in: -->
9305
+ * <fly-currency-selector
9306
+ * mode="multi"
9307
+ * [allowedCodes]="tenantCurrencies()"
9308
+ * (selectionDetailChange)="onCurrenciesPicked($event)" />
9309
+ * ```
9310
+ */
9311
+ declare class FlyCurrencySelectorComponent implements ControlValueAccessor {
9312
+ private readonly http;
9313
+ private readonly _i18n;
9314
+ /** `'single'` (default) replaces the pick; `'multi'` accumulates chips. Set-once at compose time. */
9315
+ readonly mode: _angular_core.InputSignal<FlyCurrencySelectorMode>;
9316
+ /** Static rows — supply these to skip the fetch entirely (offline surfaces, fixtures). */
9317
+ readonly currencies: _angular_core.InputSignal<readonly FlyCurrency[] | null>;
9318
+ /** Host-supplied loader, used when `[currencies]` is absent. Falls back to `GET /api/currencies/brief`. */
9319
+ readonly fetchFn: _angular_core.InputSignal<FlyCurrencyFetchFn | null>;
9320
+ /** Restrict the offered set to these ISO 4217 codes (case-insensitive). Empty = offer everything. */
9321
+ readonly allowedCodes: _angular_core.InputSignal<readonly string[]>;
9322
+ /**
9323
+ * Codes to surface in a "frequently used" group above the full list, in the order given.
9324
+ * Deliberately empty by default: which currencies matter is the consuming app's business
9325
+ * fact, and baking a house list into the design system would ship that opinion everywhere.
9326
+ */
9327
+ readonly pinnedCodes: _angular_core.InputSignal<readonly string[]>;
9328
+ /** Disable the whole control (also driven by reactive-forms `setDisabledState`). */
9329
+ readonly disabled: _angular_core.InputSignal<boolean>;
9330
+ /** Show the trigger clear (✕) affordance when there is a selection. */
9331
+ readonly clearable: _angular_core.InputSignal<boolean>;
9332
+ /** Trigger text when nothing is picked. Omit for the localized default. */
9333
+ readonly placeholder: _angular_core.InputSignal<string | null>;
9334
+ /** Placeholder for the in-panel search box. Omit for the localized default. */
9335
+ readonly searchPlaceholder: _angular_core.InputSignal<string | null>;
9336
+ /** Optional accessible name for the trigger (else the consumer's `<label for>` should reference it). */
9337
+ readonly ariaLabel: _angular_core.InputSignal<string>;
9338
+ /** The picked ISO 4217 codes, emitted after every pick / removal / clear. */
9339
+ readonly selectionChange: _angular_core.OutputEmitterRef<readonly string[]>;
9340
+ /** The picked rows in full — so a host formatting an amount has `symbol` + `decimalDigits` without re-resolving. */
9341
+ readonly selectionDetailChange: _angular_core.OutputEmitterRef<readonly FlyCurrency[]>;
9342
+ /** Emits when the panel opens (`true`) / closes (`false`). */
9343
+ readonly openedChange: _angular_core.OutputEmitterRef<boolean>;
9344
+ private readonly _uid;
9345
+ readonly listboxId: string;
9346
+ readonly triggerId: string;
9347
+ readonly isOpen: _angular_core.WritableSignal<boolean>;
9348
+ readonly searchTerm: _angular_core.WritableSignal<string>;
9349
+ readonly activeIndex: _angular_core.WritableSignal<number>;
9350
+ readonly loading: _angular_core.WritableSignal<boolean>;
9351
+ readonly loadFailed: _angular_core.WritableSignal<boolean>;
9352
+ /** True when flag emoji compose on this platform; false routes every tile to the code fallback. */
9353
+ readonly flagsRenderable: _angular_core.WritableSignal<boolean>;
9354
+ private readonly _loaded;
9355
+ private readonly _selectedCodes;
9356
+ private readonly _cvaDisabled;
9357
+ private _fetchStarted;
9358
+ private readonly searchEl?;
9359
+ private readonly triggerEl?;
9360
+ private _onChange;
9361
+ private _onTouched;
9362
+ constructor();
9363
+ readonly effectiveDisabled: _angular_core.Signal<boolean>;
9364
+ readonly isMulti: _angular_core.Signal<boolean>;
9365
+ readonly placeholderText: _angular_core.Signal<string>;
9366
+ readonly searchPlaceholderText: _angular_core.Signal<string>;
9367
+ readonly noResultsText: _angular_core.Signal<string>;
9368
+ readonly loadingText: _angular_core.Signal<string>;
9369
+ readonly errorText: _angular_core.Signal<string>;
9370
+ readonly retryText: _angular_core.Signal<string>;
9371
+ readonly clearText: _angular_core.Signal<string>;
9372
+ readonly pinnedGroupText: _angular_core.Signal<string>;
9373
+ readonly allGroupText: _angular_core.Signal<string>;
9374
+ /** Every offered row, after the `allowedCodes` restriction. */
9375
+ readonly available: _angular_core.Signal<readonly FlyCurrency[]>;
9376
+ private readonly _byCode;
9377
+ private readonly _selectedSet;
9378
+ /** Picked rows in pick order. A code with no matching row yet (value set before the fetch landed) is skipped, not faked. */
9379
+ readonly selected: _angular_core.Signal<readonly FlyCurrency[]>;
9380
+ readonly hasSelection: _angular_core.Signal<boolean>;
9381
+ /**
9382
+ * Rows matching the search box. Word-wise AND over code / name / symbol — every
9383
+ * whitespace-separated token must match something, in any order, which is the same
9384
+ * contract `LookupQuery.ToLikePatterns` gives the backend's `?search=`.
9385
+ */
9386
+ readonly filtered: _angular_core.Signal<readonly FlyCurrency[]>;
9387
+ /** The pinned rows, in the order the host listed them, minus anything the search filtered out. */
9388
+ readonly pinned: _angular_core.Signal<readonly FlyCurrency[]>;
9389
+ /** Everything not already shown in the pinned group. */
9390
+ readonly rest: _angular_core.Signal<readonly FlyCurrency[]>;
9391
+ /** Flat keyboard-navigation order — pinned group first, matching the render order. */
9392
+ readonly navOptions: _angular_core.Signal<readonly FlyCurrency[]>;
9393
+ optionId(index: number): string;
9394
+ readonly activeDescendant: _angular_core.Signal<string>;
9395
+ navIndexOf(code: string): number;
9396
+ isSelected(code: string): boolean;
9397
+ /**
9398
+ * Two-letter tile shown when the platform can't compose flag emoji. ISO 4217 codes are
9399
+ * built as "country code + currency initial" (AED = AE + Dirham), so the first two letters
9400
+ * ARE the country for the overwhelming majority — a correct-by-construction fallback rather
9401
+ * than an arbitrary truncation.
9402
+ */
9403
+ tileCode(currency: FlyCurrency): string;
9404
+ toggleOpen(): void;
9405
+ open(): void;
9406
+ close(restoreFocus?: boolean): void;
9407
+ pick(currency: FlyCurrency): void;
9408
+ remove(code: string, event?: Event): void;
9409
+ clear(event?: Event): void;
9410
+ onTriggerKeydown(event: KeyboardEvent): void;
9411
+ onPanelKeydown(event: KeyboardEvent): void;
9412
+ onSearchInput(value: string): void;
9413
+ onOptionHover(index: number): void;
9414
+ retry(): void;
9415
+ private _load;
9416
+ writeValue(value: FlyCurrencySelectorValue): void;
9417
+ registerOnChange(fn: (v: FlyCurrencySelectorValue) => void): void;
9418
+ registerOnTouched(fn: () => void): void;
9419
+ setDisabledState(isDisabled: boolean): void;
9420
+ /** The form-control value: the single code (or null) in single mode, the code array in multi. */
9421
+ private _controlValue;
9422
+ private _commit;
9423
+ private _touch;
9424
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FlyCurrencySelectorComponent, never>;
9425
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlyCurrencySelectorComponent, "fly-currency-selector", never, { "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "currencies": { "alias": "currencies"; "required": false; "isSignal": true; }; "fetchFn": { "alias": "fetchFn"; "required": false; "isSignal": true; }; "allowedCodes": { "alias": "allowedCodes"; "required": false; "isSignal": true; }; "pinnedCodes": { "alias": "pinnedCodes"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "searchPlaceholder": { "alias": "searchPlaceholder"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "selectionChange": "selectionChange"; "selectionDetailChange": "selectionDetailChange"; "openedChange": "openedChange"; }, never, never, true, never>;
9426
+ }
9427
+
8098
9428
  /**
8099
9429
  * Document-wide open-overlay stack — Escape arbitration for stacked overlays.
8100
9430
  *
@@ -8374,6 +9704,28 @@ type FlySearchInputSize = 'sm' | 'md' | 'lg';
8374
9704
  * is wrong half the time. The two-way `[(value)]` gives you the live text and
8375
9705
  * `(queryChange)` gives you the settled query, explicitly. Reactive-forms hosts wire
8376
9706
  * `(queryChange)` to `control.setValue(...)`.
9707
+ *
9708
+ * ## Nova morph (`collapsible`)
9709
+ * `[collapsible]` renders the Nova SearchField morph — a circular magnifier that
9710
+ * grows into a pill (D2 §3.1: 28×28 closed, `--fly-search-expanded-width` open,
9711
+ * default 230px, `--nova-ease-structural` / `--nova-duration-settle`). Two extras
9712
+ * beyond the geometry:
9713
+ * - **Controlled or uncontrolled**, your choice — see {@link open}. Every existing
9714
+ * consumer is uncontrolled (the default) and is unaffected.
9715
+ * - **A trailing slot** for composing something like the Home magic-bar's inline
9716
+ * Filters button, instead of hand-rolling the whole field per app:
9717
+ * ```html
9718
+ * <fly-search-input [collapsible]="true" [showFilterToggle]="false" ...>
9719
+ * <button flySearchTrailing type="button" (click)="openFilters()">Filters</button>
9720
+ * </fly-search-input>
9721
+ * ```
9722
+ * Rendered only while the field is expanded (never in the closed circle, so
9723
+ * projected content can't visibly break the morph geometry) and never while
9724
+ * `disabled`. It adds to the pill's content width same as the clear/filter
9725
+ * buttons do — widen `--fly-search-expanded-width` to fit it. This is a
9726
+ * SEPARATE mechanism from {@link showFilterToggle}'s built-in chevron; use
9727
+ * whichever fits — the chevron for the common toggle-a-panel case, this slot
9728
+ * when the affordance itself (icon, label, badge) needs to be bespoke.
8377
9729
  */
8378
9730
  declare class FlySearchInputComponent {
8379
9731
  private readonly i18n;
@@ -8438,6 +9790,30 @@ declare class FlySearchInputComponent {
8438
9790
  readonly showFilterToggle: _angular_core.InputSignal<boolean>;
8439
9791
  /** Reflects the host panel's open state — rotates the chevron and sets `aria-expanded`. */
8440
9792
  readonly filterPanelOpen: _angular_core.InputSignal<boolean>;
9793
+ /**
9794
+ * Controls a `collapsible` field's open/closed state from the OUTSIDE, the
9795
+ * `open`/`onToggle` contract Nova's SearchField spec calls for (D2 §3.1).
9796
+ * `null` (the default) means UNCONTROLLED — every existing consumer, which
9797
+ * never passes this input — and the field keeps managing its own expand/
9798
+ * collapse exactly as it always has (focus, hover, held value, filter panel).
9799
+ *
9800
+ * Passing `true`/`false` makes it CONTROLLED, the same "the host decides,
9801
+ * this component only asks" shape {@link filterPanelOpen}/{@link
9802
+ * filterToggled} already establish two properties up: the host binds `[open]`
9803
+ * and listens on {@link expandedChange}, which doubles as `onToggle` while
9804
+ * controlled (see its doc). Only consulted when {@link collapsible} is
9805
+ * `true` — open/closed has no meaning for an always-open field.
9806
+ *
9807
+ * Why not a `model()` two-way signal like {@link value}: `isExpanded` here
9808
+ * is normally the OUTPUT of several independent low-level signals (focus,
9809
+ * hover, held value, filter-panel state), not one value the component owns
9810
+ * outright — a `model()` would have to pick one of those to be "the" source
9811
+ * of truth and the others would silently stop mattering. An `input` that
9812
+ * simply overrides the rendered state when non-null, paired with the
9813
+ * existing `expandedChange` intent signal, lets the low-level triggers
9814
+ * keep working unchanged underneath in BOTH modes.
9815
+ */
9816
+ readonly open: _angular_core.InputSignal<boolean | null>;
8441
9817
  /**
8442
9818
  * The settled query — fires `debounceMs` after typing stops, and immediately on
8443
9819
  * clear.
@@ -8464,9 +9840,18 @@ declare class FlySearchInputComponent {
8464
9840
  /** Fires when the user clears the box (button or Escape). */
8465
9841
  readonly cleared: _angular_core.OutputEmitterRef<void>;
8466
9842
  /**
8467
- * Fires whenever a `collapsible` field expands (`true`) or collapses (`false`).
8468
- * Lets a host react to the reveal e.g. yield sibling space to the growing
8469
- * field, or dim a title while the search is open.
9843
+ * Fires whenever a `collapsible` field's internal gesture state (focus, hover,
9844
+ * held value, filter panel) says it should expand (`true`) or collapse
9845
+ * (`false`). Lets a host react to the reveal e.g. yield sibling space to
9846
+ * the growing field, or dim a title while the search is open.
9847
+ *
9848
+ * While {@link open} is bound (controlled mode), this is the `onToggle` half
9849
+ * of the D2 §3.1 `open`/`onToggle` contract: it reports what the user's
9850
+ * gesture WANTS, not the currently-rendered state (that stays pinned to
9851
+ * whatever `open` says until the host reacts) — the same request/response
9852
+ * shape {@link filterToggled} already uses for the filter panel. A host that
9853
+ * doesn't bind `open` never notices the difference: with `open` unset the
9854
+ * wanted state and the rendered state are the same value by construction.
8470
9855
  */
8471
9856
  readonly expandedChange: _angular_core.OutputEmitterRef<boolean>;
8472
9857
  /**
@@ -8486,9 +9871,23 @@ declare class FlySearchInputComponent {
8486
9871
  private readonly inputFocused;
8487
9872
  private readonly hovered;
8488
9873
  /**
8489
- * Whether a `collapsible` field is currently open. Non-collapsible fields are
8490
- * always "expanded". Open when: the field has focus, OR (hover trigger) it's
8491
- * hovered, OR it holds a query and {@link stayExpandedWithValue} is on.
9874
+ * What the field's own low-level gesture signals want its open state to be:
9875
+ * open when the field has focus, OR (hover trigger) it's hovered, OR it
9876
+ * holds a query and {@link stayExpandedWithValue} is on, OR the filter panel
9877
+ * is open (otherwise moving the pointer from the chevron to the panel
9878
+ * collapses the field out from under the gesture, taking its own anchor
9879
+ * with it). Non-collapsible fields always want "expanded".
9880
+ *
9881
+ * This is the UNCONTROLLED answer — see {@link isExpanded} for what actually
9882
+ * renders, and {@link expandedChange} for how this reaches a controlled host.
9883
+ */
9884
+ private readonly desiredExpanded;
9885
+ /**
9886
+ * Whether a `collapsible` field is currently RENDERED open. Equals {@link
9887
+ * desiredExpanded} unless a controlled {@link open} is bound, in which case
9888
+ * the bound value wins outright — the host is the single source of truth,
9889
+ * same as `[open]` on a controlled `<fly-drawer>`. Non-collapsible fields
9890
+ * ignore `open` entirely (always "expanded"; open/closed has no meaning).
8492
9891
  */
8493
9892
  readonly isExpanded: _angular_core.Signal<boolean>;
8494
9893
  /** Collapsed + a pointer trigger ⇒ the whole control is the button that expands it. */
@@ -8517,7 +9916,7 @@ declare class FlySearchInputComponent {
8517
9916
  /** Moves focus into the input — for hosts wiring a `/` or Ctrl+F shortcut. */
8518
9917
  focus(): void;
8519
9918
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<FlySearchInputComponent, never>;
8520
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlySearchInputComponent, "fly-search-input", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "placeholderKey": { "alias": "placeholderKey"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "ariaLabelKey": { "alias": "ariaLabelKey"; "required": false; "isSignal": true; }; "debounceMs": { "alias": "debounceMs"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "collapsible": { "alias": "collapsible"; "required": false; "isSignal": true; }; "expandTrigger": { "alias": "expandTrigger"; "required": false; "isSignal": true; }; "stayExpandedWithValue": { "alias": "stayExpandedWithValue"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "showFilterToggle": { "alias": "showFilterToggle"; "required": false; "isSignal": true; }; "filterPanelOpen": { "alias": "filterPanelOpen"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "queryChange": "queryChange"; "searched": "searched"; "submitted": "submitted"; "cleared": "cleared"; "expandedChange": "expandedChange"; "filterToggled": "filterToggled"; }, never, never, true, never>;
9919
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlySearchInputComponent, "fly-search-input", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "placeholderKey": { "alias": "placeholderKey"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "ariaLabelKey": { "alias": "ariaLabelKey"; "required": false; "isSignal": true; }; "debounceMs": { "alias": "debounceMs"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "collapsible": { "alias": "collapsible"; "required": false; "isSignal": true; }; "expandTrigger": { "alias": "expandTrigger"; "required": false; "isSignal": true; }; "stayExpandedWithValue": { "alias": "stayExpandedWithValue"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "showFilterToggle": { "alias": "showFilterToggle"; "required": false; "isSignal": true; }; "filterPanelOpen": { "alias": "filterPanelOpen"; "required": false; "isSignal": true; }; "open": { "alias": "open"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "queryChange": "queryChange"; "searched": "searched"; "submitted": "submitted"; "cleared": "cleared"; "expandedChange": "expandedChange"; "filterToggled": "filterToggled"; }, never, ["[flySearchTrailing]"], true, never>;
8521
9920
  }
8522
9921
 
8523
9922
  /**
@@ -9114,6 +10513,14 @@ declare function resolveStateMessageKey(kind: StateMessageKind, override?: strin
9114
10513
  * Empty / loading / error / success / warning page state.
9115
10514
  * Source visual: the legacy `.circles-state-message` block (+ `--error`
9116
10515
  * modifier). Extra CTAs project into the default slot.
10516
+ *
10517
+ * `kind="empty"` renders the D2 §3.3 EmptyState anatomy (UX-refresh S1.9): a
10518
+ * 46px icon TILE (radius 16, `var(--w07)` fill, `var(--w12)` border) instead
10519
+ * of a bare washed-out glyph, `messageKey` promoted to a bold title, and an
10520
+ * optional `noteKey` for the lighter description line underneath. `noteKey`
10521
+ * is additive — omitting it renders exactly the single-line empty state that
10522
+ * shipped before this task, just inside the new icon tile. Every other kind
10523
+ * (`loading`/`error`/`success`/`warning`) is visually unchanged.
9117
10524
  */
9118
10525
  declare class FlyStateMessageComponent {
9119
10526
  readonly kind: _angular_core.InputSignal<StateMessageKind>;
@@ -9121,6 +10528,8 @@ declare class FlyStateMessageComponent {
9121
10528
  readonly messageKey: _angular_core.InputSignal<string | undefined>;
9122
10529
  /** `pi-*` class override, e.g. `pi-bolt`. */
9123
10530
  readonly iconClass: _angular_core.InputSignal<string | undefined>;
10531
+ /** Lighter description line under the title — `kind="empty"` only. Omit for the single-line empty state. */
10532
+ readonly noteKey: _angular_core.InputSignal<string | undefined>;
9124
10533
  readonly retryLabelKey: _angular_core.InputSignal<string>;
9125
10534
  /** Renders the retry button (kind=error only). */
9126
10535
  readonly showRetry: _angular_core.InputSignal<boolean>;
@@ -9128,7 +10537,7 @@ declare class FlyStateMessageComponent {
9128
10537
  protected readonly icon: _angular_core.Signal<string>;
9129
10538
  protected readonly resolvedMessageKey: _angular_core.Signal<string | undefined>;
9130
10539
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<FlyStateMessageComponent, never>;
9131
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlyStateMessageComponent, "fly-state-message", never, { "kind": { "alias": "kind"; "required": false; "isSignal": true; }; "messageKey": { "alias": "messageKey"; "required": false; "isSignal": true; }; "iconClass": { "alias": "iconClass"; "required": false; "isSignal": true; }; "retryLabelKey": { "alias": "retryLabelKey"; "required": false; "isSignal": true; }; "showRetry": { "alias": "showRetry"; "required": false; "isSignal": true; }; }, { "retried": "retried"; }, never, ["*"], true, never>;
10540
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlyStateMessageComponent, "fly-state-message", never, { "kind": { "alias": "kind"; "required": false; "isSignal": true; }; "messageKey": { "alias": "messageKey"; "required": false; "isSignal": true; }; "iconClass": { "alias": "iconClass"; "required": false; "isSignal": true; }; "noteKey": { "alias": "noteKey"; "required": false; "isSignal": true; }; "retryLabelKey": { "alias": "retryLabelKey"; "required": false; "isSignal": true; }; "showRetry": { "alias": "showRetry"; "required": false; "isSignal": true; }; }, { "retried": "retried"; }, never, ["*"], true, never>;
9132
10541
  }
9133
10542
 
9134
10543
  /** Inline busy indicator — spinner glyph plus optional label. */
@@ -9165,6 +10574,17 @@ declare class FlyActionStackComponent {
9165
10574
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlyActionStackComponent, "fly-action-stack", never, { "triggerVariant": { "alias": "triggerVariant"; "required": false; "isSignal": true; }; "triggerTooltipKey": { "alias": "triggerTooltipKey"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
9166
10575
  }
9167
10576
 
10577
+ /**
10578
+ * As of UX-refresh S1.9, `status` also recognizes the D2 §5 priority
10579
+ * vocabulary (`critical`/`urgent`/`high`/`normal`/`low`), coloured from the
10580
+ * same shared Nova tone map as the five ratified status values
10581
+ * (`published`/`review`/`approved`/`draft`/`archived` — `nova-status-tone()`
10582
+ * / `nova-priority-tone()` in `app-surface/styles/_mixins.scss`). This is
10583
+ * additive to the existing 10-value workflow-status set, not a new input:
10584
+ * apps pass a priority the exact same way they already pass a status —
10585
+ * `[status]="item.priority"` — and must have a matching `common.status.
10586
+ * <value>` locale entry, same as today.
10587
+ */
9168
10588
  declare class StatusBadgeComponent {
9169
10589
  status: _angular_core.InputSignal<string>;
9170
10590
  /** Render as a colour-coded "status light" dot with the label on hover/SR
@@ -9178,6 +10598,62 @@ declare class StatusBadgeComponent {
9178
10598
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<StatusBadgeComponent, "fly-status-badge", never, { "status": { "alias": "status"; "required": true; "isSignal": true; }; "dot": { "alias": "dot"; "required": false; "isSignal": true; }; "domain": { "alias": "domain"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
9179
10599
  }
9180
10600
 
10601
+ /**
10602
+ * TypeScript mirror of the Sass `nova-priority-tone()` / `nova-status-tone()`
10603
+ * functions in `app-surface/styles/_mixins.scss`.
10604
+ *
10605
+ * The kit owns this map ONCE (UX-refresh S1.9 — see the Sass file's own
10606
+ * comment for the full RAD justification: 20 Stage-4 apps would otherwise each
10607
+ * re-derive "Critical → red, Urgent/High → orange…"). It is authored twice —
10608
+ * once as a Sass function for a component's own compile-time literal classes
10609
+ * (`.status-badge--critical { color: ui.nova-priority-tone('critical'); }`),
10610
+ * once here as a plain object — because a Sass `@function` cannot be called
10611
+ * from an Angular template. Anything binding a colour off a RUNTIME value
10612
+ * (page data, not a fixed template literal — e.g. `[style.color]` on a
10613
+ * hand-composed leading status dot) reads this map instead.
10614
+ *
10615
+ * Values are CSS custom-property NAMES (no `var()` wrapper), so a caller binds
10616
+ * them through Angular:
10617
+ *
10618
+ * ```html
10619
+ * <span [style.color]="'var(' + novaPriorityToneVar(item.priority) + ')'"></span>
10620
+ * ```
10621
+ *
10622
+ * Bind with `[style.color]` — never interpolate into a literal `style="…"`
10623
+ * attribute. A static `style` attribute containing `{{ }}` is not a binding at
10624
+ * all: Angular emits it as an inline style, which the platform's strict CSP
10625
+ * (`style-src 'self' 'nonce-…'`) blocks outright, and the failure surfaces as a
10626
+ * silently uncoloured dot plus a console entry naming a sha256 nobody can trace
10627
+ * back to here. `[style.color]` is set via the CSSOM and is unaffected.
10628
+ *
10629
+ * Keep this in sync with `_mixins.scss`'s two functions — `nova-tone.spec.ts`
10630
+ * pins both maps' key/value pairs so a drift between the Sass and TS copies
10631
+ * fails a test instead of shipping a colour mismatch between a component's own
10632
+ * CSS classes and a page's hand-bound dot.
10633
+ */
10634
+ /** D2 §5 priority map. Keys are lower-case; unknown keys resolve via {@link novaPriorityToneVar}'s fallback. */
10635
+ declare const NOVA_PRIORITY_TONE: Readonly<Record<string, string>>;
10636
+ /**
10637
+ * D2 §5 status map. `under-review` is the canonical key; `review` is accepted
10638
+ * as a synonym — it is the shorter key `fly-status-badge`'s pre-existing
10639
+ * status vocabulary already shipped for the same real-world state.
10640
+ */
10641
+ declare const NOVA_STATUS_TONE: Readonly<Record<string, string>>;
10642
+ /** The ramp's own "meta / neutral" step — the fallback for a key neither map recognizes. */
10643
+ declare const NOVA_TONE_FALLBACK = "--w42";
10644
+ /**
10645
+ * Resolves a priority string to a Nova custom-property NAME (e.g. `--sys-red`),
10646
+ * case-insensitive.
10647
+ *
10648
+ * Accepts nullish. A status/priority field is routinely optional in the domain
10649
+ * models these badges render, so `undefined` reaching here is ordinary data,
10650
+ * not a caller bug — and the signature freezes at 1.8.0, where widening it later
10651
+ * would be a MAJOR. Nullish resolves to the same neutral step as an unknown key.
10652
+ */
10653
+ declare function novaPriorityToneVar(priority: string | null | undefined): string;
10654
+ /** Resolves a status string to a Nova custom-property NAME (e.g. `--sys-green`), case-insensitive. Accepts nullish — see {@link novaPriorityToneVar}. */
10655
+ declare function novaStatusToneVar(status: string | null | undefined): string;
10656
+
9181
10657
  declare class DashboardKpiComponent {
9182
10658
  label: _angular_core.InputSignal<string>;
9183
10659
  value: _angular_core.InputSignal<string | number>;
@@ -9208,7 +10684,7 @@ interface FlyMetaItem {
9208
10684
  * global `.mono` utility for the small monospace value treatment.
9209
10685
  */
9210
10686
  declare class FlyMetaListComponent {
9211
- readonly items: _angular_core.InputSignal<FlyMetaItem[]>;
10687
+ readonly items: _angular_core.InputSignal<readonly FlyMetaItem[]>;
9212
10688
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<FlyMetaListComponent, never>;
9213
10689
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlyMetaListComponent, "fly-meta", never, { "items": { "alias": "items"; "required": true; "isSignal": true; }; }, {}, never, ["*"], true, never>;
9214
10690
  }
@@ -9221,6 +10697,19 @@ declare class FlyMetaListComponent {
9221
10697
  *
9222
10698
  * <fly-pagination [page]="page()" [totalPages]="totalPages()"
9223
10699
  * [rangeText]="rangeText()" (pageChange)="goToPage($event)" />
10700
+ *
10701
+ * Restyled to the D2 §5 pagination canon (UX-refresh S1.9): prev/next are 26px
10702
+ * circular arrow buttons (an SVG chevron replaces the old text label; the
10703
+ * label survives as the button's `aria-label`, already wired) and the current
10704
+ * indicator is a solid-accent pill with tabular numerals. D2 describes a row
10705
+ * of numbered "page dots" for the reference signals-list pager — this kit
10706
+ * deliberately keeps the existing prev/current/next SHAPE rather than adding a
10707
+ * numbered-page-range renderer (a new page-window/ellipsis computation, not a
10708
+ * restyle) and applies the same visual language — 26px circular arrows, a
10709
+ * 24px-tall accent-filled current indicator, tabular-nums — to it instead; see
10710
+ * `.workflow/plans/ux-refresh/notes/S1.9-content-primitives.md` for the full
10711
+ * reasoning. `data-arrow` on the prev/next glyphs mirrors under RTL exactly
10712
+ * like the existing first/last chevrons.
9224
10713
  */
9225
10714
  declare class FlyPaginationComponent {
9226
10715
  readonly page: _angular_core.InputSignal<number>;
@@ -9244,6 +10733,17 @@ declare function canGoNext(page: number, totalPages: number): boolean;
9244
10733
  declare function clampPage(page: number, totalPages: number): number;
9245
10734
 
9246
10735
  type CardLayout = 'row' | 'column';
10736
+ /**
10737
+ * Row-layout density (UX-refresh S1.9, D2 §5). `roomy` (default) is today's
10738
+ * anatomy unchanged. `compact` is the real behaviour the design calls for when
10739
+ * a detail pane opens beside the list — NOT a size token: the title drops to
10740
+ * 12.5px and `fly-card-status` is hidden (the design moves status INTO the
10741
+ * meta strip in compact mode; since the card has no way to know which
10742
+ * projected meta chip IS the status, the app renders that chip itself — see
10743
+ * COMPONENTS.md). Column layout ignores this input; it has its own fixed
10744
+ * density.
10745
+ */
10746
+ type CardDensity = 'roomy' | 'compact';
9247
10747
  /**
9248
10748
  * Listing card shell — one anatomy for the three reference card patterns:
9249
10749
  *
@@ -9273,9 +10773,20 @@ type CardLayout = 'row' | 'column';
9273
10773
  * Hover: the default interactive hover darkens the hairline and keeps the
9274
10774
  * resting shadow (cluster/trend source); `lift` opts into the
9275
10775
  * translateY/`--shadow-filter` raise for pages that want it.
10776
+ *
10777
+ * Row-layout visual canon (D2 §5, UX-refresh S1.9): a plain (non-selectable)
10778
+ * row rests transparent and tints `var(--w04)` on hover, separated from its
10779
+ * siblings by a 1px `var(--w07)` hairline rendered as a host pseudo-element —
10780
+ * NOT a border, so it disappears under `[selectable]`'s card treatment
10781
+ * (bordered `var(--w07)`/`var(--w04)`, selected → `var(--accent)`/
10782
+ * `var(--tint-sel)`, hover → `var(--w06)`/`var(--w14)`) without a seam. Rows
10783
+ * animate in with `itemIn`, staggered 40ms; column cards use `riseIn`,
10784
+ * staggered 55ms (skill §5's item/card stagger split).
9276
10785
  */
9277
10786
  declare class FlyCardComponent {
9278
10787
  readonly layout: _angular_core.InputSignal<CardLayout>;
10788
+ /** Row-layout density (`roomy` default / `compact`) — ignored in column layout. */
10789
+ readonly density: _angular_core.InputSignal<CardDensity>;
9279
10790
  /** Renders the hover/focus-revealed selection checkbox — row layout only. */
9280
10791
  readonly selectable: _angular_core.InputSignal<boolean>;
9281
10792
  readonly selected: _angular_core.ModelSignal<boolean>;
@@ -9304,7 +10815,7 @@ declare class FlyCardComponent {
9304
10815
  */
9305
10816
  protected onKey(event: Event): void;
9306
10817
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<FlyCardComponent, never>;
9307
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlyCardComponent, "fly-card", never, { "layout": { "alias": "layout"; "required": false; "isSignal": true; }; "selectable": { "alias": "selectable"; "required": false; "isSignal": true; }; "selected": { "alias": "selected"; "required": false; "isSignal": true; }; "interactive": { "alias": "interactive"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "lift": { "alias": "lift"; "required": false; "isSignal": true; }; "selectLabelKey": { "alias": "selectLabelKey"; "required": false; "isSignal": true; }; "selectLabel": { "alias": "selectLabel"; "required": false; "isSignal": true; }; }, { "selected": "selectedChange"; "activated": "activated"; }, never, ["fly-card-media", "fly-card-title", "*", "fly-card-body", "fly-card-meta", "fly-card-status", "fly-card-footer", "fly-card-actions"], true, never>;
10818
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlyCardComponent, "fly-card", never, { "layout": { "alias": "layout"; "required": false; "isSignal": true; }; "density": { "alias": "density"; "required": false; "isSignal": true; }; "selectable": { "alias": "selectable"; "required": false; "isSignal": true; }; "selected": { "alias": "selected"; "required": false; "isSignal": true; }; "interactive": { "alias": "interactive"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "lift": { "alias": "lift"; "required": false; "isSignal": true; }; "selectLabelKey": { "alias": "selectLabelKey"; "required": false; "isSignal": true; }; "selectLabel": { "alias": "selectLabel"; "required": false; "isSignal": true; }; }, { "selected": "selectedChange"; "activated": "activated"; }, never, ["fly-card-media", "fly-card-title", "*", "fly-card-body", "fly-card-meta", "fly-card-status", "fly-card-footer", "fly-card-actions"], true, never>;
9308
10819
  }
9309
10820
 
9310
10821
  /**
@@ -10071,6 +11582,7 @@ declare function initialExpanded(sections: readonly Pick<FlyAppModuleSection, 'c
10071
11582
  */
10072
11583
  declare function sectionHintKey(section: Pick<FlyAppModuleSection, 'collapsible' | 'hintKey' | 'collapsedHintKey'>, expanded: boolean): string | null;
10073
11584
 
11585
+ type TabsVariant = 'underline' | 'segmented';
10074
11586
  /**
10075
11587
  * Underline tab row + panels — visual port of the signal-detail sidecard tab
10076
11588
  * row (`.llc__tabs` / `.llc__tab`); also replaces the job-profile
@@ -10085,6 +11597,14 @@ declare function sectionHintKey(section: Pick<FlyAppModuleSection, 'collapsible'
10085
11597
  * </fly-tabs>
10086
11598
  * ```
10087
11599
  *
11600
+ * `variant="segmented"` (UX-refresh S1.9, D2 §1.3) renders the OTHER tab
11601
+ * anatomy the source design uses for its detail-page tab strips (Metadata /
11602
+ * Evidence / Linked trends / … and Tasks' 3-tab row): a pill-shaped
11603
+ * `role="tablist"` track with the active tab as a raised pill inside it,
11604
+ * instead of an underline baseline. Same component, same a11y wiring, same
11605
+ * `fly-tab` children — only the CSS skin switches; `underline` (default)
11606
+ * keeps every existing consumer pixel-identical.
11607
+ *
10088
11608
  * a11y: `role="tablist"`/`tab`/`tabpanel` with `aria-selected`/`aria-controls`
10089
11609
  * wiring, roving tabindex (active tab is the tab stop), RTL-aware arrow-key
10090
11610
  * navigation with wrap-around and Home/End; arrows move both selection and
@@ -10099,6 +11619,8 @@ declare class FlyTabsComponent {
10099
11619
  readonly selected: _angular_core.ModelSignal<string | undefined>;
10100
11620
  /** Group label for the tablist. */
10101
11621
  readonly ariaLabelKey: _angular_core.InputSignal<string | undefined>;
11622
+ /** Tab-strip skin — `underline` (default, unchanged) or `segmented` (D2 §1.3 pill track). */
11623
+ readonly variant: _angular_core.InputSignal<TabsVariant>;
10102
11624
  protected readonly tabItems: _angular_core.Signal<readonly any[]>;
10103
11625
  readonly activeId: _angular_core.Signal<string | null>;
10104
11626
  tabId(id: string): string;
@@ -10106,7 +11628,7 @@ declare class FlyTabsComponent {
10106
11628
  protected select(id: string): void;
10107
11629
  protected onKey(event: KeyboardEvent): void;
10108
11630
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<FlyTabsComponent, never>;
10109
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlyTabsComponent, "fly-tabs", never, { "selected": { "alias": "selected"; "required": false; "isSignal": true; }; "ariaLabelKey": { "alias": "ariaLabelKey"; "required": false; "isSignal": true; }; }, { "selected": "selectedChange"; }, ["tabItems"], ["*"], true, never>;
11631
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlyTabsComponent, "fly-tabs", never, { "selected": { "alias": "selected"; "required": false; "isSignal": true; }; "ariaLabelKey": { "alias": "ariaLabelKey"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; }, { "selected": "selectedChange"; }, ["tabItems"], ["*"], true, never>;
10110
11632
  }
10111
11633
  /**
10112
11634
  * One tab of a `fly-tabs` group: declares the tab button (id, label, optional
@@ -10270,7 +11792,7 @@ declare function nextSegmentIndex(current: number, key: string, length: number,
10270
11792
  declare class FlySegmentedComponent {
10271
11793
  private readonly i18n;
10272
11794
  private readonly el;
10273
- readonly options: _angular_core.InputSignal<SegmentedOption[]>;
11795
+ readonly options: _angular_core.InputSignal<readonly SegmentedOption[]>;
10274
11796
  readonly value: _angular_core.ModelSignal<string | undefined>;
10275
11797
  readonly disabled: _angular_core.InputSignal<boolean>;
10276
11798
  readonly ariaLabelKey: _angular_core.InputSignal<string | undefined>;
@@ -10338,9 +11860,11 @@ declare class FlySliderComponent {
10338
11860
  declare function clampSliderValue(value: number, min: number, max: number): number;
10339
11861
  /**
10340
11862
  * Gradient fill for the range track (the legacy confidence-slider
10341
- * `--rng-track`): brand teal→purple up to the value, rest neutral. All colour
10342
- * stops resolve through tokens so themes restyle the track. Mirrored under RTL
10343
- * (native range inputs flip, `to right` would not).
11863
+ * `--rng-track`): D2 §1.3's confidence-meter recipe, `linear-gradient(90deg, var(--accent),
11864
+ * var(--sys-teal))` this slider IS that confidence control (the class docblock names it as the
11865
+ * port), so the fill up to the value runs accent→teal, the rest sits at the Nova input-border
11866
+ * tier (`--w14`). All colour stops resolve through tokens so themes restyle the track. Mirrored
11867
+ * under RTL (native range inputs flip, `to right` would not).
10344
11868
  */
10345
11869
  declare function sliderTrackGradient(value: number, min: number, max: number, rtl: boolean): string;
10346
11870
 
@@ -10628,7 +12152,7 @@ declare function nextEnabledIndex(items: readonly ActionMenuItem[], current: num
10628
12152
  declare class FlyActionMenuComponent {
10629
12153
  private readonly el;
10630
12154
  private readonly injector;
10631
- readonly items: _angular_core.InputSignal<ActionMenuItem[]>;
12155
+ readonly items: _angular_core.InputSignal<readonly ActionMenuItem[]>;
10632
12156
  readonly triggerTooltipKey: _angular_core.InputSignal<string>;
10633
12157
  /** Id of the activated item. */
10634
12158
  readonly selected: _angular_core.OutputEmitterRef<string>;
@@ -10736,6 +12260,6 @@ declare const AUDIENCE_ERROR_CODES: {
10736
12260
  };
10737
12261
  type AudienceErrorCode = (typeof AUDIENCE_ERROR_CODES)[keyof typeof AUDIENCE_ERROR_CODES];
10738
12262
 
10739
- export { AGENT_DRAG_MIME, AGENT_PAYLOAD_VERSION, APP_LOOKUP, AUDIENCE_ERROR_CODES, AUDIENCE_LIMITS, AUDIENCE_PRESETS, AUDIENCE_TERM_KINDS, AgentActionBus, AgentActionUnsupportedDispatchError, AgentCommandRegistry, AgentDropRegistry, AgentFlightAnimator, AgentLookupRegistry, AgentPayloadOversizeError, AudienceBuilderComponent, AuthService, BilingualFieldComponent, CRON_MODES, CRON_WEEKDAYS, ContextMenuComponent, DEFAULT_AGENT_PAYLOAD_LIMITS, DEFAULT_FLY_THEME_MODE, DS_BASELINE_LOCALES, DashboardKpiComponent, DialogResult, EntityLookupComponent, FLYOS_LAUNCH_EVENT, FLYOS_LAUNCH_REQUEST_EVENT, FLYOS_REMOTE_ROUTE_EVENT, FLY_ACCENT_PROPERTY, FLY_ADMIN_ROLES, FLY_CHUNK_RELOAD_FLAG, FLY_COMPACT_THRESHOLD, FLY_COUNTRIES, FLY_EMOJI_BY_ID, FLY_EMOJI_CATEGORIES, FLY_EMOJI_CATEGORY_BY_ID, FLY_EMOJI_DEFAULT_CATEGORIES, FLY_EMOJI_PACK, FLY_EMOJI_PACK_MISSING_MESSAGE, FLY_EMOJI_PREVIEW_COUNT, FLY_EMPTY_VALUE, FLY_LOCALE_CATALOG, FLY_NF_CACHE_HEAL_FLAG, FLY_RELOAD_DEBOUNCE_MS, FLY_RELOAD_REARM_MS, FLY_REMOTE_BASE_PATH, FLY_REMOTE_CONTEXT_EVENT, FLY_REMOTE_CONTEXT_STORE_KEY, FLY_REMOTE_ROUTES, FLY_SCAN_PENDING_DEFAULT_DELAY_MS, FLY_SCAN_PENDING_MAX_RETRIES, FLY_SCAN_PENDING_STATUS, FLY_SEARCH_DEBOUNCE_MS, FLY_SKIN_TONES, FLY_STANDALONE_AUTH_CONFIG, FLY_THEME_MODE_IDS, FLY_WINDOW_HELP_HINT_EVENT, FLY_WINDOW_PAGE_TITLE_EVENT, FlyAchievementProgressComponent, FlyActionMenuComponent, FlyActionStackComponent, FlyAgentDraggableDirective, FlyAnimatedEmojiComponent, FlyAppHomeComponent, FlyAppTopbarComponent, FlyAuthLiveRefresh, FlyBadgeWallComponent, FlyBlockUiComponent, FlyBreadcrumbComponent, FlyButtonComponent, FlyBytesPipe, FlyCaptchaComponent, FlyCardActionsComponent, FlyCardBodyComponent, FlyCardComponent, FlyCardFooterComponent, FlyCardGridComponent, FlyCardMediaComponent, FlyCardMetaComponent, FlyCardStatusComponent, FlyCardTitleComponent, FlyCellDirective, FlyCheckboxComponent, FlyChipComponent, FlyChunkReloadErrorHandler, FlyClickOutsideDirective, FlyCollapsibleComponent, FlyCommentThreadComponent, FlyCompactNumberPipe, FlyConfirmDialogComponent, FlyControlDirective, FlyCronBuilderComponent, FlyDataTableComponent, FlyDatePipe, FlyDateTimePipe, FlyDebouncer, FlyDecimalNumberPipe, FlyDetailCardComponent, FlyDetailShellComponent, FlyDrawerComponent, FlyDurationPipe, FlyDynamicFormComponent, FlyEmojiPickerComponent, FlyFieldComponent, FlyFileDownloadService, FlyFileUploadComponent, FlyFilterPanelComponent, FlyFormBannerComponent, FlyFormFooterComponent, FlyFormGridComponent, FlyFormSectionComponent, FlyFullNumberPipe, FlyGanttComponent, FlyHubClient, FlyIconButtonComponent, FlyIfAdminDirective, FlyIfRoleDirective, FlyImageUploadComponent, FlyLeaderboardComponent, FlyMetaListComponent, FlyModalComponent, FlyModerationQueueComponent, FlyModuleIconDirective, FlyPaginationComponent, FlyPeoplePickerComponent, FlyPointsTierComponent, FlyProgressComponent, FlyRelativeTimePipe, FlyRemoteContextService, FlyRemoteRouter, FlyRemoteRouterOutletComponent, FlySearchInputComponent, FlySectionHeaderComponent, FlySecureSrcDirective, FlySegmentedComponent, FlySelectComponent, FlySkeletonComponent, FlySliderComponent, FlySparklineComponent, FlySpinnerComponent, FlyStandaloneAuthCallbackComponent, FlyStandaloneAuthService, FlyStateMessageComponent, FlyDynamicFormComponent as FlySurveyFormComponent, FlyTabComponent, FlyTabsComponent, FlyTagsInputComponent, FlyThemeService, FlyTimePipe, FlyToastService, FlyToggleComponent, FlyTooltipDirective, FlyTreeNavComponent, FlyTypeaheadComponent, FlyUserDirectoryService, FlyWindowHelpService, FlyWindowTitleService, FlyosPendingLaunchesGlobalKey, FlyosShellHandlesLaunchRequestsGlobalKey, FlyosShellOwnsHistoryGlobalKey, GANTT_ZOOMS, I18nService, LAUNCH_CONTEXT, MessageBoxButtons, MessageBoxComponent, MessageBoxIcon, MessageBoxService, MockAuthService, OverlayStack, PRESENCE_COLORS, PageHeaderComponent, RTL_LOCALE_SET, SHARE_ORG_CHART_SYSTEM_KEY_APPS, SHARE_ORG_CHART_SYSTEM_KEY_DEFAULT, SHARE_PANEL_DEFAULT_FILE_LEVELS, STATE_DEFAULT_ICONS, STATE_DEFAULT_MESSAGE_KEYS, STEP_UP_CODE, STEP_UP_REAUTH_HANDLER, STEP_UP_RETURN_KEY, SUPPORTED_AGENT_PAYLOAD_VERSIONS, SharePanelComponent, SourceAppResolver, StandaloneWindowManagerService, StatusBadgeComponent, StepUpService, ToastHostComponent, TranslatePipe, WINDOW_DATA, WINDOW_HELP_HINT, WindowManagerService, applySkinTone, applySuggestion, ariaSort, buildCron, canConfirm, canGoNext, canGoPrev, captureFocus, clampPage, clampSliderValue, connectRemoteLaunch, enterActivatesNatively, filterGroup, filterSuggestions, findLocaleByDialect, findLocaleByPrefix, firstEnabledIndex, firstModuleIndex, flattenModules, flyAdminGuard, flyApiErrorMessage, flyCaptchaBase64Utf8, flyCaptchaBuildToken, flyCaptchaSha256Hex, flyCompactNumber, flyDebounced, flyDecimalNumber, flyDownloadBlob, flyDuration, flyEmojiFor, flyEmojiIsTonable, flyEmojiPackUrl, flyExportFileName, flyFirstEnabledIndex, flyFormatBytes, flyFormatDate, flyFormatDateTime, flyFormatTime, flyFullNumber, flyNextEnabledIndex, flyNextSegmentIndex, flyRelativeTime, flyResolveActiveTab, flyRoleGuard, flyScanPendingDelayMs, flyScanRetry, flySignedCompact, flySkinToneLabelKey, flyStandaloneAuthGuard, flyStandaloneAuthInterceptor, flyToDateOnly, flyToPage, flyUnwrap, flyUnwrapLenient, hasAnyRoleIn, healNativeFederationCacheOnce, initialExpanded, isAccentColor, isChunkLoadError, isFlyAuthStorePopulated, isNativeFederationCacheError, isRtlLocale, isRtlLocaleEntry, isValidCron, isValidSingleField, loadRemoteStyles, matchFlyRoutePattern, nextEnabledIndex, nextModuleIndex, nextSegmentIndex, nextSort, normalizeFlyTheme, normalizeRoles, overlayStack, parseCron, parseStepUpChallenge, parseTags, presenceColorFor, printConsoleSecurityWarning, provideFlyChunkReloadRecovery, provideFlyEmojiPack, provideFlyStandaloneAuth, reloadOnceForChunkError, requestAppLaunch, resolveActiveModule, resolveActiveSection, resolveActiveTab, resolveCellValue, resolveStateIcon, resolveStateMessageKey, restoreFocus, sameTags, sectionHintKey, sectionLayout, sliderTrackGradient, sparklinePath, sparklinePoints, stepUpInterceptor, stepUpReturnKey, trimAgentPayload, trimAgentString, unloadRemoteStyles, utf8ByteLength, validateAgentPayload, warnIfEmbeddedSessionMissing };
10740
- export type { ActionMenuItem, AgentAction, AgentActionDispatch, AgentActionVerb, AgentChipHostInputs, AgentCommand, AgentCommandContextBinding, AgentCommandHandle, AgentCommandRegistration, AgentCommandScope, AgentCommandSlashSpec, AgentDragPayload, AgentDraggableItem, AgentDropChipMode, AgentDropRendererRegistration, AgentEnvelopeAttachment, AgentMcpScope, AgentMessageEnvelope, AgentPayloadLimits, AgentPayloadValidationResult, AppEveryonePrincipal, AppEveryoneTerm, AppLookup, AppLookupEntry, AudienceEditTarget, AudienceErrorCode, AudienceFilter, AudienceOptions, AudiencePresetKind, AudienceTerm, AudienceTermKind, BreadcrumbItem, ButtonSize, ButtonVariant, CardLayout, ChartTerm, ChildWindowData, ChipTone, ConfirmKind, ConnectRemoteLaunchOptions, ContextMenuAlign, ContextMenuItem, ContextMenuSection, CronAdvancedFieldDef, CronMode, CronParts, CronWeekday, DesktopApp, DesktopAppCategory, DesktopAppKind, DetailSection, DialogResultWithAcknowledgement, EmbeddedSessionProbe, EntityLinkSelection, FilterGroup, FlyAchievementRow, FlyApiError, FlyApiResponse, FlyAppHomeLayout, FlyAppModule, FlyAppModuleSection, FlyAuthRefreshPayload, FlyAuthStoreReadable, FlyBadgeTile, FlyBreadcrumbItem, FlyCaptchaChallenge, FlyCaptchaSolution, FlyCaptchaState, FlyCellContext, FlyColumn, FlyColumnKind, FlyComment, FlyCommentDeleteRequest, FlyCommentEditRequest, FlyCommentLoadMoreRequest, FlyCommentLoadRepliesRequest, FlyCommentLockToggleRequest, FlyCommentPage, FlyCommentReportReason, FlyCommentReportRequest, FlyCommentReportStatus, FlyCommentSubmitRequest, FlyCountry, FlyDrawerSide, FlyDrawerSize, FlyEmojiCategory, FlyEmojiCell, FlyEmojiEntry, FlyEmojiPack, FlyEmojiPackEntry, FlyEmojiPackManifest, FlyEmojiPickerSize, FlyEmojiPickerTab, FlyEmojiSection, FlyFileInfo, FlyFileSelection, FlyFormAnswer, FlyFormAnswerValue, FlyFormDefinition, FlyFormFieldOptions, FlyFormOption, FlyFormQuestion, FlyFormQuestionType, FlyFormScoreDisplay, FlyLaunchEventDetail, FlyLaunchRequestDetail, FlyLeaderboardRow, FlyLiveRefreshOptions, FlyLocaleEntry, FlyMetaItem, FlyModerationLoadPageRequest, FlyModerationLockThreadRequest, FlyModerationOpenSubjectRequest, FlyModerationReport, FlyModerationReportPage, FlyModerationResolutionStatus, FlyModerationResolveRequest, FlyNavigableItem, FlyPageMeta, FlyPageResult, FlyPaged, FlyPeoplePickerMode, FlyPeoplePickerOption, FlyPeopleSearchFn, FlyPointsSummary, FlyRemoteContext, FlyRemoteEagerRoute, FlyRemoteLazyRoute, FlyRemoteLoadedComponent, FlyRemoteMatch, FlyRemoteRoute, FlyRemoteRouteEventDetail, FlySearchExpandTrigger, FlySearchInputSize, FlySecureSrcState, FlySelectOption, FlySelectValue, FlySkeletonAnimation, FlySkeletonLayout, FlySkeletonShape, FlySkinTone, FlySort, FlyStandaloneAuthConfig, FlyFileSelection as FlySurveyFileSelection, FlyFormAnswer as FlySurveyFormAnswer, FlyFormAnswerValue as FlySurveyFormAnswerValue, FlyFormDefinition as FlySurveyFormDefinition, FlyFormFieldOptions as FlySurveyFormFieldOptions, FlyFormOption as FlySurveyFormOption, FlyFormQuestion as FlySurveyFormQuestion, FlyFormQuestionType as FlySurveyQuestionType, FlyThemeMode, FlyTooltipPlacement, FlyTreeNavNode, FlyTypeaheadOption, FlyWindowHelpHintEventDetail, FlyWindowHelpPublisher, FlyWindowPageTitleEventDetail, FlyWindowTitlePublisher, FlyosPendingLaunches, FocusRestore, FormBannerKind, GanttDependency, GanttDependencyCreate, GanttRow, GanttRowDatesChange, GanttRowKind, GanttZoom, IconButtonVariant, LaunchContext, LoadBundleOptions, LookupDescriptor, LookupHandle, LookupRegistration, LookupResult, LookupSearch, MessageBoxButton, MessageBoxDontAskAgainConfig, MessageBoxOptions, MessageBoxOptionsWithAcknowledgement, MockAuthConfig, OpenWindowOptions, OuPrincipal, OuTerm, OverlayHandle, PageHeaderVariant, PresetTerm, ProgressTone, RemoteAppDef, RequestAppLaunchOptions, RoleOuLookupRow, RolePrincipal, RolesTerm, SegmentedOption, ShareOrgChartOption, ShareOuNode, SharePanelLevelOption, SharePermissionEntry, SharePrincipal, SharePrincipalKind, ShareUserResult, StateMessageKind, StepUpChallenge, StepUpReauthHandler, StepUpReauthRequest, ToastAction, ToastEntry, ToastOptions, ToastVariant, User, UserPrincipal, UsersTerm, WindowHelpHint, WindowInstance, WindowState };
12263
+ export { AGENT_DRAG_MIME, AGENT_PAYLOAD_VERSION, APP_LOOKUP, AUDIENCE_ERROR_CODES, AUDIENCE_LIMITS, AUDIENCE_PRESETS, AUDIENCE_TERM_KINDS, AgentActionBus, AgentActionUnsupportedDispatchError, AgentCommandRegistry, AgentDropRegistry, AgentFlightAnimator, AgentLookupRegistry, AgentPayloadOversizeError, AudienceBuilderComponent, AuthService, BilingualFieldComponent, CRON_MODES, CRON_WEEKDAYS, ContextMenuComponent, DEFAULT_AGENT_PAYLOAD_LIMITS, DEFAULT_FLY_THEME_MODE, DS_BASELINE_LOCALES, DashboardKpiComponent, DialogResult, EntityLookupComponent, FLYOS_LAUNCH_EVENT, FLYOS_LAUNCH_REQUEST_EVENT, FLYOS_REMOTE_ROUTE_EVENT, FLY_ACCENT_PROPERTY, FLY_ADMIN_ROLES, FLY_CHUNK_RELOAD_FLAG, FLY_COMPACT_THRESHOLD, FLY_COUNTRIES, FLY_EMOJI_BY_ID, FLY_EMOJI_CATEGORIES, FLY_EMOJI_CATEGORY_BY_ID, FLY_EMOJI_DEFAULT_CATEGORIES, FLY_EMOJI_PACK, FLY_EMOJI_PACK_MISSING_MESSAGE, FLY_EMOJI_PREVIEW_COUNT, FLY_EMPTY_VALUE, FLY_LOCALE_CATALOG, FLY_MAGIC_BAR_EVENT, FLY_MAGIC_BAR_ICONS, FLY_MAGIC_BAR_STORE_KEY, FLY_NF_CACHE_HEAL_FLAG, FLY_RELOAD_DEBOUNCE_MS, FLY_RELOAD_REARM_MS, FLY_REMOTE_BASE_PATH, FLY_REMOTE_CONTEXT_EVENT, FLY_REMOTE_CONTEXT_STORE_KEY, FLY_REMOTE_ROUTES, FLY_SCAN_PENDING_DEFAULT_DELAY_MS, FLY_SCAN_PENDING_MAX_RETRIES, FLY_SCAN_PENDING_STATUS, FLY_SEARCH_DEBOUNCE_MS, FLY_SKIN_TONES, FLY_STANDALONE_AUTH_CONFIG, FLY_THEME_MODE_IDS, FLY_WINDOW_HELP_HINT_EVENT, FLY_WINDOW_PAGE_TITLE_EVENT, FlyAchievementProgressComponent, FlyActionMenuComponent, FlyActionStackComponent, FlyAgentDraggableDirective, FlyAnimatedEmojiComponent, FlyAppHomeComponent, FlyAppTopbarComponent, FlyAuthLiveRefresh, FlyBadgeWallComponent, FlyBlockUiComponent, FlyBreadcrumbComponent, FlyButtonComponent, FlyBytesPipe, FlyCaptchaComponent, FlyCardActionsComponent, FlyCardBodyComponent, FlyCardComponent, FlyCardFooterComponent, FlyCardGridComponent, FlyCardMediaComponent, FlyCardMetaComponent, FlyCardStatusComponent, FlyCardTitleComponent, FlyCellDirective, FlyCheckboxComponent, FlyChipComponent, FlyChunkReloadErrorHandler, FlyClickOutsideDirective, FlyCollapsibleComponent, FlyCommentThreadComponent, FlyCompactNumberPipe, FlyConfirmDialogComponent, FlyControlDirective, FlyCronBuilderComponent, FlyCurrencySelectorComponent, FlyDataTableComponent, FlyDatePipe, FlyDateTimePipe, FlyDebouncer, FlyDecimalNumberPipe, FlyDetailCardComponent, FlyDetailShellComponent, FlyDrawerComponent, FlyDurationPipe, FlyDynamicFormComponent, FlyEmojiPickerComponent, FlyFieldComponent, FlyFileDownloadService, FlyFileUploadComponent, FlyFilterPanelComponent, FlyFormBannerComponent, FlyFormFooterComponent, FlyFormGridComponent, FlyFormSectionComponent, FlyFullNumberPipe, FlyGanttComponent, FlyHubClient, FlyIconButtonComponent, FlyIfAdminDirective, FlyIfRoleDirective, FlyImageUploadComponent, FlyLeaderboardComponent, FlyMagicActionsComponent, FlyMetaListComponent, FlyModalComponent, FlyModerationQueueComponent, FlyModuleIconDirective, FlyPaginationComponent, FlyPeoplePickerComponent, FlyPointsTierComponent, FlyProgressComponent, FlyRelativeTimePipe, FlyRemoteContextService, FlyRemoteRouter, FlyRemoteRouterOutletComponent, FlySearchInputComponent, FlySectionHeaderComponent, FlySecureSrcDirective, FlySegmentedComponent, FlySelectComponent, FlySkeletonComponent, FlySliderComponent, FlySparklineComponent, FlySpinnerComponent, FlyStandaloneAuthCallbackComponent, FlyStandaloneAuthService, FlyStateMessageComponent, FlyDynamicFormComponent as FlySurveyFormComponent, FlyTabComponent, FlyTabsComponent, FlyTagsInputComponent, FlyThemeService, FlyTimePipe, FlyToastService, FlyToggleComponent, FlyTooltipDirective, FlyTreeNavComponent, FlyTypeaheadComponent, FlyUserDirectoryService, FlyWindowHelpService, FlyWindowTitleService, FlyosPendingLaunchesGlobalKey, FlyosShellHandlesLaunchRequestsGlobalKey, FlyosShellOwnsHistoryGlobalKey, GANTT_ZOOMS, I18nService, LAUNCH_CONTEXT, MAGIC_BAR_SEARCH_WIDTH_DEFAULT, MAGIC_BAR_SEARCH_WIDTH_MAX, MAGIC_BAR_SEARCH_WIDTH_MIN, MagicBarRegistry, MessageBoxButtons, MessageBoxComponent, MessageBoxIcon, MessageBoxService, MockAuthService, NOVA_PRIORITY_TONE, NOVA_STATUS_TONE, NOVA_TONE_FALLBACK, OverlayStack, PRESENCE_COLORS, PageHeaderComponent, RTL_LOCALE_SET, SHARE_ORG_CHART_SYSTEM_KEY_APPS, SHARE_ORG_CHART_SYSTEM_KEY_DEFAULT, SHARE_PANEL_DEFAULT_FILE_LEVELS, STATE_DEFAULT_ICONS, STATE_DEFAULT_MESSAGE_KEYS, STEP_UP_CODE, STEP_UP_REAUTH_HANDLER, STEP_UP_RETURN_KEY, SUPPORTED_AGENT_PAYLOAD_VERSIONS, SharePanelComponent, SourceAppResolver, StandaloneWindowManagerService, StatusBadgeComponent, StepUpService, ToastHostComponent, TranslatePipe, WINDOW_DATA, WINDOW_HELP_HINT, WindowManagerService, applySkinTone, applySuggestion, ariaSort, buildCron, canConfirm, canGoNext, canGoPrev, captureFocus, clampMagicBarSearchWidth, clampPage, clampSliderValue, connectRemoteLaunch, enterActivatesNatively, filterGroup, filterSuggestions, findLocaleByDialect, findLocaleByPrefix, firstEnabledIndex, firstModuleIndex, flattenModules, flyAdminGuard, flyApiErrorMessage, flyCaptchaBase64Utf8, flyCaptchaBuildToken, flyCaptchaSha256Hex, flyCompactNumber, flyDebounced, flyDecimalNumber, flyDownloadBlob, flyDuration, flyEmojiFor, flyEmojiIsTonable, flyEmojiPackUrl, flyExportFileName, flyFirstEnabledIndex, flyFormatBytes, flyFormatDate, flyFormatDateTime, flyFormatTime, flyFullNumber, flyNextEnabledIndex, flyNextSegmentIndex, flyRelativeTime, flyResolveActiveTab, flyRoleGuard, flyScanPendingDelayMs, flyScanRetry, flySignedCompact, flySkinToneLabelKey, flyStandaloneAuthGuard, flyStandaloneAuthInterceptor, flyToDateOnly, flyToPage, flyUnwrap, flyUnwrapLenient, hasAnyRoleIn, healNativeFederationCacheOnce, initialExpanded, isAccentColor, isChunkLoadError, isFlyAuthStorePopulated, isNativeFederationCacheError, isRtlLocale, isRtlLocaleEntry, isValidCron, isValidSingleField, loadRemoteStyles, magicBarOwnerKey, magicBarSearchText, matchFlyRoutePattern, nextEnabledIndex, nextModuleIndex, nextSegmentIndex, nextSort, normalizeFlyTheme, normalizeRoles, novaPriorityToneVar, novaStatusToneVar, overlayStack, parseCron, parseStepUpChallenge, parseTags, presenceColorFor, printConsoleSecurityWarning, provideFlyChunkReloadRecovery, provideFlyEmojiPack, provideFlyStandaloneAuth, reloadOnceForChunkError, requestAppLaunch, resolveActiveModule, resolveActiveSection, resolveActiveTab, resolveCellValue, resolveStateIcon, resolveStateMessageKey, restoreFocus, sameTags, sectionHintKey, sectionLayout, sliderTrackGradient, sparklinePath, sparklinePoints, stepUpInterceptor, stepUpReturnKey, trimAgentPayload, trimAgentString, unloadRemoteStyles, utf8ByteLength, validateAgentPayload, warnIfEmbeddedSessionMissing };
12264
+ export type { ActionMenuItem, AgentAction, AgentActionDispatch, AgentActionVerb, AgentChipHostInputs, AgentCommand, AgentCommandContextBinding, AgentCommandHandle, AgentCommandRegistration, AgentCommandScope, AgentCommandSlashSpec, AgentDragPayload, AgentDraggableItem, AgentDropChipMode, AgentDropRendererRegistration, AgentEnvelopeAttachment, AgentMcpScope, AgentMessageEnvelope, AgentPayloadLimits, AgentPayloadValidationResult, AppEveryonePrincipal, AppEveryoneTerm, AppLookup, AppLookupEntry, AudienceEditTarget, AudienceErrorCode, AudienceFilter, AudienceOptions, AudiencePresetKind, AudienceTerm, AudienceTermKind, BreadcrumbItem, ButtonSize, ButtonVariant, CardDensity, CardLayout, ChartTerm, ChildWindowData, ChipTone, ConfirmKind, ConnectRemoteLaunchOptions, ContextMenuAlign, ContextMenuItem, ContextMenuSection, CronAdvancedFieldDef, CronMode, CronParts, CronWeekday, DesktopApp, DesktopAppCategory, DesktopAppKind, DetailSection, DialogResultWithAcknowledgement, EmbeddedSessionProbe, EntityLinkSelection, FilterGroup, FlyAchievementRow, FlyApiError, FlyApiResponse, FlyAppHomeLayout, FlyAppModule, FlyAppModuleSection, FlyAuthRefreshPayload, FlyAuthStoreReadable, FlyBadgeTile, FlyBreadcrumbItem, FlyCaptchaChallenge, FlyCaptchaSolution, FlyCaptchaState, FlyCellContext, FlyColumn, FlyColumnKind, FlyComment, FlyCommentDeleteRequest, FlyCommentEditRequest, FlyCommentLoadMoreRequest, FlyCommentLoadRepliesRequest, FlyCommentLockToggleRequest, FlyCommentPage, FlyCommentReportReason, FlyCommentReportRequest, FlyCommentReportStatus, FlyCommentSubmitRequest, FlyCountry, FlyCurrency, FlyCurrencyFetchFn, FlyCurrencySelectorMode, FlyCurrencySelectorValue, FlyDrawerBodyPadding, FlyDrawerPosition, FlyDrawerSide, FlyDrawerSize, FlyDrawerVariant, FlyEmojiCategory, FlyEmojiCell, FlyEmojiEntry, FlyEmojiPack, FlyEmojiPackEntry, FlyEmojiPackManifest, FlyEmojiPickerSize, FlyEmojiPickerTab, FlyEmojiSection, FlyFileInfo, FlyFileSelection, FlyFormAnswer, FlyFormAnswerValue, FlyFormDefinition, FlyFormFieldOptions, FlyFormOption, FlyFormQuestion, FlyFormQuestionType, FlyFormScoreDisplay, FlyLaunchEventDetail, FlyLaunchRequestDetail, FlyLeaderboardRow, FlyLiveRefreshOptions, FlyLocaleEntry, FlyMagicBarIconName, FlyMetaItem, FlyModerationLoadPageRequest, FlyModerationLockThreadRequest, FlyModerationOpenSubjectRequest, FlyModerationReport, FlyModerationReportPage, FlyModerationResolutionStatus, FlyModerationResolveRequest, FlyNavigableItem, FlyPageMeta, FlyPageResult, FlyPaged, FlyPeoplePickerMode, FlyPeoplePickerOption, FlyPeopleSearchFn, FlyPointsSummary, FlyRemoteContext, FlyRemoteEagerRoute, FlyRemoteLazyRoute, FlyRemoteLoadedComponent, FlyRemoteMatch, FlyRemoteRoute, FlyRemoteRouteEventDetail, FlySearchExpandTrigger, FlySearchInputSize, FlySecureSrcState, FlySelectOption, FlySelectValue, FlySkeletonAnimation, FlySkeletonLayout, FlySkeletonShape, FlySkinTone, FlySort, FlyStandaloneAuthConfig, FlyFileSelection as FlySurveyFileSelection, FlyFormAnswer as FlySurveyFormAnswer, FlyFormAnswerValue as FlySurveyFormAnswerValue, FlyFormDefinition as FlySurveyFormDefinition, FlyFormFieldOptions as FlySurveyFormFieldOptions, FlyFormOption as FlySurveyFormOption, FlyFormQuestion as FlySurveyFormQuestion, FlyFormQuestionType as FlySurveyQuestionType, FlyThemeMode, FlyTooltipPlacement, FlyTreeNavNode, FlyTypeaheadOption, FlyWindowHelpHintEventDetail, FlyWindowHelpPublisher, FlyWindowPageTitleEventDetail, FlyWindowTitlePublisher, FlyosPendingLaunches, FocusRestore, FormBannerKind, GanttDependency, GanttDependencyCreate, GanttRow, GanttRowDatesChange, GanttRowKind, GanttZoom, IconButtonVariant, LaunchContext, LoadBundleOptions, LookupDescriptor, LookupHandle, LookupRegistration, LookupResult, LookupSearch, MagicBarAction, MagicBarActionKind, MagicBarActionSpec, MagicBarActionView, MagicBarContribution, MagicBarGroup, MagicBarGroupSpec, MagicBarGroupView, MagicBarOwnerRef, MagicBarPublisher, MagicBarRadioMenu, MagicBarRadioMenuSpec, MagicBarRadioMenuView, MagicBarRadioOption, MagicBarSearch, MagicBarSearchSeed, MagicBarSearchSpec, MagicBarSearchView, MagicBarTextParams, MagicBarTone, MagicBarView, MessageBoxButton, MessageBoxDontAskAgainConfig, MessageBoxOptions, MessageBoxOptionsWithAcknowledgement, MockAuthConfig, OpenWindowOptions, OuPrincipal, OuTerm, OverlayHandle, PageHeaderVariant, PresetTerm, ProgressTone, RemoteAppDef, RequestAppLaunchOptions, RoleOuLookupRow, RolePrincipal, RolesTerm, SegmentedOption, ShareOrgChartOption, ShareOuNode, SharePanelLevelOption, SharePermissionEntry, SharePrincipal, SharePrincipalKind, ShareUserResult, StateMessageKind, StepUpChallenge, StepUpReauthHandler, StepUpReauthRequest, TabsVariant, ToastAction, ToastEntry, ToastOptions, ToastVariant, User, UserPrincipal, UsersTerm, WindowHelpHint, WindowInstance, WindowState };
10741
12265
  //# sourceMappingURL=flyos-design-system.d.ts.map