@magmonium/one 0.2.36 → 0.2.38

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.
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, inject, Injectable, signal, computed, DestroyRef, DOCUMENT, ApplicationRef, RendererFactory2, createComponent, EnvironmentInjector, Pipe, ChangeDetectorRef, untracked, ElementRef, afterNextRender, input, ChangeDetectionStrategy, Component, effect, Injector, reflectComponentType, model, HostListener, Renderer2, Directive, output, viewChild, ViewEncapsulation, forwardRef, contentChild, TemplateRef, ViewContainerRef, inputBinding, outputBinding, linkedSignal, afterRenderEffect, runInInjectionContext, Input, booleanAttribute, HostAttributeToken, EventEmitter, Output, ViewChild, ContentChild, provideZonelessChangeDetection, makeEnvironmentProviders, HostBinding, provideAppInitializer, provideBrowserGlobalErrorListeners, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
3
3
  import { HttpClient, HttpParams, provideHttpClient, withFetch, withInterceptors } from '@angular/common/http';
4
- import { firstValueFrom, of, tap, catchError, throwError, shareReplay, finalize, map, forkJoin, Observable, pipe, interval, fromEvent, switchMap as switchMap$1, filter, EMPTY, combineLatest, Subject, race, take, from } from 'rxjs';
4
+ import { firstValueFrom, of, tap, catchError, throwError, shareReplay, finalize, map, forkJoin, Observable, pipe, interval, fromEvent, switchMap as switchMap$1, filter, EMPTY, Subject, combineLatest, race, take, from } from 'rxjs';
5
5
  import { rxResource, toObservable, toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
6
  import { signalStore, withState, withMethods, patchState, withHooks, withComputed, withProps } from '@ngrx/signals';
7
7
  import { rxMethod } from '@ngrx/signals/rxjs-interop';
@@ -3172,6 +3172,14 @@ const NotificationStore = signalStore({ providedIn: 'root' }, withState(initialN
3172
3172
  * Nav model — see libs/one/CONTEXT.md (NavId, NavKind, Address, Anchor, NavRef)
3173
3173
  * and docs/adr/0014.
3174
3174
  */
3175
+ /**
3176
+ * The parameter name a `dynamic` Nav carries when it authored none. One
3177
+ * constant because the emitted route, the Address a NavRef renders and the row
3178
+ * that fills it are the same string.
3179
+ */
3180
+ const DEFAULT_NAV_PARAM = 'id';
3181
+ /** The parameter a `dynamic` Nav contributes, authored or defaulted. */
3182
+ const navParamOf = (nav) => nav?.param ?? DEFAULT_NAV_PARAM;
3175
3183
  const ROOT_NAV$1 = 'root';
3176
3184
  /**
3177
3185
  * The segment a Nav carries when it *is* its parent's own content — the route
@@ -3248,8 +3256,9 @@ const splitNavId = (navId, navMap) => {
3248
3256
  const anchorNavId = (navId, navMap) => splitNavId(navId, navMap).url.join(NAV_ID_SEP) || ROOT_NAV$1;
3249
3257
  /**
3250
3258
  * Route path for the Url part of a NavId. `root` -> `/`. A `dynamic` Nav
3251
- * contributes `<segment>/:id`, which is why a concrete path can only be
3252
- * rendered against a live location (see `renderAddress`).
3259
+ * contributes `:id` alone — its own segment is a name, not an address — which
3260
+ * is why a concrete path can only be rendered against a live location (see
3261
+ * `renderAddress`).
3253
3262
  */
3254
3263
  const navIdToRoutePath = (navId, navMap) => {
3255
3264
  const segments = navIdToSegments(navId).slice(1);
@@ -3263,12 +3272,11 @@ const navIdToRoutePath = (navId, navMap) => {
3263
3272
  // no segment of its own — `app → default → trending` is `/app/trending`,
3264
3273
  // the address the generated route table already answers at.
3265
3274
  const path = segment === DEFAULT_NAV_SEGMENT ? '' : (nav?.path ?? segment);
3266
- return nav?.presentation === 'dynamic'
3267
- ? `${path}/:${nav.param ?? 'id'}`
3268
- : path;
3275
+ // A dynamic Nav *is* the parameter: it contributes `:id` and no segment
3276
+ // of its own, so `comics → issue` (dynamic) is `/comics/:issueId`. The
3277
+ // Nav's own name stays a name — it never reaches the URL.
3278
+ return nav?.presentation === 'dynamic' ? `:${navParamOf(nav)}` : path;
3269
3279
  })
3270
- // A dynamic Nav mounted at its app's own root declares `path: ''` — it
3271
- // contributes `:id` and no segment of its own.
3272
3280
  .flatMap((part) => part.split(URL_SEP).filter(Boolean));
3273
3281
  return parts.length ? URL_SEP + parts.join(URL_SEP) : URL_SEP;
3274
3282
  };
@@ -3410,6 +3418,9 @@ const NAV_MAIN_BUTTONS = new InjectionToken('NAV_MAIN_BUTTONS');
3410
3418
  function isNavMenuConfig(entry) {
3411
3419
  return typeof entry === 'object' && 'navMenu' in entry;
3412
3420
  }
3421
+ function isNavRowsConfig(entry) {
3422
+ return typeof entry === 'object' && 'navRows' in entry;
3423
+ }
3413
3424
  /**
3414
3425
  * Multi-provided, and resolved **last-wins**: the library provides its own
3415
3426
  * Platform Nav panels first so an app registering at the same NavId replaces
@@ -3452,147 +3463,6 @@ function getNavWidgetEntry(appId) {
3452
3463
  return windowRegistry().get(appId);
3453
3464
  }
3454
3465
 
3455
- const emptyResult = () => ({
3456
- breadcrumb: { header: { label: '', id: '' }, trail: [] },
3457
- navMenus: [],
3458
- });
3459
- /**
3460
- * One trail/menu entry. `nav` names where it goes by NavId — the NavKind on the
3461
- * target decides whether following it routes or opens a panel, so nothing here
3462
- * chooses a link kind (ADR 0014).
3463
- */
3464
- const toTrailItem = (navId, navMap, anchor) => {
3465
- const nav = navMap[navId];
3466
- return {
3467
- id: navId,
3468
- label: nav?.title ?? navIdSegment(navId),
3469
- icon: nav?.icon,
3470
- nav: navId,
3471
- address: renderAddress(navId, navMap, anchor),
3472
- };
3473
- };
3474
- /** A Nav that *is* its parent's own content rather than a place beside it. */
3475
- const isDefaultNav = (navId) => navIdSegment(navId) === DEFAULT_NAV_SEGMENT;
3476
- /**
3477
- * The Nav the User is standing on as the nav shows it. A `default` node names
3478
- * no place of its own — it is the route answering its parent's empty path — so
3479
- * landing on `root_app_default` is standing on `root_app`, and the panel says
3480
- * so rather than naming a segment that is on no menu.
3481
- */
3482
- const visibleNavId = (navId) => {
3483
- let id = navId;
3484
- while (id !== ROOT_NAV$1 && isDefaultNav(id))
3485
- id = parentNavId(id) ?? ROOT_NAV$1;
3486
- return id;
3487
- };
3488
- /**
3489
- * The direct children of a Nav. `children` is the authored list, but a Nav that
3490
- * lists none is not childless: the map already holds every node fetched for
3491
- * this descent, and a child is named by its own id. Reading the map when the
3492
- * list is empty is what keeps a generated tree — whose `root.yml` names the app
3493
- * and nothing else — from titling a leaf over an empty panel.
3494
- */
3495
- const childIdsOf = (navId, navMap) => {
3496
- const declared = navMap[navId]?.children;
3497
- if (declared?.length)
3498
- return declared;
3499
- return Object.keys(navMap).filter((id) => parentNavId(id) === navId);
3500
- };
3501
- /**
3502
- * The children a menu may draw. A Nav needs a title to be a row at all, and a
3503
- * `default` node is not a row: it is its parent's own content, so it is
3504
- * *transparent* — its own children take its place in the list, spliced where
3505
- * it stood. `app → default → { trending, latest }` is one list of two rows
3506
- * under app, which is the tree the User was drawing when they put a `default`
3507
- * in the middle of it. Filtering the node out without adopting its children
3508
- * left that app with no rows at all.
3509
- */
3510
- const menuChildIds = (navId, navMap) => childIdsOf(navId, navMap).flatMap((childId) => {
3511
- if (isDefaultNav(childId))
3512
- return menuChildIds(childId, navMap);
3513
- return navMap[childId]?.title ? [childId] : [];
3514
- });
3515
- /**
3516
- * Whose children the menu draws. A Nav with rows of its own draws them — that
3517
- * is the descent. A leaf has none, and descending into nothing left the panel
3518
- * on an empty state; it draws its *siblings* instead, so the menu stays the
3519
- * list the User moved through and the row they are on is the one marked
3520
- * active. Root is the floor: its own children are the last list there is.
3521
- */
3522
- const navMenuOwnerId = (navId, navMap, hasOwnContent = false) => {
3523
- const visible = visibleNavId(navId);
3524
- if (visible === ROOT_NAV$1 || menuChildIds(visible, navMap).length) {
3525
- return visible;
3526
- }
3527
- // A panel that answers with a widget of its own keeps its own title —
3528
- // titling it after its parent while showing its own content reads as the
3529
- // wrong panel. Being a Murl is not that proof: a Murl leaf nothing is
3530
- // registered for draws nothing, and an empty panel must not name itself.
3531
- if (hasOwnContent)
3532
- return visible;
3533
- // Nothing of its own and no rows under it: hand the panel to the nearest
3534
- // ancestor that has rows, so the User reads the list they are in with their
3535
- // own row marked. Where no ancestor lists anything there is no better title
3536
- // than the one we are on — a mistitled empty panel is worse than a titled one.
3537
- for (let ancestor = parentNavId(visible); ancestor; ancestor = parentNavId(ancestor)) {
3538
- const owner = visibleNavId(ancestor);
3539
- if (menuChildIds(owner, navMap).length)
3540
- return owner;
3541
- if (owner === ROOT_NAV$1)
3542
- break;
3543
- }
3544
- return visible;
3545
- };
3546
- const buildNavMenus = (navId, navMap, anchor) => menuChildIds(navId, navMap).map((childId) => toTrailItem(childId, navMap, anchor));
3547
- /**
3548
- * Merges a widget's emitted trail over the derived one, matching by depth.
3549
- * With a single keyspace there is nothing to translate — an emitted entry is
3550
- * already in the same ids everything else uses.
3551
- */
3552
- const mergeTrail = (derived, override, derivedHeader) => {
3553
- const depth = (id) => navIdChain(id).length;
3554
- const trail = derived.map((item) => {
3555
- const emitted = override.trail?.find((e) => depth(e.id) === depth(item.id));
3556
- return emitted ? { ...item, ...emitted } : item;
3557
- });
3558
- return { trail, header: override.header ?? derivedHeader };
3559
- };
3560
- function deriveBreadcrumb(params) {
3561
- const { navId, navMap, anchor, breadcrumb, navMenu, hasOwnContent } = params;
3562
- if (!navId)
3563
- return emptyResult();
3564
- // The header and the trail belong to whichever Nav owns the menu below them:
3565
- // on a leaf that is the parent, so the User reads the list they are in with
3566
- // their own row marked, rather than a title over an empty panel.
3567
- const ownerId = navMenuOwnerId(navId, navMap, hasOwnContent);
3568
- // An emitted breadcrumb names the panel it was emitted for. Once the panel
3569
- // has been handed up to an ancestor it is no longer that panel, so the
3570
- // override would title the ancestor's list after the leaf we left.
3571
- const ownPanel = ownerId === visibleNavId(navId);
3572
- const chain = navIdChain(ownerId);
3573
- const derivedTrail = chain
3574
- .slice(0, -1)
3575
- .filter((id) => !isDefaultNav(id))
3576
- .map((id) => toTrailItem(id, navMap, anchor));
3577
- const nav = navMap[ownerId];
3578
- const derivedHeader = {
3579
- id: ownerId,
3580
- label: nav?.title ?? (ownerId === ROOT_NAV$1 ? '' : navIdSegment(ownerId)),
3581
- icon: nav?.icon,
3582
- nav: ownerId,
3583
- address: renderAddress(ownerId, navMap, anchor),
3584
- };
3585
- const { trail, header } = breadcrumb && ownPanel
3586
- ? mergeTrail(derivedTrail, breadcrumb, derivedHeader)
3587
- : { trail: derivedTrail, header: derivedHeader };
3588
- return {
3589
- breadcrumb: { trail, header },
3590
- navMenus: navMenu?.length && ownPanel
3591
- ? navMenu
3592
- : buildNavMenus(ownerId, navMap, anchor),
3593
- };
3594
- }
3595
-
3596
3466
  /**
3597
3467
  * Platform Nav — the chrome this library owns (CONTEXT.md Platform Nav,
3598
3468
  * ADR 0016).
@@ -3610,9 +3480,9 @@ function deriveBreadcrumb(params) {
3610
3480
  * overrides by registering at the same NavId.
3611
3481
  */
3612
3482
  /**
3613
- * Platform Navs that also carry a chrome button — search, notification and user
3614
- * in the menubar, settings in the footer. The button is a shortcut to the same
3615
- * NavId the row names, not a substitute for it: one NavRef, reached either way.
3483
+ * Platform Navs reached by a chrome button rather than a root row — search,
3484
+ * notification and user in the menubar, settings in the footer. Kept out of
3485
+ * root's rows at runtime so the menu does not repeat the menubar.
3616
3486
  */
3617
3487
  const PLATFORM_BUTTON_NAV_IDS = [
3618
3488
  'root_search',
@@ -3621,12 +3491,12 @@ const PLATFORM_BUTTON_NAV_IDS = [
3621
3491
  'root_settings',
3622
3492
  ];
3623
3493
  /**
3624
- * Platform children rendered as rows in the root panel the chrome, behind
3625
- * whatever App Navs the app authored. A panel that listed the app's pages and
3626
- * nothing else made chrome reachable only by finding its icon, so the rows are
3627
- * the readable half of the same NavRefs the buttons hold.
3494
+ * Platform children rendered as rows in the root panel. Empty on purpose
3495
+ * every Platform Nav carries a button of its own, and a row beside the icon
3496
+ * that already opens it is the same NavRef twice. Root's runtime rows are App
3497
+ * Navs only.
3628
3498
  */
3629
- const PLATFORM_ROOT_CHILDREN = [...PLATFORM_BUTTON_NAV_IDS];
3499
+ const PLATFORM_ROOT_CHILDREN = [];
3630
3500
  /**
3631
3501
  * Root carries no title of its own — an app's `navs/root.yml` names the app,
3632
3502
  * and that is the one field of root the asset owns outright.
@@ -3732,8 +3602,9 @@ const createPlatformNavMap = () => Object.fromEntries(Object.entries(PLATFORM_NA
3732
3602
  * same id. An extensible one merges: the asset contributes its App Nav
3733
3603
  * children (and, at `root`, the app's own `title` / `logo` / `icon`), the
3734
3604
  * platform children follow, and NavKind and NavPresentation stay the
3735
- * library's — so an asset cannot delete chrome by omitting it from `root.yml`,
3736
- * and shipping a closed Platform NavId cannot redefine it.
3605
+ * library's — so an asset cannot delete chrome (settings still exists even
3606
+ * though it is not a root row), and shipping a closed Platform NavId cannot
3607
+ * redefine it.
3737
3608
  */
3738
3609
  const mergePlatformNav = (nav, navId) => {
3739
3610
  const platform = PLATFORM_NAV_MAP[navId];
@@ -3742,9 +3613,10 @@ const mergePlatformNav = (nav, navId) => {
3742
3613
  if (!isExtensiblePlatformNavId(navId))
3743
3614
  return { ...platform };
3744
3615
  const platformChildren = platform.children ?? [];
3745
- // An app that listed a platform child of its own gets it once, in the
3746
- // library's own place: the seed is what fixes chrome's order.
3747
- const appChildren = (nav.children ?? []).filter((childId) => !platformChildren.includes(childId));
3616
+ const appChildren = (nav.children ?? []).filter((childId) => !platformChildren.includes(childId) &&
3617
+ // Chrome-button Navs stay addressable but never become root menu rows,
3618
+ // even when an older asset still listed them under root.
3619
+ !(navId === ROOT_NAV$1 && PLATFORM_BUTTON_NAV_IDS.includes(childId)));
3748
3620
  return {
3749
3621
  ...nav,
3750
3622
  kind: platform.kind,
@@ -3766,6 +3638,206 @@ const unfetchedPlatformNav = (navId) => {
3766
3638
  : undefined;
3767
3639
  };
3768
3640
 
3641
+ const emptyResult = () => ({
3642
+ breadcrumb: { header: { label: '', id: '' }, trail: [] },
3643
+ navMenus: [],
3644
+ });
3645
+ /**
3646
+ * One trail/menu entry. `nav` names where it goes by NavId — the NavKind on the
3647
+ * target decides whether following it routes or opens a panel, so nothing here
3648
+ * chooses a link kind (ADR 0014).
3649
+ */
3650
+ const toTrailItem = (navId, navMap, anchor,
3651
+ /** A dynamic node standing on an instance reads that row's own label. */
3652
+ label) => {
3653
+ const nav = navMap[navId];
3654
+ return {
3655
+ id: navId,
3656
+ label: label ?? nav?.title ?? navIdSegment(navId),
3657
+ icon: nav?.icon,
3658
+ nav: navId,
3659
+ address: renderAddress(navId, navMap, anchor),
3660
+ };
3661
+ };
3662
+ /**
3663
+ * One resolved NavRow as a menu row. `nav` is the dynamic **node**, never a
3664
+ * per-instance id nothing registers — a NavRef names a node and the instance
3665
+ * rides alongside as the param this Nav declared, which is what `renderAddress`
3666
+ * fills. `id` carries the value only so the list has stable keys.
3667
+ */
3668
+ const navRowTrailItem = (navId, nav, row, navMap, anchor) => ({
3669
+ id: `${navId}${NAV_ID_SEP}${row.value}`,
3670
+ label: row.label,
3671
+ icon: row.icon ?? nav.icon,
3672
+ nav: navId,
3673
+ address: renderAddress(navId, navMap, anchor, {
3674
+ [navParamOf(nav)]: row.value,
3675
+ }),
3676
+ });
3677
+ /** A Nav that *is* its parent's own content rather than a place beside it. */
3678
+ const isDefaultNav = (navId) => navIdSegment(navId) === DEFAULT_NAV_SEGMENT;
3679
+ /**
3680
+ * The Nav the User is standing on as the nav shows it. A `default` node names
3681
+ * no place of its own — it is the route answering its parent's empty path — so
3682
+ * landing on `root_app_default` is standing on `root_app`, and the panel says
3683
+ * so rather than naming a segment that is on no menu.
3684
+ */
3685
+ const visibleNavId = (navId) => {
3686
+ let id = navId;
3687
+ while (id !== ROOT_NAV$1 && isDefaultNav(id))
3688
+ id = parentNavId(id) ?? ROOT_NAV$1;
3689
+ return id;
3690
+ };
3691
+ /**
3692
+ * The direct children of a Nav. `children` is the authored list, but a Nav that
3693
+ * lists none is not childless: the map already holds every node fetched for
3694
+ * this descent, and a child is named by its own id. Reading the map when the
3695
+ * list is empty is what keeps a generated tree — whose `root.yml` names the app
3696
+ * and nothing else — from titling a leaf over an empty panel.
3697
+ *
3698
+ * The Platform Navs reached by a chrome button are the one exclusion: root
3699
+ * seeds `children: []` so they are never rows beside the icons that already
3700
+ * open them, and discovering them off the map would put them back.
3701
+ */
3702
+ const childIdsOf = (navId, navMap) => {
3703
+ const declared = navMap[navId]?.children;
3704
+ if (declared?.length)
3705
+ return declared;
3706
+ return Object.keys(navMap).filter((id) => parentNavId(id) === navId && !PLATFORM_BUTTON_NAV_IDS.includes(id));
3707
+ };
3708
+ /**
3709
+ * The children a menu may draw. A Nav needs a title to be a row at all, and a
3710
+ * `default` node is not a row: it is its parent's own content, so it is
3711
+ * *transparent* — its own children take its place in the list, spliced where
3712
+ * it stood. `app → default → { trending, latest }` is one list of two rows
3713
+ * under app, which is the tree the User was drawing when they put a `default`
3714
+ * in the middle of it. Filtering the node out without adopting its children
3715
+ * left that app with no rows at all.
3716
+ */
3717
+ const menuChildIds = (navId, navMap) => childIdsOf(navId, navMap).flatMap((childId) => {
3718
+ if (isDefaultNav(childId))
3719
+ return menuChildIds(childId, navMap);
3720
+ return navMap[childId]?.title ? [childId] : [];
3721
+ });
3722
+ /**
3723
+ * Whose children the menu draws. A Nav with rows of its own draws them — that
3724
+ * is the descent. A leaf has none, and descending into nothing left the panel
3725
+ * on an empty state; it draws its *siblings* instead, so the menu stays the
3726
+ * list the User moved through and the row they are on is the one marked
3727
+ * active. Root is the floor: its own children are the last list there is.
3728
+ */
3729
+ const navMenuOwnerId = (navId, navMap, hasOwnContent = false) => {
3730
+ const visible = visibleNavId(navId);
3731
+ if (visible === ROOT_NAV$1 || menuChildIds(visible, navMap).length) {
3732
+ return visible;
3733
+ }
3734
+ // A panel that answers with a widget of its own keeps its own title —
3735
+ // titling it after its parent while showing its own content reads as the
3736
+ // wrong panel. Being a Murl is not that proof: a Murl leaf nothing is
3737
+ // registered for draws nothing, and an empty panel must not name itself.
3738
+ if (hasOwnContent)
3739
+ return visible;
3740
+ // Nothing of its own and no rows under it: hand the panel to the nearest
3741
+ // ancestor that has rows, so the User reads the list they are in with their
3742
+ // own row marked. Where no ancestor lists anything there is no better title
3743
+ // than the one we are on — a mistitled empty panel is worse than a titled one.
3744
+ for (let ancestor = parentNavId(visible); ancestor; ancestor = parentNavId(ancestor)) {
3745
+ const owner = visibleNavId(ancestor);
3746
+ if (menuChildIds(owner, navMap).length)
3747
+ return owner;
3748
+ if (owner === ROOT_NAV$1)
3749
+ break;
3750
+ }
3751
+ return visible;
3752
+ };
3753
+ /**
3754
+ * The rows one panel draws. A `dynamic` child with a NavRowSource behind it is
3755
+ * **transparent** the way a Default Nav is: its resolved rows are spliced where
3756
+ * its own row stood, so the User reads the categories rather than a row named
3757
+ * after the node that lists them.
3758
+ *
3759
+ * Three states and not two. Rows: splice them. No source registered at all:
3760
+ * the Nav is an ordinary row, which is what a `dynamic` Nav was before a source
3761
+ * could be authored. A source that resolved *nothing*: splice nothing — falling
3762
+ * back to the node's own row would draw a link into a list that is empty, and
3763
+ * falling through to the static siblings around it would show a panel that
3764
+ * looks correct and is not.
3765
+ */
3766
+ const buildNavMenus = (navId, navMap, anchor, dynamicRows = {}) => menuChildIds(navId, navMap).flatMap((childId) => {
3767
+ const nav = navMap[childId];
3768
+ const resolved = nav && dynamicRows[childId];
3769
+ if (!nav || nav.presentation !== 'dynamic' || !resolved) {
3770
+ return [toTrailItem(childId, navMap, anchor)];
3771
+ }
3772
+ return resolved.rows.map((row) => navRowTrailItem(childId, nav, row, navMap, anchor));
3773
+ });
3774
+ /**
3775
+ * Merges a widget's emitted trail over the derived one, matching by depth.
3776
+ * With a single keyspace there is nothing to translate — an emitted entry is
3777
+ * already in the same ids everything else uses.
3778
+ */
3779
+ const mergeTrail = (derived, override, derivedHeader) => {
3780
+ const depth = (id) => navIdChain(id).length;
3781
+ const trail = derived.map((item) => {
3782
+ const emitted = override.trail?.find((e) => depth(e.id) === depth(item.id));
3783
+ return emitted ? { ...item, ...emitted } : item;
3784
+ });
3785
+ return { trail, header: override.header ?? derivedHeader };
3786
+ };
3787
+ function deriveBreadcrumb(params) {
3788
+ const { navId, navMap, anchor, breadcrumb, navMenu, hasOwnContent, dynamicRows, routeParams, } = params;
3789
+ if (!navId)
3790
+ return emptyResult();
3791
+ /**
3792
+ * The label a dynamic node wears while the User stands on one of its rows.
3793
+ * Falls back to the node's own title when nothing matches — a deep link that
3794
+ * arrived before the rows did, or a row that has since gone — because a raw
3795
+ * segment is a worse answer than the node's name but a better one than a
3796
+ * blank.
3797
+ */
3798
+ const rowLabel = (id) => {
3799
+ const nav = navMap[id];
3800
+ if (nav?.presentation !== 'dynamic')
3801
+ return undefined;
3802
+ const value = routeParams?.[navParamOf(nav)];
3803
+ if (!value)
3804
+ return undefined;
3805
+ return dynamicRows?.[id]?.rows.find((row) => row.value === value)?.label;
3806
+ };
3807
+ // The header and the trail belong to whichever Nav owns the menu below them:
3808
+ // on a leaf that is the parent, so the User reads the list they are in with
3809
+ // their own row marked, rather than a title over an empty panel.
3810
+ const ownerId = navMenuOwnerId(navId, navMap, hasOwnContent);
3811
+ // An emitted breadcrumb names the panel it was emitted for. Once the panel
3812
+ // has been handed up to an ancestor it is no longer that panel, so the
3813
+ // override would title the ancestor's list after the leaf we left.
3814
+ const ownPanel = ownerId === visibleNavId(navId);
3815
+ const chain = navIdChain(ownerId);
3816
+ const derivedTrail = chain
3817
+ .slice(0, -1)
3818
+ .filter((id) => !isDefaultNav(id))
3819
+ .map((id) => toTrailItem(id, navMap, anchor, rowLabel(id)));
3820
+ const nav = navMap[ownerId];
3821
+ const derivedHeader = {
3822
+ id: ownerId,
3823
+ label: rowLabel(ownerId) ??
3824
+ nav?.title ??
3825
+ (ownerId === ROOT_NAV$1 ? '' : navIdSegment(ownerId)),
3826
+ icon: nav?.icon,
3827
+ nav: ownerId,
3828
+ address: renderAddress(ownerId, navMap, anchor),
3829
+ };
3830
+ const { trail, header } = breadcrumb && ownPanel
3831
+ ? mergeTrail(derivedTrail, breadcrumb, derivedHeader)
3832
+ : { trail: derivedTrail, header: derivedHeader };
3833
+ return {
3834
+ breadcrumb: { trail, header },
3835
+ navMenus: navMenu?.length && ownPanel
3836
+ ? navMenu
3837
+ : buildNavMenus(ownerId, navMap, anchor, dynamicRows),
3838
+ };
3839
+ }
3840
+
3769
3841
  class GetNavService {
3770
3842
  httpService = inject(HttpService);
3771
3843
  assetStore = inject(AssetStore);
@@ -3861,6 +3933,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
3861
3933
  const initialState$3 = {
3862
3934
  path: '/',
3863
3935
  routeNavId: undefined,
3936
+ routeParams: {},
3864
3937
  murl: [],
3865
3938
  appLink: undefined,
3866
3939
  appNavId: undefined,
@@ -3883,6 +3956,21 @@ const routeNavIdOf = (root) => {
3883
3956
  }
3884
3957
  return navId;
3885
3958
  };
3959
+ /**
3960
+ * Every path parameter on the matched chain, deepest last. Merged rather than
3961
+ * read off the leaf: two dynamic Navs on one path each contribute their own
3962
+ * (`:id/:issueId`), and only the chain holds both.
3963
+ */
3964
+ const routeParamsOf = (root) => {
3965
+ const params = {};
3966
+ for (let r = root; r; r = r.firstChild) {
3967
+ for (const [key, value] of Object.entries(r.params ?? {})) {
3968
+ if (typeof value === 'string')
3969
+ params[key] = value;
3970
+ }
3971
+ }
3972
+ return params;
3973
+ };
3886
3974
  const murlOf = (root) => {
3887
3975
  const raw = root.queryParams?.[MURL_PARAM];
3888
3976
  return typeof raw === 'string' ? raw.split(MURL_SEP).filter(Boolean) : [];
@@ -3940,32 +4028,69 @@ const NavStore = signalStore({ providedIn: 'root' }, withState(initialState$3),
3940
4028
  * selector from the Angular tag used to create an unregistered custom
3941
4029
  * element and leave theme / language blank.
3942
4030
  */
3943
- const widgetEntry = computed(() => {
4031
+ /**
4032
+ * One NavId against every registered map, Remote first. Split out of
4033
+ * `widgetEntry` because a `dynamic` Nav's rows are looked up by *its own*
4034
+ * id while the User stands on its parent — the rows draw in the parent's
4035
+ * panel, so the candidate list the open panel walks would never reach them.
4036
+ */
4037
+ const entryAt = (candidate) => {
3944
4038
  const appNavId = store.appNavId();
3945
4039
  const appLink = store.appLink();
3946
4040
  const maps = navWidgetMaps ?? [];
3947
- for (const candidate of widgetNavIds()) {
3948
- const navId = candidate;
3949
- if (appLink && appNavId) {
3950
- const registered = store.remoteWidgets()[appLink];
3951
- const localId = toLocalNavId(navId, appNavId);
3952
- if (registered && localId) {
3953
- const entry = registered.widgetMap()[localId];
3954
- if (entry)
3955
- return { entry, remote: true, navId: candidate };
3956
- }
3957
- }
3958
- for (let i = maps.length - 1; i >= 0; i--) {
3959
- const entry = maps[i]()[navId];
3960
- if (entry !== undefined)
3961
- return { entry, remote: false, navId: candidate };
4041
+ const navId = candidate;
4042
+ if (appLink && appNavId) {
4043
+ const registered = store.remoteWidgets()[appLink];
4044
+ const localId = toLocalNavId(navId, appNavId);
4045
+ if (registered && localId) {
4046
+ const entry = registered.widgetMap()[localId];
4047
+ if (entry)
4048
+ return { entry, remote: true };
3962
4049
  }
3963
4050
  }
4051
+ for (let i = maps.length - 1; i >= 0; i--) {
4052
+ const entry = maps[i]()[navId];
4053
+ if (entry !== undefined)
4054
+ return { entry, remote: false };
4055
+ }
4056
+ return undefined;
4057
+ };
4058
+ const widgetEntry = computed(() => {
4059
+ for (const candidate of widgetNavIds()) {
4060
+ const hit = entryAt(candidate);
4061
+ if (hit)
4062
+ return { ...hit, navId: candidate };
4063
+ }
3964
4064
  return undefined;
3965
4065
  }, ...(ngDevMode ? [{ debugName: "widgetEntry" }] : /* istanbul ignore next */ []));
4066
+ /**
4067
+ * Every `dynamic` Nav with a NavRowSource behind it, resolved. Walks the
4068
+ * whole map rather than the open panel's own descent: the rows are drawn by
4069
+ * whichever ancestor owns the panel, and reading each source's signal here
4070
+ * is what makes the panel recompute when the store behind it fills.
4071
+ */
4072
+ const dynamicRows = computed(() => {
4073
+ const out = {};
4074
+ for (const nav of Object.values(store.navMap())) {
4075
+ if (nav.presentation !== 'dynamic')
4076
+ continue;
4077
+ const hit = entryAt(nav.navId);
4078
+ if (!hit || !isNavRowsConfig(hit.entry))
4079
+ continue;
4080
+ out[nav.navId] = {
4081
+ rows: hit.entry.navRows() ?? [],
4082
+ loading: hit.entry.loading?.(),
4083
+ };
4084
+ }
4085
+ return out;
4086
+ }, ...(ngDevMode ? [{ debugName: "dynamicRows" }] : /* istanbul ignore next */ []));
3966
4087
  const resolvedWidget = computed(() => {
3967
4088
  const hit = widgetEntry();
3968
- if (!hit || isNavMenuConfig(hit.entry))
4089
+ // Neither of the two row-shaped entries fills a panel with a component:
4090
+ // one replaces a panel's rows, the other contributes rows to its
4091
+ // parent's, and `normalizeNavWidgetEntry` would read a `content` off
4092
+ // neither.
4093
+ if (!hit || isNavMenuConfig(hit.entry) || isNavRowsConfig(hit.entry))
3969
4094
  return null;
3970
4095
  const config = normalizeNavWidgetEntry(hit.entry);
3971
4096
  if (!config.content)
@@ -4016,6 +4141,8 @@ const NavStore = signalStore({ providedIn: 'root' }, withState(initialState$3),
4016
4141
  navId: panelNavId(),
4017
4142
  navMap: store.navMap(),
4018
4143
  anchor: { navId: store.routeNavId() ?? ROOT_NAV$1, path: store.path() },
4144
+ dynamicRows: dynamicRows(),
4145
+ routeParams: store.routeParams(),
4019
4146
  breadcrumb: menuConfig?.breadcramb?.() ??
4020
4147
  (typeof widgetConfig?.breadcramb === 'function'
4021
4148
  ? widgetConfig.breadcramb()
@@ -4119,6 +4246,7 @@ const NavStore = signalStore({ providedIn: 'root' }, withState(initialState$3),
4119
4246
  */
4120
4247
  const syncFromRouter = rxMethod(pipe(filter((s) => !!s), tap((snapshot) => {
4121
4248
  const routeNavId = routeNavIdOf(snapshot.root);
4249
+ const routeParams = routeParamsOf(snapshot.root);
4122
4250
  const murl = murlOf(snapshot.root);
4123
4251
  const path = router.url.split(MURL_SEP)[0].split('?')[0];
4124
4252
  untracked(() => {
@@ -4127,6 +4255,7 @@ const NavStore = signalStore({ providedIn: 'root' }, withState(initialState$3),
4127
4255
  patchState(store, {
4128
4256
  path,
4129
4257
  routeNavId,
4258
+ routeParams,
4130
4259
  murl,
4131
4260
  // Address changes clear the icon-opened flag (ADR 0013), except
4132
4261
  // an explicit `keepPanel` goToNav (AppLogo while open).
@@ -6642,7 +6771,7 @@ class SectionFormItemComponent extends ConfigComponent {
6642
6771
  break;
6643
6772
  }
6644
6773
  case InputType.TOGGLE: {
6645
- const { ToggleInputComponent } = await import('./magmonium-one-toggle-F27rRHhf.mjs');
6774
+ const { ToggleInputComponent } = await import('./magmonium-one-toggle-wEeMiUQz.mjs');
6646
6775
  this.createDynamicComponent(seq, ToggleInputComponent, [], true);
6647
6776
  break;
6648
6777
  }
@@ -6654,12 +6783,12 @@ class SectionFormItemComponent extends ConfigComponent {
6654
6783
  break;
6655
6784
  }
6656
6785
  case InputType.PASSWORD: {
6657
- const { PasswordInputComponent } = await import('./magmonium-one-password-MtQpTJX1.mjs');
6786
+ const { PasswordInputComponent } = await import('./magmonium-one-password-DmEMAVca.mjs');
6658
6787
  this.createDynamicComponent(seq, PasswordInputComponent);
6659
6788
  break;
6660
6789
  }
6661
6790
  case InputType.OTP: {
6662
- const { OtpInputComponent } = await import('./magmonium-one-otp-B4nZEh_m.mjs');
6791
+ const { OtpInputComponent } = await import('./magmonium-one-otp-JmUyDNPb.mjs');
6663
6792
  this.createDynamicComponent(seq, OtpInputComponent);
6664
6793
  break;
6665
6794
  }
@@ -8104,28 +8233,31 @@ class MenuComponent {
8104
8233
  const hide = this.hide();
8105
8234
  const extra = this.extra();
8106
8235
  const isAdmin = this.isAdmin();
8107
- let result = [];
8108
- if (back) {
8109
- result = back.options ?? async ?? [];
8110
- }
8111
- else {
8112
- result = async ?? config ?? [];
8113
- }
8114
- if (!isAdmin) {
8115
- result = result.map((group) => group.filter((item) => !item.adminOnly));
8116
- }
8117
- if (hide?.length) {
8118
- result = result.map((group) => group.filter((item) => !hide.includes(item.id)));
8119
- }
8120
8236
  const vRule = this.visibilityRule();
8121
8237
  const data = this.extraData();
8122
- if (vRule) {
8123
- result = result.map((group) => group.filter((item) => vRule(item.visibilityKey ?? item.id, data)));
8124
- }
8125
- if (extra?.length && !back) {
8126
- result = [...result, extra];
8127
- }
8128
- return result.filter((group) => group.length > 0);
8238
+ // Filtering recurses so a parent is judged by what survives under it: a row
8239
+ // whose every child was hidden would open an empty box, which reads as a
8240
+ // broken menu rather than an unavailable one. A `file` parent is exempt —
8241
+ // its options are fetched on drill and there is nothing here to count.
8242
+ const filterGroups = (groups) => groups
8243
+ .map((group) => group.filter((item) => {
8244
+ if (!isAdmin && item.adminOnly)
8245
+ return false;
8246
+ if (hide?.length && hide.includes(item.id))
8247
+ return false;
8248
+ if (vRule && !vRule(item.visibilityKey ?? item.id, data)) {
8249
+ return false;
8250
+ }
8251
+ if (item.options)
8252
+ return filterGroups(item.options).length > 0;
8253
+ return true;
8254
+ }))
8255
+ .filter((group) => group.length > 0);
8256
+ const source = back
8257
+ ? back.options ?? async ?? []
8258
+ : async ?? config ?? [];
8259
+ const result = filterGroups(source);
8260
+ return extra?.length && !back ? [...result, extra] : result;
8129
8261
  }, ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
8130
8262
  isLoading = computed(() => this.#asyncOptions.isLoading(), ...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
8131
8263
  // --- Handlers ---
@@ -8185,6 +8317,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
8185
8317
 
8186
8318
  class ContextMenuBoxComponent {
8187
8319
  options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
8320
+ hide = input(...(ngDevMode ? [undefined, { debugName: "hide" }] : /* istanbul ignore next */ []));
8188
8321
  file = input(...(ngDevMode ? [undefined, { debugName: "file" }] : /* istanbul ignore next */ []));
8189
8322
  width = input('250px', ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
8190
8323
  height = input('auto', ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
@@ -8197,12 +8330,12 @@ class ContextMenuBoxComponent {
8197
8330
  this.action.emit(item);
8198
8331
  };
8199
8332
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ContextMenuBoxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
8200
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: ContextMenuBoxComponent, isStandalone: true, selector: "m-context-menu-box", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, file: { classPropertyName: "file", publicName: "file", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, isAdmin: { classPropertyName: "isAdmin", publicName: "isAdmin", isSignal: true, isRequired: false, transformFunction: null }, visibilityRule: { classPropertyName: "visibilityRule", publicName: "visibilityRule", isSignal: true, isRequired: false, transformFunction: null }, disableRule: { classPropertyName: "disableRule", publicName: "disableRule", isSignal: true, isRequired: false, transformFunction: null }, extraData: { classPropertyName: "extraData", publicName: "extraData", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, ngImport: i0, template: "<div class=\"m-context-menu-box\" [style.width]=\"width()\" [style.max-height]=\"height()\">\n <m-menu\n [config]=\"options()\"\n [file]=\"file()\"\n [isAdmin]=\"isAdmin()\"\n [visibilityRule]=\"visibilityRule()\"\n [disableRule]=\"disableRule()\"\n [extraData]=\"extraData()\"\n (action)=\"emitAction($event)\"\n />\n</div>\n", styles: ["@keyframes toggle-pulse{0%,to{transform:scale(1)}50%{transform:scale(1.02)}}@keyframes thumb-slide{0%{transform:translate(0) scale(1)}50%{transform:translate(.3em) scale(.9)}to{transform:translate(.6em) scale(1)}}.m-context-menu-box{overflow-y:auto;border-radius:0;border:1px solid var(--m-mm);background:var(--m-background);animation:context-menu-in .2s ease-out}@keyframes context-menu-in{0%{opacity:0;transform:scale(.95) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}:host-context(.align-bottom){display:block;width:100%!important;max-width:100%!important}:host-context(.align-bottom) .m-context-menu-box{width:100%!important;max-width:100%!important;max-height:70vh!important;border-left:none;border-right:none;border-bottom:none}\n"], dependencies: [{ kind: "component", type: MenuComponent, selector: "m-menu", inputs: ["config", "file", "root", "url", "extra", "hide", "hideLink", "isAdmin", "visibilityRule", "disableRule", "extraData"], outputs: ["action"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
8333
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: ContextMenuBoxComponent, isStandalone: true, selector: "m-context-menu-box", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, hide: { classPropertyName: "hide", publicName: "hide", isSignal: true, isRequired: false, transformFunction: null }, file: { classPropertyName: "file", publicName: "file", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, isAdmin: { classPropertyName: "isAdmin", publicName: "isAdmin", isSignal: true, isRequired: false, transformFunction: null }, visibilityRule: { classPropertyName: "visibilityRule", publicName: "visibilityRule", isSignal: true, isRequired: false, transformFunction: null }, disableRule: { classPropertyName: "disableRule", publicName: "disableRule", isSignal: true, isRequired: false, transformFunction: null }, extraData: { classPropertyName: "extraData", publicName: "extraData", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, ngImport: i0, template: "<div class=\"m-context-menu-box\" [style.width]=\"width()\" [style.max-height]=\"height()\">\n <m-menu\n [config]=\"options()\"\n [hide]=\"hide()\"\n [file]=\"file()\"\n [isAdmin]=\"isAdmin()\"\n [visibilityRule]=\"visibilityRule()\"\n [disableRule]=\"disableRule()\"\n [extraData]=\"extraData()\"\n (action)=\"emitAction($event)\"\n />\n</div>\n", styles: ["@keyframes toggle-pulse{0%,to{transform:scale(1)}50%{transform:scale(1.02)}}@keyframes thumb-slide{0%{transform:translate(0) scale(1)}50%{transform:translate(.3em) scale(.9)}to{transform:translate(.6em) scale(1)}}.m-context-menu-box{overflow-y:auto;border-radius:0;border:1px solid var(--m-mm);background:var(--m-background);animation:context-menu-in .2s ease-out}@keyframes context-menu-in{0%{opacity:0;transform:scale(.95) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}:host-context(.align-bottom){display:block;width:100%!important;max-width:100%!important}:host-context(.align-bottom) .m-context-menu-box{width:100%!important;max-width:100%!important;max-height:70vh!important;border-left:none;border-right:none;border-bottom:none}\n"], dependencies: [{ kind: "component", type: MenuComponent, selector: "m-menu", inputs: ["config", "file", "root", "url", "extra", "hide", "hideLink", "isAdmin", "visibilityRule", "disableRule", "extraData"], outputs: ["action"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
8201
8334
  }
8202
8335
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ContextMenuBoxComponent, decorators: [{
8203
8336
  type: Component,
8204
- args: [{ selector: 'm-context-menu-box', imports: [MenuComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"m-context-menu-box\" [style.width]=\"width()\" [style.max-height]=\"height()\">\n <m-menu\n [config]=\"options()\"\n [file]=\"file()\"\n [isAdmin]=\"isAdmin()\"\n [visibilityRule]=\"visibilityRule()\"\n [disableRule]=\"disableRule()\"\n [extraData]=\"extraData()\"\n (action)=\"emitAction($event)\"\n />\n</div>\n", styles: ["@keyframes toggle-pulse{0%,to{transform:scale(1)}50%{transform:scale(1.02)}}@keyframes thumb-slide{0%{transform:translate(0) scale(1)}50%{transform:translate(.3em) scale(.9)}to{transform:translate(.6em) scale(1)}}.m-context-menu-box{overflow-y:auto;border-radius:0;border:1px solid var(--m-mm);background:var(--m-background);animation:context-menu-in .2s ease-out}@keyframes context-menu-in{0%{opacity:0;transform:scale(.95) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}:host-context(.align-bottom){display:block;width:100%!important;max-width:100%!important}:host-context(.align-bottom) .m-context-menu-box{width:100%!important;max-width:100%!important;max-height:70vh!important;border-left:none;border-right:none;border-bottom:none}\n"] }]
8205
- }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], file: [{ type: i0.Input, args: [{ isSignal: true, alias: "file", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], isAdmin: [{ type: i0.Input, args: [{ isSignal: true, alias: "isAdmin", required: false }] }], action: [{ type: i0.Output, args: ["action"] }], visibilityRule: [{ type: i0.Input, args: [{ isSignal: true, alias: "visibilityRule", required: false }] }], disableRule: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableRule", required: false }] }], extraData: [{ type: i0.Input, args: [{ isSignal: true, alias: "extraData", required: false }] }] } });
8337
+ args: [{ selector: 'm-context-menu-box', imports: [MenuComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"m-context-menu-box\" [style.width]=\"width()\" [style.max-height]=\"height()\">\n <m-menu\n [config]=\"options()\"\n [hide]=\"hide()\"\n [file]=\"file()\"\n [isAdmin]=\"isAdmin()\"\n [visibilityRule]=\"visibilityRule()\"\n [disableRule]=\"disableRule()\"\n [extraData]=\"extraData()\"\n (action)=\"emitAction($event)\"\n />\n</div>\n", styles: ["@keyframes toggle-pulse{0%,to{transform:scale(1)}50%{transform:scale(1.02)}}@keyframes thumb-slide{0%{transform:translate(0) scale(1)}50%{transform:translate(.3em) scale(.9)}to{transform:translate(.6em) scale(1)}}.m-context-menu-box{overflow-y:auto;border-radius:0;border:1px solid var(--m-mm);background:var(--m-background);animation:context-menu-in .2s ease-out}@keyframes context-menu-in{0%{opacity:0;transform:scale(.95) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}:host-context(.align-bottom){display:block;width:100%!important;max-width:100%!important}:host-context(.align-bottom) .m-context-menu-box{width:100%!important;max-width:100%!important;max-height:70vh!important;border-left:none;border-right:none;border-bottom:none}\n"] }]
8338
+ }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], hide: [{ type: i0.Input, args: [{ isSignal: true, alias: "hide", required: false }] }], file: [{ type: i0.Input, args: [{ isSignal: true, alias: "file", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], isAdmin: [{ type: i0.Input, args: [{ isSignal: true, alias: "isAdmin", required: false }] }], action: [{ type: i0.Output, args: ["action"] }], visibilityRule: [{ type: i0.Input, args: [{ isSignal: true, alias: "visibilityRule", required: false }] }], disableRule: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableRule", required: false }] }], extraData: [{ type: i0.Input, args: [{ isSignal: true, alias: "extraData", required: false }] }] } });
8206
8339
 
8207
8340
  class ContextMenuComponent extends ConfigComponent {
8208
8341
  toggle = model(...(ngDevMode ? [undefined, { debugName: "toggle" }] : /* istanbul ignore next */ []));
@@ -8231,15 +8364,11 @@ class ContextMenuComponent extends ConfigComponent {
8231
8364
  label: 'actions',
8232
8365
  inverted: this.inverted() ?? this.contextMenuConfig().inverted,
8233
8366
  }), ...(ngDevMode ? [{ debugName: "triggerButtonConfig" }] : /* istanbul ignore next */ []));
8234
- contextMenuOptions = computed(() => {
8235
- const options = this.contextMenuConfig().options;
8236
- const exclude = this.exclude();
8237
- if (!options)
8238
- return [];
8239
- if (!exclude || !exclude.length)
8240
- return options;
8241
- return options.map((group) => group.filter((item) => !exclude.includes(item.id)));
8242
- }, ...(ngDevMode ? [{ debugName: "contextMenuOptions" }] : /* istanbul ignore next */ []));
8367
+ // `exclude` is not applied here: a menu nests, and a filter run once over the
8368
+ // root groups cannot reach an item a layer down, nor one a `file` parent has
8369
+ // not fetched yet. It is handed to the menu as `hide` instead, which the menu
8370
+ // re-applies at whatever depth is on screen.
8371
+ contextMenuOptions = computed(() => this.contextMenuConfig().options ?? [], ...(ngDevMode ? [{ debugName: "contextMenuOptions" }] : /* istanbul ignore next */ []));
8243
8372
  selectorConfig = computed(() => ({
8244
8373
  component: ContextMenuBoxComponent,
8245
8374
  base: 'm-context-menu',
@@ -8249,6 +8378,7 @@ class ContextMenuComponent extends ConfigComponent {
8249
8378
  toggle: true,
8250
8379
  bindings: [
8251
8380
  inputBinding('options', this.contextMenuOptions),
8381
+ inputBinding('hide', this.exclude),
8252
8382
  inputBinding('visibilityRule', this.visibilityRule),
8253
8383
  inputBinding('disableRule', this.disableRule),
8254
8384
  inputBinding('extraData', this.extraData),
@@ -15464,6 +15594,11 @@ const initialModalState = {
15464
15594
  activePanel: undefined,
15465
15595
  };
15466
15596
  const ModalStore = signalStore({ providedIn: 'root' }, withState(initialModalState), withMethods((state, domService = inject(DomService), deviceService = inject(DeviceService)) => {
15597
+ // Every modal that has gone, by id. A modal is dismissed from two places —
15598
+ // its own close affordance and this store — and only one of those runs
15599
+ // through a ModalRef, so a caller waiting on an answer would otherwise wait
15600
+ // forever on the other.
15601
+ const closed = new Subject();
15467
15602
  const modalComp = inject(MODAL_COMPONENT);
15468
15603
  const panelComp = inject(PANEL_COMPONENT);
15469
15604
  const confirmComp = inject(CONFIRM_COMPONENT);
@@ -15515,6 +15650,7 @@ const ModalStore = signalStore({ providedIn: 'root' }, withState(initialModalSta
15515
15650
  ? remaining[remaining.length - 1]
15516
15651
  : undefined,
15517
15652
  });
15653
+ closed.next(modalId);
15518
15654
  };
15519
15655
  /**
15520
15656
  * The panel a dock request would displace: whatever currently holds the edge.
@@ -15651,26 +15787,69 @@ const ModalStore = signalStore({ providedIn: 'root' }, withState(initialModalSta
15651
15787
  const cleanupPanelsOnClose = rxMethod(pipe(filter((panelMap) => !Object.keys(panelMap).length), tap(() => {
15652
15788
  domService.cleanup(state.panelParentClassName());
15653
15789
  })));
15654
- const confirm = (opts, onConfirm) => {
15790
+ /**
15791
+ * The question as a value: subscribing asks it, and the single emission is
15792
+ * the answer — `true` for the commit, `false` for a refusal and for a
15793
+ * dismissal, which is a refusal by another route. Completes with that
15794
+ * emission, so a `switchMap` over it moves on rather than holding the
15795
+ * modal's answer open.
15796
+ *
15797
+ * Unsubscribing before it answers takes the modal away with it: the caller
15798
+ * that asked is gone, and a dialog nothing is waiting on is a dialog whose
15799
+ * answer lands nowhere.
15800
+ */
15801
+ const ask = (opts) => new Observable((subscriber) => {
15655
15802
  const modalRef = new ModalRef();
15656
- const id = open({
15803
+ let settled = false;
15804
+ let id = '';
15805
+ const settle = (result, dismiss) => {
15806
+ if (settled)
15807
+ return;
15808
+ settled = true;
15809
+ watch.unsubscribe();
15810
+ if (dismiss)
15811
+ close(id);
15812
+ subscriber.next(result);
15813
+ subscriber.complete();
15814
+ };
15815
+ const watch = closed
15816
+ .pipe(filter((closedId) => closedId === id))
15817
+ .subscribe(() => settle(false, false));
15818
+ id = open({
15657
15819
  component: confirmComp,
15658
15820
  providers: [{ provide: MODAL_REF, useValue: modalRef }],
15659
15821
  bindings: [
15660
15822
  inputBinding('header', () => opts.header ?? ''),
15661
15823
  inputBinding('body', () => opts.body ?? ''),
15824
+ inputBinding('params', () => opts.params ?? {}),
15662
15825
  inputBinding('type', () => opts.type ?? 'info'),
15826
+ inputBinding('kind', () => opts.kind ?? 'yes'),
15827
+ inputBinding('confirmLabel', () => opts.confirmLabel ?? ''),
15828
+ inputBinding('cancelLabel', () => opts.cancelLabel ?? ''),
15663
15829
  ],
15664
15830
  });
15665
- modalRef.onClose((result) => {
15831
+ modalRef.onClose((result) => settle(!!result, true));
15832
+ return () => {
15833
+ if (settled)
15834
+ return;
15835
+ settled = true;
15836
+ watch.unsubscribe();
15837
+ close(id);
15838
+ };
15839
+ });
15840
+ // The callback form, kept for every caller drawn against it. One
15841
+ // implementation underneath: a refusal runs nothing, which is what an
15842
+ // `onConfirm` that never fires already meant.
15843
+ const confirm = (opts, onConfirm) => {
15844
+ ask(opts).subscribe((result) => {
15666
15845
  if (result)
15667
15846
  onConfirm();
15668
- close(id);
15669
15847
  });
15670
15848
  };
15671
15849
  return {
15672
15850
  open,
15673
15851
  close,
15852
+ ask,
15674
15853
  confirm,
15675
15854
  openPanel,
15676
15855
  closePanel,
@@ -16069,16 +16248,41 @@ function injectAuthenticate() {
16069
16248
  class ConfirmComponent {
16070
16249
  header = input('', ...(ngDevMode ? [{ debugName: "header" }] : /* istanbul ignore next */ []));
16071
16250
  body = input('', ...(ngDevMode ? [{ debugName: "body" }] : /* istanbul ignore next */ []));
16251
+ /**
16252
+ * The MessageVariable values the two keys above name — a row's name or id the
16253
+ * asker knows and the message asks about. Values and never text: they reach
16254
+ * `TranslatePipe` as params rather than spliced into the key, so the message
16255
+ * still resolves per language. Empty is a message with no slots, which is
16256
+ * every confirmation drawn before this.
16257
+ */
16258
+ params = input({}, ...(ngDevMode ? [{ debugName: "params" }] : /* istanbul ignore next */ []));
16072
16259
  type = input('info', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
16260
+ /**
16261
+ * Whether the question can be refused. `yes` is an acknowledgement — the one
16262
+ * button commits and there is nothing else to press — and stays the default,
16263
+ * which is what every ConfirmComponent drawn before this was.
16264
+ */
16265
+ kind = input('yes', ...(ngDevMode ? [{ debugName: "kind" }] : /* istanbul ignore next */ []));
16266
+ /**
16267
+ * The wording of each button, as a TranslationAsset key. Empty falls back to
16268
+ * the library's own — derived from `type` for the commit, `cancel` for the
16269
+ * refusal — so a caller that has nothing to say about the buttons says
16270
+ * nothing.
16271
+ */
16272
+ confirmLabel = input('', ...(ngDevMode ? [{ debugName: "confirmLabel" }] : /* istanbul ignore next */ []));
16273
+ cancelLabel = input('', ...(ngDevMode ? [{ debugName: "cancelLabel" }] : /* istanbul ignore next */ []));
16073
16274
  #modalRef = inject(MODAL_REF);
16074
- confirmLabel = computed(() => {
16275
+ confirmText = computed(() => {
16276
+ if (this.confirmLabel())
16277
+ return this.confirmLabel();
16075
16278
  switch (this.type()) {
16076
16279
  case 'danger':
16077
16280
  return 'delete';
16078
16281
  default:
16079
16282
  return 'okay';
16080
16283
  }
16081
- }, ...(ngDevMode ? [{ debugName: "confirmLabel" }] : /* istanbul ignore next */ []));
16284
+ }, ...(ngDevMode ? [{ debugName: "confirmText" }] : /* istanbul ignore next */ []));
16285
+ cancelText = computed(() => this.cancelLabel() || 'cancel', ...(ngDevMode ? [{ debugName: "cancelText" }] : /* istanbul ignore next */ []));
16082
16286
  iconName = computed(() => {
16083
16287
  switch (this.type()) {
16084
16288
  case 'danger':
@@ -16094,26 +16298,39 @@ class ConfirmComponent {
16094
16298
  accept() {
16095
16299
  this.#modalRef.close(true);
16096
16300
  }
16301
+ // The refusal is a result like any other, so it closes with `false` rather
16302
+ // than dismissing: a caller waiting on the answer gets one either way.
16303
+ decline() {
16304
+ this.#modalRef.close(false);
16305
+ }
16097
16306
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ConfirmComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
16098
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: ConfirmComponent, isStandalone: true, selector: "m-confirm", inputs: { header: { classPropertyName: "header", publicName: "header", isSignal: true, isRequired: false, transformFunction: null }, body: { classPropertyName: "body", publicName: "body", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
16307
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: ConfirmComponent, isStandalone: true, selector: "m-confirm", inputs: { header: { classPropertyName: "header", publicName: "header", isSignal: true, isRequired: false, transformFunction: null }, body: { classPropertyName: "body", publicName: "body", isSignal: true, isRequired: false, transformFunction: null }, params: { classPropertyName: "params", publicName: "params", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, kind: { classPropertyName: "kind", publicName: "kind", isSignal: true, isRequired: false, transformFunction: null }, confirmLabel: { classPropertyName: "confirmLabel", publicName: "confirmLabel", isSignal: true, isRequired: false, transformFunction: null }, cancelLabel: { classPropertyName: "cancelLabel", publicName: "cancelLabel", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
16099
16308
  <div class="confirm confirm--{{ type() }}">
16100
16309
  <div class="confirm__header">
16101
16310
  <div class="confirm__icon">
16102
16311
  <m-icon [name]="iconName()" />
16103
16312
  </div>
16104
16313
  @if (header()) {
16105
- <m-header [level]="3">{{ header() | translate }}</m-header>
16314
+ <!-- The heading takes the key and its values rather than projected
16315
+ text: m-header translates its own label, and a MessageVariable
16316
+ fills the same way it does everywhere else. -->
16317
+ <m-header [level]="3" [label]="header()" [params]="params()" />
16106
16318
  }
16107
16319
  </div>
16108
16320
 
16109
16321
  <div class="confirm__content">
16110
16322
  @if (body()) {
16111
- <p class="confirm__body" [innerHTML]="body() | translate"></p>
16323
+ <p class="confirm__body" [innerHTML]="body() | translate: params()"></p>
16112
16324
  }
16113
16325
  </div>
16114
16326
 
16115
16327
  <div class="confirm__actions">
16116
- <m-one-button name="okay" (clicked)="accept()" />
16328
+ @if (kind() === 'yes-no') {
16329
+ <!-- asset: buttons/confirm_cancel.yml -->
16330
+ <m-one-button name="confirm_cancel" [label]="cancelText()" (clicked)="decline()" />
16331
+ }
16332
+ <!-- asset: buttons/okay.yml -->
16333
+ <m-one-button name="okay" [label]="confirmText()" (clicked)="accept()" />
16117
16334
  </div>
16118
16335
  </div>
16119
16336
  `, isInline: true, styles: ["@keyframes toggle-pulse{0%,to{transform:scale(1)}50%{transform:scale(1.02)}}@keyframes thumb-slide{0%{transform:translate(0) scale(1)}50%{transform:translate(.3em) scale(.9)}to{transform:translate(.6em) scale(1)}}.confirm{display:flex;flex-direction:column;min-width:320px;max-width:440px;padding:2.5rem;background:var(--m-backdrop-modal, rgba(255, 255, 255, .85));backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);border:0;position:relative;overflow:hidden}.confirm__header{display:flex;flex-direction:column;align-items:center;text-align:center;gap:.9375rem;margin-bottom:1.5rem}.confirm__icon{width:64px;height:64px;border-radius:1.6rem;display:flex;align-items:center;justify-content:center;font-size:2rem;background:var(--m-backdrop-mm, rgba(65, 105, 225, .1));color:var(--m-mm, #4169e1)}.confirm__icon .m-icon{width:32px;height:32px}.confirm__title{margin:0;font-size:1.375rem;font-weight:700;color:var(--m-text-900);letter-spacing:-.02em}.confirm__content{text-align:center;margin-bottom:2rem}.confirm__body{margin:0;font-size:1rem;line-height:1.6;color:var(--m-text-600)}.confirm__actions{width:100%;margin-top:auto;display:flex;justify-content:center;gap:1rem}.confirm--danger .confirm__icon{background:var(--m-backdrop-error, rgba(235, 25, 26, .1));color:var(--m-error, #EB191A)}.confirm--warning .confirm__icon{background:var(--m-backdrop-warning, rgba(247, 122, 2, .1));color:var(--m-warning, #F77A02)}.confirm--success .confirm__icon{background:var(--m-backdrop-success, rgba(109, 168, 47, .1));color:var(--m-success, #6da82f)}.confirm--info .confirm__icon{background:var(--m-info-lite, rgba(3, 102, 214, .1));color:var(--m-info, #0366d6)}\n"], dependencies: [{ kind: "component", type: ButtonComponent, selector: "m-button,m-one-button", inputs: ["config", "color", "labelClass", "fullWidth", "nav", "navParams", "href", "disabled", "variant", "name", "baseUrl", "one", "remote", "label", "noTranslate", "params", "noNative", "icon", "isRightIcon", "iconOnly", "stacked", "imgSrc", "nonClickable", "inverted", "isSubmit", "tabindex"], outputs: ["configChange", "clicked"] }, { kind: "component", type: IconComponent, selector: "m-icon, m-one-icon", inputs: ["config", "name", "color", "size", "one", "baseUrl", "remote"], outputs: ["configChange"] }, { kind: "component", type: HeaderComponent$1, selector: "m-header", inputs: ["level", "label", "actionButton", "actionLabel", "noTranslate", "params"], outputs: ["actionClick"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
@@ -16127,22 +16344,30 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
16127
16344
  <m-icon [name]="iconName()" />
16128
16345
  </div>
16129
16346
  @if (header()) {
16130
- <m-header [level]="3">{{ header() | translate }}</m-header>
16347
+ <!-- The heading takes the key and its values rather than projected
16348
+ text: m-header translates its own label, and a MessageVariable
16349
+ fills the same way it does everywhere else. -->
16350
+ <m-header [level]="3" [label]="header()" [params]="params()" />
16131
16351
  }
16132
16352
  </div>
16133
16353
 
16134
16354
  <div class="confirm__content">
16135
16355
  @if (body()) {
16136
- <p class="confirm__body" [innerHTML]="body() | translate"></p>
16356
+ <p class="confirm__body" [innerHTML]="body() | translate: params()"></p>
16137
16357
  }
16138
16358
  </div>
16139
16359
 
16140
16360
  <div class="confirm__actions">
16141
- <m-one-button name="okay" (clicked)="accept()" />
16361
+ @if (kind() === 'yes-no') {
16362
+ <!-- asset: buttons/confirm_cancel.yml -->
16363
+ <m-one-button name="confirm_cancel" [label]="cancelText()" (clicked)="decline()" />
16364
+ }
16365
+ <!-- asset: buttons/okay.yml -->
16366
+ <m-one-button name="okay" [label]="confirmText()" (clicked)="accept()" />
16142
16367
  </div>
16143
16368
  </div>
16144
16369
  `, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@keyframes toggle-pulse{0%,to{transform:scale(1)}50%{transform:scale(1.02)}}@keyframes thumb-slide{0%{transform:translate(0) scale(1)}50%{transform:translate(.3em) scale(.9)}to{transform:translate(.6em) scale(1)}}.confirm{display:flex;flex-direction:column;min-width:320px;max-width:440px;padding:2.5rem;background:var(--m-backdrop-modal, rgba(255, 255, 255, .85));backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);border:0;position:relative;overflow:hidden}.confirm__header{display:flex;flex-direction:column;align-items:center;text-align:center;gap:.9375rem;margin-bottom:1.5rem}.confirm__icon{width:64px;height:64px;border-radius:1.6rem;display:flex;align-items:center;justify-content:center;font-size:2rem;background:var(--m-backdrop-mm, rgba(65, 105, 225, .1));color:var(--m-mm, #4169e1)}.confirm__icon .m-icon{width:32px;height:32px}.confirm__title{margin:0;font-size:1.375rem;font-weight:700;color:var(--m-text-900);letter-spacing:-.02em}.confirm__content{text-align:center;margin-bottom:2rem}.confirm__body{margin:0;font-size:1rem;line-height:1.6;color:var(--m-text-600)}.confirm__actions{width:100%;margin-top:auto;display:flex;justify-content:center;gap:1rem}.confirm--danger .confirm__icon{background:var(--m-backdrop-error, rgba(235, 25, 26, .1));color:var(--m-error, #EB191A)}.confirm--warning .confirm__icon{background:var(--m-backdrop-warning, rgba(247, 122, 2, .1));color:var(--m-warning, #F77A02)}.confirm--success .confirm__icon{background:var(--m-backdrop-success, rgba(109, 168, 47, .1));color:var(--m-success, #6da82f)}.confirm--info .confirm__icon{background:var(--m-info-lite, rgba(3, 102, 214, .1));color:var(--m-info, #0366d6)}\n"] }]
16145
- }], propDecorators: { header: [{ type: i0.Input, args: [{ isSignal: true, alias: "header", required: false }] }], body: [{ type: i0.Input, args: [{ isSignal: true, alias: "body", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }] } });
16370
+ }], propDecorators: { header: [{ type: i0.Input, args: [{ isSignal: true, alias: "header", required: false }] }], body: [{ type: i0.Input, args: [{ isSignal: true, alias: "body", required: false }] }], params: [{ type: i0.Input, args: [{ isSignal: true, alias: "params", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], kind: [{ type: i0.Input, args: [{ isSignal: true, alias: "kind", required: false }] }], confirmLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmLabel", required: false }] }], cancelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelLabel", required: false }] }] } });
16146
16371
 
16147
16372
  function injectInstallApp() {
16148
16373
  const modalStore = inject(ModalStore);
@@ -20062,7 +20287,7 @@ class WrapperInputComponent extends ConfigComponent {
20062
20287
  break;
20063
20288
  }
20064
20289
  case InputType.TOGGLE: {
20065
- const { ToggleInputComponent } = await import('./magmonium-one-toggle-F27rRHhf.mjs');
20290
+ const { ToggleInputComponent } = await import('./magmonium-one-toggle-wEeMiUQz.mjs');
20066
20291
  this.createDynamicComponent(seq, ToggleInputComponent, [], true);
20067
20292
  break;
20068
20293
  }
@@ -20074,12 +20299,12 @@ class WrapperInputComponent extends ConfigComponent {
20074
20299
  break;
20075
20300
  }
20076
20301
  case InputType.PASSWORD: {
20077
- const { PasswordInputComponent } = await import('./magmonium-one-password-MtQpTJX1.mjs');
20302
+ const { PasswordInputComponent } = await import('./magmonium-one-password-DmEMAVca.mjs');
20078
20303
  this.createDynamicComponent(seq, PasswordInputComponent);
20079
20304
  break;
20080
20305
  }
20081
20306
  case InputType.OTP: {
20082
- const { OtpInputComponent } = await import('./magmonium-one-otp-B4nZEh_m.mjs');
20307
+ const { OtpInputComponent } = await import('./magmonium-one-otp-JmUyDNPb.mjs');
20083
20308
  this.createDynamicComponent(seq, OtpInputComponent);
20084
20309
  break;
20085
20310
  }
@@ -34298,5 +34523,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
34298
34523
  * Generated bundle index. Do not edit.
34299
34524
  */
34300
34525
 
34301
- export { DEFAULT_NAV_SEGMENT as $, ACCESS_DOMAINS as A, BaseInputComponent as B, COMPONENT_INPUT_REGISTRY as C, CardComponent as D, CardWrapperComponent as E, CarouselComponent as F, ChartComponent as G, CheckboxInputComponent as H, IS_DESIGN_MODE as I, ClearableInputComponent as J, ColComponent as K, LabelComponent as L, ColorPickerInputComponent as M, CommentItemComponent as N, CommentsApiService as O, CommentsComponent as P, CommentsStore as Q, ComponentInputComponent as R, ComponentStepperComponent as S, TranslatePipe as T, ConfigComponent as U, ConfirmComponent as V, ContextMenuComponent as W, CustomIconClass as X, CustomIconEditComponent as Y, DEFAULT_FILTER_RANGE_MODE as Z, DEFAULT_FILTER_VARIANT as _, BaseTextInputComponent as a, NAV_ID_SEP as a$, DEFAULT_SIZE as a0, DashboardCardComponent as a1, DateInputComponent as a2, DatePickerComponent as a3, DeviceService as a4, DomService as a5, Domain as a6, DotGridComponent as a7, DragListDirective as a8, DragListItemDirective as a9, InstrumentScoreComponent as aA, InterceptorObservables as aB, JumbotronComponent as aC, KeyValueComponent as aD, LAYOUT_ASSET_FOLDER as aE, LOGIN_COMPONENT as aF, LOGIN_STORE as aG, LanguageComponent as aH, LogoComponent as aI, MAG_SOCKET_EVENT as aJ, MHeroColorDirective as aK, MHeroComponent as aL, MODAL_REF as aM, MODAL_STORE_REF as aN, MRefDirective as aO, MStepComponent as aP, MURL_PARAM as aQ, MURL_SEP as aR, ManifestEnrichmentService as aS, MenuComponent as aT, ModalDirective as aU, ModalRef as aV, ModalStore as aW, MoneyPipe as aX, MultiRangeInputComponent as aY, MurlUrlSerializer as aZ, NAV_DEFAULT_MURL as a_, DraggableDirective as aa, DropdownInputComponent as ab, FILTER_GROUP_CONTEXT as ac, FILTER_RANGE_MODES as ad, FILTER_VARIANTS as ae, FLEX_VARIANTS as af, FOLDER_PICK_LISTENER as ag, FORM_ASSET_FOLDER as ah, FileService as ai, FileUploadDirective as aj, FileUploadInputComponent as ak, FlexComponent as al, FlexItemComponent as am, FormGroupComponent as an, FrameComponent as ao, FreezeService as ap, GRID_BREAKPOINTS as aq, GetNavService as ar, HeaderComponent$1 as as, HighlightDirective as at, HttpService as au, ICON_SOURCE as av, IS_SIDE_PANEL as aw, IconComponent as ax, ImgComponent as ay, InputType as az, TextOutputComponent as b, SectionBadgesComponent as b$, NAV_MAIN_BUTTONS as b0, NAV_SEGMENT_RE as b1, NAV_STORE_REF as b2, NAV_WC_COMPONENTS as b3, NAV_WIDGET_MAP as b4, NavComponent as b5, NavDetailsComponent as b6, NavHeaderComponent as b7, NavMenuComponent as b8, NavStore as b9, PwaInstallComponent as bA, ROOT_NAV$1 as bB, RadioGroupComponent as bC, RadioInputComponent as bD, RangeInputComponent as bE, RatingInputComponent as bF, ReactiveElementComponent as bG, RemoteComponent as bH, RemoteLoaderService as bI, ResizeElementComponent as bJ, RouteContainer as bK, RowComponent as bL, SEARCH_QUERY as bM, SEARCH_RESULTS_EVENT as bN, SECTION_ACCORDION_GROUP as bO, SECTION_FORM_CONTEXT as bP, SHARED_ICONS as bQ, SIZE_CONTEXT as bR, ScoreComponent as bS, ScrollComponent as bT, ScrollService as bU, SearchPanelComponent as bV, SearchStore as bW, SearchUserPanelComponent as bX, SectionAccordionDirective as bY, SectionAccordionGroupDirective as bZ, SectionBackComponent as b_, NavTrailComponent as ba, NothingComponent as bb, NotificationElementComponent as bc, NotificationGroupComponent as bd, NotificationPopupComponent as be, NotificationService as bf, NotificationStore as bg, NotificationType as bh, NotificationWidgetComponent as bi, ONE_ASSET_BASE_URL as bj, OPTIONS_SOURCE as bk, OVERLAY_WIDGETS as bl, OneApp as bm, OptionsSourceDirective as bn, OverlayBodyComponent as bo, OverlayRef as bp, OverlayService as bq, PLATFORM_BUTTON_NAV_IDS as br, PLATFORM_EXTENSIBLE_NAV_IDS as bs, PLATFORM_NAV_MAP as bt, PLATFORM_ROOT_CHILDREN as bu, PaginationComponent as bv, PanelComponent as bw, PercentagePipe as bx, PlaygroundComponent as by, PositionDirective as bz, ButtonComponent as c, UlComponent as c$, SectionButtonGroupComponent as c0, SectionCardComponent as c1, SectionCarouselComponent as c2, SectionComponent as c3, SectionFilterComponent as c4, SectionFilterGroupComponent as c5, SectionFilterMenuComponent as c6, SectionFilterPanelComponent as c7, SectionFilterRangePanelComponent as c8, SectionFooterComponent as c9, StrokeLinejoin as cA, SummaryComponent as cB, SvgGeneratorComponent as cC, SvgGeneratorService as cD, SvgService as cE, TOTAL_COLUMNS as cF, TRANSLATION_SOURCE as cG, TableComponent as cH, TechnicalMeterComponent as cI, TextInputComponent as cJ, TextareaInputComponent as cK, ThemeComponent as cL, ThemeDataService as cM, ThemeService as cN, ThemeStore as cO, TimeAgoPipe as cP, TimelineComponent as cQ, ToggleButtonComponent as cR, ToggleInputComponent as cS, ToggleRadioInputComponent as cT, ToolTipDirective as cU, TooltipComponent as cV, TranslateService as cW, TreeGridComponent as cX, URL_SEP as cY, USER_STORE_REF as cZ, USER_TAB_MAP as c_, SectionFormComponent as ca, SectionFormItemComponent as cb, SectionHeaderComponent as cc, SectionHeroComponent as cd, SectionPaginationComponent as ce, SectionSearchComponent as cf, SectionStepperComponent as cg, SectionTabsComponent as ch, SectionToggleComponent as ci, SectionToggleItemDirective as cj, SelectableCardInputComponent as ck, SelectorDirective as cl, SettingsSearchBarComponent as cm, SettingsSearchService as cn, ShapeComponent as co, SharedStoreRegistry as cp, SidePanelDirective as cq, Size as cr, SocketStore as cs, SortComponent as ct, StatComponent as cu, StepComponent as cv, StepperComponent as cw, StepsComponent as cx, StorageService as cy, StrokeLinecap as cz, APP_CONTEXT_REF as d, hexToRgb as d$, UniverseComponent as d0, UserApiService as d1, UserAvatarComponent as d2, UserComponent as d3, UserNavComponent as d4, UserSettingsComponent as d5, UserStore as d6, WC_ROUTE_CHANGED_EVENT as d7, WC_SEARCH_GROUPS as d8, WIN_USER_TAB_HOOK as d9, evaluate as dA, evaluateBool as dB, filterHoldsList as dC, filterHoldsOneBound as dD, filterHoldsOptions as dE, filterHoldsRange as dF, filterList as dG, filterOne as dH, filterPanelOf as dI, filterPanelWidth as dJ, filterRange as dK, filterTreeGridRows as dL, filterValueList as dM, filterValues as dN, flattenTreeGridRows as dO, formatBadgeCount as dP, fullName as dQ, generateClipPath as dR, generateTransform as dS, getClassList as dT, getProperty as dU, getScrollParent as dV, getTierFromPreviewPath as dW, getTreeGridRow as dX, getUniqueId as dY, getValue as dZ, hasErrorComputed as d_, WIN_USER_TAB_KEY as da, WatermarkComponent as db, WcRouterStore as dc, WrapperInputComponent as dd, anchorNavId as de, applyColorsToElement as df, bootstrapMagApp as dg, bootstrapPwaInstall as dh, buildWcBaseUrl as di, calculateLuminance as dj, calculateRanks as dk, cellText as dl, checkFilterCondition as dm, childNavId as dn, classListSignal as dp, coerceSize as dq, cornerEdge as dr, cornerSide as ds, createMap as dt, createPlatformNavMap as du, deriveAvatarGradient as dv, deriveContrastColor as dw, deriveOppositeColor as dx, derivePropertyName as dy, emailValidation as dz, ASSET_BASE_URL as e, provideSizeContext as e$, hslToRgb$1 as e0, initMagmoniumApp as e1, initialNotificationState as e2, initialState$2 as e3, initials as e4, injectAuthenticate as e5, injectInstallApp as e6, injectParentSize as e7, injectScrollSticky as e8, isButtonName as e9, minValidation as eA, miniMarkToHtml as eB, navIdChain as eC, navIdFor as eD, navIdSegment as eE, navIdToRoutePath as eF, navIdToSegments as eG, navToId as eH, parentNavId as eI, parseAddress as eJ, parseColor as eK, parsePatternNames as eL, patternValidation as eM, patternsValidation as eN, platformNavWidgets as eO, privateGuard as eP, processImageToSvg as eQ, provideAppContext as eR, provideMagAppConfig as eS, provideMagWcConfig as eT, provideMagWcRoutes as eU, provideModalComponents as eV, provideMurlUrlSerializer as eW, provideNavWidgets as eX, provideOverlayWidgets as eY, providePlatformNavWidgets as eZ, provideSearch as e_, isCancelledComputed as ea, isExtensiblePlatformNavId as eb, isJson as ec, isLoadingComputed as ed, isLocalhost as ee, isPlatformNavId as ef, isSize as eg, isTierPreview as eh, isUrlLocalhost as ei, isValidNavId as ej, isValidNavSegment as ek, isWebComponent as el, linkToId as em, linkToNav as en, loadingActions as eo, mInterceptor as ep, manualValidation as eq, matchFieldValidation as er, maxLengthValidation as es, maxValidation as et, mergePlatformNav as eu, mergeUnique as ev, mergeUniqueBy as ew, mergeUniqueWith as ex, minAgeValidation as ey, minLengthValidation as ez, AccordionBodyDirective as f, provideUserTabs as f0, publicGuard as f1, readFieldPatterns as f2, renderAddress as f3, requiredValidation as f4, resolveConfigAsset as f5, resolveIconSize as f6, resolvePallet as f7, resolvePatternRules as f8, resolveSize as f9, rgbToHex as fa, rgbToHsl as fb, rowHasChildren as fc, samePatterns as fd, segmentsToNavId as fe, setProperty as ff, setTreeGridChildren as fg, settingsWidgets as fh, shouldShowBadge as fi, splitNavId as fj, splitOnMatch as fk, stringToColor as fl, toAttrBool as fm, toAttrNumber as fn, toCssLength as fo, toHostNavId as fp, toLength$1 as fq, toLocalNavId as fr, toggleTreeGridRow as fs, unfetchedPlatformNav as ft, urlValidation as fu, AccordionComponent as g, AccordionGroupComponent as h, ActionComponent as i, AnimatedGraphsComponent as j, AppCardComponent as k, AppRelationType as l, AppTileComponent as m, AssetStore as n, AssetUrlPipe as o, Assets as p, AuthActivityPageComponent as q, AuthApiService as r, AuthStore as s, AutosizeDirective as t, BadgeComponent as u, BandingComponent as v, BaseArrayInputComponent as w, BaseRootWebComponent as x, BaseWebComponent as y, ButtonGroupComponent as z };
34302
- //# sourceMappingURL=magmonium-one-magmonium-one-BiogYqpG.mjs.map
34526
+ export { DEFAULT_NAV_PARAM as $, ACCESS_DOMAINS as A, BaseInputComponent as B, COMPONENT_INPUT_REGISTRY as C, CardComponent as D, CardWrapperComponent as E, CarouselComponent as F, ChartComponent as G, CheckboxInputComponent as H, IS_DESIGN_MODE as I, ClearableInputComponent as J, ColComponent as K, LabelComponent as L, ColorPickerInputComponent as M, CommentItemComponent as N, CommentsApiService as O, CommentsComponent as P, CommentsStore as Q, ComponentInputComponent as R, ComponentStepperComponent as S, TranslatePipe as T, ConfigComponent as U, ConfirmComponent as V, ContextMenuComponent as W, CustomIconClass as X, CustomIconEditComponent as Y, DEFAULT_FILTER_RANGE_MODE as Z, DEFAULT_FILTER_VARIANT as _, BaseTextInputComponent as a, NAV_DEFAULT_MURL as a$, DEFAULT_NAV_SEGMENT as a0, DEFAULT_SIZE as a1, DashboardCardComponent as a2, DateInputComponent as a3, DatePickerComponent as a4, DeviceService as a5, DomService as a6, Domain as a7, DotGridComponent as a8, DragListDirective as a9, InputType as aA, InstrumentScoreComponent as aB, InterceptorObservables as aC, JumbotronComponent as aD, KeyValueComponent as aE, LAYOUT_ASSET_FOLDER as aF, LOGIN_COMPONENT as aG, LOGIN_STORE as aH, LanguageComponent as aI, LogoComponent as aJ, MAG_SOCKET_EVENT as aK, MHeroColorDirective as aL, MHeroComponent as aM, MODAL_REF as aN, MODAL_STORE_REF as aO, MRefDirective as aP, MStepComponent as aQ, MURL_PARAM as aR, MURL_SEP as aS, ManifestEnrichmentService as aT, MenuComponent as aU, ModalDirective as aV, ModalRef as aW, ModalStore as aX, MoneyPipe as aY, MultiRangeInputComponent as aZ, MurlUrlSerializer as a_, DragListItemDirective as aa, DraggableDirective as ab, DropdownInputComponent as ac, FILTER_GROUP_CONTEXT as ad, FILTER_RANGE_MODES as ae, FILTER_VARIANTS as af, FLEX_VARIANTS as ag, FOLDER_PICK_LISTENER as ah, FORM_ASSET_FOLDER as ai, FileService as aj, FileUploadDirective as ak, FileUploadInputComponent as al, FlexComponent as am, FlexItemComponent as an, FormGroupComponent as ao, FrameComponent as ap, FreezeService as aq, GRID_BREAKPOINTS as ar, GetNavService as as, HeaderComponent$1 as at, HighlightDirective as au, HttpService as av, ICON_SOURCE as aw, IS_SIDE_PANEL as ax, IconComponent as ay, ImgComponent as az, TextOutputComponent as b, SectionBackComponent as b$, NAV_ID_SEP as b0, NAV_MAIN_BUTTONS as b1, NAV_SEGMENT_RE as b2, NAV_STORE_REF as b3, NAV_WC_COMPONENTS as b4, NAV_WIDGET_MAP as b5, NavComponent as b6, NavDetailsComponent as b7, NavHeaderComponent as b8, NavMenuComponent as b9, PositionDirective as bA, PwaInstallComponent as bB, ROOT_NAV$1 as bC, RadioGroupComponent as bD, RadioInputComponent as bE, RangeInputComponent as bF, RatingInputComponent as bG, ReactiveElementComponent as bH, RemoteComponent as bI, RemoteLoaderService as bJ, ResizeElementComponent as bK, RouteContainer as bL, RowComponent as bM, SEARCH_QUERY as bN, SEARCH_RESULTS_EVENT as bO, SECTION_ACCORDION_GROUP as bP, SECTION_FORM_CONTEXT as bQ, SHARED_ICONS as bR, SIZE_CONTEXT as bS, ScoreComponent as bT, ScrollComponent as bU, ScrollService as bV, SearchPanelComponent as bW, SearchStore as bX, SearchUserPanelComponent as bY, SectionAccordionDirective as bZ, SectionAccordionGroupDirective as b_, NavStore as ba, NavTrailComponent as bb, NothingComponent as bc, NotificationElementComponent as bd, NotificationGroupComponent as be, NotificationPopupComponent as bf, NotificationService as bg, NotificationStore as bh, NotificationType as bi, NotificationWidgetComponent as bj, ONE_ASSET_BASE_URL as bk, OPTIONS_SOURCE as bl, OVERLAY_WIDGETS as bm, OneApp as bn, OptionsSourceDirective as bo, OverlayBodyComponent as bp, OverlayRef as bq, OverlayService as br, PLATFORM_BUTTON_NAV_IDS as bs, PLATFORM_EXTENSIBLE_NAV_IDS as bt, PLATFORM_NAV_MAP as bu, PLATFORM_ROOT_CHILDREN as bv, PaginationComponent as bw, PanelComponent as bx, PercentagePipe as by, PlaygroundComponent as bz, ButtonComponent as c, USER_TAB_MAP as c$, SectionBadgesComponent as c0, SectionButtonGroupComponent as c1, SectionCardComponent as c2, SectionCarouselComponent as c3, SectionComponent as c4, SectionFilterComponent as c5, SectionFilterGroupComponent as c6, SectionFilterMenuComponent as c7, SectionFilterPanelComponent as c8, SectionFilterRangePanelComponent as c9, StrokeLinecap as cA, StrokeLinejoin as cB, SummaryComponent as cC, SvgGeneratorComponent as cD, SvgGeneratorService as cE, SvgService as cF, TOTAL_COLUMNS as cG, TRANSLATION_SOURCE as cH, TableComponent as cI, TechnicalMeterComponent as cJ, TextInputComponent as cK, TextareaInputComponent as cL, ThemeComponent as cM, ThemeDataService as cN, ThemeService as cO, ThemeStore as cP, TimeAgoPipe as cQ, TimelineComponent as cR, ToggleButtonComponent as cS, ToggleInputComponent as cT, ToggleRadioInputComponent as cU, ToolTipDirective as cV, TooltipComponent as cW, TranslateService as cX, TreeGridComponent as cY, URL_SEP as cZ, USER_STORE_REF as c_, SectionFooterComponent as ca, SectionFormComponent as cb, SectionFormItemComponent as cc, SectionHeaderComponent as cd, SectionHeroComponent as ce, SectionPaginationComponent as cf, SectionSearchComponent as cg, SectionStepperComponent as ch, SectionTabsComponent as ci, SectionToggleComponent as cj, SectionToggleItemDirective as ck, SelectableCardInputComponent as cl, SelectorDirective as cm, SettingsSearchBarComponent as cn, SettingsSearchService as co, ShapeComponent as cp, SharedStoreRegistry as cq, SidePanelDirective as cr, Size as cs, SocketStore as ct, SortComponent as cu, StatComponent as cv, StepComponent as cw, StepperComponent as cx, StepsComponent as cy, StorageService as cz, APP_CONTEXT_REF as d, hasErrorComputed as d$, UlComponent as d0, UniverseComponent as d1, UserApiService as d2, UserAvatarComponent as d3, UserComponent as d4, UserNavComponent as d5, UserSettingsComponent as d6, UserStore as d7, WC_ROUTE_CHANGED_EVENT as d8, WC_SEARCH_GROUPS as d9, emailValidation as dA, evaluate as dB, evaluateBool as dC, filterHoldsList as dD, filterHoldsOneBound as dE, filterHoldsOptions as dF, filterHoldsRange as dG, filterList as dH, filterOne as dI, filterPanelOf as dJ, filterPanelWidth as dK, filterRange as dL, filterTreeGridRows as dM, filterValueList as dN, filterValues as dO, flattenTreeGridRows as dP, formatBadgeCount as dQ, fullName as dR, generateClipPath as dS, generateTransform as dT, getClassList as dU, getProperty as dV, getScrollParent as dW, getTierFromPreviewPath as dX, getTreeGridRow as dY, getUniqueId as dZ, getValue as d_, WIN_USER_TAB_HOOK as da, WIN_USER_TAB_KEY as db, WatermarkComponent as dc, WcRouterStore as dd, WrapperInputComponent as de, anchorNavId as df, applyColorsToElement as dg, bootstrapMagApp as dh, bootstrapPwaInstall as di, buildWcBaseUrl as dj, calculateLuminance as dk, calculateRanks as dl, cellText as dm, checkFilterCondition as dn, childNavId as dp, classListSignal as dq, coerceSize as dr, cornerEdge as ds, cornerSide as dt, createMap as du, createPlatformNavMap as dv, deriveAvatarGradient as dw, deriveContrastColor as dx, deriveOppositeColor as dy, derivePropertyName as dz, ASSET_BASE_URL as e, provideNavWidgets as e$, hexToRgb as e0, hslToRgb$1 as e1, initMagmoniumApp as e2, initialNotificationState as e3, initialState$2 as e4, initials as e5, injectAuthenticate as e6, injectInstallApp as e7, injectParentSize as e8, injectScrollSticky as e9, mergeUniqueWith as eA, minAgeValidation as eB, minLengthValidation as eC, minValidation as eD, miniMarkToHtml as eE, navIdChain as eF, navIdFor as eG, navIdSegment as eH, navIdToRoutePath as eI, navIdToSegments as eJ, navParamOf as eK, navToId as eL, parentNavId as eM, parseAddress as eN, parseColor as eO, parsePatternNames as eP, patternValidation as eQ, patternsValidation as eR, platformNavWidgets as eS, privateGuard as eT, processImageToSvg as eU, provideAppContext as eV, provideMagAppConfig as eW, provideMagWcConfig as eX, provideMagWcRoutes as eY, provideModalComponents as eZ, provideMurlUrlSerializer as e_, isButtonName as ea, isCancelledComputed as eb, isExtensiblePlatformNavId as ec, isJson as ed, isLoadingComputed as ee, isLocalhost as ef, isNavMenuConfig as eg, isNavRowsConfig as eh, isPlatformNavId as ei, isSize as ej, isTierPreview as ek, isUrlLocalhost as el, isValidNavId as em, isValidNavSegment as en, isWebComponent as eo, linkToId as ep, linkToNav as eq, loadingActions as er, mInterceptor as es, manualValidation as et, matchFieldValidation as eu, maxLengthValidation as ev, maxValidation as ew, mergePlatformNav as ex, mergeUnique as ey, mergeUniqueBy as ez, AccordionBodyDirective as f, provideOverlayWidgets as f0, providePlatformNavWidgets as f1, provideSearch as f2, provideSizeContext as f3, provideUserTabs as f4, publicGuard as f5, readFieldPatterns as f6, renderAddress as f7, requiredValidation as f8, resolveConfigAsset as f9, resolveIconSize as fa, resolvePallet as fb, resolvePatternRules as fc, resolveSize as fd, rgbToHex as fe, rgbToHsl as ff, rowHasChildren as fg, samePatterns as fh, segmentsToNavId as fi, setProperty as fj, setTreeGridChildren as fk, settingsWidgets as fl, shouldShowBadge as fm, splitNavId as fn, splitOnMatch as fo, stringToColor as fp, toAttrBool as fq, toAttrNumber as fr, toCssLength as fs, toHostNavId as ft, toLength$1 as fu, toLocalNavId as fv, toggleTreeGridRow as fw, unfetchedPlatformNav as fx, urlValidation as fy, AccordionComponent as g, AccordionGroupComponent as h, ActionComponent as i, AnimatedGraphsComponent as j, AppCardComponent as k, AppRelationType as l, AppTileComponent as m, AssetStore as n, AssetUrlPipe as o, Assets as p, AuthActivityPageComponent as q, AuthApiService as r, AuthStore as s, AutosizeDirective as t, BadgeComponent as u, BandingComponent as v, BaseArrayInputComponent as w, BaseRootWebComponent as x, BaseWebComponent as y, ButtonGroupComponent as z };
34527
+ //# sourceMappingURL=magmonium-one-magmonium-one-BOkBE_Fl.mjs.map