@magmonium/one 0.3.14 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (21) hide show
  1. package/assets/button_groups/notification_actions.json +5 -0
  2. package/assets/buttons/accept_notification.json +4 -0
  3. package/assets/buttons/login_new_user.json +4 -0
  4. package/assets/buttons/search_result.json +4 -0
  5. package/assets/fields/comment_text.json +6 -0
  6. package/assets/i18n/en.json +23 -0
  7. package/assets/index.json +1 -1
  8. package/fesm2022/{magmonium-one-image-editor-CurYe_Mb.mjs → magmonium-one-image-editor-CqTVP7Li.mjs} +2 -2
  9. package/fesm2022/{magmonium-one-image-editor-CurYe_Mb.mjs.map → magmonium-one-image-editor-CqTVP7Li.mjs.map} +1 -1
  10. package/fesm2022/{magmonium-one-magmonium-one-Dr2fBHOB.mjs → magmonium-one-magmonium-one-DCRM0N5X.mjs} +1803 -1120
  11. package/fesm2022/magmonium-one-magmonium-one-DCRM0N5X.mjs.map +1 -0
  12. package/fesm2022/{magmonium-one-otp-B-NBB6PF.mjs → magmonium-one-otp-Cq5Hfnh_.mjs} +2 -2
  13. package/fesm2022/{magmonium-one-otp-B-NBB6PF.mjs.map → magmonium-one-otp-Cq5Hfnh_.mjs.map} +1 -1
  14. package/fesm2022/{magmonium-one-password-yXiSYlMS.mjs → magmonium-one-password-B4R18v54.mjs} +2 -2
  15. package/fesm2022/{magmonium-one-password-yXiSYlMS.mjs.map → magmonium-one-password-B4R18v54.mjs.map} +1 -1
  16. package/fesm2022/{magmonium-one-toggle-atjxl_R_.mjs → magmonium-one-toggle-DXiBGDPh.mjs} +2 -2
  17. package/fesm2022/{magmonium-one-toggle-atjxl_R_.mjs.map → magmonium-one-toggle-DXiBGDPh.mjs.map} +1 -1
  18. package/fesm2022/magmonium-one.mjs +1 -1
  19. package/package.json +1 -1
  20. package/types/magmonium-one.d.ts +291 -77
  21. package/fesm2022/magmonium-one-magmonium-one-Dr2fBHOB.mjs.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
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, viewChildren, afterEveryRender, EventEmitter, Output, ViewChild, ContentChild, provideZonelessChangeDetection, makeEnvironmentProviders, HostBinding, provideAppInitializer, provideBrowserGlobalErrorListeners, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
2
+ import { InjectionToken, signal, inject, Injectable, computed, DestroyRef, DOCUMENT, ApplicationRef, RendererFactory2, createComponent, EnvironmentInjector, Pipe, ChangeDetectorRef, untracked, ElementRef, afterNextRender, input, ChangeDetectionStrategy, Component, effect, Injector, reflectComponentType, inputBinding, model, HostListener, Renderer2, Directive, output, viewChild, ViewEncapsulation, forwardRef, runInInjectionContext, contentChild, TemplateRef, ViewContainerRef, outputBinding, linkedSignal, afterRenderEffect, Input, booleanAttribute, HostAttributeToken, viewChildren, afterEveryRender, EventEmitter, Output, ViewChild, ContentChild, provideZonelessChangeDetection, makeEnvironmentProviders, HostBinding, provideAppInitializer, provideBrowserGlobalErrorListeners, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
3
3
  import { HttpClient, HttpParams, HttpErrorResponse, provideHttpClient, withFetch, withInterceptors } from '@angular/common/http';
4
- import { firstValueFrom, of, tap, catchError, throwError, shareReplay, finalize, forkJoin, map, Observable, pipe, interval, fromEvent, switchMap as switchMap$1, filter, EMPTY, Subject, combineLatest, race, take, from, startWith } from 'rxjs';
4
+ import { firstValueFrom, of, tap, catchError, throwError, shareReplay, finalize, forkJoin, map, Observable, pipe, interval, fromEvent, switchMap as switchMap$1, filter, Subject, EMPTY, from, combineLatest, race, take, startWith } 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';
@@ -102,6 +102,13 @@ const NAV_STORE_REF = new InjectionToken('NAV_STORE_REF');
102
102
  const MODAL_STORE_REF = new InjectionToken('MODAL_STORE_REF');
103
103
  const USER_STORE_REF = new InjectionToken('USER_STORE_REF');
104
104
  const APP_CONTEXT_REF = new InjectionToken('APP_CONTEXT_REF');
105
+ /**
106
+ * This application's own AppLink. `root` is per bootstrapped app, so a Remote
107
+ * never reads its host's — unlike NavStore's `appLink`, which is the host's
108
+ * active app. The interceptor names the App in `X-Mag-App` with it (api ADR
109
+ * 0007) and init asks for Agreement to it.
110
+ */
111
+ const APP_LINK = new InjectionToken('APP_LINK', { providedIn: 'root', factory: () => signal(undefined) });
105
112
  const IS_SIDE_PANEL = new InjectionToken('IS_SIDE_PANEL');
106
113
  // SVG markup supplied by name from memory instead of fetched as an asset.
107
114
  // `m-icon` reads it before its own resource, so a glyph that exists only in a
@@ -3212,8 +3219,15 @@ const NotificationStore = signalStore({ providedIn: 'root' }, withState(initialN
3212
3219
  },
3213
3220
  notify: (notification) => {
3214
3221
  const id = notification.id ?? generateId();
3215
- const newNotification = { ...notification, id };
3216
- const exists = !!state.notificationMap()[id];
3222
+ const existing = state.notificationMap()[id];
3223
+ const exists = !!existing;
3224
+ // An upsert keeps what the User did to the row unless the caller says
3225
+ // otherwise: a re-raised Violation stays read (ADR 0157).
3226
+ const newNotification = {
3227
+ ...notification,
3228
+ id,
3229
+ read: notification.read ?? existing?.read,
3230
+ };
3217
3231
  patchState(state, {
3218
3232
  notifications: exists
3219
3233
  ? state.notifications()
@@ -3222,7 +3236,7 @@ const NotificationStore = signalStore({ providedIn: 'root' }, withState(initialN
3222
3236
  ...state.notificationMap(),
3223
3237
  [id]: newNotification,
3224
3238
  },
3225
- popupNotifications: exists
3239
+ popupNotifications: exists || notification.silent
3226
3240
  ? state.popupNotifications()
3227
3241
  : [id, ...state.popupNotifications()],
3228
3242
  });
@@ -3261,7 +3275,9 @@ const NotificationStore = signalStore({ providedIn: 'root' }, withState(initialN
3261
3275
  state.notifications().forEach((id) => {
3262
3276
  const notification = updatedMap[id];
3263
3277
  if (notification) {
3264
- if (notification.severity === 'error') {
3278
+ // A persistent error stands until what raised it withdraws it — a
3279
+ // blocking Violation (ADR 0157) — so it is read, not cleared.
3280
+ if (notification.severity === 'error' && !notification.persistent) {
3265
3281
  toRemove.push(id);
3266
3282
  }
3267
3283
  else {
@@ -3505,7 +3521,7 @@ params) => {
3505
3521
  (murl.length > 0 &&
3506
3522
  anchor.navId.startsWith(`${urlNavId}${NAV_ID_SEP}`)))
3507
3523
  ? anchor.path
3508
- : fillParams(navIdToRoutePath(urlNavId, navMap), params);
3524
+ : fillRoutePath(urlNavId, navMap, params);
3509
3525
  // Always keeps the leading `/`: a bare `|search` is a *relative* URL and
3510
3526
  // would resolve against the current directory (ADR 0013).
3511
3527
  const base = path === URL_SEP ? URL_SEP : path.replace(/\/$/, '');
@@ -3515,6 +3531,22 @@ params) => {
3515
3531
  const fillParams = (path, params) => params
3516
3532
  ? path.replace(/:([a-zA-Z0-9_]+)/g, (match, name) => params[name] !== undefined ? String(params[name]) : match)
3517
3533
  : path;
3534
+ /**
3535
+ * A Url NavId's route path with its params filled — and, for a NavTail, the
3536
+ * rest appended as its tail value names it, separators kept, since the tail is
3537
+ * every segment below the Nav and not one (m-one-ui CONTEXT.md NavTail). No
3538
+ * tail value is no rest: the Nav's own address.
3539
+ */
3540
+ const fillRoutePath = (navId, navMap, params) => {
3541
+ const path = fillParams(navIdToRoutePath(navId, navMap), params);
3542
+ const tailName = navMap[navId]?.tail;
3543
+ const rest = tailName && params?.[tailName] !== undefined
3544
+ ? String(params[tailName]).replace(/^\/+/, '')
3545
+ : '';
3546
+ if (!rest)
3547
+ return path;
3548
+ return path === URL_SEP ? `${URL_SEP}${rest}` : `${path}${URL_SEP}${rest}`;
3549
+ };
3518
3550
  /**
3519
3551
  * Splits a location into its route path and its Murl segments. Accepts the
3520
3552
  * percent-encoded form too, because `|` is not URL-unreserved and any encoder
@@ -4201,6 +4233,28 @@ function deriveBreadcrumb(params) {
4201
4233
  const mountFor = (navId, mounts) => mounts
4202
4234
  .filter((mount) => toLocalNavId(navId, mount.appNavId) !== undefined)
4203
4235
  .sort((a, b) => b.appNavId.length - a.appNavId.length)[0];
4236
+ /**
4237
+ * The route the page stands on where a `tail` Remote fills it. The host routes
4238
+ * only down to the mount — `root_app` for `/app/<link>/<navUrl>` — and the
4239
+ * navUrl below is the Remote's own route, so the Nav is the one the Remote
4240
+ * reported, rewritten into the host's keyspace (ADR 0015). Until it reports,
4241
+ * the app's root stands in: a cold deep link opens the app's menu, not the
4242
+ * host's.
4243
+ *
4244
+ * Only a mount hung on the Nav the host routed counts. The page's own slot
4245
+ * carries no `urlMode` and is a tail app by being the page.
4246
+ */
4247
+ const tailRouteOf = (hostNavId, mounts, reported) => {
4248
+ if (!hostNavId)
4249
+ return undefined;
4250
+ const mount = mounts.find(({ appNavId, urlMode }) => (urlMode ?? 'tail') === 'tail' && parentNavId(appNavId) === hostNavId);
4251
+ if (!mount)
4252
+ return undefined;
4253
+ const route = reported[mount.name];
4254
+ return route
4255
+ ? { navId: toHostNavId(route.navId, mount.appNavId), params: route.params }
4256
+ : { navId: mount.appNavId, params: {} };
4257
+ };
4204
4258
 
4205
4259
  /** One chain can cross the host and several Remotes, so the mount is per NavId. */
4206
4260
  const mountIn = (navId, ctx) => mountFor(navId, ctx.mounts ??
@@ -4304,6 +4358,8 @@ const initialState$3 = {
4304
4358
  path: '/',
4305
4359
  routeNavId: undefined,
4306
4360
  routeParams: {},
4361
+ hostRoute: { navId: undefined, params: {} },
4362
+ mountRoutes: {},
4307
4363
  routeChain: [],
4308
4364
  murl: [],
4309
4365
  appLink: undefined,
@@ -4582,6 +4638,17 @@ const NavStore = signalStore({ providedIn: 'root' }, withState(initialState$3),
4582
4638
  return undefined;
4583
4639
  };
4584
4640
  const widgetEntry = computed(() => firstEntry(widgetNavIds()), ...(ngDevMode ? [{ debugName: "widgetEntry" }] : /* istanbul ignore next */ []));
4641
+ /**
4642
+ * The instances the panel is drawn for: the Browse's while one is open —
4643
+ * the Router still describes the Page behind the panel, not the Nav the
4644
+ * User is looking into — and the Router's otherwise (CONTEXT.md Browse).
4645
+ */
4646
+ const panelParams = computed(() => store.menuNavId()
4647
+ ? Object.fromEntries(Object.entries(store.menuParams() ?? {}).map(([name, value]) => [
4648
+ name,
4649
+ String(value),
4650
+ ]))
4651
+ : store.routeParams(), ...(ngDevMode ? [{ debugName: "panelParams" }] : /* istanbul ignore next */ []));
4585
4652
  /**
4586
4653
  * Every `dynamic` Nav with a NavRowSource behind it, resolved. Walks the
4587
4654
  * whole map rather than the open panel's own descent: the rows are drawn by
@@ -4590,30 +4657,23 @@ const NavStore = signalStore({ providedIn: 'root' }, withState(initialState$3),
4590
4657
  */
4591
4658
  const dynamicRows = computed(() => {
4592
4659
  const out = {};
4660
+ const params = panelParams();
4593
4661
  for (const nav of Object.values(store.navMap())) {
4594
4662
  if (nav.presentation !== 'dynamic')
4595
4663
  continue;
4596
4664
  const hit = entryAt(nav.navId);
4597
4665
  if (!hit || !isNavRowsConfig(hit.entry))
4598
4666
  continue;
4667
+ const rows = hit.entry.navRowsFor
4668
+ ? hit.entry.navRowsFor(params)
4669
+ : hit.entry.navRows();
4599
4670
  out[nav.navId] = {
4600
- rows: hit.entry.navRows() ?? [],
4671
+ rows: rows ?? [],
4601
4672
  loading: hit.entry.loading?.(),
4602
4673
  };
4603
4674
  }
4604
4675
  return out;
4605
4676
  }, ...(ngDevMode ? [{ debugName: "dynamicRows" }] : /* istanbul ignore next */ []));
4606
- /**
4607
- * The instances the panel is drawn for: the Browse's while one is open —
4608
- * the Router still describes the Page behind the panel, not the Nav the
4609
- * User is looking into — and the Router's otherwise (CONTEXT.md Browse).
4610
- */
4611
- const panelParams = computed(() => store.menuNavId()
4612
- ? Object.fromEntries(Object.entries(store.menuParams() ?? {}).map(([name, value]) => [
4613
- name,
4614
- String(value),
4615
- ]))
4616
- : store.routeParams(), ...(ngDevMode ? [{ debugName: "panelParams" }] : /* istanbul ignore next */ []));
4617
4677
  /**
4618
4678
  * Every `dynamic` Nav with a NavInstanceSource behind it, resolved against
4619
4679
  * the parameters the panel is drawn for (ADR 0030) — a Browse's own, so the
@@ -4902,32 +4962,37 @@ const NavStore = signalStore({ providedIn: 'root' }, withState(initialState$3),
4902
4962
  * page rather than stepping out one Murl at a time (ADR 0013).
4903
4963
  *
4904
4964
  * `keepPanel` is for the AppLogo: home navigation while the menu is open
4905
- * must not clear `navOpenedByUser`, so the panel stays up on root.
4965
+ * must not clear `navOpenedByUser`, so the panel stays up on root. It also
4966
+ * raises a closed panel — a gesture whose landing is read from its panel,
4967
+ * as the editor's CodeTree is. Applied ahead of a mount's own move too:
4968
+ * the host's path changes all the same once the mount reports.
4906
4969
  */
4907
4970
  const goToNav = (navId, params, options) => {
4971
+ const willOpen = untracked(() => splitNavId(navId, store.navMap()).murl.length > 0);
4972
+ if (options?.keepPanel && !willOpen) {
4973
+ patchState(store, {
4974
+ navOpenedByUser: true,
4975
+ keepPanelOnPathChange: true,
4976
+ });
4977
+ }
4908
4978
  // A side app's own Nav moves that app; it reports, and its m-remote
4909
4979
  // writes the URL through `out` — one write path, not two.
4910
4980
  const mount = mountOf(navId);
4911
4981
  if (mount?.navigate) {
4912
4982
  const map = untracked(() => store.navMap());
4913
4983
  const own = navIdToRoutePath(mount.appNavId, map);
4914
- const full = navIdToRoutePath(navId, map);
4915
- mount.navigate(full.slice(own === URL_SEP ? 1 : own.length + 1));
4984
+ const full = fillRoutePath(navId, map, params);
4985
+ mount.navigate(full.slice(own === URL_SEP ? 1 : own.length + 1), {
4986
+ replaceUrl: !!options?.replaceUrl,
4987
+ });
4916
4988
  return;
4917
4989
  }
4918
4990
  const wasOpen = untracked(() => store.hasMurl());
4919
4991
  patchState(store, { menuNavId: undefined });
4920
4992
  const address = addressFor(navId, params);
4921
- const willOpen = untracked(() => splitNavId(navId, store.navMap()).murl.length > 0);
4922
4993
  if (willOpen && !wasOpen) {
4923
4994
  patchState(store, { panelPushed: true });
4924
4995
  }
4925
- if (options?.keepPanel && !willOpen) {
4926
- patchState(store, {
4927
- navOpenedByUser: true,
4928
- keepPanelOnPathChange: true,
4929
- });
4930
- }
4931
4996
  router.navigateByUrl(address, {
4932
4997
  replaceUrl: !!options?.replaceUrl || (wasOpen && willOpen),
4933
4998
  });
@@ -4947,20 +5012,55 @@ const NavStore = signalStore({ providedIn: 'root' }, withState(initialState$3),
4947
5012
  }
4948
5013
  return navId;
4949
5014
  };
4950
- /** The route parameter one Nav contributes, read off the map. */
4951
- const paramNameOf = (navId) => navParamOf(untracked(() => store.navMap())[knownNavId(navId)]);
5015
+ /**
5016
+ * The route parameter one Nav contributes, read off the map — a static
5017
+ * NavTail's being its tail, the only value it carries.
5018
+ */
5019
+ const paramNameOf = (navId) => {
5020
+ const nav = untracked(() => store.navMap())[knownNavId(navId)];
5021
+ return nav?.tail && nav.presentation !== 'dynamic'
5022
+ ? nav.tail
5023
+ : navParamOf(nav);
5024
+ };
4952
5025
  /**
4953
5026
  * Follows a NavRef whose dynamic segments are keyed by the *Nav* that
4954
5027
  * contributes each one rather than by its parameter name (m-one-ui
4955
5028
  * CONTEXT.md OutcomeNav). The map is what knows the names, so a NavParam
4956
5029
  * renamed after the caller was emitted still fills the right segment.
5030
+ *
5031
+ * The map holds only the Nav stood on, its chain and its children, so a
5032
+ * target further down is fetched first: addressed from a partial map, an
5033
+ * unknown Nav contributes its own segment where its value belongs.
4957
5034
  */
4958
5035
  const followNav = (navId, byNav, options) => {
4959
- const entries = Object.entries(byNav ?? {});
4960
- const params = entries.length
4961
- ? Object.fromEntries(entries.map(([id, value]) => [paramNameOf(id), value]))
4962
- : undefined;
4963
- goToNav(knownNavId(navId), params, options);
5036
+ const follow = () => {
5037
+ const entries = Object.entries(byNav ?? {});
5038
+ const params = entries.length
5039
+ ? Object.fromEntries(entries.map(([id, value]) => [paramNameOf(id), value]))
5040
+ : undefined;
5041
+ goToNav(knownNavId(navId), params, options);
5042
+ };
5043
+ const target = knownNavId(navId);
5044
+ const map = untracked(() => store.navMap());
5045
+ if (navIdChain(target).every((id) => map[id]))
5046
+ return follow();
5047
+ getNavService
5048
+ .getNav(target, map, {
5049
+ appNavId: untracked(() => store.appNavId()),
5050
+ appLink: untracked(() => store.appLink()),
5051
+ mounts: untracked(() => store.allMounts()),
5052
+ })
5053
+ .subscribe({
5054
+ next: (delta) => {
5055
+ if (!Object.keys(delta).length)
5056
+ return;
5057
+ patchState(store, (state) => ({
5058
+ navMap: { ...state.navMap, ...delta },
5059
+ }));
5060
+ },
5061
+ complete: follow,
5062
+ error: follow,
5063
+ });
4964
5064
  };
4965
5065
  /** The current value of the parameter one dynamic Nav contributes. */
4966
5066
  const routeParamOf = (navId) => untracked(() => store.routeParams())[paramNameOf(navId)];
@@ -5013,6 +5113,22 @@ const NavStore = signalStore({ providedIn: 'root' }, withState(initialState$3),
5013
5113
  }
5014
5114
  router.navigateByUrl(untracked(() => store.path()), { replaceUrl: true });
5015
5115
  };
5116
+ /**
5117
+ * The host's route with a `tail` mount's own laid over it, when one fills
5118
+ * the page. Both halves change on their own — the host on NavigationEnd,
5119
+ * the mount on its report — so each writer recomputes the whole.
5120
+ */
5121
+ const standingRoute = (hostRoute) => {
5122
+ const tail = tailRouteOf(hostRoute.navId, untracked(() => store.allMounts()), untracked(() => store.mountRoutes()));
5123
+ return {
5124
+ hostRoute,
5125
+ routeNavId: tail?.navId ?? hostRoute.navId,
5126
+ routeParams: tail
5127
+ ? { ...hostRoute.params, ...tail.params }
5128
+ : hostRoute.params,
5129
+ };
5130
+ };
5131
+ const settleRoute = () => patchState(store, standingRoute(untracked(() => store.hostRoute())));
5016
5132
  /**
5017
5133
  * Reads the Address the Router just settled on.
5018
5134
  *
@@ -5039,8 +5155,7 @@ const NavStore = signalStore({ providedIn: 'root' }, withState(initialState$3),
5039
5155
  patchState(store, {
5040
5156
  path,
5041
5157
  outlets,
5042
- routeNavId,
5043
- routeParams,
5158
+ ...standingRoute({ navId: routeNavId, params: routeParams }),
5044
5159
  routeChain,
5045
5160
  murl,
5046
5161
  menuNavId: undefined,
@@ -5061,9 +5176,19 @@ const NavStore = signalStore({ providedIn: 'root' }, withState(initialState$3),
5061
5176
  const standsOn = (navId, params) => !untracked(() => splitNavId(navId, store.navMap())).murl.length &&
5062
5177
  untracked(() => addressFor(navId, params)) ===
5063
5178
  untracked(() => store.path());
5064
- const setSelected = (navId, params) => navId && !standsOn(navId, params)
5065
- ? goToNav(navId, params)
5066
- : closePanel();
5179
+ /**
5180
+ * A row naming the Page already stood on only closes the panel — unless it
5181
+ * asks to keep it, when the panel is what it came for and is raised.
5182
+ */
5183
+ const setSelected = (navId, params, options) => {
5184
+ if (!navId)
5185
+ return closePanel();
5186
+ if (!standsOn(navId, params))
5187
+ return goToNav(navId, params, options);
5188
+ if (!options?.keepPanel)
5189
+ return closePanel();
5190
+ patchState(store, { navOpenedByUser: true, menuNavId: undefined });
5191
+ };
5067
5192
  /**
5068
5193
  * The one click that derives its own target instead of naming one. With no
5069
5194
  * default Murl it opens the panel without touching the address — that state
@@ -5098,10 +5223,13 @@ const NavStore = signalStore({ providedIn: 'root' }, withState(initialState$3),
5098
5223
  const setAppLink = (appLink, appNavId) => {
5099
5224
  patchState(store, {
5100
5225
  appLink,
5101
- appNavId: appLink
5102
- ? (appNavId ?? untracked(() => store.routeNavId()) ?? undefined)
5103
- : undefined,
5226
+ // Only a host names where the app is mounted (m-ui's slot). A
5227
+ // standalone app sets its link for its WC config alone: defaulting to
5228
+ // the route made it a Remote mounted at `root`, and every Nav fetched
5229
+ // after that went to the WC bundle rather than to its own assets.
5230
+ appNavId: appLink ? appNavId : undefined,
5104
5231
  });
5232
+ settleRoute();
5105
5233
  loadWcConfig(appLink);
5106
5234
  };
5107
5235
  const registerMount = (mount) => {
@@ -5111,6 +5239,7 @@ const NavStore = signalStore({ providedIn: 'root' }, withState(initialState$3),
5111
5239
  patchState(store, (state) => ({
5112
5240
  mounts: { ...state.mounts, [mount.name]: mount },
5113
5241
  }));
5242
+ settleRoute();
5114
5243
  translateService.mountRemoteApp(mount.link);
5115
5244
  loadWcConfig(mount.link);
5116
5245
  if (mount.createMenu)
@@ -5136,7 +5265,21 @@ const NavStore = signalStore({ providedIn: 'root' }, withState(initialState$3),
5136
5265
  translateService.unmountRemoteApp(mount.link);
5137
5266
  patchState(store, (state) => ({
5138
5267
  mounts: Object.fromEntries(Object.entries(state.mounts).filter(([key]) => key !== name)),
5268
+ mountRoutes: Object.fromEntries(Object.entries(state.mountRoutes).filter(([key]) => key !== name)),
5269
+ }));
5270
+ settleRoute();
5271
+ };
5272
+ /**
5273
+ * A mount's own Router moved. Only a `tail` mount filling the page changes
5274
+ * where the page stands; the others are remembered for when one does.
5275
+ */
5276
+ const setMountRoute = (name, route) => {
5277
+ patchState(store, (state) => ({
5278
+ mountRoutes: route
5279
+ ? { ...state.mountRoutes, [name]: route }
5280
+ : Object.fromEntries(Object.entries(state.mountRoutes).filter(([key]) => key !== name)),
5139
5281
  }));
5282
+ settleRoute();
5140
5283
  };
5141
5284
  const registerWidgets = (appLink, entry) => {
5142
5285
  patchState(store, (state) => ({
@@ -5207,6 +5350,7 @@ const NavStore = signalStore({ providedIn: 'root' }, withState(initialState$3),
5207
5350
  setAppLink,
5208
5351
  registerMount,
5209
5352
  unregisterMount,
5353
+ setMountRoute,
5210
5354
  mountOf,
5211
5355
  setWcConfig,
5212
5356
  loadWcConfig,
@@ -5352,78 +5496,457 @@ const NavStore = signalStore({ providedIn: 'root' }, withState(initialState$3),
5352
5496
  };
5353
5497
  }));
5354
5498
 
5355
- function initMagmoniumApp({ backend, authUrl, socketUrl, }) {
5356
- return () => {
5357
- inject(FreezeService); // ensure the loading effect is always active
5358
- const httpService = inject(HttpService);
5359
- const translateService = inject(TranslateService);
5360
- const themeStore = inject(ThemeStore);
5361
- const loginStore = inject(LOGIN_STORE);
5362
- const navStore = inject(NavStore, { optional: true });
5363
- translateService.init();
5364
- SharedStoreRegistry.setThemeStore(themeStore);
5365
- SharedStoreRegistry.setTranslateService(translateService);
5366
- SharedStoreRegistry.setLoadingActions(loadingActions);
5367
- SharedStoreRegistry.setNotificationStore(inject(NotificationStore));
5368
- if (navStore) {
5369
- SharedStoreRegistry.setNavStore(navStore);
5499
+ function getUniqueId() {
5500
+ return Date.now().toString(36) + Math.random().toString(36).substr(2);
5501
+ }
5502
+
5503
+ const MODAL_COMPONENT = new InjectionToken('MODAL_COMPONENT');
5504
+ const PANEL_COMPONENT = new InjectionToken('PANEL_COMPONENT');
5505
+ const CONFIRM_COMPONENT = new InjectionToken('CONFIRM_COMPONENT');
5506
+ /**
5507
+ * The body an overlay opened by name is filled with — what `mModal` and
5508
+ * `mSidePanel` already build by hand, reached through a token here so
5509
+ * `ModalStore.openScreen` can build the same thing without importing the
5510
+ * component into the store (the reason the three above are tokens).
5511
+ */
5512
+ const OVERLAY_BODY_COMPONENT = new InjectionToken('OVERLAY_BODY_COMPONENT');
5513
+
5514
+ const MODAL_REF = new InjectionToken('MODAL_REF');
5515
+ class ModalRef {
5516
+ closeCallback;
5517
+ changeCallback;
5518
+ /** Commit a result and dismiss (single-pick, confirm, …). */
5519
+ close(result) {
5520
+ this.closeCallback?.(result);
5521
+ }
5522
+ /**
5523
+ * Commit a result without dismissing. Multi-pick panels use this so each
5524
+ * tick updates the field while the panel stays open.
5525
+ */
5526
+ change(result) {
5527
+ this.changeCallback?.(result);
5528
+ }
5529
+ onClose(callback) {
5530
+ this.closeCallback = callback;
5531
+ }
5532
+ onChange(callback) {
5533
+ this.changeCallback = callback;
5534
+ }
5535
+ }
5536
+
5537
+ /**
5538
+ * A DockedPanel takes the viewport edge and displaces the older SidePanel inboard.
5539
+ * Docking is desktop-only and requires the page to stay readable behind both panels.
5540
+ * See ADR 0004.
5541
+ */
5542
+ const DOCK_MIN_PAGE_REMAINDER = 320;
5543
+ const DOCK_TRANSITION = '300ms cubic-bezier(0.2, 0, 0, 1)';
5544
+ const DEFAULT_PANEL_WIDTH = '400px';
5545
+ /**
5546
+ * Reads a px panel width. Any other unit is undockable — the displacement offset
5547
+ * must be known before the panel exists in the DOM.
5548
+ */
5549
+ const parsePanelWidth = (width) => {
5550
+ if (!width?.endsWith('px')) {
5551
+ return undefined;
5552
+ }
5553
+ const value = Number.parseFloat(width);
5554
+ return Number.isFinite(value) ? value : undefined;
5555
+ };
5556
+ /**
5557
+ * A CSS length as a panel needs it. An authored width is free text — the
5558
+ * Screen editor takes `400` as readily as `400px` — and a unitless number is
5559
+ * not a length: the browser drops the declaration and the panel collapses to
5560
+ * its content. A bare number means px, which is what every other authored
5561
+ * dimension in the library already assumes; anything carrying a unit, a
5562
+ * percentage or a `calc()` is passed through untouched.
5563
+ */
5564
+ const panelCssLength = (value) => {
5565
+ const trimmed = value?.trim();
5566
+ if (!trimmed)
5567
+ return undefined;
5568
+ return /^-?\d*\.?\d+$/.test(trimmed) ? `${trimmed}px` : trimmed;
5569
+ };
5570
+ const hasRoomToDock = (baseWidth, panelWidth, viewportWidth) => {
5571
+ const base = parsePanelWidth(baseWidth);
5572
+ const panel = parsePanelWidth(panelWidth);
5573
+ if (base === undefined || panel === undefined) {
5574
+ return false;
5575
+ }
5576
+ return viewportWidth - (base + panel) >= DOCK_MIN_PAGE_REMAINDER;
5577
+ };
5578
+
5579
+ const initialModalState = {
5580
+ modalTriggerMap: {},
5581
+ className: 'modal',
5582
+ parentClassName: 'modals',
5583
+ activeModal: undefined,
5584
+ panelTriggerMap: {},
5585
+ panelClassName: 'panel',
5586
+ panelParentClassName: 'panels',
5587
+ activePanel: undefined,
5588
+ };
5589
+ const ModalStore = signalStore({ providedIn: 'root' }, withState(initialModalState), withMethods((state, domService = inject(DomService), deviceService = inject(DeviceService)) => {
5590
+ // Every modal that has gone, by id. A modal is dismissed from two places —
5591
+ // its own close affordance and this store — and only one of those runs
5592
+ // through a ModalRef, so a caller waiting on an answer would otherwise wait
5593
+ // forever on the other.
5594
+ const closed = new Subject();
5595
+ const modalComp = inject(MODAL_COMPONENT);
5596
+ const panelComp = inject(PANEL_COMPONENT);
5597
+ const confirmComp = inject(CONFIRM_COMPONENT);
5598
+ const overlayBodyComp = inject(OVERLAY_BODY_COMPONENT);
5599
+ const open = (modalTrigger) => {
5600
+ const id = modalTrigger.id ?? getUniqueId();
5601
+ const modalComponentRef = domService.create({
5602
+ component: modalComp,
5603
+ className: state.className(),
5604
+ id,
5605
+ parentClassName: state.parentClassName(),
5606
+ bindings: [
5607
+ inputBinding('name', () => modalTrigger.name),
5608
+ inputBinding('component', () => modalTrigger.component),
5609
+ inputBinding('bindings', () => modalTrigger.bindings),
5610
+ inputBinding('providers', () => modalTrigger.providers),
5611
+ inputBinding('one', () => modalTrigger.one ?? false),
5612
+ inputBinding('instanceId', () => id),
5613
+ inputBinding('config', () => modalTrigger.config),
5614
+ ],
5615
+ });
5616
+ patchState(state, {
5617
+ modalTriggerMap: {
5618
+ ...state.modalTriggerMap(),
5619
+ [id]: {
5620
+ ...modalTrigger,
5621
+ ref: modalComponentRef,
5622
+ },
5623
+ },
5624
+ activeModal: id,
5625
+ });
5626
+ return id;
5627
+ };
5628
+ const close = (id) => {
5629
+ const modalId = id ?? state.activeModal();
5630
+ const modalTriggerMap = state.modalTriggerMap();
5631
+ if (!modalId) {
5632
+ return;
5370
5633
  }
5371
- if (loginStore) {
5372
- SharedStoreRegistry.setLoginStore(loginStore);
5634
+ // A modal that has already gone. Closing it again is what a body and its
5635
+ // own close affordance both doing their job looks like (ADR 0031), and
5636
+ // the state patch below would hand `activeModal` to somebody else's
5637
+ // overlay, so the second call answers nothing.
5638
+ if (id && !modalTriggerMap[id]) {
5639
+ return;
5373
5640
  }
5374
- const effectiveBackend = backend || 'http://localhost:8000';
5375
- if (!backend) {
5376
- console.warn('initMagmoniumApp: No backend URL provided, defaulting to http://localhost:8000. ' +
5377
- 'Check your environment configuration if this is unexpected.');
5641
+ domService.destroy({
5642
+ componentRef: modalTriggerMap[modalId]?.ref,
5643
+ parentClassName: state.parentClassName(),
5644
+ id: modalId,
5645
+ });
5646
+ delete modalTriggerMap[modalId];
5647
+ const remaining = Object.keys(modalTriggerMap);
5648
+ patchState(state, {
5649
+ modalTriggerMap: { ...modalTriggerMap },
5650
+ activeModal: remaining.length
5651
+ ? remaining[remaining.length - 1]
5652
+ : undefined,
5653
+ });
5654
+ closed.next(modalId);
5655
+ };
5656
+ /**
5657
+ * The panel a dock request would displace: whatever currently holds the edge.
5658
+ * Docking is decided once, at open — never re-evaluated on resize (ADR 0004).
5659
+ */
5660
+ const resolveDockTarget = (side, width) => {
5661
+ if (!deviceService.isDesktop()) {
5662
+ return undefined;
5378
5663
  }
5379
- // Auth URL defaults to Backend URL so single-host apps stay unchanged (ADR 0012).
5380
- const effectiveAuth = authUrl || effectiveBackend;
5381
- httpService.setUrl(effectiveBackend);
5382
- httpService.setAuthUrl(effectiveAuth);
5383
- themeStore.init();
5384
- if (socketUrl) {
5385
- const socketStore = inject(SocketStore);
5386
- let lastToken;
5387
- effect(() => {
5388
- const tokens = loginStore?.tokens();
5389
- const currentToken = tokens?.auth;
5390
- if (!currentToken) {
5391
- socketStore.disconnect();
5392
- lastToken = undefined;
5393
- return;
5394
- }
5395
- // If we already connected with this exact token, skip
5396
- if (lastToken === currentToken)
5397
- return;
5398
- // If another instance (e.g. host app) has already established a socket,
5399
- // and we are a new instance (e.g. WC) that hasn't connected yet, skip.
5400
- if (SharedStoreRegistry.isHostSocketActive() &&
5401
- lastToken === undefined) {
5402
- return;
5403
- }
5404
- // Connect (or reconnect if lastToken was different)
5405
- socketStore.connect(`${socketUrl}?token=${currentToken}`);
5406
- SharedStoreRegistry.setSocketUrl(socketUrl);
5407
- lastToken = currentToken;
5664
+ const baseId = state.activePanel();
5665
+ const base = baseId ? state.panelTriggerMap()[baseId] : undefined;
5666
+ if (!baseId || !base || (base.side ?? 'right') !== side) {
5667
+ return undefined;
5668
+ }
5669
+ const viewportWidth = typeof window === 'undefined' ? 0 : window.innerWidth;
5670
+ return hasRoomToDock(base.width, width, viewportWidth)
5671
+ ? baseId
5672
+ : undefined;
5673
+ };
5674
+ const openPanel = (panelTrigger) => {
5675
+ const id = panelTrigger.id ?? getUniqueId();
5676
+ const side = panelTrigger.side ?? 'right';
5677
+ // Authored free text, made a CSS length: a unitless `400` is dropped by
5678
+ // the browser and the panel opens at the width of its own content.
5679
+ const width = panelCssLength(panelTrigger.width) ?? DEFAULT_PANEL_WIDTH;
5680
+ const height = panelCssLength(panelTrigger.height);
5681
+ const isMobile = deviceService.isMobile();
5682
+ if (panelTrigger.dock) {
5683
+ const activeId = state.activePanel();
5684
+ // Max two panels: a further dock request replaces the current DockedPanel,
5685
+ // which restores the panel underneath to the edge before we displace it again.
5686
+ if (activeId && state.panelTriggerMap()[activeId]?.dockedOver) {
5687
+ closePanel(activeId);
5688
+ }
5689
+ }
5690
+ const dockedOver = panelTrigger.dock
5691
+ ? resolveDockTarget(side, width)
5692
+ : undefined;
5693
+ const styles = isMobile
5694
+ ? {
5695
+ position: 'fixed',
5696
+ bottom: '0',
5697
+ left: '0',
5698
+ width: '100%',
5699
+ height: '90%',
5700
+ zIndex: '1000',
5701
+ }
5702
+ : {
5703
+ position: 'fixed',
5704
+ top: '0',
5705
+ bottom: '0',
5706
+ [side]: '0',
5707
+ width,
5708
+ zIndex: '1000',
5709
+ transition: `${side} ${DOCK_TRANSITION}`,
5710
+ };
5711
+ const panelComponentRef = domService.create({
5712
+ component: panelComp,
5713
+ className: `${state.panelClassName()} panel--${side}`,
5714
+ id,
5715
+ parentClassName: state.panelParentClassName(),
5716
+ styles,
5717
+ bindings: [
5718
+ inputBinding('component', () => panelTrigger.component),
5719
+ inputBinding('bindings', () => panelTrigger.bindings),
5720
+ inputBinding('providers', () => panelTrigger.providers),
5721
+ inputBinding('side', () => side),
5722
+ inputBinding('instanceId', () => id),
5723
+ inputBinding('docked', () => !!state.panelTriggerMap()[id]?.dockedOver),
5724
+ inputBinding('height', () => height),
5725
+ inputBinding('closeProhibited', () => !!panelTrigger.closeProhibited),
5726
+ ],
5727
+ });
5728
+ if (dockedOver) {
5729
+ domService.updateStyleById({
5730
+ id: dockedOver,
5731
+ parentClassName: state.panelParentClassName(),
5732
+ styles: { [side]: width },
5408
5733
  });
5409
5734
  }
5410
- if (!loginStore)
5411
- return EMPTY;
5412
- // Load saved login IDs before init so the modal shows them if it opens
5413
- if (!loginStore.tokens()) {
5414
- loginStore.loadSavedLoginIds();
5735
+ patchState(state, {
5736
+ panelTriggerMap: {
5737
+ ...state.panelTriggerMap(),
5738
+ [id]: {
5739
+ ...panelTrigger,
5740
+ side,
5741
+ width,
5742
+ dockedOver,
5743
+ ref: panelComponentRef,
5744
+ },
5745
+ },
5746
+ activePanel: id,
5747
+ });
5748
+ return id;
5749
+ };
5750
+ const closePanel = (id) => {
5751
+ const panelId = id ?? state.activePanel();
5752
+ const panelTriggerMap = state.panelTriggerMap();
5753
+ if (!panelId) {
5754
+ return;
5415
5755
  }
5416
- // Always call init — interceptor handles no-token case via authenticate()
5417
- return httpService
5418
- .put('auth', ['init'])
5419
- .pipe(tap(({ navs, tokens, user }) => {
5420
- loginStore.initApp({ navs, tokens, user });
5421
- }), catchError(() => {
5422
- loginStore.loadSavedLoginIds();
5423
- return EMPTY;
5424
- }));
5756
+ // A panel that has already gone — `close`'s reason, and here it would
5757
+ // also promote a DockedPanel a second time.
5758
+ if (id && !panelTriggerMap[id]) {
5759
+ return;
5760
+ }
5761
+ const closing = panelTriggerMap[panelId];
5762
+ domService.destroy({
5763
+ componentRef: closing?.ref,
5764
+ parentClassName: state.panelParentClassName(),
5765
+ id: panelId,
5766
+ });
5767
+ delete panelTriggerMap[panelId];
5768
+ // Closing a DockedPanel returns the panel it displaced to the edge.
5769
+ if (closing?.dockedOver && panelTriggerMap[closing.dockedOver]) {
5770
+ domService.updateStyleById({
5771
+ id: closing.dockedOver,
5772
+ parentClassName: state.panelParentClassName(),
5773
+ styles: { [closing.side ?? 'right']: '0' },
5774
+ });
5775
+ }
5776
+ // Closing a displaced panel promotes its DockedPanel: already at the edge,
5777
+ // so nothing moves — its seam just goes dashed -> solid.
5778
+ const promotedId = Object.keys(panelTriggerMap).find((key) => panelTriggerMap[key]?.dockedOver === panelId);
5779
+ if (promotedId) {
5780
+ panelTriggerMap[promotedId] = {
5781
+ ...panelTriggerMap[promotedId],
5782
+ dockedOver: undefined,
5783
+ };
5784
+ }
5785
+ const remaining = Object.keys(panelTriggerMap);
5786
+ patchState(state, {
5787
+ panelTriggerMap: { ...panelTriggerMap },
5788
+ activePanel: remaining.length
5789
+ ? remaining[remaining.length - 1]
5790
+ : undefined,
5791
+ });
5425
5792
  };
5426
- }
5793
+ const cleanupOnClose = rxMethod(pipe(filter((modalMap) => !Object.keys(modalMap).length), tap(() => {
5794
+ domService.cleanup(state.parentClassName());
5795
+ })));
5796
+ const cleanupPanelsOnClose = rxMethod(pipe(filter((panelMap) => !Object.keys(panelMap).length), tap(() => {
5797
+ domService.cleanup(state.panelParentClassName());
5798
+ })));
5799
+ /**
5800
+ * The question as a value: subscribing asks it, and the single emission is
5801
+ * the answer — `true` for the commit, `false` for a refusal and for a
5802
+ * dismissal, which is a refusal by another route. Completes with that
5803
+ * emission, so a `switchMap` over it moves on rather than holding the
5804
+ * modal's answer open.
5805
+ *
5806
+ * Unsubscribing before it answers takes the modal away with it: the caller
5807
+ * that asked is gone, and a dialog nothing is waiting on is a dialog whose
5808
+ * answer lands nowhere.
5809
+ */
5810
+ const ask = (opts) => new Observable((subscriber) => {
5811
+ const modalRef = new ModalRef();
5812
+ let settled = false;
5813
+ let id = '';
5814
+ const settle = (result, dismiss) => {
5815
+ if (settled)
5816
+ return;
5817
+ settled = true;
5818
+ watch.unsubscribe();
5819
+ if (dismiss)
5820
+ close(id);
5821
+ subscriber.next(result);
5822
+ subscriber.complete();
5823
+ };
5824
+ const watch = closed
5825
+ .pipe(filter((closedId) => closedId === id))
5826
+ .subscribe(() => settle(false, false));
5827
+ id = open({
5828
+ component: confirmComp,
5829
+ providers: [{ provide: MODAL_REF, useValue: modalRef }],
5830
+ bindings: [
5831
+ inputBinding('header', () => opts.header ?? ''),
5832
+ inputBinding('body', () => opts.body ?? ''),
5833
+ inputBinding('params', () => opts.params ?? {}),
5834
+ inputBinding('type', () => opts.type ?? 'info'),
5835
+ inputBinding('kind', () => opts.kind ?? 'yes'),
5836
+ inputBinding('confirmLabel', () => opts.confirmLabel ?? ''),
5837
+ inputBinding('cancelLabel', () => opts.cancelLabel ?? ''),
5838
+ ],
5839
+ });
5840
+ modalRef.onClose((result) => settle(!!result, true));
5841
+ return () => {
5842
+ if (settled)
5843
+ return;
5844
+ settled = true;
5845
+ watch.unsubscribe();
5846
+ close(id);
5847
+ };
5848
+ });
5849
+ /**
5850
+ * Opens one Screen as an overlay and hands it its inputs — what a
5851
+ * generated FeatureStore calls where a Control's `mModal` would be the
5852
+ * drawn answer (m-one-ui OpenScreen).
5853
+ *
5854
+ * The same body the two directives build, reached the same way: the widget
5855
+ * is loaded on first open, so nothing it names is in the initial bundle.
5856
+ * Returns the overlay's own id and waits for nothing — the caller is a
5857
+ * `tap` inside a request pipe, and a store that held its emission open
5858
+ * until a panel closed would be answering for a gesture nobody made.
5859
+ */
5860
+ const openScreen = (trigger) => {
5861
+ const bindings = [
5862
+ inputBinding('widget', () => trigger.widget),
5863
+ inputBinding('inputs', () => trigger.inputs ?? {}),
5864
+ // The body binds these onto the Screen it creates (ADR 0033). A
5865
+ // Screen the opener listens to nothing of hands an empty record,
5866
+ // which binds nothing at all.
5867
+ inputBinding('outputs', () => trigger.outputs ?? {}),
5868
+ ];
5869
+ // Its own ModalRef, the way each directive mints one: the body closes
5870
+ // itself through this. Nothing here listens for the *result* — a store
5871
+ // has nowhere to put a panel's answer — but the close dismisses, which is
5872
+ // the whole of what a body opened this way can ask for (ADR 0031).
5873
+ const modalRef = new ModalRef();
5874
+ // What the body answered reaches the caller either way (ADR 0031): a
5875
+ // `change` reports and the overlay stays, a `close` reports and then it
5876
+ // goes. The order on a close is deliberate — a handler that reads the
5877
+ // Screen it opened must run while that Screen is still there.
5878
+ modalRef.onChange((result) => trigger.onResult?.(result));
5879
+ const providers = [{ provide: MODAL_REF, useValue: modalRef }];
5880
+ if (trigger.as === 'side_panel') {
5881
+ const panelId = openPanel({
5882
+ component: overlayBodyComp,
5883
+ bindings,
5884
+ providers,
5885
+ side: trigger.side,
5886
+ width: trigger.width,
5887
+ height: trigger.height,
5888
+ dock: trigger.dock,
5889
+ closeProhibited: trigger.closeProhibited,
5890
+ });
5891
+ modalRef.onClose((result) => {
5892
+ trigger.onResult?.(result);
5893
+ closePanel(panelId);
5894
+ });
5895
+ return panelId;
5896
+ }
5897
+ const modalId = open({
5898
+ component: overlayBodyComp,
5899
+ bindings,
5900
+ providers,
5901
+ config: trigger.config,
5902
+ });
5903
+ modalRef.onClose((result) => {
5904
+ trigger.onResult?.(result);
5905
+ close(modalId);
5906
+ });
5907
+ return modalId;
5908
+ };
5909
+ /**
5910
+ * Closes the overlay with this id, whichever kind it is — what a caller
5911
+ * holding only what `openScreen` returned can say (ADR 0031). Nothing for
5912
+ * an id nothing answers to, which is what a body that already closed itself
5913
+ * leaves behind.
5914
+ */
5915
+ const dismiss = (id) => {
5916
+ if (state.modalTriggerMap()[id]) {
5917
+ close(id);
5918
+ return;
5919
+ }
5920
+ if (state.panelTriggerMap()[id])
5921
+ closePanel(id);
5922
+ };
5923
+ // The callback form, kept for every caller drawn against it. One
5924
+ // implementation underneath: a refusal runs nothing, which is what an
5925
+ // `onConfirm` that never fires already meant.
5926
+ const confirm = (opts, onConfirm) => {
5927
+ ask(opts).subscribe((result) => {
5928
+ if (result)
5929
+ onConfirm();
5930
+ });
5931
+ };
5932
+ return {
5933
+ open,
5934
+ close,
5935
+ dismiss,
5936
+ ask,
5937
+ confirm,
5938
+ openScreen,
5939
+ openPanel,
5940
+ closePanel,
5941
+ cleanupOnClose,
5942
+ cleanupPanelsOnClose,
5943
+ };
5944
+ }), withHooks({
5945
+ onInit({ cleanupOnClose, modalTriggerMap, cleanupPanelsOnClose, panelTriggerMap, }) {
5946
+ cleanupOnClose(modalTriggerMap);
5947
+ cleanupPanelsOnClose(panelTriggerMap);
5948
+ },
5949
+ }));
5427
5950
 
5428
5951
  const MAGMONIUM = `
5429
5952
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="-15 -15 120 165">
@@ -6969,124 +7492,810 @@ class ButtonComponent extends ReactiveElementComponent {
6969
7492
  if (isPrimary && color === 'inverseText') {
6970
7493
  return resolvePallet('mm', this.themeStore.color()).color;
6971
7494
  }
6972
- const pallet = resolvePallet(color, this.themeStore.color());
6973
- return isPrimary ? pallet.contrastColor : pallet.color;
6974
- }, ...(ngDevMode ? [{ debugName: "buttonColor" }] : /* istanbul ignore next */ []));
6975
- constructor() {
6976
- super();
6977
- effect(() => {
6978
- const isPrimary = this.isPrimary();
6979
- const colorInput = this.colorInput();
6980
- const el = this.elementRef.nativeElement;
6981
- if (isPrimary && colorInput === 'inverseText') {
6982
- el.style.setProperty('--m-button-color-contrast', this.buttonColor());
6983
- el.style.setProperty('--m-one-button-color-contrast', this.buttonColor());
6984
- }
6985
- });
7495
+ const pallet = resolvePallet(color, this.themeStore.color());
7496
+ return isPrimary ? pallet.contrastColor : pallet.color;
7497
+ }, ...(ngDevMode ? [{ debugName: "buttonColor" }] : /* istanbul ignore next */ []));
7498
+ constructor() {
7499
+ super();
7500
+ effect(() => {
7501
+ const isPrimary = this.isPrimary();
7502
+ const colorInput = this.colorInput();
7503
+ const el = this.elementRef.nativeElement;
7504
+ if (isPrimary && colorInput === 'inverseText') {
7505
+ el.style.setProperty('--m-button-color-contrast', this.buttonColor());
7506
+ el.style.setProperty('--m-one-button-color-contrast', this.buttonColor());
7507
+ }
7508
+ });
7509
+ }
7510
+ buttonIcon = computed(() => {
7511
+ const name = this.config()?.icon;
7512
+ if (!name) {
7513
+ return undefined;
7514
+ }
7515
+ return {
7516
+ name: this.config()?.icon,
7517
+ color: this.buttonColor(),
7518
+ baseUrl: this.baseUrl(),
7519
+ remote: this.remote() ?? this.config()?.remote,
7520
+ };
7521
+ }, ...(ngDevMode ? [{ debugName: "buttonIcon" }] : /* istanbul ignore next */ []));
7522
+ overrideProperty = computed(() => {
7523
+ const button = {};
7524
+ // The rest of what a `buttons/<name>.yml` carries, so a one-off Button
7525
+ // needs no file (ADR 0010). An omitted attribute is skipped rather than
7526
+ // written as undefined — writing it would blank whatever the asset set.
7527
+ const put = (key, value) => {
7528
+ if (value !== undefined)
7529
+ button[key] = value;
7530
+ };
7531
+ put('label', this.label());
7532
+ put('icon', this.icon());
7533
+ put('imgSrc', this.imgSrc());
7534
+ put('tabindex', toAttrNumber(this.tabindex()));
7535
+ put('noTranslate', toAttrBool(this.noTranslate()));
7536
+ put('params', this.params());
7537
+ put('isRightIcon', toAttrBool(this.isRightIcon()));
7538
+ put('iconOnly', toAttrBool(this.iconOnly()));
7539
+ put('stacked', toAttrBool(this.stacked()));
7540
+ put('nonClickable', toAttrBool(this.nonClickable()));
7541
+ put('inverted', toAttrBool(this.inverted()));
7542
+ put('isSubmit', toAttrBool(this.isSubmit()));
7543
+ if (this.color()) {
7544
+ button['color'] = this.color();
7545
+ }
7546
+ if (this.labelClass()) {
7547
+ button['labelClass'] = this.labelClass();
7548
+ }
7549
+ if (typeof this.fullWidth() !== 'undefined') {
7550
+ button['fullWidth'] = toAttrBool(this.fullWidth());
7551
+ }
7552
+ if (this.nav()) {
7553
+ button['nav'] = this.nav();
7554
+ }
7555
+ if (this.navParams()) {
7556
+ button['navParams'] = this.navParams();
7557
+ }
7558
+ if (this.href()) {
7559
+ button['href'] = this.href();
7560
+ }
7561
+ if (typeof this.disabled() !== 'undefined') {
7562
+ button['disabled'] = this.disabled();
7563
+ }
7564
+ if (this.variant()) {
7565
+ button['variant'] = this.variant();
7566
+ }
7567
+ // Force primary and clear ghost if the color is 'inverse' or 'inverseText', unless explicitly ghost or secondary
7568
+ const finalColor = button.color || this.config()?.color;
7569
+ const isExplicitGhost = button.variant === 'ghost' || this.config()?.variant === 'ghost';
7570
+ const isExplicitSecondary = button.variant === 'secondary' ||
7571
+ this.config()?.variant === 'secondary';
7572
+ if ((finalColor === 'inverse' || finalColor === 'inverseText') &&
7573
+ !isExplicitGhost &&
7574
+ !isExplicitSecondary) {
7575
+ button['color'] = 'inverseText';
7576
+ button['variant'] = 'primary';
7577
+ }
7578
+ else if (finalColor === 'inverse') {
7579
+ button['color'] = 'inverseText';
7580
+ }
7581
+ if (this.config()?.nav || this.nav()) {
7582
+ button['variant'] = this.isMurlActive() ? undefined : 'ghost';
7583
+ }
7584
+ return button;
7585
+ }, ...(ngDevMode ? [{ debugName: "overrideProperty" }] : /* istanbul ignore next */ []));
7586
+ resolveComponentOverrides() {
7587
+ return this.overrideProperty();
7588
+ }
7589
+ onClick() {
7590
+ if (this.isFormSubmit()) {
7591
+ // Called rather than left to a native `type="submit"`: the `<form>` is
7592
+ // only an ancestor while nothing re-projects this Button out of it.
7593
+ this.sectionForm?.submit();
7594
+ }
7595
+ this.clicked.emit(this.config());
7596
+ }
7597
+ formatBadgeCount = (count, max = 99) => formatBadgeCount(count, max);
7598
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7599
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: ButtonComponent, isStandalone: true, selector: "m-button,m-one-button", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, labelClass: { classPropertyName: "labelClass", publicName: "labelClass", isSignal: true, isRequired: false, transformFunction: null }, fullWidth: { classPropertyName: "fullWidth", publicName: "fullWidth", isSignal: true, isRequired: false, transformFunction: null }, nav: { classPropertyName: "nav", publicName: "nav", isSignal: true, isRequired: false, transformFunction: null }, navParams: { classPropertyName: "navParams", publicName: "navParams", isSignal: true, isRequired: false, transformFunction: null }, href: { classPropertyName: "href", publicName: "href", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, baseUrl: { classPropertyName: "baseUrl", publicName: "baseUrl", isSignal: true, isRequired: false, transformFunction: null }, one: { classPropertyName: "one", publicName: "one", isSignal: true, isRequired: false, transformFunction: null }, remote: { classPropertyName: "remote", publicName: "remote", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, noTranslate: { classPropertyName: "noTranslate", publicName: "noTranslate", isSignal: true, isRequired: false, transformFunction: null }, params: { classPropertyName: "params", publicName: "params", isSignal: true, isRequired: false, transformFunction: null }, noNative: { classPropertyName: "noNative", publicName: "noNative", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, isRightIcon: { classPropertyName: "isRightIcon", publicName: "isRightIcon", isSignal: true, isRequired: false, transformFunction: null }, iconOnly: { classPropertyName: "iconOnly", publicName: "iconOnly", isSignal: true, isRequired: false, transformFunction: null }, stacked: { classPropertyName: "stacked", publicName: "stacked", isSignal: true, isRequired: false, transformFunction: null }, imgSrc: { classPropertyName: "imgSrc", publicName: "imgSrc", isSignal: true, isRequired: false, transformFunction: null }, nonClickable: { classPropertyName: "nonClickable", publicName: "nonClickable", isSignal: true, isRequired: false, transformFunction: null }, inverted: { classPropertyName: "inverted", publicName: "inverted", isSignal: true, isRequired: false, transformFunction: null }, isSubmit: { classPropertyName: "isSubmit", publicName: "isSubmit", isSignal: true, isRequired: false, transformFunction: null }, tabindex: { classPropertyName: "tabindex", publicName: "tabindex", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { config: "configChange", clicked: "clicked" }, viewQueries: [{ propertyName: "button", first: true, predicate: ["button"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@if (config(); as config) {\n <!-- One branch for every in-app target: `mRef` names a NavId and the store\n reads the NavKind off that node to decide route vs panel (ADR 0014). -->\n @if (config.nav) {\n @if (!noNative()) {\n <button\n type=\"button\"\n class=\"{{ className() }}\"\n [attr.data-testid]=\"config.name + '-btn'\"\n [attr.tabindex]=\"config.tabindex\"\n [disabled]=\"config.disabled\"\n [mRef]=\"config.nav\"\n [mRefParams]=\"config.navParams\"\n [attr.aria-label]=\"config.noTranslate ? config.label : (config.label | translate: config.params)\"\n mRefLinkActive=\"tab\"\n (keydown.enter)=\"onClick()\"\n (click)=\"onClick()\"\n #button\n >\n <ng-container *ngTemplateOutlet=\"buttonContent; context: { button: config }\"></ng-container>\n </button>\n } @else {\n <div\n role=\"button\"\n [attr.tabindex]=\"config.tabindex ?? 0\"\n class=\"non-native {{ className() }}\"\n [attr.data-testid]=\"config.name + '-btn'\"\n [attr.aria-label]=\"config.noTranslate ? config.label : (config.label | translate: config.params)\"\n [attr.aria-disabled]=\"config.disabled ? 'true' : 'false'\"\n (keydown.enter)=\"onClick()\"\n (click)=\"onClick()\"\n #button\n >\n <ng-container *ngTemplateOutlet=\"buttonContent; context: { button: config }\"></ng-container>\n </div>\n }\n } @else if (config.href) {\n <a\n class=\"{{ className() }}\"\n [attr.data-testid]=\"config.name + '-btn'\"\n [attr.tabindex]=\"config.tabindex\"\n [href]=\"config.href\"\n [attr.aria-label]=\"config.noTranslate ? config.label : (config.label | translate: config.params)\"\n (click)=\"onClick()\"\n #button\n >\n <ng-container *ngTemplateOutlet=\"buttonContent; context: { button: config }\"></ng-container>\n </a>\n } @else {\n @if (!noNative()) {\n <button\n type=\"button\"\n class=\"{{ className() }}\"\n [attr.data-testid]=\"config.name + '-btn'\"\n [attr.tabindex]=\"config.tabindex\"\n [disabled]=\"isDisabled()\"\n [attr.aria-label]=\"config.noTranslate ? config.label : (config.label | translate: config.params)\"\n (keydown.enter)=\"onClick()\"\n (click)=\"onClick()\"\n #button\n >\n <ng-container *ngTemplateOutlet=\"buttonContent; context: { button: config }\"></ng-container>\n </button>\n } @else {\n <div\n role=\"button\"\n [attr.tabindex]=\"config.tabindex ?? 0\"\n class=\"non-native {{ className() }}\"\n [attr.data-testid]=\"config.name + '-btn'\"\n [attr.aria-label]=\"config.noTranslate ? config.label : (config.label | translate: config.params)\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : 'false'\"\n (keydown.enter)=\"onClick()\"\n (click)=\"onClick()\"\n #button\n >\n <ng-container *ngTemplateOutlet=\"buttonContent; context: { button: config }\"></ng-container>\n </div>\n }\n }\n}\n\n<ng-template #buttonContent let-button=\"button\">\n @if (button.imgSrc) {\n <div class=\"button-icon button-icon--img\">\n <m-img [src]=\"button.imgSrc\" [remote]=\"button.remote\" [alt]=\"button.label || button.name || ''\" />\n @if (button.badge && button.badge.count) {\n <m-badge\n [config]=\"{ variant: button.badge.variant ?? 'danger', position: 'absolute' }\"\n >{{ formatBadgeCount(button.badge.count) }}</m-badge\n >\n }\n </div>\n } @else if (buttonIcon(); as icon) {\n <div class=\"button-icon\">\n @if (isFromOne()) {\n <m-one-icon [config]=\"icon\" />\n } @else {\n <m-icon [config]=\"icon\" />\n }\n @if (button.badge && button.badge.count) {\n <m-badge\n [config]=\"{ variant: button.badge.variant ?? 'danger', position: 'absolute' }\"\n >{{ formatBadgeCount(button.badge.count) }}</m-badge\n >\n }\n </div>\n }\n @if (button.label && !button.iconOnly) {\n <span class=\"button-label {{ button.labelClass || '' }}\">\n {{ button.noTranslate ? button.label : (button.label | translate: button.params) }}\n </span>\n }\n @if (!buttonIcon() && button.badge && button.badge.count) {\n <m-badge [config]=\"{ variant: button.badge.variant ?? 'danger', position: 'static' }\">{{\n formatBadgeCount(button.badge.count)\n }}</m-badge>\n }\n</ng-template>\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)}}:host{display:inline-flex;align-items:center;justify-content:center;vertical-align:middle;box-sizing:border-box;overflow:hidden;transition:box-shadow .15s ease;--m-btn-size: var(--m-button-size, 1em);--m-btn-color: var(--m-button-color, var(--m-one-button-color, var(--m-mm)));--m-btn-color-contrast: var(--m-button-color-contrast, var(--m-one-button-color-contrast, #ffffff));--m-btn-color-opposite: var(--m-button-color-opposite, var(--m-one-button-color-opposite, #e1b941));--m-btn-h: calc(var(--m-btn-size) * 2.25);width:var(--m-button-width, var(--m-one-button-width, auto));min-width:0;height:var(--m-btn-h);font-size:var(--m-btn-size)}:host-context(.inverse),:host-context(.tabs-inverse),:host.inverse{--m-btn-color: var(--m-button-color, var(--m-one-button-color, var(--m-inverse-text)))}:host:has(.full-width){display:flex;width:100%}:host:has(.full-width) button .button-label{white-space:normal;overflow:visible;text-overflow:clip;word-break:break-word}:host:has(.only-icon),:host:has(.toggle){width:var(--m-btn-h);min-width:var(--m-btn-h)}:host:has(.has-badge){overflow:visible}:host:has(.stacked),:host:has(.toggle){height:auto}button:not(.get):not(.toggle){height:calc(var(--input-size, var(--m-btn-size)) * 2);min-height:calc(var(--input-size, var(--m-btn-size)) * 2);border-width:max(1px,var(--input-size, var(--m-btn-size)) * .0625);border-radius:calc(var(--input-size, var(--m-btn-size)) * .4);padding:calc(var(--input-size, var(--m-btn-size)) * .5) calc(var(--input-size, var(--m-btn-size)) * .5);gap:calc(var(--input-size, var(--m-btn-size)) * .375);font-size:var(--input-size, var(--m-btn-size));border-color:var(--m-btn-color);transition:border-color .2s ease,box-shadow .2s ease,background-color .2s ease,opacity .2s ease}button:not(.get):not(.toggle):hover:not(:disabled){background-color:color-mix(in srgb,var(--m-btn-color) 6%,transparent)}button:not(.get):not(.toggle):disabled{opacity:.6;cursor:not-allowed}button:not(.get):not(.toggle){height:auto;padding:calc(var(--m-btn-size) * .625) calc(var(--m-btn-size) * 1.25);gap:calc(var(--m-btn-size) * .375);border-style:solid;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;font-family:inherit;cursor:pointer;appearance:none;width:100%;height:100%;min-height:0;padding:0 calc(var(--m-btn-size) * 1.25);border-width:var(--m-button-border-width, 1px);border-radius:var(--m-button-radius, calc(var(--m-btn-size) * .5));color:var(--m-btn-color);font-weight:300;line-height:1;-webkit-user-select:none;user-select:none;position:relative;outline:none;box-shadow:var(--m-button-shadow, var(--m-one-button-shadow, none));transition:filter .15s ease,background .15s ease}button:not(.get):not(.toggle):hover:not(:disabled){filter:brightness(1.04)}button:not(.get):not(.toggle):focus-visible:not(:disabled){outline:2px solid color-mix(in srgb,var(--m-focus) 45%,transparent);outline-offset:-2px}button:not(.get):not(.toggle):active:not(:disabled){transform:scale(.97)}button:not(.get):not(.toggle):disabled{opacity:.35;cursor:not-allowed;pointer-events:none;filter:grayscale(80%)}button:not(.get):not(.toggle).read-only{pointer-events:none!important;cursor:default!important;transform:none!important;box-shadow:none!important;background:transparent!important;border-color:transparent!important;opacity:1!important}button:not(.get):not(.toggle).read-only .button-icon{transform:none!important;color:inherit!important}button:not(.get):not(.toggle).primary{background:var(--m-btn-color);border-color:var(--m-btn-color);color:var(--m-btn-color-contrast)}button:not(.get):not(.toggle).primary:hover:not(:disabled){filter:none;background:color-mix(in srgb,var(--m-btn-color) 88%,black);border-color:color-mix(in srgb,var(--m-btn-color) 88%,black)}button:not(.get):not(.toggle).primary:active:not(:disabled){filter:brightness(.94);transform:scale(.97)}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab){background:transparent;border-color:transparent;color:var(--m-btn-color);box-shadow:none}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab):hover:not(:disabled){filter:none;background:color-mix(in srgb,var(--m-btn-color) 8%,transparent)}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab):active:not(:disabled){background:color-mix(in srgb,var(--m-btn-color) 14%,transparent);transform:scale(.97)}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab).secondary{border:var(--m-button-border-width, 1px) solid color-mix(in srgb,var(--m-btn-color) 15%,transparent)}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab).secondary:hover:not(:disabled){filter:none;border-color:color-mix(in srgb,var(--m-btn-color) 40%,transparent);background:color-mix(in srgb,var(--m-btn-color) 6%,transparent)}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab).secondary:active:not(:disabled){border-color:color-mix(in srgb,var(--m-btn-color) 50%,transparent);background:color-mix(in srgb,var(--m-btn-color) 12%,transparent)}button:not(.get):not(.toggle).secondary:not(.primary):not(.ghost){background:transparent;border-color:var(--m-btn-color);color:var(--m-btn-color)}button:not(.get):not(.toggle).secondary:not(.primary):not(.ghost):hover:not(:disabled){filter:none;background:color-mix(in srgb,var(--m-btn-color) 8%,transparent)}button:not(.get):not(.toggle).secondary:not(.primary):not(.ghost):active:not(:disabled){background:color-mix(in srgb,var(--m-btn-color) 14%,transparent);transform:scale(.97)}button:not(.get):not(.toggle).tab{background:var(--m-backdrop-border);border-color:var(--m-backdrop-border);color:var(--m-btn-color)}button:not(.get):not(.toggle).tab:hover:not(:disabled){background:color-mix(in srgb,var(--m-backdrop-border) 82%,black);border-color:color-mix(in srgb,var(--m-backdrop-border) 82%,black);filter:none}button:not(.get):not(.toggle).tab:active:not(:disabled){background:color-mix(in srgb,var(--m-backdrop-border) 70%,black);border-color:color-mix(in srgb,var(--m-backdrop-border) 70%,black);transform:scale(.97)}button:not(.get):not(.toggle).segmented .button-icon,button:not(.get):not(.toggle).badge-accent .button-icon,button:not(.get):not(.toggle).with-right-icon .button-icon{display:inline-flex;align-items:center;justify-content:center;color:var(--m-btn-color-opposite);order:1}button:not(.get):not(.toggle).segmented .button-label,button:not(.get):not(.toggle).badge-accent .button-label,button:not(.get):not(.toggle).with-right-icon .button-label{order:-1}button:not(.get):not(.toggle).segmented.primary .button-icon,button:not(.get):not(.toggle).badge-accent.primary .button-icon,button:not(.get):not(.toggle).with-right-icon.primary .button-icon{color:var(--m-btn-color-opposite)}button:not(.get):not(.toggle).with-left-icon .button-icon{order:-1}button:not(.get):not(.toggle).with-left-icon .button-label{order:1}button:not(.get):not(.toggle).stacked{flex-direction:column;gap:calc(var(--m-btn-size) * .3);height:auto;min-height:var(--m-btn-h);padding:calc(var(--m-btn-size) * .625) calc(var(--m-btn-size) * .875)}button:not(.get):not(.toggle).stacked .button-label{font-size:calc(var(--m-btn-size) * .8)}button:not(.get):not(.toggle).only-icon{padding:0;border-width:var(--m-button-border-width, 1px);aspect-ratio:1;display:inline-flex;align-items:center;justify-content:center}button:not(.get):not(.toggle).only-icon m-icon,button:not(.get):not(.toggle).only-icon m-one-icon{display:inline-flex}m-badge{--m-badge-height: 1.5em;--m-badge-min-width: 1.5em;--m-badge-padding: 0 .3em;--m-badge-gap: .1em}.button-label{display:inline-flex;align-items:center;line-height:normal;font-size:inherit;min-width:0;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.button-icon{position:relative;display:inline-flex;align-items:center;justify-content:center}.button-icon--img{width:calc(var(--m-btn-size) * 1.75);height:calc(var(--m-btn-size) * 1.75);overflow:hidden}.button-icon--img m-img{width:100%;height:100%;display:block}.get{appearance:none;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;height:var(--m-btn-h);padding:0 min(var(--m-btn-size) * 1.75,2rem);border-radius:4px;background:linear-gradient(135deg,var(--m-mm),var(--m-focus),var(--m-success),var(--m-mm));background-size:200% auto;color:#fff;font-size:calc(var(--m-btn-size) * .8);font-weight:300;letter-spacing:.06em;text-transform:uppercase;border:none;cursor:pointer;white-space:nowrap;line-height:1;transition:background-position .2s ease,transform .15s ease}.get:hover{background-position:right center}.get:focus-visible{outline:2px solid color-mix(in srgb,var(--m-focus) 45%,transparent);outline-offset:-2px}.get:active{transform:scale(.97)}.toggle{appearance:none;display:inline-flex;align-items:center;justify-content:center;width:100%;height:100%;border:none;background:transparent;padding:0 min(var(--m-btn-size),1.25rem);border-radius:var(--m-button-radius, calc(var(--m-btn-size) * .375));box-shadow:none;color:var(--m-btn-color, var(--m-text-secondary));opacity:.65;font-family:inherit;font-size:var(--m-btn-size);font-weight:300;cursor:pointer;box-sizing:border-box;-webkit-user-select:none;user-select:none;transition:background .15s ease,color .15s ease,opacity .15s ease;min-width:0}.toggle .button-icon{flex-shrink:0}.toggle .button-label{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%;min-width:0}.toggle:hover:not(:disabled){background:var(--m-button-hover-background, color-mix(in srgb, var(--m-focus) 8%, transparent));color:var(--m-button-hover-color, var(--m-text));opacity:1}.toggle:focus-visible:not(:disabled){outline:2px solid color-mix(in srgb,var(--m-focus) 45%,transparent);outline-offset:-2px;opacity:1}.toggle.primary{background:var(--m-button-active-background, var(--m-mm));color:var(--m-button-active-color, #ffffff);opacity:1}.toggle.primary:hover:not(:disabled){background:var(--m-button-active-background, var(--m-mm));color:var(--m-button-active-color, #ffffff);opacity:1}.toggle.primary:active:not(:disabled){transform:scale(.97)}.non-native:not(.get):not(.toggle){appearance:none;display:inline-flex;align-items:center;justify-content:center;width:100%;height:100%;min-height:0;padding:0 calc(var(--m-btn-size) * 1.25);border-width:2px;border-radius:4px;color:var(--m-btn-color);font-weight:300;line-height:1;-webkit-user-select:none;user-select:none;position:relative;outline:none;box-shadow:var(--m-button-shadow, var(--m-one-button-shadow, none));transition:filter .15s ease,background .15s ease}.non-native:not(.get):not(.toggle):hover:not([aria-disabled=true]){filter:brightness(1.04)}.non-native:not(.get):not(.toggle):focus-visible:not([aria-disabled=true]){outline:2px solid color-mix(in srgb,var(--m-focus) 45%,transparent);outline-offset:-2px}.non-native:not(.get):not(.toggle):active:not([aria-disabled=true]){transform:scale(.97)}.non-native:not(.get):not(.toggle)[aria-disabled=true]{opacity:.35;cursor:not-allowed;pointer-events:none;filter:grayscale(80%)}.non-native:not(.get):not(.toggle).primary{background:var(--m-btn-color);border-color:var(--m-btn-color);color:var(--m-btn-color-contrast)}.non-native:not(.get):not(.toggle).primary:hover:not([aria-disabled=true]){filter:none;background:color-mix(in srgb,var(--m-btn-color) 88%,black);border-color:color-mix(in srgb,var(--m-btn-color) 88%,black)}.non-native:not(.get):not(.toggle).primary:active:not([aria-disabled=true]){filter:brightness(.94);transform:scale(.97)}.non-native:not(.get):not(.toggle).ghost:not(.primary):not(.tab){background:transparent;border-color:transparent;color:var(--m-btn-color);box-shadow:none}.non-native:not(.get):not(.toggle).ghost:not(.primary):not(.tab):hover:not([aria-disabled=true]){filter:none;background:color-mix(in srgb,var(--m-btn-color) 8%,transparent)}.non-native:not(.get):not(.toggle).ghost:not(.primary):not(.tab):active:not([aria-disabled=true]){background:color-mix(in srgb,var(--m-btn-color) 14%,transparent);transform:scale(.97)}.non-native:not(.get):not(.toggle):disabled{opacity:.3;cursor:not-allowed}@container togglegroup (max-width: 320px){.non-native:not(.get):not(.toggle).with-left-icon .button-label,.non-native:not(.get):not(.toggle).with-right-icon .button-label{display:none!important}}@media(max-width:600px){.non-native:not(.get):not(.toggle).with-left-icon .button-label,.non-native:not(.get):not(.toggle).with-right-icon .button-label{display:none!important}}\n"], dependencies: [{ kind: "component", type: i0.forwardRef(() => IconComponent), selector: "m-icon, m-one-icon", inputs: ["config", "name", "color", "size", "one", "baseUrl", "remote"], outputs: ["configChange"] }, { kind: "component", type: i0.forwardRef(() => BadgeComponent), selector: "m-badge", inputs: ["config"], outputs: ["configChange"] }, { kind: "ngmodule", type: i0.forwardRef(() => RouterModule) }, { kind: "directive", type: i0.forwardRef(() => MRefDirective), selector: "[mRef]", inputs: ["mRef", "mRefLinkActive", "mRefToggle", "mRefParams"] }, { kind: "directive", type: i0.forwardRef(() => NgTemplateOutlet), selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i0.forwardRef(() => ImgComponent), selector: "m-img", inputs: ["src", "data", "dataType", "alt", "priority", "fill", "width", "height", "remote", "ngSrcset", "sizes"] }, { kind: "pipe", type: i0.forwardRef(() => TranslatePipe), name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
7600
+ }
7601
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ButtonComponent, decorators: [{
7602
+ type: Component,
7603
+ args: [{ selector: 'm-button,m-one-button', imports: [
7604
+ forwardRef(() => TranslatePipe),
7605
+ forwardRef(() => IconComponent),
7606
+ forwardRef(() => BadgeComponent),
7607
+ RouterModule,
7608
+ MRefDirective,
7609
+ forwardRef(() => NgTemplateOutlet),
7610
+ forwardRef(() => ImgComponent),
7611
+ ], encapsulation: ViewEncapsulation.Emulated, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (config(); as config) {\n <!-- One branch for every in-app target: `mRef` names a NavId and the store\n reads the NavKind off that node to decide route vs panel (ADR 0014). -->\n @if (config.nav) {\n @if (!noNative()) {\n <button\n type=\"button\"\n class=\"{{ className() }}\"\n [attr.data-testid]=\"config.name + '-btn'\"\n [attr.tabindex]=\"config.tabindex\"\n [disabled]=\"config.disabled\"\n [mRef]=\"config.nav\"\n [mRefParams]=\"config.navParams\"\n [attr.aria-label]=\"config.noTranslate ? config.label : (config.label | translate: config.params)\"\n mRefLinkActive=\"tab\"\n (keydown.enter)=\"onClick()\"\n (click)=\"onClick()\"\n #button\n >\n <ng-container *ngTemplateOutlet=\"buttonContent; context: { button: config }\"></ng-container>\n </button>\n } @else {\n <div\n role=\"button\"\n [attr.tabindex]=\"config.tabindex ?? 0\"\n class=\"non-native {{ className() }}\"\n [attr.data-testid]=\"config.name + '-btn'\"\n [attr.aria-label]=\"config.noTranslate ? config.label : (config.label | translate: config.params)\"\n [attr.aria-disabled]=\"config.disabled ? 'true' : 'false'\"\n (keydown.enter)=\"onClick()\"\n (click)=\"onClick()\"\n #button\n >\n <ng-container *ngTemplateOutlet=\"buttonContent; context: { button: config }\"></ng-container>\n </div>\n }\n } @else if (config.href) {\n <a\n class=\"{{ className() }}\"\n [attr.data-testid]=\"config.name + '-btn'\"\n [attr.tabindex]=\"config.tabindex\"\n [href]=\"config.href\"\n [attr.aria-label]=\"config.noTranslate ? config.label : (config.label | translate: config.params)\"\n (click)=\"onClick()\"\n #button\n >\n <ng-container *ngTemplateOutlet=\"buttonContent; context: { button: config }\"></ng-container>\n </a>\n } @else {\n @if (!noNative()) {\n <button\n type=\"button\"\n class=\"{{ className() }}\"\n [attr.data-testid]=\"config.name + '-btn'\"\n [attr.tabindex]=\"config.tabindex\"\n [disabled]=\"isDisabled()\"\n [attr.aria-label]=\"config.noTranslate ? config.label : (config.label | translate: config.params)\"\n (keydown.enter)=\"onClick()\"\n (click)=\"onClick()\"\n #button\n >\n <ng-container *ngTemplateOutlet=\"buttonContent; context: { button: config }\"></ng-container>\n </button>\n } @else {\n <div\n role=\"button\"\n [attr.tabindex]=\"config.tabindex ?? 0\"\n class=\"non-native {{ className() }}\"\n [attr.data-testid]=\"config.name + '-btn'\"\n [attr.aria-label]=\"config.noTranslate ? config.label : (config.label | translate: config.params)\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : 'false'\"\n (keydown.enter)=\"onClick()\"\n (click)=\"onClick()\"\n #button\n >\n <ng-container *ngTemplateOutlet=\"buttonContent; context: { button: config }\"></ng-container>\n </div>\n }\n }\n}\n\n<ng-template #buttonContent let-button=\"button\">\n @if (button.imgSrc) {\n <div class=\"button-icon button-icon--img\">\n <m-img [src]=\"button.imgSrc\" [remote]=\"button.remote\" [alt]=\"button.label || button.name || ''\" />\n @if (button.badge && button.badge.count) {\n <m-badge\n [config]=\"{ variant: button.badge.variant ?? 'danger', position: 'absolute' }\"\n >{{ formatBadgeCount(button.badge.count) }}</m-badge\n >\n }\n </div>\n } @else if (buttonIcon(); as icon) {\n <div class=\"button-icon\">\n @if (isFromOne()) {\n <m-one-icon [config]=\"icon\" />\n } @else {\n <m-icon [config]=\"icon\" />\n }\n @if (button.badge && button.badge.count) {\n <m-badge\n [config]=\"{ variant: button.badge.variant ?? 'danger', position: 'absolute' }\"\n >{{ formatBadgeCount(button.badge.count) }}</m-badge\n >\n }\n </div>\n }\n @if (button.label && !button.iconOnly) {\n <span class=\"button-label {{ button.labelClass || '' }}\">\n {{ button.noTranslate ? button.label : (button.label | translate: button.params) }}\n </span>\n }\n @if (!buttonIcon() && button.badge && button.badge.count) {\n <m-badge [config]=\"{ variant: button.badge.variant ?? 'danger', position: 'static' }\">{{\n formatBadgeCount(button.badge.count)\n }}</m-badge>\n }\n</ng-template>\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)}}:host{display:inline-flex;align-items:center;justify-content:center;vertical-align:middle;box-sizing:border-box;overflow:hidden;transition:box-shadow .15s ease;--m-btn-size: var(--m-button-size, 1em);--m-btn-color: var(--m-button-color, var(--m-one-button-color, var(--m-mm)));--m-btn-color-contrast: var(--m-button-color-contrast, var(--m-one-button-color-contrast, #ffffff));--m-btn-color-opposite: var(--m-button-color-opposite, var(--m-one-button-color-opposite, #e1b941));--m-btn-h: calc(var(--m-btn-size) * 2.25);width:var(--m-button-width, var(--m-one-button-width, auto));min-width:0;height:var(--m-btn-h);font-size:var(--m-btn-size)}:host-context(.inverse),:host-context(.tabs-inverse),:host.inverse{--m-btn-color: var(--m-button-color, var(--m-one-button-color, var(--m-inverse-text)))}:host:has(.full-width){display:flex;width:100%}:host:has(.full-width) button .button-label{white-space:normal;overflow:visible;text-overflow:clip;word-break:break-word}:host:has(.only-icon),:host:has(.toggle){width:var(--m-btn-h);min-width:var(--m-btn-h)}:host:has(.has-badge){overflow:visible}:host:has(.stacked),:host:has(.toggle){height:auto}button:not(.get):not(.toggle){height:calc(var(--input-size, var(--m-btn-size)) * 2);min-height:calc(var(--input-size, var(--m-btn-size)) * 2);border-width:max(1px,var(--input-size, var(--m-btn-size)) * .0625);border-radius:calc(var(--input-size, var(--m-btn-size)) * .4);padding:calc(var(--input-size, var(--m-btn-size)) * .5) calc(var(--input-size, var(--m-btn-size)) * .5);gap:calc(var(--input-size, var(--m-btn-size)) * .375);font-size:var(--input-size, var(--m-btn-size));border-color:var(--m-btn-color);transition:border-color .2s ease,box-shadow .2s ease,background-color .2s ease,opacity .2s ease}button:not(.get):not(.toggle):hover:not(:disabled){background-color:color-mix(in srgb,var(--m-btn-color) 6%,transparent)}button:not(.get):not(.toggle):disabled{opacity:.6;cursor:not-allowed}button:not(.get):not(.toggle){height:auto;padding:calc(var(--m-btn-size) * .625) calc(var(--m-btn-size) * 1.25);gap:calc(var(--m-btn-size) * .375);border-style:solid;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;font-family:inherit;cursor:pointer;appearance:none;width:100%;height:100%;min-height:0;padding:0 calc(var(--m-btn-size) * 1.25);border-width:var(--m-button-border-width, 1px);border-radius:var(--m-button-radius, calc(var(--m-btn-size) * .5));color:var(--m-btn-color);font-weight:300;line-height:1;-webkit-user-select:none;user-select:none;position:relative;outline:none;box-shadow:var(--m-button-shadow, var(--m-one-button-shadow, none));transition:filter .15s ease,background .15s ease}button:not(.get):not(.toggle):hover:not(:disabled){filter:brightness(1.04)}button:not(.get):not(.toggle):focus-visible:not(:disabled){outline:2px solid color-mix(in srgb,var(--m-focus) 45%,transparent);outline-offset:-2px}button:not(.get):not(.toggle):active:not(:disabled){transform:scale(.97)}button:not(.get):not(.toggle):disabled{opacity:.35;cursor:not-allowed;pointer-events:none;filter:grayscale(80%)}button:not(.get):not(.toggle).read-only{pointer-events:none!important;cursor:default!important;transform:none!important;box-shadow:none!important;background:transparent!important;border-color:transparent!important;opacity:1!important}button:not(.get):not(.toggle).read-only .button-icon{transform:none!important;color:inherit!important}button:not(.get):not(.toggle).primary{background:var(--m-btn-color);border-color:var(--m-btn-color);color:var(--m-btn-color-contrast)}button:not(.get):not(.toggle).primary:hover:not(:disabled){filter:none;background:color-mix(in srgb,var(--m-btn-color) 88%,black);border-color:color-mix(in srgb,var(--m-btn-color) 88%,black)}button:not(.get):not(.toggle).primary:active:not(:disabled){filter:brightness(.94);transform:scale(.97)}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab){background:transparent;border-color:transparent;color:var(--m-btn-color);box-shadow:none}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab):hover:not(:disabled){filter:none;background:color-mix(in srgb,var(--m-btn-color) 8%,transparent)}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab):active:not(:disabled){background:color-mix(in srgb,var(--m-btn-color) 14%,transparent);transform:scale(.97)}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab).secondary{border:var(--m-button-border-width, 1px) solid color-mix(in srgb,var(--m-btn-color) 15%,transparent)}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab).secondary:hover:not(:disabled){filter:none;border-color:color-mix(in srgb,var(--m-btn-color) 40%,transparent);background:color-mix(in srgb,var(--m-btn-color) 6%,transparent)}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab).secondary:active:not(:disabled){border-color:color-mix(in srgb,var(--m-btn-color) 50%,transparent);background:color-mix(in srgb,var(--m-btn-color) 12%,transparent)}button:not(.get):not(.toggle).secondary:not(.primary):not(.ghost){background:transparent;border-color:var(--m-btn-color);color:var(--m-btn-color)}button:not(.get):not(.toggle).secondary:not(.primary):not(.ghost):hover:not(:disabled){filter:none;background:color-mix(in srgb,var(--m-btn-color) 8%,transparent)}button:not(.get):not(.toggle).secondary:not(.primary):not(.ghost):active:not(:disabled){background:color-mix(in srgb,var(--m-btn-color) 14%,transparent);transform:scale(.97)}button:not(.get):not(.toggle).tab{background:var(--m-backdrop-border);border-color:var(--m-backdrop-border);color:var(--m-btn-color)}button:not(.get):not(.toggle).tab:hover:not(:disabled){background:color-mix(in srgb,var(--m-backdrop-border) 82%,black);border-color:color-mix(in srgb,var(--m-backdrop-border) 82%,black);filter:none}button:not(.get):not(.toggle).tab:active:not(:disabled){background:color-mix(in srgb,var(--m-backdrop-border) 70%,black);border-color:color-mix(in srgb,var(--m-backdrop-border) 70%,black);transform:scale(.97)}button:not(.get):not(.toggle).segmented .button-icon,button:not(.get):not(.toggle).badge-accent .button-icon,button:not(.get):not(.toggle).with-right-icon .button-icon{display:inline-flex;align-items:center;justify-content:center;color:var(--m-btn-color-opposite);order:1}button:not(.get):not(.toggle).segmented .button-label,button:not(.get):not(.toggle).badge-accent .button-label,button:not(.get):not(.toggle).with-right-icon .button-label{order:-1}button:not(.get):not(.toggle).segmented.primary .button-icon,button:not(.get):not(.toggle).badge-accent.primary .button-icon,button:not(.get):not(.toggle).with-right-icon.primary .button-icon{color:var(--m-btn-color-opposite)}button:not(.get):not(.toggle).with-left-icon .button-icon{order:-1}button:not(.get):not(.toggle).with-left-icon .button-label{order:1}button:not(.get):not(.toggle).stacked{flex-direction:column;gap:calc(var(--m-btn-size) * .3);height:auto;min-height:var(--m-btn-h);padding:calc(var(--m-btn-size) * .625) calc(var(--m-btn-size) * .875)}button:not(.get):not(.toggle).stacked .button-label{font-size:calc(var(--m-btn-size) * .8)}button:not(.get):not(.toggle).only-icon{padding:0;border-width:var(--m-button-border-width, 1px);aspect-ratio:1;display:inline-flex;align-items:center;justify-content:center}button:not(.get):not(.toggle).only-icon m-icon,button:not(.get):not(.toggle).only-icon m-one-icon{display:inline-flex}m-badge{--m-badge-height: 1.5em;--m-badge-min-width: 1.5em;--m-badge-padding: 0 .3em;--m-badge-gap: .1em}.button-label{display:inline-flex;align-items:center;line-height:normal;font-size:inherit;min-width:0;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.button-icon{position:relative;display:inline-flex;align-items:center;justify-content:center}.button-icon--img{width:calc(var(--m-btn-size) * 1.75);height:calc(var(--m-btn-size) * 1.75);overflow:hidden}.button-icon--img m-img{width:100%;height:100%;display:block}.get{appearance:none;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;height:var(--m-btn-h);padding:0 min(var(--m-btn-size) * 1.75,2rem);border-radius:4px;background:linear-gradient(135deg,var(--m-mm),var(--m-focus),var(--m-success),var(--m-mm));background-size:200% auto;color:#fff;font-size:calc(var(--m-btn-size) * .8);font-weight:300;letter-spacing:.06em;text-transform:uppercase;border:none;cursor:pointer;white-space:nowrap;line-height:1;transition:background-position .2s ease,transform .15s ease}.get:hover{background-position:right center}.get:focus-visible{outline:2px solid color-mix(in srgb,var(--m-focus) 45%,transparent);outline-offset:-2px}.get:active{transform:scale(.97)}.toggle{appearance:none;display:inline-flex;align-items:center;justify-content:center;width:100%;height:100%;border:none;background:transparent;padding:0 min(var(--m-btn-size),1.25rem);border-radius:var(--m-button-radius, calc(var(--m-btn-size) * .375));box-shadow:none;color:var(--m-btn-color, var(--m-text-secondary));opacity:.65;font-family:inherit;font-size:var(--m-btn-size);font-weight:300;cursor:pointer;box-sizing:border-box;-webkit-user-select:none;user-select:none;transition:background .15s ease,color .15s ease,opacity .15s ease;min-width:0}.toggle .button-icon{flex-shrink:0}.toggle .button-label{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%;min-width:0}.toggle:hover:not(:disabled){background:var(--m-button-hover-background, color-mix(in srgb, var(--m-focus) 8%, transparent));color:var(--m-button-hover-color, var(--m-text));opacity:1}.toggle:focus-visible:not(:disabled){outline:2px solid color-mix(in srgb,var(--m-focus) 45%,transparent);outline-offset:-2px;opacity:1}.toggle.primary{background:var(--m-button-active-background, var(--m-mm));color:var(--m-button-active-color, #ffffff);opacity:1}.toggle.primary:hover:not(:disabled){background:var(--m-button-active-background, var(--m-mm));color:var(--m-button-active-color, #ffffff);opacity:1}.toggle.primary:active:not(:disabled){transform:scale(.97)}.non-native:not(.get):not(.toggle){appearance:none;display:inline-flex;align-items:center;justify-content:center;width:100%;height:100%;min-height:0;padding:0 calc(var(--m-btn-size) * 1.25);border-width:2px;border-radius:4px;color:var(--m-btn-color);font-weight:300;line-height:1;-webkit-user-select:none;user-select:none;position:relative;outline:none;box-shadow:var(--m-button-shadow, var(--m-one-button-shadow, none));transition:filter .15s ease,background .15s ease}.non-native:not(.get):not(.toggle):hover:not([aria-disabled=true]){filter:brightness(1.04)}.non-native:not(.get):not(.toggle):focus-visible:not([aria-disabled=true]){outline:2px solid color-mix(in srgb,var(--m-focus) 45%,transparent);outline-offset:-2px}.non-native:not(.get):not(.toggle):active:not([aria-disabled=true]){transform:scale(.97)}.non-native:not(.get):not(.toggle)[aria-disabled=true]{opacity:.35;cursor:not-allowed;pointer-events:none;filter:grayscale(80%)}.non-native:not(.get):not(.toggle).primary{background:var(--m-btn-color);border-color:var(--m-btn-color);color:var(--m-btn-color-contrast)}.non-native:not(.get):not(.toggle).primary:hover:not([aria-disabled=true]){filter:none;background:color-mix(in srgb,var(--m-btn-color) 88%,black);border-color:color-mix(in srgb,var(--m-btn-color) 88%,black)}.non-native:not(.get):not(.toggle).primary:active:not([aria-disabled=true]){filter:brightness(.94);transform:scale(.97)}.non-native:not(.get):not(.toggle).ghost:not(.primary):not(.tab){background:transparent;border-color:transparent;color:var(--m-btn-color);box-shadow:none}.non-native:not(.get):not(.toggle).ghost:not(.primary):not(.tab):hover:not([aria-disabled=true]){filter:none;background:color-mix(in srgb,var(--m-btn-color) 8%,transparent)}.non-native:not(.get):not(.toggle).ghost:not(.primary):not(.tab):active:not([aria-disabled=true]){background:color-mix(in srgb,var(--m-btn-color) 14%,transparent);transform:scale(.97)}.non-native:not(.get):not(.toggle):disabled{opacity:.3;cursor:not-allowed}@container togglegroup (max-width: 320px){.non-native:not(.get):not(.toggle).with-left-icon .button-label,.non-native:not(.get):not(.toggle).with-right-icon .button-label{display:none!important}}@media(max-width:600px){.non-native:not(.get):not(.toggle).with-left-icon .button-label,.non-native:not(.get):not(.toggle).with-right-icon .button-label{display:none!important}}\n"] }]
7612
+ }], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }, { type: i0.Output, args: ["configChange"] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], labelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelClass", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], nav: [{ type: i0.Input, args: [{ isSignal: true, alias: "nav", required: false }] }], navParams: [{ type: i0.Input, args: [{ isSignal: true, alias: "navParams", required: false }] }], href: [{ type: i0.Input, args: [{ isSignal: true, alias: "href", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], baseUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "baseUrl", required: false }] }], one: [{ type: i0.Input, args: [{ isSignal: true, alias: "one", required: false }] }], remote: [{ type: i0.Input, args: [{ isSignal: true, alias: "remote", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], noTranslate: [{ type: i0.Input, args: [{ isSignal: true, alias: "noTranslate", required: false }] }], params: [{ type: i0.Input, args: [{ isSignal: true, alias: "params", required: false }] }], noNative: [{ type: i0.Input, args: [{ isSignal: true, alias: "noNative", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], isRightIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRightIcon", required: false }] }], iconOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnly", required: false }] }], stacked: [{ type: i0.Input, args: [{ isSignal: true, alias: "stacked", required: false }] }], imgSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "imgSrc", required: false }] }], nonClickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "nonClickable", required: false }] }], inverted: [{ type: i0.Input, args: [{ isSignal: true, alias: "inverted", required: false }] }], isSubmit: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSubmit", required: false }] }], tabindex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabindex", required: false }] }], clicked: [{ type: i0.Output, args: ["clicked"] }], button: [{ type: i0.ViewChild, args: ['button', { isSignal: true }] }] } });
7613
+
7614
+ let HeaderComponent$1 = class HeaderComponent {
7615
+ level = input(3, ...(ngDevMode ? [{ debugName: "level" }] : /* istanbul ignore next */ []));
7616
+ label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
7617
+ // Drawn inside the heading rather than beside it. A glyph placed as the
7618
+ // heading's sibling has no line box of its own to centre against — it ends
7619
+ // up centred on whatever column it sits next to, which is how a Canvas
7620
+ // header's icon came to line up with the label slot's drop rect instead of
7621
+ // with the label. Inside, the two share one line box at every level.
7622
+ icon = input(...(ngDevMode ? [undefined, { debugName: "icon" }] : /* istanbul ignore next */ []));
7623
+ actionButton = input(...(ngDevMode ? [undefined, { debugName: "actionButton" }] : /* istanbul ignore next */ []));
7624
+ // The action Button's accessible name. It renders icon-only, so the label is
7625
+ // the only thing a screen reader has to go on — without it the button reads
7626
+ // as nothing at all.
7627
+ actionLabel = input(...(ngDevMode ? [undefined, { debugName: "actionLabel" }] : /* istanbul ignore next */ []));
7628
+ // The label is authored text rather than a translation key. Needed for text
7629
+ // carrying angle brackets above all: `translate` reads `<...>` as link
7630
+ // markup, so a heading naming a MessageVariable — `<$app>` — resolves to
7631
+ // nothing at all rather than to itself.
7632
+ noTranslate = input(false, ...(ngDevMode ? [{ debugName: "noTranslate" }] : /* istanbul ignore next */ []));
7633
+ // A message's [MessageVariable] values, the same record `m-text-output`
7634
+ // takes: a heading naming `<$count>` is a sentence with a datum in it, and
7635
+ // splicing that datum into the key instead would be parsed as a query
7636
+ // string (m-one-ui ADR 0066).
7637
+ params = input(undefined, ...(ngDevMode ? [{ debugName: "params" }] : /* istanbul ignore next */ []));
7638
+ actionClick = output();
7639
+ translateService = inject(TranslateService);
7640
+ sizeContext = inject(SIZE_CONTEXT, { optional: true });
7641
+ // The action Button sits inside the heading, whose font-size is the level's
7642
+ // own — 2.25rem at h1 — so `em` inheritance would scale the Button to the
7643
+ // heading rather than to the Section it belongs to. It reads the Size in
7644
+ // force instead, the way Icon does, and lands at the same size as every
7645
+ // other Button on that Section (ADR 0008).
7646
+ actionSize = computed(() => resolveSize(this.sizeContext?.size()), ...(ngDevMode ? [{ debugName: "actionSize" }] : /* istanbul ignore next */ []));
7647
+ actionConfig = computed(() => {
7648
+ const icon = this.actionButton();
7649
+ if (!icon)
7650
+ return undefined;
7651
+ return {
7652
+ icon,
7653
+ label: this.actionLabel(),
7654
+ iconOnly: true,
7655
+ variant: 'ghost',
7656
+ };
7657
+ }, ...(ngDevMode ? [{ debugName: "actionConfig" }] : /* istanbul ignore next */ []));
7658
+ // A computed rather than the impure TranslatePipe repeated six times: one
7659
+ // lookup per label change instead of one per change-detection tick, and it
7660
+ // still repaints when the language or an in-memory translation moves.
7661
+ text = computed(() => this.noTranslate()
7662
+ ? (this.label() ?? '')
7663
+ : this.translateService.translate(this.label(), this.params()), ...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []));
7664
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: HeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7665
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: HeaderComponent, isStandalone: true, selector: "m-header", inputs: { level: { classPropertyName: "level", publicName: "level", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, actionButton: { classPropertyName: "actionButton", publicName: "actionButton", isSignal: true, isRequired: false, transformFunction: null }, actionLabel: { classPropertyName: "actionLabel", publicName: "actionLabel", isSignal: true, isRequired: false, transformFunction: null }, noTranslate: { classPropertyName: "noTranslate", publicName: "noTranslate", isSignal: true, isRequired: false, transformFunction: null }, params: { classPropertyName: "params", publicName: "params", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { actionClick: "actionClick" }, ngImport: i0, template: `
7666
+ @switch (level()) {
7667
+ @case (1) {
7668
+ <h1 class="header__heading">
7669
+ @if (icon(); as iconName) {
7670
+ <m-icon class="header__icon" [name]="iconName" />
7671
+ }
7672
+ <span>{{ text() }}</span>
7673
+ <ng-content />
7674
+ @if (actionConfig(); as action) {
7675
+ <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
7676
+ }
7677
+ </h1>
7678
+ }
7679
+ @case (2) {
7680
+ <h2 class="header__heading">
7681
+ @if (icon(); as iconName) {
7682
+ <m-icon class="header__icon" [name]="iconName" />
7683
+ }
7684
+ <span>{{ text() }}</span>
7685
+ <ng-content />
7686
+ @if (actionConfig(); as action) {
7687
+ <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
7688
+ }
7689
+ </h2>
7690
+ }
7691
+ @case (3) {
7692
+ <h3 class="header__heading">
7693
+ @if (icon(); as iconName) {
7694
+ <m-icon class="header__icon" [name]="iconName" />
7695
+ }
7696
+ <span>{{ text() }}</span>
7697
+ <ng-content />
7698
+ @if (actionConfig(); as action) {
7699
+ <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
7700
+ }
7701
+ </h3>
7702
+ }
7703
+ @case (4) {
7704
+ <h4 class="header__heading">
7705
+ @if (icon(); as iconName) {
7706
+ <m-icon class="header__icon" [name]="iconName" />
7707
+ }
7708
+ <span>{{ text() }}</span>
7709
+ <ng-content />
7710
+ @if (actionConfig(); as action) {
7711
+ <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
7712
+ }
7713
+ </h4>
7714
+ }
7715
+ @case (5) {
7716
+ <h5 class="header__heading">
7717
+ @if (icon(); as iconName) {
7718
+ <m-icon class="header__icon" [name]="iconName" />
7719
+ }
7720
+ <span>{{ text() }}</span>
7721
+ <ng-content />
7722
+ @if (actionConfig(); as action) {
7723
+ <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
7724
+ }
7725
+ </h5>
7726
+ }
7727
+ @case (6) {
7728
+ <h6 class="header__heading">
7729
+ @if (icon(); as iconName) {
7730
+ <m-icon class="header__icon" [name]="iconName" />
7731
+ }
7732
+ <span>{{ text() }}</span>
7733
+ <ng-content />
7734
+ @if (actionConfig(); as action) {
7735
+ <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
7736
+ }
7737
+ </h6>
7738
+ }
7739
+ }
7740
+ `, 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)}}.header__heading{display:flex;flex-direction:row;align-items:center;justify-content:var(--m-header-justify, flex-start);gap:.75rem;margin:0;padding:0;line-height:1.1;font-weight:800;letter-spacing:-.025em;color:var(--m-header-color, var(--m-text));transition:transform .2s cubic-bezier(.4,0,.2,1)}.header__heading:hover{transform:translate(2px)}.header__icon{flex-shrink:0}.header__action{margin-left:auto}.header__action span{display:inline-block;vertical-align:middle}h1.header__heading{font-size:var(--m-header-font-size, 2.25rem);font-weight:300;color:var(--m-text-quaternary);letter-spacing:-.035em;line-height:1.15}h2.header__heading{font-size:var(--m-header-font-size, 1.75rem);font-weight:300;color:var(--m-text-tertiary);letter-spacing:-.03em;line-height:1.2}h3.header__heading{font-size:var(--m-header-font-size, 1.375rem);font-weight:400;color:var(--m-text-secondary);letter-spacing:-.025em}h4.header__heading{font-size:var(--m-header-font-size, 1.125rem);font-weight:500;color:var(--m-text);letter-spacing:-.02em}h5.header__heading{font-size:var(--m-header-font-size, 1rem);font-weight:600;color:var(--m-text);letter-spacing:-.01em}h6.header__heading{font-size:var(--m-header-font-size, .875rem);font-weight:600;color:var(--m-text);letter-spacing:.05em;text-transform:uppercase}\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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
7741
+ };
7742
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: HeaderComponent$1, decorators: [{
7743
+ type: Component,
7744
+ args: [{ selector: 'm-header', imports: [ButtonComponent, IconComponent], template: `
7745
+ @switch (level()) {
7746
+ @case (1) {
7747
+ <h1 class="header__heading">
7748
+ @if (icon(); as iconName) {
7749
+ <m-icon class="header__icon" [name]="iconName" />
7750
+ }
7751
+ <span>{{ text() }}</span>
7752
+ <ng-content />
7753
+ @if (actionConfig(); as action) {
7754
+ <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
7755
+ }
7756
+ </h1>
7757
+ }
7758
+ @case (2) {
7759
+ <h2 class="header__heading">
7760
+ @if (icon(); as iconName) {
7761
+ <m-icon class="header__icon" [name]="iconName" />
7762
+ }
7763
+ <span>{{ text() }}</span>
7764
+ <ng-content />
7765
+ @if (actionConfig(); as action) {
7766
+ <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
7767
+ }
7768
+ </h2>
7769
+ }
7770
+ @case (3) {
7771
+ <h3 class="header__heading">
7772
+ @if (icon(); as iconName) {
7773
+ <m-icon class="header__icon" [name]="iconName" />
7774
+ }
7775
+ <span>{{ text() }}</span>
7776
+ <ng-content />
7777
+ @if (actionConfig(); as action) {
7778
+ <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
7779
+ }
7780
+ </h3>
7781
+ }
7782
+ @case (4) {
7783
+ <h4 class="header__heading">
7784
+ @if (icon(); as iconName) {
7785
+ <m-icon class="header__icon" [name]="iconName" />
7786
+ }
7787
+ <span>{{ text() }}</span>
7788
+ <ng-content />
7789
+ @if (actionConfig(); as action) {
7790
+ <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
7791
+ }
7792
+ </h4>
7793
+ }
7794
+ @case (5) {
7795
+ <h5 class="header__heading">
7796
+ @if (icon(); as iconName) {
7797
+ <m-icon class="header__icon" [name]="iconName" />
7798
+ }
7799
+ <span>{{ text() }}</span>
7800
+ <ng-content />
7801
+ @if (actionConfig(); as action) {
7802
+ <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
7803
+ }
7804
+ </h5>
7805
+ }
7806
+ @case (6) {
7807
+ <h6 class="header__heading">
7808
+ @if (icon(); as iconName) {
7809
+ <m-icon class="header__icon" [name]="iconName" />
7810
+ }
7811
+ <span>{{ text() }}</span>
7812
+ <ng-content />
7813
+ @if (actionConfig(); as action) {
7814
+ <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
7815
+ }
7816
+ </h6>
7817
+ }
7818
+ }
7819
+ `, 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)}}.header__heading{display:flex;flex-direction:row;align-items:center;justify-content:var(--m-header-justify, flex-start);gap:.75rem;margin:0;padding:0;line-height:1.1;font-weight:800;letter-spacing:-.025em;color:var(--m-header-color, var(--m-text));transition:transform .2s cubic-bezier(.4,0,.2,1)}.header__heading:hover{transform:translate(2px)}.header__icon{flex-shrink:0}.header__action{margin-left:auto}.header__action span{display:inline-block;vertical-align:middle}h1.header__heading{font-size:var(--m-header-font-size, 2.25rem);font-weight:300;color:var(--m-text-quaternary);letter-spacing:-.035em;line-height:1.15}h2.header__heading{font-size:var(--m-header-font-size, 1.75rem);font-weight:300;color:var(--m-text-tertiary);letter-spacing:-.03em;line-height:1.2}h3.header__heading{font-size:var(--m-header-font-size, 1.375rem);font-weight:400;color:var(--m-text-secondary);letter-spacing:-.025em}h4.header__heading{font-size:var(--m-header-font-size, 1.125rem);font-weight:500;color:var(--m-text);letter-spacing:-.02em}h5.header__heading{font-size:var(--m-header-font-size, 1rem);font-weight:600;color:var(--m-text);letter-spacing:-.01em}h6.header__heading{font-size:var(--m-header-font-size, .875rem);font-weight:600;color:var(--m-text);letter-spacing:.05em;text-transform:uppercase}\n"] }]
7820
+ }], propDecorators: { level: [{ type: i0.Input, args: [{ isSignal: true, alias: "level", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], actionButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionButton", required: false }] }], actionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionLabel", required: false }] }], noTranslate: [{ type: i0.Input, args: [{ isSignal: true, alias: "noTranslate", required: false }] }], params: [{ type: i0.Input, args: [{ isSignal: true, alias: "params", required: false }] }], actionClick: [{ type: i0.Output, args: ["actionClick"] }] } });
7821
+
7822
+ /**
7823
+ * Asks the user to agree to every Declared Permission of an App at once — no
7824
+ * subset (store ADR 0006). Closes `true` on agreement and `false` on the other
7825
+ * button, which is Cancel or, when the App cannot open without it, Back to
7826
+ * Store.
7827
+ */
7828
+ class AgreementComponent {
7829
+ header = input('', ...(ngDevMode ? [{ debugName: "header" }] : /* istanbul ignore next */ []));
7830
+ params = input({}, ...(ngDevMode ? [{ debugName: "params" }] : /* istanbul ignore next */ []));
7831
+ permissions = input([], ...(ngDevMode ? [{ debugName: "permissions" }] : /* istanbul ignore next */ []));
7832
+ confirmLabel = input('agree', ...(ngDevMode ? [{ debugName: "confirmLabel" }] : /* istanbul ignore next */ []));
7833
+ cancelLabel = input('cancel', ...(ngDevMode ? [{ debugName: "cancelLabel" }] : /* istanbul ignore next */ []));
7834
+ #modalRef = inject(MODAL_REF);
7835
+ accept() {
7836
+ this.#modalRef.close(true);
7837
+ }
7838
+ decline() {
7839
+ this.#modalRef.close(false);
7840
+ }
7841
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AgreementComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7842
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AgreementComponent, isStandalone: true, selector: "m-agreement", inputs: { header: { classPropertyName: "header", publicName: "header", isSignal: true, isRequired: false, transformFunction: null }, params: { classPropertyName: "params", publicName: "params", isSignal: true, isRequired: false, transformFunction: null }, permissions: { classPropertyName: "permissions", publicName: "permissions", 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: `
7843
+ <div class="agreement">
7844
+ <div class="agreement__header">
7845
+ <m-header [level]="3" [label]="header()" [params]="params()" />
7846
+ <p class="agreement__body">{{ 'agreement-body' | translate }}</p>
7847
+ </div>
7848
+
7849
+ <ul class="agreement__list">
7850
+ @for (permission of permissions(); track permission.id) {
7851
+ <li class="agreement__item">
7852
+ <span class="agreement__icon"><m-icon [name]="permission.icon" /></span>
7853
+ <span class="agreement__text">
7854
+ <span class="agreement__name">{{ permission.nameKey | translate }}</span>
7855
+ <span class="agreement__description">{{
7856
+ permission.descriptionKey | translate
7857
+ }}</span>
7858
+ </span>
7859
+ </li>
7860
+ }
7861
+ </ul>
7862
+
7863
+ <div class="agreement__actions">
7864
+ <!-- asset: buttons/confirm_cancel.yml -->
7865
+ <m-one-button name="confirm_cancel" [label]="cancelLabel()" (clicked)="decline()" />
7866
+ <!-- asset: buttons/okay.yml -->
7867
+ <m-one-button name="okay" [label]="confirmLabel()" (clicked)="accept()" />
7868
+ </div>
7869
+ </div>
7870
+ `, 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)}}.agreement{display:flex;flex-direction:column;min-width:320px;max-width:480px;padding:2.5rem;background:var(--m-backdrop-modal, rgba(255, 255, 255, .85));backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px)}.agreement__header{display:flex;flex-direction:column;align-items:center;text-align:center;gap:.9375rem;margin-bottom:1.5rem}.agreement__body{margin:0;font-size:1rem;line-height:1.6;color:var(--m-text-600)}.agreement__list{list-style:none;margin:0 0 2rem;padding:0;display:flex;flex-direction:column;gap:1rem}.agreement__item{display:flex;align-items:flex-start;gap:1rem}.agreement__icon{flex:0 0 40px;height:40px;display:flex;align-items:center;justify-content:center;border-radius:12px;background:var(--m-backdrop-mm, rgba(65, 105, 225, .1));color:var(--m-mm, #4169e1)}.agreement__text{display:flex;flex-direction:column;gap:.25rem}.agreement__name{font-weight:600;color:var(--m-text-900)}.agreement__description{font-size:.875rem;color:var(--m-text-600)}.agreement__actions{width:100%;display:flex;justify-content:center;gap:1rem}\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", "icon", "actionButton", "actionLabel", "noTranslate", "params"], outputs: ["actionClick"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
7871
+ }
7872
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AgreementComponent, decorators: [{
7873
+ type: Component,
7874
+ args: [{ selector: 'm-agreement', imports: [ButtonComponent, IconComponent, TranslatePipe, HeaderComponent$1], template: `
7875
+ <div class="agreement">
7876
+ <div class="agreement__header">
7877
+ <m-header [level]="3" [label]="header()" [params]="params()" />
7878
+ <p class="agreement__body">{{ 'agreement-body' | translate }}</p>
7879
+ </div>
7880
+
7881
+ <ul class="agreement__list">
7882
+ @for (permission of permissions(); track permission.id) {
7883
+ <li class="agreement__item">
7884
+ <span class="agreement__icon"><m-icon [name]="permission.icon" /></span>
7885
+ <span class="agreement__text">
7886
+ <span class="agreement__name">{{ permission.nameKey | translate }}</span>
7887
+ <span class="agreement__description">{{
7888
+ permission.descriptionKey | translate
7889
+ }}</span>
7890
+ </span>
7891
+ </li>
7892
+ }
7893
+ </ul>
7894
+
7895
+ <div class="agreement__actions">
7896
+ <!-- asset: buttons/confirm_cancel.yml -->
7897
+ <m-one-button name="confirm_cancel" [label]="cancelLabel()" (clicked)="decline()" />
7898
+ <!-- asset: buttons/okay.yml -->
7899
+ <m-one-button name="okay" [label]="confirmLabel()" (clicked)="accept()" />
7900
+ </div>
7901
+ </div>
7902
+ `, 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)}}.agreement{display:flex;flex-direction:column;min-width:320px;max-width:480px;padding:2.5rem;background:var(--m-backdrop-modal, rgba(255, 255, 255, .85));backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px)}.agreement__header{display:flex;flex-direction:column;align-items:center;text-align:center;gap:.9375rem;margin-bottom:1.5rem}.agreement__body{margin:0;font-size:1rem;line-height:1.6;color:var(--m-text-600)}.agreement__list{list-style:none;margin:0 0 2rem;padding:0;display:flex;flex-direction:column;gap:1rem}.agreement__item{display:flex;align-items:flex-start;gap:1rem}.agreement__icon{flex:0 0 40px;height:40px;display:flex;align-items:center;justify-content:center;border-radius:12px;background:var(--m-backdrop-mm, rgba(65, 105, 225, .1));color:var(--m-mm, #4169e1)}.agreement__text{display:flex;flex-direction:column;gap:.25rem}.agreement__name{font-weight:600;color:var(--m-text-900)}.agreement__description{font-size:.875rem;color:var(--m-text-600)}.agreement__actions{width:100%;display:flex;justify-content:center;gap:1rem}\n"] }]
7903
+ }], propDecorators: { header: [{ type: i0.Input, args: [{ isSignal: true, alias: "header", required: false }] }], params: [{ type: i0.Input, args: [{ isSignal: true, alias: "params", required: false }] }], permissions: [{ type: i0.Input, args: [{ isSignal: true, alias: "permissions", required: false }] }], confirmLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmLabel", required: false }] }], cancelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelLabel", required: false }] }] } });
7904
+
7905
+ // One modal per App at a time: init and every refused api call of the same
7906
+ // App wait on the same answer instead of stacking modals.
7907
+ const pending = new Map();
7908
+ /**
7909
+ * Asks the user to agree to every Declared Permission of an App (store ADR
7910
+ * 0006) and records it with `POST store/app/<id>/permission`. `hardStop` is
7911
+ * the init gate: the modal cannot be dismissed, and its other button leaves
7912
+ * for the Store.
7913
+ */
7914
+ function injectAgreeToApp() {
7915
+ const modalStore = inject(ModalStore);
7916
+ const httpService = inject(HttpService);
7917
+ return (app, permissions, hardStop = false) => {
7918
+ const appId = app.id ?? '';
7919
+ const existing = pending.get(appId);
7920
+ if (existing)
7921
+ return existing;
7922
+ const appName = app.name ?? app.link ?? '';
7923
+ const answer = new Promise((resolve, reject) => {
7924
+ const modalRef = new ModalRef();
7925
+ const id = modalStore.open({
7926
+ component: AgreementComponent,
7927
+ providers: [{ provide: MODAL_REF, useValue: modalRef }],
7928
+ bindings: [
7929
+ inputBinding('header', () => `agreement_title?appName=${appName}`),
7930
+ inputBinding('permissions', () => permissions),
7931
+ inputBinding('cancelLabel', () => (hardStop ? 'back-to-store' : 'cancel')),
7932
+ ],
7933
+ config: hardStop ? { closeProhibited: true, backdropClose: false } : undefined,
7934
+ });
7935
+ modalRef.onClose(async (agreed) => {
7936
+ modalStore.close(id);
7937
+ if (!agreed) {
7938
+ reject({
7939
+ type: hardStop ? 'back_to_store' : 'agreement_declined',
7940
+ });
7941
+ return;
7942
+ }
7943
+ try {
7944
+ await firstValueFrom(httpService.post('store', ['app', appId, 'permission'], {}));
7945
+ resolve();
7946
+ }
7947
+ catch (e) {
7948
+ reject(e);
7949
+ }
7950
+ });
7951
+ }).finally(() => pending.delete(appId));
7952
+ pending.set(appId, answer);
7953
+ return answer;
7954
+ };
7955
+ }
7956
+
7957
+ class ConfirmComponent {
7958
+ header = input('', ...(ngDevMode ? [{ debugName: "header" }] : /* istanbul ignore next */ []));
7959
+ body = input('', ...(ngDevMode ? [{ debugName: "body" }] : /* istanbul ignore next */ []));
7960
+ /**
7961
+ * The MessageVariable values the two keys above name — a row's name or id the
7962
+ * asker knows and the message asks about. Values and never text: they reach
7963
+ * `TranslatePipe` as params rather than spliced into the key, so the message
7964
+ * still resolves per language. Empty is a message with no slots, which is
7965
+ * every confirmation drawn before this.
7966
+ */
7967
+ params = input({}, ...(ngDevMode ? [{ debugName: "params" }] : /* istanbul ignore next */ []));
7968
+ type = input('info', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
7969
+ /**
7970
+ * Whether the question can be refused. `yes` is an acknowledgement — the one
7971
+ * button commits and there is nothing else to press — and stays the default,
7972
+ * which is what every ConfirmComponent drawn before this was.
7973
+ */
7974
+ kind = input('yes', ...(ngDevMode ? [{ debugName: "kind" }] : /* istanbul ignore next */ []));
7975
+ /**
7976
+ * The wording of each button, as a TranslationAsset key. Empty falls back to
7977
+ * the library's own — derived from `type` for the commit, `cancel` for the
7978
+ * refusal — so a caller that has nothing to say about the buttons says
7979
+ * nothing.
7980
+ */
7981
+ confirmLabel = input('', ...(ngDevMode ? [{ debugName: "confirmLabel" }] : /* istanbul ignore next */ []));
7982
+ cancelLabel = input('', ...(ngDevMode ? [{ debugName: "cancelLabel" }] : /* istanbul ignore next */ []));
7983
+ #modalRef = inject(MODAL_REF);
7984
+ confirmText = computed(() => {
7985
+ if (this.confirmLabel())
7986
+ return this.confirmLabel();
7987
+ switch (this.type()) {
7988
+ case 'danger':
7989
+ return 'delete';
7990
+ default:
7991
+ return 'okay';
7992
+ }
7993
+ }, ...(ngDevMode ? [{ debugName: "confirmText" }] : /* istanbul ignore next */ []));
7994
+ cancelText = computed(() => this.cancelLabel() || 'cancel', ...(ngDevMode ? [{ debugName: "cancelText" }] : /* istanbul ignore next */ []));
7995
+ iconName = computed(() => {
7996
+ switch (this.type()) {
7997
+ case 'danger':
7998
+ return 'trash';
7999
+ case 'warning':
8000
+ return 'exclamation-triangle';
8001
+ case 'success':
8002
+ return 'check-circle';
8003
+ default:
8004
+ return 'info';
8005
+ }
8006
+ }, ...(ngDevMode ? [{ debugName: "iconName" }] : /* istanbul ignore next */ []));
8007
+ accept() {
8008
+ this.#modalRef.close(true);
6986
8009
  }
6987
- buttonIcon = computed(() => {
6988
- const name = this.config()?.icon;
6989
- if (!name) {
6990
- return undefined;
8010
+ // The refusal is a result like any other, so it closes with `false` rather
8011
+ // than dismissing: a caller waiting on the answer gets one either way.
8012
+ decline() {
8013
+ this.#modalRef.close(false);
8014
+ }
8015
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ConfirmComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
8016
+ 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: `
8017
+ <div class="confirm confirm--{{ type() }}">
8018
+ <div class="confirm__header">
8019
+ <div class="confirm__icon">
8020
+ <m-icon [name]="iconName()" />
8021
+ </div>
8022
+ @if (header()) {
8023
+ <!-- The heading takes the key and its values rather than projected
8024
+ text: m-header translates its own label, and a MessageVariable
8025
+ fills the same way it does everywhere else. -->
8026
+ <m-header [level]="3" [label]="header()" [params]="params()" />
6991
8027
  }
6992
- return {
6993
- name: this.config()?.icon,
6994
- color: this.buttonColor(),
6995
- baseUrl: this.baseUrl(),
6996
- remote: this.remote() ?? this.config()?.remote,
6997
- };
6998
- }, ...(ngDevMode ? [{ debugName: "buttonIcon" }] : /* istanbul ignore next */ []));
6999
- overrideProperty = computed(() => {
7000
- const button = {};
7001
- // The rest of what a `buttons/<name>.yml` carries, so a one-off Button
7002
- // needs no file (ADR 0010). An omitted attribute is skipped rather than
7003
- // written as undefined — writing it would blank whatever the asset set.
7004
- const put = (key, value) => {
7005
- if (value !== undefined)
7006
- button[key] = value;
7007
- };
7008
- put('label', this.label());
7009
- put('icon', this.icon());
7010
- put('imgSrc', this.imgSrc());
7011
- put('tabindex', toAttrNumber(this.tabindex()));
7012
- put('noTranslate', toAttrBool(this.noTranslate()));
7013
- put('params', this.params());
7014
- put('isRightIcon', toAttrBool(this.isRightIcon()));
7015
- put('iconOnly', toAttrBool(this.iconOnly()));
7016
- put('stacked', toAttrBool(this.stacked()));
7017
- put('nonClickable', toAttrBool(this.nonClickable()));
7018
- put('inverted', toAttrBool(this.inverted()));
7019
- put('isSubmit', toAttrBool(this.isSubmit()));
7020
- if (this.color()) {
7021
- button['color'] = this.color();
8028
+ </div>
8029
+
8030
+ <div class="confirm__content">
8031
+ @if (body()) {
8032
+ <p class="confirm__body" [innerHTML]="body() | translate: params()"></p>
7022
8033
  }
7023
- if (this.labelClass()) {
7024
- button['labelClass'] = this.labelClass();
8034
+ </div>
8035
+
8036
+ <div class="confirm__actions">
8037
+ @if (kind() === 'yes-no') {
8038
+ <!-- asset: buttons/confirm_cancel.yml -->
8039
+ <m-one-button name="confirm_cancel" [label]="cancelText()" (clicked)="decline()" />
7025
8040
  }
7026
- if (typeof this.fullWidth() !== 'undefined') {
7027
- button['fullWidth'] = toAttrBool(this.fullWidth());
8041
+ <!-- asset: buttons/okay.yml -->
8042
+ <m-one-button name="okay" [label]="confirmText()" (clicked)="accept()" />
8043
+ </div>
8044
+ </div>
8045
+ `, 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", "icon", "actionButton", "actionLabel", "noTranslate", "params"], outputs: ["actionClick"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
8046
+ }
8047
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ConfirmComponent, decorators: [{
8048
+ type: Component,
8049
+ args: [{ selector: 'm-confirm', imports: [ButtonComponent, IconComponent, TranslatePipe, HeaderComponent$1], template: `
8050
+ <div class="confirm confirm--{{ type() }}">
8051
+ <div class="confirm__header">
8052
+ <div class="confirm__icon">
8053
+ <m-icon [name]="iconName()" />
8054
+ </div>
8055
+ @if (header()) {
8056
+ <!-- The heading takes the key and its values rather than projected
8057
+ text: m-header translates its own label, and a MessageVariable
8058
+ fills the same way it does everywhere else. -->
8059
+ <m-header [level]="3" [label]="header()" [params]="params()" />
7028
8060
  }
7029
- if (this.nav()) {
7030
- button['nav'] = this.nav();
8061
+ </div>
8062
+
8063
+ <div class="confirm__content">
8064
+ @if (body()) {
8065
+ <p class="confirm__body" [innerHTML]="body() | translate: params()"></p>
7031
8066
  }
7032
- if (this.navParams()) {
7033
- button['navParams'] = this.navParams();
8067
+ </div>
8068
+
8069
+ <div class="confirm__actions">
8070
+ @if (kind() === 'yes-no') {
8071
+ <!-- asset: buttons/confirm_cancel.yml -->
8072
+ <m-one-button name="confirm_cancel" [label]="cancelText()" (clicked)="decline()" />
7034
8073
  }
7035
- if (this.href()) {
7036
- button['href'] = this.href();
8074
+ <!-- asset: buttons/okay.yml -->
8075
+ <m-one-button name="okay" [label]="confirmText()" (clicked)="accept()" />
8076
+ </div>
8077
+ </div>
8078
+ `, 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"] }]
8079
+ }], 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 }] }] } });
8080
+
8081
+ /**
8082
+ * Installs an App after asking. An App declaring Permissions is installed only
8083
+ * with Agreement (store ADR 0006), so its modal lists them and the request
8084
+ * carries `agree: true`; `declared` spares the lookup when the caller already
8085
+ * holds them. `hardStop` is the init gate: the modal cannot be dismissed and
8086
+ * refusing leaves for the Store.
8087
+ */
8088
+ function injectInstallApp() {
8089
+ const modalStore = inject(ModalStore);
8090
+ const httpService = inject(HttpService);
8091
+ return async (app, declared, hardStop = false) => {
8092
+ const appName = app.name ?? app.link ?? '';
8093
+ const appId = app.id ?? '';
8094
+ const permissions = declared ??
8095
+ (app.permissions?.length
8096
+ ? await firstValueFrom(httpService.get('store', ['app', appId, 'permission'])).catch(() => [])
8097
+ : []);
8098
+ return new Promise((resolve, reject) => {
8099
+ const modalRef = new ModalRef();
8100
+ const id = permissions.length
8101
+ ? modalStore.open({
8102
+ component: AgreementComponent,
8103
+ providers: [{ provide: MODAL_REF, useValue: modalRef }],
8104
+ bindings: [
8105
+ inputBinding('header', () => `install_app_title?appName=${appName}`),
8106
+ inputBinding('permissions', () => permissions),
8107
+ inputBinding('confirmLabel', () => 'install'),
8108
+ inputBinding('cancelLabel', () => hardStop ? 'back-to-store' : 'cancel'),
8109
+ ],
8110
+ config: hardStop
8111
+ ? { closeProhibited: true, backdropClose: false }
8112
+ : undefined,
8113
+ })
8114
+ : modalStore.open({
8115
+ component: ConfirmComponent,
8116
+ providers: [{ provide: MODAL_REF, useValue: modalRef }],
8117
+ bindings: [
8118
+ inputBinding('header', () => `install_app_title?appName=${appName}`),
8119
+ inputBinding('body', () => `install_app_body?appName=${appName}`),
8120
+ inputBinding('type', () => 'info'),
8121
+ ],
8122
+ });
8123
+ modalRef.onClose(async (confirmed) => {
8124
+ modalStore.close(id);
8125
+ if (!confirmed) {
8126
+ reject(hardStop ? { type: 'back_to_store' } : new Error('app_install_declined'));
8127
+ return;
8128
+ }
8129
+ try {
8130
+ const body = await firstValueFrom(httpService.post('store', ['request', appId], permissions.length ? { agree: true } : {}));
8131
+ if (body?.relation?.type === 5) {
8132
+ reject({ type: 'install_pending', appName });
8133
+ return;
8134
+ }
8135
+ resolve();
8136
+ }
8137
+ catch (e) {
8138
+ reject(e);
8139
+ }
8140
+ });
8141
+ });
8142
+ };
8143
+ }
8144
+
8145
+ /** Where refusing the hard stop goes — the host's Store. */
8146
+ const STORE_PATH = '/store';
8147
+ /**
8148
+ * The init step every App passes before it renders (store ADR 0006): its apis
8149
+ * refuse without a current Agreement, so the App asks first — Agreement to an
8150
+ * installed App whose Declared Permissions grew, install-with-Agreement for a
8151
+ * visitor. The modal cannot be dismissed; its other button leaves for the
8152
+ * Store. The Relation it reads is kept per AppLink and is what AppContext
8153
+ * reads too, so an App fetches it once.
8154
+ */
8155
+ class AgreementGate {
8156
+ #http = inject(HttpService);
8157
+ #injector = inject(Injector);
8158
+ #views = new Map();
8159
+ #revision = signal(0, ...(ngDevMode ? [{ debugName: "#revision" }] : /* istanbul ignore next */ []));
8160
+ /** Moves whenever a kept Relation is dropped, so a reader can read again. */
8161
+ revision = this.#revision.asReadonly();
8162
+ /** Refusing the hard stop leaves the App for the host's Store. */
8163
+ leaveForStore = () => window.location.assign(STORE_PATH);
8164
+ /** The caller's Relation to `link`, read once until `forget`. */
8165
+ view(link) {
8166
+ let view = this.#views.get(link);
8167
+ if (!view) {
8168
+ view = firstValueFrom(this.#http.get('store', ['app', link, 'relation']));
8169
+ view.catch(() => this.#views.delete(link));
8170
+ this.#views.set(link, view);
8171
+ }
8172
+ return view;
8173
+ }
8174
+ forget(link) {
8175
+ this.#views.delete(link);
8176
+ this.#revision.update((n) => n + 1);
8177
+ }
8178
+ /**
8179
+ * Resolves once the App may open. Never resolves when the user leaves for
8180
+ * the Store. A failed read lets the App open — its apis are the hard stop,
8181
+ * and they refuse on their own.
8182
+ */
8183
+ async ensure(link, name) {
8184
+ let view;
8185
+ try {
8186
+ view = await this.view(link);
7037
8187
  }
7038
- if (typeof this.disabled() !== 'undefined') {
7039
- button['disabled'] = this.disabled();
8188
+ catch {
8189
+ return;
7040
8190
  }
7041
- if (this.variant()) {
7042
- button['variant'] = this.variant();
8191
+ const app = { id: view.app, link, name };
8192
+ try {
8193
+ if (view.needsAgreement) {
8194
+ const agreeToApp = runInInjectionContext(this.#injector, injectAgreeToApp);
8195
+ await agreeToApp(app, view.permissions, true);
8196
+ this.forget(link);
8197
+ }
8198
+ else if (view.type === null && view.permissions.length) {
8199
+ const installApp = runInInjectionContext(this.#injector, injectInstallApp);
8200
+ await installApp(app, view.permissions, true);
8201
+ this.forget(link);
8202
+ }
7043
8203
  }
7044
- // Force primary and clear ghost if the color is 'inverse' or 'inverseText', unless explicitly ghost or secondary
7045
- const finalColor = button.color || this.config()?.color;
7046
- const isExplicitGhost = button.variant === 'ghost' || this.config()?.variant === 'ghost';
7047
- const isExplicitSecondary = button.variant === 'secondary' ||
7048
- this.config()?.variant === 'secondary';
7049
- if ((finalColor === 'inverse' || finalColor === 'inverseText') &&
7050
- !isExplicitGhost &&
7051
- !isExplicitSecondary) {
7052
- button['color'] = 'inverseText';
7053
- button['variant'] = 'primary';
8204
+ catch (refusal) {
8205
+ if (refusal?.type === 'back_to_store') {
8206
+ this.leaveForStore();
8207
+ return new Promise(() => undefined);
8208
+ }
7054
8209
  }
7055
- else if (finalColor === 'inverse') {
7056
- button['color'] = 'inverseText';
8210
+ }
8211
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AgreementGate, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
8212
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AgreementGate, providedIn: 'root' });
8213
+ }
8214
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AgreementGate, decorators: [{
8215
+ type: Injectable,
8216
+ args: [{ providedIn: 'root' }]
8217
+ }] });
8218
+
8219
+ function initMagmoniumApp({ backend, authUrl, socketUrl, }) {
8220
+ return () => {
8221
+ inject(FreezeService); // ensure the loading effect is always active
8222
+ const httpService = inject(HttpService);
8223
+ const translateService = inject(TranslateService);
8224
+ const themeStore = inject(ThemeStore);
8225
+ const loginStore = inject(LOGIN_STORE);
8226
+ const navStore = inject(NavStore, { optional: true });
8227
+ const appLink = inject(APP_LINK);
8228
+ const agreementGate = inject(AgreementGate);
8229
+ translateService.init();
8230
+ SharedStoreRegistry.setThemeStore(themeStore);
8231
+ SharedStoreRegistry.setTranslateService(translateService);
8232
+ SharedStoreRegistry.setLoadingActions(loadingActions);
8233
+ SharedStoreRegistry.setNotificationStore(inject(NotificationStore));
8234
+ if (navStore) {
8235
+ SharedStoreRegistry.setNavStore(navStore);
7057
8236
  }
7058
- if (this.config()?.nav || this.nav()) {
7059
- button['variant'] = this.isMurlActive() ? undefined : 'ghost';
8237
+ if (loginStore) {
8238
+ SharedStoreRegistry.setLoginStore(loginStore);
7060
8239
  }
7061
- return button;
7062
- }, ...(ngDevMode ? [{ debugName: "overrideProperty" }] : /* istanbul ignore next */ []));
7063
- resolveComponentOverrides() {
7064
- return this.overrideProperty();
7065
- }
7066
- onClick() {
7067
- if (this.isFormSubmit()) {
7068
- // Called rather than left to a native `type="submit"`: the `<form>` is
7069
- // only an ancestor while nothing re-projects this Button out of it.
7070
- this.sectionForm?.submit();
8240
+ const effectiveBackend = backend || 'http://localhost:8000';
8241
+ if (!backend) {
8242
+ console.warn('initMagmoniumApp: No backend URL provided, defaulting to http://localhost:8000. ' +
8243
+ 'Check your environment configuration if this is unexpected.');
7071
8244
  }
7072
- this.clicked.emit(this.config());
7073
- }
7074
- formatBadgeCount = (count, max = 99) => formatBadgeCount(count, max);
7075
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7076
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: ButtonComponent, isStandalone: true, selector: "m-button,m-one-button", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, labelClass: { classPropertyName: "labelClass", publicName: "labelClass", isSignal: true, isRequired: false, transformFunction: null }, fullWidth: { classPropertyName: "fullWidth", publicName: "fullWidth", isSignal: true, isRequired: false, transformFunction: null }, nav: { classPropertyName: "nav", publicName: "nav", isSignal: true, isRequired: false, transformFunction: null }, navParams: { classPropertyName: "navParams", publicName: "navParams", isSignal: true, isRequired: false, transformFunction: null }, href: { classPropertyName: "href", publicName: "href", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, baseUrl: { classPropertyName: "baseUrl", publicName: "baseUrl", isSignal: true, isRequired: false, transformFunction: null }, one: { classPropertyName: "one", publicName: "one", isSignal: true, isRequired: false, transformFunction: null }, remote: { classPropertyName: "remote", publicName: "remote", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, noTranslate: { classPropertyName: "noTranslate", publicName: "noTranslate", isSignal: true, isRequired: false, transformFunction: null }, params: { classPropertyName: "params", publicName: "params", isSignal: true, isRequired: false, transformFunction: null }, noNative: { classPropertyName: "noNative", publicName: "noNative", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, isRightIcon: { classPropertyName: "isRightIcon", publicName: "isRightIcon", isSignal: true, isRequired: false, transformFunction: null }, iconOnly: { classPropertyName: "iconOnly", publicName: "iconOnly", isSignal: true, isRequired: false, transformFunction: null }, stacked: { classPropertyName: "stacked", publicName: "stacked", isSignal: true, isRequired: false, transformFunction: null }, imgSrc: { classPropertyName: "imgSrc", publicName: "imgSrc", isSignal: true, isRequired: false, transformFunction: null }, nonClickable: { classPropertyName: "nonClickable", publicName: "nonClickable", isSignal: true, isRequired: false, transformFunction: null }, inverted: { classPropertyName: "inverted", publicName: "inverted", isSignal: true, isRequired: false, transformFunction: null }, isSubmit: { classPropertyName: "isSubmit", publicName: "isSubmit", isSignal: true, isRequired: false, transformFunction: null }, tabindex: { classPropertyName: "tabindex", publicName: "tabindex", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { config: "configChange", clicked: "clicked" }, viewQueries: [{ propertyName: "button", first: true, predicate: ["button"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@if (config(); as config) {\n <!-- One branch for every in-app target: `mRef` names a NavId and the store\n reads the NavKind off that node to decide route vs panel (ADR 0014). -->\n @if (config.nav) {\n @if (!noNative()) {\n <button\n type=\"button\"\n class=\"{{ className() }}\"\n [attr.data-testid]=\"config.name + '-btn'\"\n [attr.tabindex]=\"config.tabindex\"\n [disabled]=\"config.disabled\"\n [mRef]=\"config.nav\"\n [mRefParams]=\"config.navParams\"\n [attr.aria-label]=\"config.noTranslate ? config.label : (config.label | translate: config.params)\"\n mRefLinkActive=\"tab\"\n (keydown.enter)=\"onClick()\"\n (click)=\"onClick()\"\n #button\n >\n <ng-container *ngTemplateOutlet=\"buttonContent; context: { button: config }\"></ng-container>\n </button>\n } @else {\n <div\n role=\"button\"\n [attr.tabindex]=\"config.tabindex ?? 0\"\n class=\"non-native {{ className() }}\"\n [attr.data-testid]=\"config.name + '-btn'\"\n [attr.aria-label]=\"config.noTranslate ? config.label : (config.label | translate: config.params)\"\n [attr.aria-disabled]=\"config.disabled ? 'true' : 'false'\"\n (keydown.enter)=\"onClick()\"\n (click)=\"onClick()\"\n #button\n >\n <ng-container *ngTemplateOutlet=\"buttonContent; context: { button: config }\"></ng-container>\n </div>\n }\n } @else if (config.href) {\n <a\n class=\"{{ className() }}\"\n [attr.data-testid]=\"config.name + '-btn'\"\n [attr.tabindex]=\"config.tabindex\"\n [href]=\"config.href\"\n [attr.aria-label]=\"config.noTranslate ? config.label : (config.label | translate: config.params)\"\n (click)=\"onClick()\"\n #button\n >\n <ng-container *ngTemplateOutlet=\"buttonContent; context: { button: config }\"></ng-container>\n </a>\n } @else {\n @if (!noNative()) {\n <button\n type=\"button\"\n class=\"{{ className() }}\"\n [attr.data-testid]=\"config.name + '-btn'\"\n [attr.tabindex]=\"config.tabindex\"\n [disabled]=\"isDisabled()\"\n [attr.aria-label]=\"config.noTranslate ? config.label : (config.label | translate: config.params)\"\n (keydown.enter)=\"onClick()\"\n (click)=\"onClick()\"\n #button\n >\n <ng-container *ngTemplateOutlet=\"buttonContent; context: { button: config }\"></ng-container>\n </button>\n } @else {\n <div\n role=\"button\"\n [attr.tabindex]=\"config.tabindex ?? 0\"\n class=\"non-native {{ className() }}\"\n [attr.data-testid]=\"config.name + '-btn'\"\n [attr.aria-label]=\"config.noTranslate ? config.label : (config.label | translate: config.params)\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : 'false'\"\n (keydown.enter)=\"onClick()\"\n (click)=\"onClick()\"\n #button\n >\n <ng-container *ngTemplateOutlet=\"buttonContent; context: { button: config }\"></ng-container>\n </div>\n }\n }\n}\n\n<ng-template #buttonContent let-button=\"button\">\n @if (button.imgSrc) {\n <div class=\"button-icon button-icon--img\">\n <m-img [src]=\"button.imgSrc\" [remote]=\"button.remote\" [alt]=\"button.label || button.name || ''\" />\n @if (button.badge && button.badge.count) {\n <m-badge\n [config]=\"{ variant: button.badge.variant ?? 'danger', position: 'absolute' }\"\n >{{ formatBadgeCount(button.badge.count) }}</m-badge\n >\n }\n </div>\n } @else if (buttonIcon(); as icon) {\n <div class=\"button-icon\">\n @if (isFromOne()) {\n <m-one-icon [config]=\"icon\" />\n } @else {\n <m-icon [config]=\"icon\" />\n }\n @if (button.badge && button.badge.count) {\n <m-badge\n [config]=\"{ variant: button.badge.variant ?? 'danger', position: 'absolute' }\"\n >{{ formatBadgeCount(button.badge.count) }}</m-badge\n >\n }\n </div>\n }\n @if (button.label && !button.iconOnly) {\n <span class=\"button-label {{ button.labelClass || '' }}\">\n {{ button.noTranslate ? button.label : (button.label | translate: button.params) }}\n </span>\n }\n @if (!buttonIcon() && button.badge && button.badge.count) {\n <m-badge [config]=\"{ variant: button.badge.variant ?? 'danger', position: 'static' }\">{{\n formatBadgeCount(button.badge.count)\n }}</m-badge>\n }\n</ng-template>\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)}}:host{display:inline-flex;align-items:center;justify-content:center;vertical-align:middle;box-sizing:border-box;overflow:hidden;transition:box-shadow .15s ease;--m-btn-size: var(--m-button-size, 1em);--m-btn-color: var(--m-button-color, var(--m-one-button-color, var(--m-mm)));--m-btn-color-contrast: var(--m-button-color-contrast, var(--m-one-button-color-contrast, #ffffff));--m-btn-color-opposite: var(--m-button-color-opposite, var(--m-one-button-color-opposite, #e1b941));--m-btn-h: calc(var(--m-btn-size) * 2.25);width:var(--m-button-width, var(--m-one-button-width, auto));min-width:0;height:var(--m-btn-h);font-size:var(--m-btn-size)}:host-context(.inverse),:host-context(.tabs-inverse),:host.inverse{--m-btn-color: var(--m-button-color, var(--m-one-button-color, var(--m-inverse-text)))}:host:has(.full-width){display:flex;width:100%}:host:has(.full-width) button .button-label{white-space:normal;overflow:visible;text-overflow:clip;word-break:break-word}:host:has(.only-icon),:host:has(.toggle){width:var(--m-btn-h);min-width:var(--m-btn-h)}:host:has(.has-badge){overflow:visible}:host:has(.stacked),:host:has(.toggle){height:auto}button:not(.get):not(.toggle){height:calc(var(--input-size, var(--m-btn-size)) * 2);min-height:calc(var(--input-size, var(--m-btn-size)) * 2);border-width:max(1px,var(--input-size, var(--m-btn-size)) * .0625);border-radius:calc(var(--input-size, var(--m-btn-size)) * .4);padding:calc(var(--input-size, var(--m-btn-size)) * .5) calc(var(--input-size, var(--m-btn-size)) * .5);gap:calc(var(--input-size, var(--m-btn-size)) * .375);font-size:var(--input-size, var(--m-btn-size));border-color:var(--m-btn-color);transition:border-color .2s ease,box-shadow .2s ease,background-color .2s ease,opacity .2s ease}button:not(.get):not(.toggle):hover:not(:disabled){background-color:color-mix(in srgb,var(--m-btn-color) 6%,transparent)}button:not(.get):not(.toggle):disabled{opacity:.6;cursor:not-allowed}button:not(.get):not(.toggle){height:auto;padding:calc(var(--m-btn-size) * .625) calc(var(--m-btn-size) * 1.25);gap:calc(var(--m-btn-size) * .375);border-style:solid;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;font-family:inherit;cursor:pointer;appearance:none;width:100%;height:100%;min-height:0;padding:0 calc(var(--m-btn-size) * 1.25);border-width:var(--m-button-border-width, 1px);border-radius:var(--m-button-radius, calc(var(--m-btn-size) * .5));color:var(--m-btn-color);font-weight:300;line-height:1;-webkit-user-select:none;user-select:none;position:relative;outline:none;box-shadow:var(--m-button-shadow, var(--m-one-button-shadow, none));transition:filter .15s ease,background .15s ease}button:not(.get):not(.toggle):hover:not(:disabled){filter:brightness(1.04)}button:not(.get):not(.toggle):focus-visible:not(:disabled){outline:2px solid color-mix(in srgb,var(--m-focus) 45%,transparent);outline-offset:-2px}button:not(.get):not(.toggle):active:not(:disabled){transform:scale(.97)}button:not(.get):not(.toggle):disabled{opacity:.35;cursor:not-allowed;pointer-events:none;filter:grayscale(80%)}button:not(.get):not(.toggle).read-only{pointer-events:none!important;cursor:default!important;transform:none!important;box-shadow:none!important;background:transparent!important;border-color:transparent!important;opacity:1!important}button:not(.get):not(.toggle).read-only .button-icon{transform:none!important;color:inherit!important}button:not(.get):not(.toggle).primary{background:var(--m-btn-color);border-color:var(--m-btn-color);color:var(--m-btn-color-contrast)}button:not(.get):not(.toggle).primary:hover:not(:disabled){filter:none;background:color-mix(in srgb,var(--m-btn-color) 88%,black);border-color:color-mix(in srgb,var(--m-btn-color) 88%,black)}button:not(.get):not(.toggle).primary:active:not(:disabled){filter:brightness(.94);transform:scale(.97)}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab){background:transparent;border-color:transparent;color:var(--m-btn-color);box-shadow:none}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab):hover:not(:disabled){filter:none;background:color-mix(in srgb,var(--m-btn-color) 8%,transparent)}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab):active:not(:disabled){background:color-mix(in srgb,var(--m-btn-color) 14%,transparent);transform:scale(.97)}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab).secondary{border:var(--m-button-border-width, 1px) solid color-mix(in srgb,var(--m-btn-color) 15%,transparent)}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab).secondary:hover:not(:disabled){filter:none;border-color:color-mix(in srgb,var(--m-btn-color) 40%,transparent);background:color-mix(in srgb,var(--m-btn-color) 6%,transparent)}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab).secondary:active:not(:disabled){border-color:color-mix(in srgb,var(--m-btn-color) 50%,transparent);background:color-mix(in srgb,var(--m-btn-color) 12%,transparent)}button:not(.get):not(.toggle).secondary:not(.primary):not(.ghost){background:transparent;border-color:var(--m-btn-color);color:var(--m-btn-color)}button:not(.get):not(.toggle).secondary:not(.primary):not(.ghost):hover:not(:disabled){filter:none;background:color-mix(in srgb,var(--m-btn-color) 8%,transparent)}button:not(.get):not(.toggle).secondary:not(.primary):not(.ghost):active:not(:disabled){background:color-mix(in srgb,var(--m-btn-color) 14%,transparent);transform:scale(.97)}button:not(.get):not(.toggle).tab{background:var(--m-backdrop-border);border-color:var(--m-backdrop-border);color:var(--m-btn-color)}button:not(.get):not(.toggle).tab:hover:not(:disabled){background:color-mix(in srgb,var(--m-backdrop-border) 82%,black);border-color:color-mix(in srgb,var(--m-backdrop-border) 82%,black);filter:none}button:not(.get):not(.toggle).tab:active:not(:disabled){background:color-mix(in srgb,var(--m-backdrop-border) 70%,black);border-color:color-mix(in srgb,var(--m-backdrop-border) 70%,black);transform:scale(.97)}button:not(.get):not(.toggle).segmented .button-icon,button:not(.get):not(.toggle).badge-accent .button-icon,button:not(.get):not(.toggle).with-right-icon .button-icon{display:inline-flex;align-items:center;justify-content:center;color:var(--m-btn-color-opposite);order:1}button:not(.get):not(.toggle).segmented .button-label,button:not(.get):not(.toggle).badge-accent .button-label,button:not(.get):not(.toggle).with-right-icon .button-label{order:-1}button:not(.get):not(.toggle).segmented.primary .button-icon,button:not(.get):not(.toggle).badge-accent.primary .button-icon,button:not(.get):not(.toggle).with-right-icon.primary .button-icon{color:var(--m-btn-color-opposite)}button:not(.get):not(.toggle).with-left-icon .button-icon{order:-1}button:not(.get):not(.toggle).with-left-icon .button-label{order:1}button:not(.get):not(.toggle).stacked{flex-direction:column;gap:calc(var(--m-btn-size) * .3);height:auto;min-height:var(--m-btn-h);padding:calc(var(--m-btn-size) * .625) calc(var(--m-btn-size) * .875)}button:not(.get):not(.toggle).stacked .button-label{font-size:calc(var(--m-btn-size) * .8)}button:not(.get):not(.toggle).only-icon{padding:0;border-width:var(--m-button-border-width, 1px);aspect-ratio:1;display:inline-flex;align-items:center;justify-content:center}button:not(.get):not(.toggle).only-icon m-icon,button:not(.get):not(.toggle).only-icon m-one-icon{display:inline-flex}m-badge{--m-badge-height: 1.5em;--m-badge-min-width: 1.5em;--m-badge-padding: 0 .3em;--m-badge-gap: .1em}.button-label{display:inline-flex;align-items:center;line-height:normal;font-size:inherit;min-width:0;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.button-icon{position:relative;display:inline-flex;align-items:center;justify-content:center}.button-icon--img{width:calc(var(--m-btn-size) * 1.75);height:calc(var(--m-btn-size) * 1.75);overflow:hidden}.button-icon--img m-img{width:100%;height:100%;display:block}.get{appearance:none;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;height:var(--m-btn-h);padding:0 min(var(--m-btn-size) * 1.75,2rem);border-radius:4px;background:linear-gradient(135deg,var(--m-mm),var(--m-focus),var(--m-success),var(--m-mm));background-size:200% auto;color:#fff;font-size:calc(var(--m-btn-size) * .8);font-weight:300;letter-spacing:.06em;text-transform:uppercase;border:none;cursor:pointer;white-space:nowrap;line-height:1;transition:background-position .2s ease,transform .15s ease}.get:hover{background-position:right center}.get:focus-visible{outline:2px solid color-mix(in srgb,var(--m-focus) 45%,transparent);outline-offset:-2px}.get:active{transform:scale(.97)}.toggle{appearance:none;display:inline-flex;align-items:center;justify-content:center;width:100%;height:100%;border:none;background:transparent;padding:0 min(var(--m-btn-size),1.25rem);border-radius:var(--m-button-radius, calc(var(--m-btn-size) * .375));box-shadow:none;color:var(--m-btn-color, var(--m-text-secondary));opacity:.65;font-family:inherit;font-size:var(--m-btn-size);font-weight:300;cursor:pointer;box-sizing:border-box;-webkit-user-select:none;user-select:none;transition:background .15s ease,color .15s ease,opacity .15s ease;min-width:0}.toggle .button-icon{flex-shrink:0}.toggle .button-label{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%;min-width:0}.toggle:hover:not(:disabled){background:var(--m-button-hover-background, color-mix(in srgb, var(--m-focus) 8%, transparent));color:var(--m-button-hover-color, var(--m-text));opacity:1}.toggle:focus-visible:not(:disabled){outline:2px solid color-mix(in srgb,var(--m-focus) 45%,transparent);outline-offset:-2px;opacity:1}.toggle.primary{background:var(--m-button-active-background, var(--m-mm));color:var(--m-button-active-color, #ffffff);opacity:1}.toggle.primary:hover:not(:disabled){background:var(--m-button-active-background, var(--m-mm));color:var(--m-button-active-color, #ffffff);opacity:1}.toggle.primary:active:not(:disabled){transform:scale(.97)}.non-native:not(.get):not(.toggle){appearance:none;display:inline-flex;align-items:center;justify-content:center;width:100%;height:100%;min-height:0;padding:0 calc(var(--m-btn-size) * 1.25);border-width:2px;border-radius:4px;color:var(--m-btn-color);font-weight:300;line-height:1;-webkit-user-select:none;user-select:none;position:relative;outline:none;box-shadow:var(--m-button-shadow, var(--m-one-button-shadow, none));transition:filter .15s ease,background .15s ease}.non-native:not(.get):not(.toggle):hover:not([aria-disabled=true]){filter:brightness(1.04)}.non-native:not(.get):not(.toggle):focus-visible:not([aria-disabled=true]){outline:2px solid color-mix(in srgb,var(--m-focus) 45%,transparent);outline-offset:-2px}.non-native:not(.get):not(.toggle):active:not([aria-disabled=true]){transform:scale(.97)}.non-native:not(.get):not(.toggle)[aria-disabled=true]{opacity:.35;cursor:not-allowed;pointer-events:none;filter:grayscale(80%)}.non-native:not(.get):not(.toggle).primary{background:var(--m-btn-color);border-color:var(--m-btn-color);color:var(--m-btn-color-contrast)}.non-native:not(.get):not(.toggle).primary:hover:not([aria-disabled=true]){filter:none;background:color-mix(in srgb,var(--m-btn-color) 88%,black);border-color:color-mix(in srgb,var(--m-btn-color) 88%,black)}.non-native:not(.get):not(.toggle).primary:active:not([aria-disabled=true]){filter:brightness(.94);transform:scale(.97)}.non-native:not(.get):not(.toggle).ghost:not(.primary):not(.tab){background:transparent;border-color:transparent;color:var(--m-btn-color);box-shadow:none}.non-native:not(.get):not(.toggle).ghost:not(.primary):not(.tab):hover:not([aria-disabled=true]){filter:none;background:color-mix(in srgb,var(--m-btn-color) 8%,transparent)}.non-native:not(.get):not(.toggle).ghost:not(.primary):not(.tab):active:not([aria-disabled=true]){background:color-mix(in srgb,var(--m-btn-color) 14%,transparent);transform:scale(.97)}.non-native:not(.get):not(.toggle):disabled{opacity:.3;cursor:not-allowed}@container togglegroup (max-width: 320px){.non-native:not(.get):not(.toggle).with-left-icon .button-label,.non-native:not(.get):not(.toggle).with-right-icon .button-label{display:none!important}}@media(max-width:600px){.non-native:not(.get):not(.toggle).with-left-icon .button-label,.non-native:not(.get):not(.toggle).with-right-icon .button-label{display:none!important}}\n"], dependencies: [{ kind: "component", type: i0.forwardRef(() => IconComponent), selector: "m-icon, m-one-icon", inputs: ["config", "name", "color", "size", "one", "baseUrl", "remote"], outputs: ["configChange"] }, { kind: "component", type: i0.forwardRef(() => BadgeComponent), selector: "m-badge", inputs: ["config"], outputs: ["configChange"] }, { kind: "ngmodule", type: i0.forwardRef(() => RouterModule) }, { kind: "directive", type: i0.forwardRef(() => MRefDirective), selector: "[mRef]", inputs: ["mRef", "mRefLinkActive", "mRefToggle", "mRefParams"] }, { kind: "directive", type: i0.forwardRef(() => NgTemplateOutlet), selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i0.forwardRef(() => ImgComponent), selector: "m-img", inputs: ["src", "data", "dataType", "alt", "priority", "fill", "width", "height", "remote", "ngSrcset", "sizes"] }, { kind: "pipe", type: i0.forwardRef(() => TranslatePipe), name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
8245
+ // Auth URL defaults to Backend URL so single-host apps stay unchanged (ADR 0012).
8246
+ const effectiveAuth = authUrl || effectiveBackend;
8247
+ httpService.setUrl(effectiveBackend);
8248
+ httpService.setAuthUrl(effectiveAuth);
8249
+ themeStore.init();
8250
+ if (socketUrl) {
8251
+ const socketStore = inject(SocketStore);
8252
+ let lastToken;
8253
+ effect(() => {
8254
+ const tokens = loginStore?.tokens();
8255
+ const currentToken = tokens?.auth;
8256
+ if (!currentToken) {
8257
+ socketStore.disconnect();
8258
+ lastToken = undefined;
8259
+ return;
8260
+ }
8261
+ // If we already connected with this exact token, skip
8262
+ if (lastToken === currentToken)
8263
+ return;
8264
+ // If another instance (e.g. host app) has already established a socket,
8265
+ // and we are a new instance (e.g. WC) that hasn't connected yet, skip.
8266
+ if (SharedStoreRegistry.isHostSocketActive() &&
8267
+ lastToken === undefined) {
8268
+ return;
8269
+ }
8270
+ // Connect (or reconnect if lastToken was different)
8271
+ socketStore.connect(`${socketUrl}?token=${currentToken}`);
8272
+ SharedStoreRegistry.setSocketUrl(socketUrl);
8273
+ lastToken = currentToken;
8274
+ });
8275
+ }
8276
+ if (!loginStore)
8277
+ return EMPTY;
8278
+ // Load saved login IDs before init so the modal shows them if it opens
8279
+ if (!loginStore.tokens()) {
8280
+ loginStore.loadSavedLoginIds();
8281
+ }
8282
+ // Always call init — interceptor handles no-token case via authenticate()
8283
+ return httpService
8284
+ .put('auth', ['init'])
8285
+ .pipe(tap(({ navs, tokens, user }) => {
8286
+ loginStore.initApp({ navs, tokens, user });
8287
+ }), catchError(() => {
8288
+ loginStore.loadSavedLoginIds();
8289
+ return EMPTY;
8290
+ }),
8291
+ // The App's apis refuse without a current Agreement (store ADR 0006),
8292
+ // so init asks for it before the App renders.
8293
+ switchMap$1(() => {
8294
+ const link = appLink();
8295
+ return link ? from(agreementGate.ensure(link)) : of(undefined);
8296
+ }));
8297
+ };
7077
8298
  }
7078
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ButtonComponent, decorators: [{
7079
- type: Component,
7080
- args: [{ selector: 'm-button,m-one-button', imports: [
7081
- forwardRef(() => TranslatePipe),
7082
- forwardRef(() => IconComponent),
7083
- forwardRef(() => BadgeComponent),
7084
- RouterModule,
7085
- MRefDirective,
7086
- forwardRef(() => NgTemplateOutlet),
7087
- forwardRef(() => ImgComponent),
7088
- ], encapsulation: ViewEncapsulation.Emulated, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (config(); as config) {\n <!-- One branch for every in-app target: `mRef` names a NavId and the store\n reads the NavKind off that node to decide route vs panel (ADR 0014). -->\n @if (config.nav) {\n @if (!noNative()) {\n <button\n type=\"button\"\n class=\"{{ className() }}\"\n [attr.data-testid]=\"config.name + '-btn'\"\n [attr.tabindex]=\"config.tabindex\"\n [disabled]=\"config.disabled\"\n [mRef]=\"config.nav\"\n [mRefParams]=\"config.navParams\"\n [attr.aria-label]=\"config.noTranslate ? config.label : (config.label | translate: config.params)\"\n mRefLinkActive=\"tab\"\n (keydown.enter)=\"onClick()\"\n (click)=\"onClick()\"\n #button\n >\n <ng-container *ngTemplateOutlet=\"buttonContent; context: { button: config }\"></ng-container>\n </button>\n } @else {\n <div\n role=\"button\"\n [attr.tabindex]=\"config.tabindex ?? 0\"\n class=\"non-native {{ className() }}\"\n [attr.data-testid]=\"config.name + '-btn'\"\n [attr.aria-label]=\"config.noTranslate ? config.label : (config.label | translate: config.params)\"\n [attr.aria-disabled]=\"config.disabled ? 'true' : 'false'\"\n (keydown.enter)=\"onClick()\"\n (click)=\"onClick()\"\n #button\n >\n <ng-container *ngTemplateOutlet=\"buttonContent; context: { button: config }\"></ng-container>\n </div>\n }\n } @else if (config.href) {\n <a\n class=\"{{ className() }}\"\n [attr.data-testid]=\"config.name + '-btn'\"\n [attr.tabindex]=\"config.tabindex\"\n [href]=\"config.href\"\n [attr.aria-label]=\"config.noTranslate ? config.label : (config.label | translate: config.params)\"\n (click)=\"onClick()\"\n #button\n >\n <ng-container *ngTemplateOutlet=\"buttonContent; context: { button: config }\"></ng-container>\n </a>\n } @else {\n @if (!noNative()) {\n <button\n type=\"button\"\n class=\"{{ className() }}\"\n [attr.data-testid]=\"config.name + '-btn'\"\n [attr.tabindex]=\"config.tabindex\"\n [disabled]=\"isDisabled()\"\n [attr.aria-label]=\"config.noTranslate ? config.label : (config.label | translate: config.params)\"\n (keydown.enter)=\"onClick()\"\n (click)=\"onClick()\"\n #button\n >\n <ng-container *ngTemplateOutlet=\"buttonContent; context: { button: config }\"></ng-container>\n </button>\n } @else {\n <div\n role=\"button\"\n [attr.tabindex]=\"config.tabindex ?? 0\"\n class=\"non-native {{ className() }}\"\n [attr.data-testid]=\"config.name + '-btn'\"\n [attr.aria-label]=\"config.noTranslate ? config.label : (config.label | translate: config.params)\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : 'false'\"\n (keydown.enter)=\"onClick()\"\n (click)=\"onClick()\"\n #button\n >\n <ng-container *ngTemplateOutlet=\"buttonContent; context: { button: config }\"></ng-container>\n </div>\n }\n }\n}\n\n<ng-template #buttonContent let-button=\"button\">\n @if (button.imgSrc) {\n <div class=\"button-icon button-icon--img\">\n <m-img [src]=\"button.imgSrc\" [remote]=\"button.remote\" [alt]=\"button.label || button.name || ''\" />\n @if (button.badge && button.badge.count) {\n <m-badge\n [config]=\"{ variant: button.badge.variant ?? 'danger', position: 'absolute' }\"\n >{{ formatBadgeCount(button.badge.count) }}</m-badge\n >\n }\n </div>\n } @else if (buttonIcon(); as icon) {\n <div class=\"button-icon\">\n @if (isFromOne()) {\n <m-one-icon [config]=\"icon\" />\n } @else {\n <m-icon [config]=\"icon\" />\n }\n @if (button.badge && button.badge.count) {\n <m-badge\n [config]=\"{ variant: button.badge.variant ?? 'danger', position: 'absolute' }\"\n >{{ formatBadgeCount(button.badge.count) }}</m-badge\n >\n }\n </div>\n }\n @if (button.label && !button.iconOnly) {\n <span class=\"button-label {{ button.labelClass || '' }}\">\n {{ button.noTranslate ? button.label : (button.label | translate: button.params) }}\n </span>\n }\n @if (!buttonIcon() && button.badge && button.badge.count) {\n <m-badge [config]=\"{ variant: button.badge.variant ?? 'danger', position: 'static' }\">{{\n formatBadgeCount(button.badge.count)\n }}</m-badge>\n }\n</ng-template>\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)}}:host{display:inline-flex;align-items:center;justify-content:center;vertical-align:middle;box-sizing:border-box;overflow:hidden;transition:box-shadow .15s ease;--m-btn-size: var(--m-button-size, 1em);--m-btn-color: var(--m-button-color, var(--m-one-button-color, var(--m-mm)));--m-btn-color-contrast: var(--m-button-color-contrast, var(--m-one-button-color-contrast, #ffffff));--m-btn-color-opposite: var(--m-button-color-opposite, var(--m-one-button-color-opposite, #e1b941));--m-btn-h: calc(var(--m-btn-size) * 2.25);width:var(--m-button-width, var(--m-one-button-width, auto));min-width:0;height:var(--m-btn-h);font-size:var(--m-btn-size)}:host-context(.inverse),:host-context(.tabs-inverse),:host.inverse{--m-btn-color: var(--m-button-color, var(--m-one-button-color, var(--m-inverse-text)))}:host:has(.full-width){display:flex;width:100%}:host:has(.full-width) button .button-label{white-space:normal;overflow:visible;text-overflow:clip;word-break:break-word}:host:has(.only-icon),:host:has(.toggle){width:var(--m-btn-h);min-width:var(--m-btn-h)}:host:has(.has-badge){overflow:visible}:host:has(.stacked),:host:has(.toggle){height:auto}button:not(.get):not(.toggle){height:calc(var(--input-size, var(--m-btn-size)) * 2);min-height:calc(var(--input-size, var(--m-btn-size)) * 2);border-width:max(1px,var(--input-size, var(--m-btn-size)) * .0625);border-radius:calc(var(--input-size, var(--m-btn-size)) * .4);padding:calc(var(--input-size, var(--m-btn-size)) * .5) calc(var(--input-size, var(--m-btn-size)) * .5);gap:calc(var(--input-size, var(--m-btn-size)) * .375);font-size:var(--input-size, var(--m-btn-size));border-color:var(--m-btn-color);transition:border-color .2s ease,box-shadow .2s ease,background-color .2s ease,opacity .2s ease}button:not(.get):not(.toggle):hover:not(:disabled){background-color:color-mix(in srgb,var(--m-btn-color) 6%,transparent)}button:not(.get):not(.toggle):disabled{opacity:.6;cursor:not-allowed}button:not(.get):not(.toggle){height:auto;padding:calc(var(--m-btn-size) * .625) calc(var(--m-btn-size) * 1.25);gap:calc(var(--m-btn-size) * .375);border-style:solid;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;font-family:inherit;cursor:pointer;appearance:none;width:100%;height:100%;min-height:0;padding:0 calc(var(--m-btn-size) * 1.25);border-width:var(--m-button-border-width, 1px);border-radius:var(--m-button-radius, calc(var(--m-btn-size) * .5));color:var(--m-btn-color);font-weight:300;line-height:1;-webkit-user-select:none;user-select:none;position:relative;outline:none;box-shadow:var(--m-button-shadow, var(--m-one-button-shadow, none));transition:filter .15s ease,background .15s ease}button:not(.get):not(.toggle):hover:not(:disabled){filter:brightness(1.04)}button:not(.get):not(.toggle):focus-visible:not(:disabled){outline:2px solid color-mix(in srgb,var(--m-focus) 45%,transparent);outline-offset:-2px}button:not(.get):not(.toggle):active:not(:disabled){transform:scale(.97)}button:not(.get):not(.toggle):disabled{opacity:.35;cursor:not-allowed;pointer-events:none;filter:grayscale(80%)}button:not(.get):not(.toggle).read-only{pointer-events:none!important;cursor:default!important;transform:none!important;box-shadow:none!important;background:transparent!important;border-color:transparent!important;opacity:1!important}button:not(.get):not(.toggle).read-only .button-icon{transform:none!important;color:inherit!important}button:not(.get):not(.toggle).primary{background:var(--m-btn-color);border-color:var(--m-btn-color);color:var(--m-btn-color-contrast)}button:not(.get):not(.toggle).primary:hover:not(:disabled){filter:none;background:color-mix(in srgb,var(--m-btn-color) 88%,black);border-color:color-mix(in srgb,var(--m-btn-color) 88%,black)}button:not(.get):not(.toggle).primary:active:not(:disabled){filter:brightness(.94);transform:scale(.97)}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab){background:transparent;border-color:transparent;color:var(--m-btn-color);box-shadow:none}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab):hover:not(:disabled){filter:none;background:color-mix(in srgb,var(--m-btn-color) 8%,transparent)}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab):active:not(:disabled){background:color-mix(in srgb,var(--m-btn-color) 14%,transparent);transform:scale(.97)}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab).secondary{border:var(--m-button-border-width, 1px) solid color-mix(in srgb,var(--m-btn-color) 15%,transparent)}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab).secondary:hover:not(:disabled){filter:none;border-color:color-mix(in srgb,var(--m-btn-color) 40%,transparent);background:color-mix(in srgb,var(--m-btn-color) 6%,transparent)}button:not(.get):not(.toggle).ghost:not(.primary):not(.tab).secondary:active:not(:disabled){border-color:color-mix(in srgb,var(--m-btn-color) 50%,transparent);background:color-mix(in srgb,var(--m-btn-color) 12%,transparent)}button:not(.get):not(.toggle).secondary:not(.primary):not(.ghost){background:transparent;border-color:var(--m-btn-color);color:var(--m-btn-color)}button:not(.get):not(.toggle).secondary:not(.primary):not(.ghost):hover:not(:disabled){filter:none;background:color-mix(in srgb,var(--m-btn-color) 8%,transparent)}button:not(.get):not(.toggle).secondary:not(.primary):not(.ghost):active:not(:disabled){background:color-mix(in srgb,var(--m-btn-color) 14%,transparent);transform:scale(.97)}button:not(.get):not(.toggle).tab{background:var(--m-backdrop-border);border-color:var(--m-backdrop-border);color:var(--m-btn-color)}button:not(.get):not(.toggle).tab:hover:not(:disabled){background:color-mix(in srgb,var(--m-backdrop-border) 82%,black);border-color:color-mix(in srgb,var(--m-backdrop-border) 82%,black);filter:none}button:not(.get):not(.toggle).tab:active:not(:disabled){background:color-mix(in srgb,var(--m-backdrop-border) 70%,black);border-color:color-mix(in srgb,var(--m-backdrop-border) 70%,black);transform:scale(.97)}button:not(.get):not(.toggle).segmented .button-icon,button:not(.get):not(.toggle).badge-accent .button-icon,button:not(.get):not(.toggle).with-right-icon .button-icon{display:inline-flex;align-items:center;justify-content:center;color:var(--m-btn-color-opposite);order:1}button:not(.get):not(.toggle).segmented .button-label,button:not(.get):not(.toggle).badge-accent .button-label,button:not(.get):not(.toggle).with-right-icon .button-label{order:-1}button:not(.get):not(.toggle).segmented.primary .button-icon,button:not(.get):not(.toggle).badge-accent.primary .button-icon,button:not(.get):not(.toggle).with-right-icon.primary .button-icon{color:var(--m-btn-color-opposite)}button:not(.get):not(.toggle).with-left-icon .button-icon{order:-1}button:not(.get):not(.toggle).with-left-icon .button-label{order:1}button:not(.get):not(.toggle).stacked{flex-direction:column;gap:calc(var(--m-btn-size) * .3);height:auto;min-height:var(--m-btn-h);padding:calc(var(--m-btn-size) * .625) calc(var(--m-btn-size) * .875)}button:not(.get):not(.toggle).stacked .button-label{font-size:calc(var(--m-btn-size) * .8)}button:not(.get):not(.toggle).only-icon{padding:0;border-width:var(--m-button-border-width, 1px);aspect-ratio:1;display:inline-flex;align-items:center;justify-content:center}button:not(.get):not(.toggle).only-icon m-icon,button:not(.get):not(.toggle).only-icon m-one-icon{display:inline-flex}m-badge{--m-badge-height: 1.5em;--m-badge-min-width: 1.5em;--m-badge-padding: 0 .3em;--m-badge-gap: .1em}.button-label{display:inline-flex;align-items:center;line-height:normal;font-size:inherit;min-width:0;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.button-icon{position:relative;display:inline-flex;align-items:center;justify-content:center}.button-icon--img{width:calc(var(--m-btn-size) * 1.75);height:calc(var(--m-btn-size) * 1.75);overflow:hidden}.button-icon--img m-img{width:100%;height:100%;display:block}.get{appearance:none;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;height:var(--m-btn-h);padding:0 min(var(--m-btn-size) * 1.75,2rem);border-radius:4px;background:linear-gradient(135deg,var(--m-mm),var(--m-focus),var(--m-success),var(--m-mm));background-size:200% auto;color:#fff;font-size:calc(var(--m-btn-size) * .8);font-weight:300;letter-spacing:.06em;text-transform:uppercase;border:none;cursor:pointer;white-space:nowrap;line-height:1;transition:background-position .2s ease,transform .15s ease}.get:hover{background-position:right center}.get:focus-visible{outline:2px solid color-mix(in srgb,var(--m-focus) 45%,transparent);outline-offset:-2px}.get:active{transform:scale(.97)}.toggle{appearance:none;display:inline-flex;align-items:center;justify-content:center;width:100%;height:100%;border:none;background:transparent;padding:0 min(var(--m-btn-size),1.25rem);border-radius:var(--m-button-radius, calc(var(--m-btn-size) * .375));box-shadow:none;color:var(--m-btn-color, var(--m-text-secondary));opacity:.65;font-family:inherit;font-size:var(--m-btn-size);font-weight:300;cursor:pointer;box-sizing:border-box;-webkit-user-select:none;user-select:none;transition:background .15s ease,color .15s ease,opacity .15s ease;min-width:0}.toggle .button-icon{flex-shrink:0}.toggle .button-label{display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%;min-width:0}.toggle:hover:not(:disabled){background:var(--m-button-hover-background, color-mix(in srgb, var(--m-focus) 8%, transparent));color:var(--m-button-hover-color, var(--m-text));opacity:1}.toggle:focus-visible:not(:disabled){outline:2px solid color-mix(in srgb,var(--m-focus) 45%,transparent);outline-offset:-2px;opacity:1}.toggle.primary{background:var(--m-button-active-background, var(--m-mm));color:var(--m-button-active-color, #ffffff);opacity:1}.toggle.primary:hover:not(:disabled){background:var(--m-button-active-background, var(--m-mm));color:var(--m-button-active-color, #ffffff);opacity:1}.toggle.primary:active:not(:disabled){transform:scale(.97)}.non-native:not(.get):not(.toggle){appearance:none;display:inline-flex;align-items:center;justify-content:center;width:100%;height:100%;min-height:0;padding:0 calc(var(--m-btn-size) * 1.25);border-width:2px;border-radius:4px;color:var(--m-btn-color);font-weight:300;line-height:1;-webkit-user-select:none;user-select:none;position:relative;outline:none;box-shadow:var(--m-button-shadow, var(--m-one-button-shadow, none));transition:filter .15s ease,background .15s ease}.non-native:not(.get):not(.toggle):hover:not([aria-disabled=true]){filter:brightness(1.04)}.non-native:not(.get):not(.toggle):focus-visible:not([aria-disabled=true]){outline:2px solid color-mix(in srgb,var(--m-focus) 45%,transparent);outline-offset:-2px}.non-native:not(.get):not(.toggle):active:not([aria-disabled=true]){transform:scale(.97)}.non-native:not(.get):not(.toggle)[aria-disabled=true]{opacity:.35;cursor:not-allowed;pointer-events:none;filter:grayscale(80%)}.non-native:not(.get):not(.toggle).primary{background:var(--m-btn-color);border-color:var(--m-btn-color);color:var(--m-btn-color-contrast)}.non-native:not(.get):not(.toggle).primary:hover:not([aria-disabled=true]){filter:none;background:color-mix(in srgb,var(--m-btn-color) 88%,black);border-color:color-mix(in srgb,var(--m-btn-color) 88%,black)}.non-native:not(.get):not(.toggle).primary:active:not([aria-disabled=true]){filter:brightness(.94);transform:scale(.97)}.non-native:not(.get):not(.toggle).ghost:not(.primary):not(.tab){background:transparent;border-color:transparent;color:var(--m-btn-color);box-shadow:none}.non-native:not(.get):not(.toggle).ghost:not(.primary):not(.tab):hover:not([aria-disabled=true]){filter:none;background:color-mix(in srgb,var(--m-btn-color) 8%,transparent)}.non-native:not(.get):not(.toggle).ghost:not(.primary):not(.tab):active:not([aria-disabled=true]){background:color-mix(in srgb,var(--m-btn-color) 14%,transparent);transform:scale(.97)}.non-native:not(.get):not(.toggle):disabled{opacity:.3;cursor:not-allowed}@container togglegroup (max-width: 320px){.non-native:not(.get):not(.toggle).with-left-icon .button-label,.non-native:not(.get):not(.toggle).with-right-icon .button-label{display:none!important}}@media(max-width:600px){.non-native:not(.get):not(.toggle).with-left-icon .button-label,.non-native:not(.get):not(.toggle).with-right-icon .button-label{display:none!important}}\n"] }]
7089
- }], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }, { type: i0.Output, args: ["configChange"] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], labelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelClass", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], nav: [{ type: i0.Input, args: [{ isSignal: true, alias: "nav", required: false }] }], navParams: [{ type: i0.Input, args: [{ isSignal: true, alias: "navParams", required: false }] }], href: [{ type: i0.Input, args: [{ isSignal: true, alias: "href", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], baseUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "baseUrl", required: false }] }], one: [{ type: i0.Input, args: [{ isSignal: true, alias: "one", required: false }] }], remote: [{ type: i0.Input, args: [{ isSignal: true, alias: "remote", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], noTranslate: [{ type: i0.Input, args: [{ isSignal: true, alias: "noTranslate", required: false }] }], params: [{ type: i0.Input, args: [{ isSignal: true, alias: "params", required: false }] }], noNative: [{ type: i0.Input, args: [{ isSignal: true, alias: "noNative", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], isRightIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRightIcon", required: false }] }], iconOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnly", required: false }] }], stacked: [{ type: i0.Input, args: [{ isSignal: true, alias: "stacked", required: false }] }], imgSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "imgSrc", required: false }] }], nonClickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "nonClickable", required: false }] }], inverted: [{ type: i0.Input, args: [{ isSignal: true, alias: "inverted", required: false }] }], isSubmit: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSubmit", required: false }] }], tabindex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabindex", required: false }] }], clicked: [{ type: i0.Output, args: ["clicked"] }], button: [{ type: i0.ViewChild, args: ['button', { isSignal: true }] }] } });
7090
8299
 
7091
8300
  /**
7092
8301
  * Sugar: a variant expands to a justify + align pair. Explicit `justify` /
@@ -7781,7 +8990,7 @@ class SectionFormItemComponent extends ConfigComponent {
7781
8990
  break;
7782
8991
  }
7783
8992
  case InputType.TOGGLE: {
7784
- const { ToggleInputComponent } = await import('./magmonium-one-toggle-atjxl_R_.mjs');
8993
+ const { ToggleInputComponent } = await import('./magmonium-one-toggle-DXiBGDPh.mjs');
7785
8994
  this.createDynamicComponent(seq, ToggleInputComponent, [], true);
7786
8995
  break;
7787
8996
  }
@@ -7793,12 +9002,12 @@ class SectionFormItemComponent extends ConfigComponent {
7793
9002
  break;
7794
9003
  }
7795
9004
  case InputType.PASSWORD: {
7796
- const { PasswordInputComponent } = await import('./magmonium-one-password-yXiSYlMS.mjs');
9005
+ const { PasswordInputComponent } = await import('./magmonium-one-password-B4R18v54.mjs');
7797
9006
  this.createDynamicComponent(seq, PasswordInputComponent);
7798
9007
  break;
7799
9008
  }
7800
9009
  case InputType.OTP: {
7801
- const { OtpInputComponent } = await import('./magmonium-one-otp-B-NBB6PF.mjs');
9010
+ const { OtpInputComponent } = await import('./magmonium-one-otp-Cq5Hfnh_.mjs');
7802
9011
  this.createDynamicComponent(seq, OtpInputComponent);
7803
9012
  break;
7804
9013
  }
@@ -9430,6 +10639,11 @@ class MenuComponent {
9430
10639
  this.#focusPending = this.#hasFocus();
9431
10640
  return;
9432
10641
  }
10642
+ // A row naming a Nav goes there itself — the NavKind on that node decides
10643
+ // whether it routes or opens a panel, the answer `[mRef]` gives (CONTEXT.md
10644
+ // NavRef). Still emitted, so whatever holds the menu closes it.
10645
+ if (item.nav)
10646
+ this.#navRef?.setSelected(item.nav, undefined, item.keepPanel ? { keepPanel: true } : undefined);
9433
10647
  this.action.emit(item);
9434
10648
  }
9435
10649
  goBack() {
@@ -9600,214 +10814,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
9600
10814
  }]
9601
10815
  }], propDecorators: { toggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "toggle", required: false }] }, { type: i0.Output, args: ["toggleChange"] }], remote: [{ type: i0.Input, args: [{ isSignal: true, alias: "remote", required: false }] }], exclude: [{ type: i0.Input, args: [{ isSignal: true, alias: "exclude", required: false }] }], 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 }] }], inverted: [{ type: i0.Input, args: [{ isSignal: true, alias: "inverted", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], action: [{ type: i0.Output, args: ["action"] }], selectorDir: [{ type: i0.ViewChild, args: [i0.forwardRef(() => SelectorDirective), { isSignal: true }] }] } });
9602
10816
 
9603
- let HeaderComponent$1 = class HeaderComponent {
9604
- level = input(3, ...(ngDevMode ? [{ debugName: "level" }] : /* istanbul ignore next */ []));
9605
- label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
9606
- // Drawn inside the heading rather than beside it. A glyph placed as the
9607
- // heading's sibling has no line box of its own to centre against — it ends
9608
- // up centred on whatever column it sits next to, which is how a Canvas
9609
- // header's icon came to line up with the label slot's drop rect instead of
9610
- // with the label. Inside, the two share one line box at every level.
9611
- icon = input(...(ngDevMode ? [undefined, { debugName: "icon" }] : /* istanbul ignore next */ []));
9612
- actionButton = input(...(ngDevMode ? [undefined, { debugName: "actionButton" }] : /* istanbul ignore next */ []));
9613
- // The action Button's accessible name. It renders icon-only, so the label is
9614
- // the only thing a screen reader has to go on — without it the button reads
9615
- // as nothing at all.
9616
- actionLabel = input(...(ngDevMode ? [undefined, { debugName: "actionLabel" }] : /* istanbul ignore next */ []));
9617
- // The label is authored text rather than a translation key. Needed for text
9618
- // carrying angle brackets above all: `translate` reads `<...>` as link
9619
- // markup, so a heading naming a MessageVariable — `<$app>` — resolves to
9620
- // nothing at all rather than to itself.
9621
- noTranslate = input(false, ...(ngDevMode ? [{ debugName: "noTranslate" }] : /* istanbul ignore next */ []));
9622
- // A message's [MessageVariable] values, the same record `m-text-output`
9623
- // takes: a heading naming `<$count>` is a sentence with a datum in it, and
9624
- // splicing that datum into the key instead would be parsed as a query
9625
- // string (m-one-ui ADR 0066).
9626
- params = input(undefined, ...(ngDevMode ? [{ debugName: "params" }] : /* istanbul ignore next */ []));
9627
- actionClick = output();
9628
- translateService = inject(TranslateService);
9629
- sizeContext = inject(SIZE_CONTEXT, { optional: true });
9630
- // The action Button sits inside the heading, whose font-size is the level's
9631
- // own — 2.25rem at h1 — so `em` inheritance would scale the Button to the
9632
- // heading rather than to the Section it belongs to. It reads the Size in
9633
- // force instead, the way Icon does, and lands at the same size as every
9634
- // other Button on that Section (ADR 0008).
9635
- actionSize = computed(() => resolveSize(this.sizeContext?.size()), ...(ngDevMode ? [{ debugName: "actionSize" }] : /* istanbul ignore next */ []));
9636
- actionConfig = computed(() => {
9637
- const icon = this.actionButton();
9638
- if (!icon)
9639
- return undefined;
9640
- return {
9641
- icon,
9642
- label: this.actionLabel(),
9643
- iconOnly: true,
9644
- variant: 'ghost',
9645
- };
9646
- }, ...(ngDevMode ? [{ debugName: "actionConfig" }] : /* istanbul ignore next */ []));
9647
- // A computed rather than the impure TranslatePipe repeated six times: one
9648
- // lookup per label change instead of one per change-detection tick, and it
9649
- // still repaints when the language or an in-memory translation moves.
9650
- text = computed(() => this.noTranslate()
9651
- ? (this.label() ?? '')
9652
- : this.translateService.translate(this.label(), this.params()), ...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []));
9653
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: HeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
9654
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: HeaderComponent, isStandalone: true, selector: "m-header", inputs: { level: { classPropertyName: "level", publicName: "level", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, actionButton: { classPropertyName: "actionButton", publicName: "actionButton", isSignal: true, isRequired: false, transformFunction: null }, actionLabel: { classPropertyName: "actionLabel", publicName: "actionLabel", isSignal: true, isRequired: false, transformFunction: null }, noTranslate: { classPropertyName: "noTranslate", publicName: "noTranslate", isSignal: true, isRequired: false, transformFunction: null }, params: { classPropertyName: "params", publicName: "params", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { actionClick: "actionClick" }, ngImport: i0, template: `
9655
- @switch (level()) {
9656
- @case (1) {
9657
- <h1 class="header__heading">
9658
- @if (icon(); as iconName) {
9659
- <m-icon class="header__icon" [name]="iconName" />
9660
- }
9661
- <span>{{ text() }}</span>
9662
- <ng-content />
9663
- @if (actionConfig(); as action) {
9664
- <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
9665
- }
9666
- </h1>
9667
- }
9668
- @case (2) {
9669
- <h2 class="header__heading">
9670
- @if (icon(); as iconName) {
9671
- <m-icon class="header__icon" [name]="iconName" />
9672
- }
9673
- <span>{{ text() }}</span>
9674
- <ng-content />
9675
- @if (actionConfig(); as action) {
9676
- <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
9677
- }
9678
- </h2>
9679
- }
9680
- @case (3) {
9681
- <h3 class="header__heading">
9682
- @if (icon(); as iconName) {
9683
- <m-icon class="header__icon" [name]="iconName" />
9684
- }
9685
- <span>{{ text() }}</span>
9686
- <ng-content />
9687
- @if (actionConfig(); as action) {
9688
- <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
9689
- }
9690
- </h3>
9691
- }
9692
- @case (4) {
9693
- <h4 class="header__heading">
9694
- @if (icon(); as iconName) {
9695
- <m-icon class="header__icon" [name]="iconName" />
9696
- }
9697
- <span>{{ text() }}</span>
9698
- <ng-content />
9699
- @if (actionConfig(); as action) {
9700
- <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
9701
- }
9702
- </h4>
9703
- }
9704
- @case (5) {
9705
- <h5 class="header__heading">
9706
- @if (icon(); as iconName) {
9707
- <m-icon class="header__icon" [name]="iconName" />
9708
- }
9709
- <span>{{ text() }}</span>
9710
- <ng-content />
9711
- @if (actionConfig(); as action) {
9712
- <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
9713
- }
9714
- </h5>
9715
- }
9716
- @case (6) {
9717
- <h6 class="header__heading">
9718
- @if (icon(); as iconName) {
9719
- <m-icon class="header__icon" [name]="iconName" />
9720
- }
9721
- <span>{{ text() }}</span>
9722
- <ng-content />
9723
- @if (actionConfig(); as action) {
9724
- <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
9725
- }
9726
- </h6>
9727
- }
9728
- }
9729
- `, 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)}}.header__heading{display:flex;flex-direction:row;align-items:center;justify-content:var(--m-header-justify, flex-start);gap:.75rem;margin:0;padding:0;line-height:1.1;font-weight:800;letter-spacing:-.025em;color:var(--m-header-color, var(--m-text));transition:transform .2s cubic-bezier(.4,0,.2,1)}.header__heading:hover{transform:translate(2px)}.header__icon{flex-shrink:0}.header__action{margin-left:auto}.header__action span{display:inline-block;vertical-align:middle}h1.header__heading{font-size:var(--m-header-font-size, 2.25rem);font-weight:300;color:var(--m-text-quaternary);letter-spacing:-.035em;line-height:1.15}h2.header__heading{font-size:var(--m-header-font-size, 1.75rem);font-weight:300;color:var(--m-text-tertiary);letter-spacing:-.03em;line-height:1.2}h3.header__heading{font-size:var(--m-header-font-size, 1.375rem);font-weight:400;color:var(--m-text-secondary);letter-spacing:-.025em}h4.header__heading{font-size:var(--m-header-font-size, 1.125rem);font-weight:500;color:var(--m-text);letter-spacing:-.02em}h5.header__heading{font-size:var(--m-header-font-size, 1rem);font-weight:600;color:var(--m-text);letter-spacing:-.01em}h6.header__heading{font-size:var(--m-header-font-size, .875rem);font-weight:600;color:var(--m-text);letter-spacing:.05em;text-transform:uppercase}\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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
9730
- };
9731
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: HeaderComponent$1, decorators: [{
9732
- type: Component,
9733
- args: [{ selector: 'm-header', imports: [ButtonComponent, IconComponent], template: `
9734
- @switch (level()) {
9735
- @case (1) {
9736
- <h1 class="header__heading">
9737
- @if (icon(); as iconName) {
9738
- <m-icon class="header__icon" [name]="iconName" />
9739
- }
9740
- <span>{{ text() }}</span>
9741
- <ng-content />
9742
- @if (actionConfig(); as action) {
9743
- <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
9744
- }
9745
- </h1>
9746
- }
9747
- @case (2) {
9748
- <h2 class="header__heading">
9749
- @if (icon(); as iconName) {
9750
- <m-icon class="header__icon" [name]="iconName" />
9751
- }
9752
- <span>{{ text() }}</span>
9753
- <ng-content />
9754
- @if (actionConfig(); as action) {
9755
- <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
9756
- }
9757
- </h2>
9758
- }
9759
- @case (3) {
9760
- <h3 class="header__heading">
9761
- @if (icon(); as iconName) {
9762
- <m-icon class="header__icon" [name]="iconName" />
9763
- }
9764
- <span>{{ text() }}</span>
9765
- <ng-content />
9766
- @if (actionConfig(); as action) {
9767
- <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
9768
- }
9769
- </h3>
9770
- }
9771
- @case (4) {
9772
- <h4 class="header__heading">
9773
- @if (icon(); as iconName) {
9774
- <m-icon class="header__icon" [name]="iconName" />
9775
- }
9776
- <span>{{ text() }}</span>
9777
- <ng-content />
9778
- @if (actionConfig(); as action) {
9779
- <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
9780
- }
9781
- </h4>
9782
- }
9783
- @case (5) {
9784
- <h5 class="header__heading">
9785
- @if (icon(); as iconName) {
9786
- <m-icon class="header__icon" [name]="iconName" />
9787
- }
9788
- <span>{{ text() }}</span>
9789
- <ng-content />
9790
- @if (actionConfig(); as action) {
9791
- <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
9792
- }
9793
- </h5>
9794
- }
9795
- @case (6) {
9796
- <h6 class="header__heading">
9797
- @if (icon(); as iconName) {
9798
- <m-icon class="header__icon" [name]="iconName" />
9799
- }
9800
- <span>{{ text() }}</span>
9801
- <ng-content />
9802
- @if (actionConfig(); as action) {
9803
- <m-button class="header__action" [config]="action" [style.--m-button-size]="actionSize()" (clicked)="actionClick.emit()" />
9804
- }
9805
- </h6>
9806
- }
9807
- }
9808
- `, 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)}}.header__heading{display:flex;flex-direction:row;align-items:center;justify-content:var(--m-header-justify, flex-start);gap:.75rem;margin:0;padding:0;line-height:1.1;font-weight:800;letter-spacing:-.025em;color:var(--m-header-color, var(--m-text));transition:transform .2s cubic-bezier(.4,0,.2,1)}.header__heading:hover{transform:translate(2px)}.header__icon{flex-shrink:0}.header__action{margin-left:auto}.header__action span{display:inline-block;vertical-align:middle}h1.header__heading{font-size:var(--m-header-font-size, 2.25rem);font-weight:300;color:var(--m-text-quaternary);letter-spacing:-.035em;line-height:1.15}h2.header__heading{font-size:var(--m-header-font-size, 1.75rem);font-weight:300;color:var(--m-text-tertiary);letter-spacing:-.03em;line-height:1.2}h3.header__heading{font-size:var(--m-header-font-size, 1.375rem);font-weight:400;color:var(--m-text-secondary);letter-spacing:-.025em}h4.header__heading{font-size:var(--m-header-font-size, 1.125rem);font-weight:500;color:var(--m-text);letter-spacing:-.02em}h5.header__heading{font-size:var(--m-header-font-size, 1rem);font-weight:600;color:var(--m-text);letter-spacing:-.01em}h6.header__heading{font-size:var(--m-header-font-size, .875rem);font-weight:600;color:var(--m-text);letter-spacing:.05em;text-transform:uppercase}\n"] }]
9809
- }], propDecorators: { level: [{ type: i0.Input, args: [{ isSignal: true, alias: "level", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], actionButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionButton", required: false }] }], actionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionLabel", required: false }] }], noTranslate: [{ type: i0.Input, args: [{ isSignal: true, alias: "noTranslate", required: false }] }], params: [{ type: i0.Input, args: [{ isSignal: true, alias: "params", required: false }] }], actionClick: [{ type: i0.Output, args: ["actionClick"] }] } });
9810
-
9811
10817
  const SECTION_CONTEXT = new InjectionToken('SECTION_CONTEXT');
9812
10818
 
9813
10819
  // The line box each heading level draws, straight from `header.sass`: its font
@@ -9923,7 +10929,7 @@ class SectionHeaderComponent {
9923
10929
  this.accordion()?.toggle();
9924
10930
  }
9925
10931
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SectionHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
9926
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: SectionHeaderComponent, isStandalone: true, selector: "m-section-header", inputs: { sticky: { classPropertyName: "sticky", publicName: "sticky", isSignal: true, isRequired: false, transformFunction: null }, level: { classPropertyName: "level", publicName: "level", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, subLabel: { classPropertyName: "subLabel", publicName: "subLabel", isSignal: true, isRequired: false, transformFunction: null }, noTranslate: { classPropertyName: "noTranslate", publicName: "noTranslate", isSignal: true, isRequired: false, transformFunction: null }, params: { classPropertyName: "params", publicName: "params", isSignal: true, isRequired: false, transformFunction: null }, reverse: { classPropertyName: "reverse", publicName: "reverse", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, menu: { classPropertyName: "menu", publicName: "menu", isSignal: true, isRequired: false, transformFunction: null }, menuName: { classPropertyName: "menuName", publicName: "menuName", 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 }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, showBack: { classPropertyName: "showBack", publicName: "showBack", isSignal: true, isRequired: false, transformFunction: null }, actionButton: { classPropertyName: "actionButton", publicName: "actionButton", isSignal: true, isRequired: false, transformFunction: null }, actionLabel: { classPropertyName: "actionLabel", publicName: "actionLabel", isSignal: true, isRequired: false, transformFunction: null }, spacing: { classPropertyName: "spacing", publicName: "spacing", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { actionClick: "actionClick", action: "action", back: "back" }, host: { properties: { "class.is-sticky-enabled": "sticky()", "class.is-sticky": "isSticky()", "class.has-menu": "hasMenu()", "class.align-left": "alignment() === \"left\"", "class.align-center": "alignment() === \"center\"", "class.align-right": "alignment() === \"right\"", "class.has-sidepanel": "sidepanel()", "class.no-border": "noBorder()", "class.spacing": "spacing()", "class.box-center": "boxAlign() === \"center\"", "class.box-right": "boxAlign() === \"right\"", "style.--m-section-header-max-width": "resolvedMaxWidth()", "style.--m-section-header-icon-box": "iconBox()" }, classAttribute: "m-section-header" }, ngImport: i0, template: "<!-- One declaration of the row, rendered by whichever branch `spacing` picks.\n Hoisted into a template rather than written twice: an `<ng-content>` may\n appear once per selector in a component, so the duplicated copy caught\n nothing and a header projecting a title rendered it in the `spacing`\n branch alone. -->\n<ng-template #body>\n @if (accordion(); as accordionRef) {\n <div\n class=\"section-header__toggle\"\n [class.section-header__toggle--rotate]=\"toggleRotates()\"\n [class.section-header__toggle--open]=\"accordionRef.isOpen()\"\n [id]=\"accordionRef.headerId\"\n [attr.aria-expanded]=\"accordionRef.isOpen()\"\n [attr.aria-controls]=\"accordionRef.bodyId\"\n >\n <m-button\n [config]=\"{ icon: toggleIconName(), iconOnly: true, variant: 'ghost' }\"\n (clicked)=\"onToggleClick()\" />\n </div>\n }\n @if (showBack()) {\n <div class=\"section-header__back\">\n <m-button\n [config]=\"{ icon: 'arrow_back', iconOnly: true }\"\n (clicked)=\"back.emit()\" />\n </div>\n } @else if (!label() && icon(); as iconName) {\n <!-- Only where no label is written. A header with one hands the icon to\n `m-header`, which draws it inside the heading's line box and so on the\n heading's own centre line. Beside a projected title there is no such\n box to borrow, so the glyph is boxed to the level's line box here and\n centred in it \u2014 otherwise it centres against the whole title column,\n which on the Canvas is the label slot's drop rect stacked above the\n heading. -->\n <div class=\"section-header__icon\">\n <m-icon [name]=\"iconName\" />\n </div>\n }\n <div\n class=\"section-header__title\"\n [class.section-header__title--reverse]=\"reverse()\"\n >\n <!-- The title slot is the catch-all rather than a `[label]` one: every\n header already projecting a heading writes it unselected, and a\n selector here would drop that content on the floor. What the design\n page emits \u2014 `<span label>` \u2014 is caught by it too, nothing else\n claiming the node. -->\n <ng-content />\n <!-- The written label, drawn beside the slot rather than as its\n `ng-content` fallback. A fallback renders only while *nothing* is\n projected, and the design Canvas always projects the slot span \u2014\n empty until a Control is dropped in it \u2014 so a fallback there would\n blank the label a header is still configured with. `label` answers\n instead, which no header projecting a title sets. -->\n @if (label()) {\n <m-header\n [level]=\"level()\"\n [label]=\"label()\"\n [icon]=\"icon()\"\n [params]=\"params()\"\n [noTranslate]=\"noTranslate()\" />\n }\n @if (subText(); as sub) {\n <span class=\"section-header__sub\">{{ sub }}</span>\n }\n </div>\n <!-- A FilterGroup projected into the header row, selected by tag rather than\n by an attribute \u2014 the same shape a Section catches its `m-action` with.\n A header has room for one icon and not for a row, so a group landing\n here is squeezed by placement (ADR 0025); nothing here enforces that,\n the caller binding `[squeeze]` on the tag it projects. -->\n <div class=\"section-header__filters\">\n <ng-content select=\"m-section-filter-group\" />\n </div>\n @if (actionConfig(); as action) {\n <div class=\"section-header__action\">\n <m-button [config]=\"action\" (clicked)=\"actionClick.emit()\" />\n </div>\n }\n @if (hasMenu()) {\n <div class=\"section-header__menu\">\n <m-context-menu\n [config]=\"menu()\"\n [name]=\"menuName()\"\n [visibilityRule]=\"visibilityRule()\"\n [disableRule]=\"disableRule()\"\n [extraData]=\"extraData()\"\n (action)=\"action.emit($event)\"\n />\n </div>\n }\n</ng-template>\n\n<!-- Always the same two boxes, whether or not a `maxWidth` is in force. The\n border and the sticky backdrop live on the host and keep spanning the\n Section's full width; only this container narrows and is placed by the\n Section's `align`, so the heading lines up with the body under it. -->\n<div class=\"section-header__container\">\n <div class=\"section-header__inner\">\n <ng-container [ngTemplateOutlet]=\"body\" />\n </div>\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)}}:host{display:flex;align-items:center;gap:.5rem;min-height:var(--section-header-min-height, calc(var(--section-header-py, .5rem) * 2 + 1.25rem));border-bottom:1px solid var(--m-backdrop-border);padding:var(--section-header-py, .85rem) var(--section-px, 1rem);width:100%;grid-column:1/-1}:host(.no-border){border-bottom:none}:host(.spacing){padding:0;width:100%}.section-header__container{width:100%;min-width:0;max-width:var(--m-section-header-max-width, none);margin-inline:0 auto}:host(.box-center) .section-header__container{margin-inline:auto}:host(.box-right) .section-header__container{margin-inline:auto 0}.section-header__inner{display:flex;align-items:center;gap:.5rem;width:100%;min-width:0}.section-header__inner .section-header__title{flex:1;min-width:0;gap:.5rem}:host(.spacing) .section-header__inner{padding:1rem 1.5rem}:host(.has-sidepanel){padding-right:50px}:host(.has-sidepanel.has-menu){padding-right:50px}:host(.spacing.has-sidepanel) .section-header__inner{padding-right:calc(1.5rem + 50px)}:host(.is-sticky-enabled){position:sticky;top:0;z-index:10}:host(.is-sticky-enabled){background:color-mix(in srgb,var(--m-background) 80%,transparent);backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%)}.section-header__toggle{display:flex;flex-shrink:0}.section-header__toggle.section-header__toggle--rotate m-button{display:flex;transition:transform .3s cubic-bezier(.4,0,.2,1)}.section-header__toggle.section-header__toggle--rotate.section-header__toggle--open m-button{transform:rotate(180deg)}.section-header__title{flex:1;min-width:0;display:flex;flex-direction:column;gap:.1rem}m-header{min-width:0}.section-header__title--reverse{flex-direction:column-reverse}.section-header__sub{font-size:.8rem;color:var(--m-text-secondary);line-height:1.2}:host(.align-center){--m-header-justify: center}:host(.align-right){--m-header-justify: flex-end}:host(.has-menu){padding-right:0}:host(.spacing.has-menu) .section-header__inner{padding-right:0}.section-header__filters{display:contents}.section-header__filters m-section-filter-group{width:auto;flex-shrink:0;border-bottom:none}.section-header__back{display:flex;align-items:center;flex-shrink:0}.section-header__icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;align-self:flex-start;height:var(--m-section-header-icon-box, 1.5125rem)}.section-header__menu,.section-header__action{margin-left:auto;flex-shrink:0;display:flex;align-items:center}.section-header__action+.section-header__menu{margin-left:0}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ContextMenuComponent, selector: "m-context-menu, m-one-context-menu", inputs: ["toggle", "remote", "exclude", "visibilityRule", "disableRule", "extraData", "inverted", "options"], outputs: ["toggleChange", "action"] }, { kind: "component", type: HeaderComponent$1, selector: "m-header", inputs: ["level", "label", "icon", "actionButton", "actionLabel", "noTranslate", "params"], outputs: ["actionClick"] }, { kind: "component", type: IconComponent, selector: "m-icon, m-one-icon", inputs: ["config", "name", "color", "size", "one", "baseUrl", "remote"], outputs: ["configChange"] }, { 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
10932
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: SectionHeaderComponent, isStandalone: true, selector: "m-section-header", inputs: { sticky: { classPropertyName: "sticky", publicName: "sticky", isSignal: true, isRequired: false, transformFunction: null }, level: { classPropertyName: "level", publicName: "level", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, subLabel: { classPropertyName: "subLabel", publicName: "subLabel", isSignal: true, isRequired: false, transformFunction: null }, noTranslate: { classPropertyName: "noTranslate", publicName: "noTranslate", isSignal: true, isRequired: false, transformFunction: null }, params: { classPropertyName: "params", publicName: "params", isSignal: true, isRequired: false, transformFunction: null }, reverse: { classPropertyName: "reverse", publicName: "reverse", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, menu: { classPropertyName: "menu", publicName: "menu", isSignal: true, isRequired: false, transformFunction: null }, menuName: { classPropertyName: "menuName", publicName: "menuName", 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 }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, showBack: { classPropertyName: "showBack", publicName: "showBack", isSignal: true, isRequired: false, transformFunction: null }, actionButton: { classPropertyName: "actionButton", publicName: "actionButton", isSignal: true, isRequired: false, transformFunction: null }, actionLabel: { classPropertyName: "actionLabel", publicName: "actionLabel", isSignal: true, isRequired: false, transformFunction: null }, spacing: { classPropertyName: "spacing", publicName: "spacing", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { actionClick: "actionClick", action: "action", back: "back" }, host: { properties: { "class.is-sticky-enabled": "sticky()", "class.is-sticky": "isSticky()", "class.has-menu": "hasMenu()", "class.align-left": "alignment() === \"left\"", "class.align-center": "alignment() === \"center\"", "class.align-right": "alignment() === \"right\"", "class.has-sidepanel": "sidepanel()", "class.no-border": "noBorder()", "class.spacing": "spacing()", "class.box-center": "boxAlign() === \"center\"", "class.box-right": "boxAlign() === \"right\"", "style.--m-section-header-max-width": "resolvedMaxWidth()", "style.--m-section-header-icon-box": "iconBox()" }, classAttribute: "m-section-header" }, ngImport: i0, template: "<!-- One declaration of the row, rendered by whichever branch `spacing` picks.\n Hoisted into a template rather than written twice: an `<ng-content>` may\n appear once per selector in a component, so the duplicated copy caught\n nothing and a header projecting a title rendered it in the `spacing`\n branch alone. -->\n<ng-template #body>\n @if (accordion(); as accordionRef) {\n <div\n class=\"section-header__toggle\"\n [class.section-header__toggle--rotate]=\"toggleRotates()\"\n [class.section-header__toggle--open]=\"accordionRef.isOpen()\"\n [id]=\"accordionRef.headerId\"\n [attr.aria-expanded]=\"accordionRef.isOpen()\"\n [attr.aria-controls]=\"accordionRef.bodyId\"\n >\n <m-button\n [config]=\"{ icon: toggleIconName(), iconOnly: true, variant: 'ghost' }\"\n (clicked)=\"onToggleClick()\" />\n </div>\n }\n @if (showBack()) {\n <div class=\"section-header__back\">\n <m-button\n [config]=\"{ icon: 'chevron-left', iconOnly: true }\"\n (clicked)=\"back.emit()\" />\n </div>\n } @else if (!label() && icon(); as iconName) {\n <!-- Only where no label is written. A header with one hands the icon to\n `m-header`, which draws it inside the heading's line box and so on the\n heading's own centre line. Beside a projected title there is no such\n box to borrow, so the glyph is boxed to the level's line box here and\n centred in it \u2014 otherwise it centres against the whole title column,\n which on the Canvas is the label slot's drop rect stacked above the\n heading. -->\n <div class=\"section-header__icon\">\n <m-icon [name]=\"iconName\" />\n </div>\n }\n <div\n class=\"section-header__title\"\n [class.section-header__title--reverse]=\"reverse()\"\n >\n <!-- The title slot is the catch-all rather than a `[label]` one: every\n header already projecting a heading writes it unselected, and a\n selector here would drop that content on the floor. What the design\n page emits \u2014 `<span label>` \u2014 is caught by it too, nothing else\n claiming the node. -->\n <ng-content />\n <!-- The written label, drawn beside the slot rather than as its\n `ng-content` fallback. A fallback renders only while *nothing* is\n projected, and the design Canvas always projects the slot span \u2014\n empty until a Control is dropped in it \u2014 so a fallback there would\n blank the label a header is still configured with. `label` answers\n instead, which no header projecting a title sets. -->\n @if (label()) {\n <m-header\n [level]=\"level()\"\n [label]=\"label()\"\n [icon]=\"icon()\"\n [params]=\"params()\"\n [noTranslate]=\"noTranslate()\" />\n }\n @if (subText(); as sub) {\n <span class=\"section-header__sub\">{{ sub }}</span>\n }\n </div>\n <!-- A FilterGroup projected into the header row, selected by tag rather than\n by an attribute \u2014 the same shape a Section catches its `m-action` with.\n A header has room for one icon and not for a row, so a group landing\n here is squeezed by placement (ADR 0025); nothing here enforces that,\n the caller binding `[squeeze]` on the tag it projects. -->\n <div class=\"section-header__filters\">\n <ng-content select=\"m-section-filter-group\" />\n </div>\n @if (actionConfig(); as action) {\n <div class=\"section-header__action\">\n <m-button [config]=\"action\" (clicked)=\"actionClick.emit()\" />\n </div>\n }\n @if (hasMenu()) {\n <div class=\"section-header__menu\">\n <m-context-menu\n [config]=\"menu()\"\n [name]=\"menuName()\"\n [visibilityRule]=\"visibilityRule()\"\n [disableRule]=\"disableRule()\"\n [extraData]=\"extraData()\"\n (action)=\"action.emit($event)\"\n />\n </div>\n }\n</ng-template>\n\n<!-- Always the same two boxes, whether or not a `maxWidth` is in force. The\n border and the sticky backdrop live on the host and keep spanning the\n Section's full width; only this container narrows and is placed by the\n Section's `align`, so the heading lines up with the body under it. -->\n<div class=\"section-header__container\">\n <div class=\"section-header__inner\">\n <ng-container [ngTemplateOutlet]=\"body\" />\n </div>\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)}}:host{display:flex;align-items:center;gap:.5rem;min-height:var(--section-header-min-height, calc(var(--section-header-py, .5rem) * 2 + 1.25rem));border-bottom:1px solid var(--m-backdrop-border);padding:var(--section-header-py, .85rem) var(--section-px, 1rem);width:100%;grid-column:1/-1}:host(.no-border){border-bottom:none}:host(.spacing){padding:0;width:100%}.section-header__container{width:100%;min-width:0;max-width:var(--m-section-header-max-width, none);margin-inline:0 auto}:host(.box-center) .section-header__container{margin-inline:auto}:host(.box-right) .section-header__container{margin-inline:auto 0}.section-header__inner{display:flex;align-items:center;gap:.5rem;width:100%;min-width:0}.section-header__inner .section-header__title{flex:1;min-width:0;gap:.5rem}:host(.spacing) .section-header__inner{padding:1rem 1.5rem}:host(.has-sidepanel){padding-right:50px}:host(.has-sidepanel.has-menu){padding-right:50px}:host(.spacing.has-sidepanel) .section-header__inner{padding-right:calc(1.5rem + 50px)}:host(.is-sticky-enabled){position:sticky;top:0;z-index:10}:host(.is-sticky-enabled){background:color-mix(in srgb,var(--m-background) 80%,transparent);backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%)}.section-header__toggle{display:flex;flex-shrink:0}.section-header__toggle.section-header__toggle--rotate m-button{display:flex;transition:transform .3s cubic-bezier(.4,0,.2,1)}.section-header__toggle.section-header__toggle--rotate.section-header__toggle--open m-button{transform:rotate(180deg)}.section-header__title{flex:1;min-width:0;display:flex;flex-direction:column;gap:.1rem}m-header{min-width:0}.section-header__title--reverse{flex-direction:column-reverse}.section-header__sub{font-size:.8rem;color:var(--m-text-secondary);line-height:1.2}:host(.align-center){--m-header-justify: center}:host(.align-right){--m-header-justify: flex-end}:host(.has-menu){padding-right:0}:host(.spacing.has-menu) .section-header__inner{padding-right:0}.section-header__filters{display:contents}.section-header__filters m-section-filter-group{width:auto;flex-shrink:0;border-bottom:none}.section-header__back{display:flex;align-items:center;flex-shrink:0}.section-header__icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;align-self:flex-start;height:var(--m-section-header-icon-box, 1.5125rem)}.section-header__menu,.section-header__action{margin-left:auto;flex-shrink:0;display:flex;align-items:center}.section-header__action+.section-header__menu{margin-left:0}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ContextMenuComponent, selector: "m-context-menu, m-one-context-menu", inputs: ["toggle", "remote", "exclude", "visibilityRule", "disableRule", "extraData", "inverted", "options"], outputs: ["toggleChange", "action"] }, { kind: "component", type: HeaderComponent$1, selector: "m-header", inputs: ["level", "label", "icon", "actionButton", "actionLabel", "noTranslate", "params"], outputs: ["actionClick"] }, { kind: "component", type: IconComponent, selector: "m-icon, m-one-icon", inputs: ["config", "name", "color", "size", "one", "baseUrl", "remote"], outputs: ["configChange"] }, { 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
9927
10933
  }
9928
10934
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SectionHeaderComponent, decorators: [{
9929
10935
  type: Component,
@@ -9948,11 +10954,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
9948
10954
  '[class.box-right]': 'boxAlign() === "right"',
9949
10955
  '[style.--m-section-header-max-width]': 'resolvedMaxWidth()',
9950
10956
  '[style.--m-section-header-icon-box]': 'iconBox()',
9951
- }, template: "<!-- One declaration of the row, rendered by whichever branch `spacing` picks.\n Hoisted into a template rather than written twice: an `<ng-content>` may\n appear once per selector in a component, so the duplicated copy caught\n nothing and a header projecting a title rendered it in the `spacing`\n branch alone. -->\n<ng-template #body>\n @if (accordion(); as accordionRef) {\n <div\n class=\"section-header__toggle\"\n [class.section-header__toggle--rotate]=\"toggleRotates()\"\n [class.section-header__toggle--open]=\"accordionRef.isOpen()\"\n [id]=\"accordionRef.headerId\"\n [attr.aria-expanded]=\"accordionRef.isOpen()\"\n [attr.aria-controls]=\"accordionRef.bodyId\"\n >\n <m-button\n [config]=\"{ icon: toggleIconName(), iconOnly: true, variant: 'ghost' }\"\n (clicked)=\"onToggleClick()\" />\n </div>\n }\n @if (showBack()) {\n <div class=\"section-header__back\">\n <m-button\n [config]=\"{ icon: 'arrow_back', iconOnly: true }\"\n (clicked)=\"back.emit()\" />\n </div>\n } @else if (!label() && icon(); as iconName) {\n <!-- Only where no label is written. A header with one hands the icon to\n `m-header`, which draws it inside the heading's line box and so on the\n heading's own centre line. Beside a projected title there is no such\n box to borrow, so the glyph is boxed to the level's line box here and\n centred in it \u2014 otherwise it centres against the whole title column,\n which on the Canvas is the label slot's drop rect stacked above the\n heading. -->\n <div class=\"section-header__icon\">\n <m-icon [name]=\"iconName\" />\n </div>\n }\n <div\n class=\"section-header__title\"\n [class.section-header__title--reverse]=\"reverse()\"\n >\n <!-- The title slot is the catch-all rather than a `[label]` one: every\n header already projecting a heading writes it unselected, and a\n selector here would drop that content on the floor. What the design\n page emits \u2014 `<span label>` \u2014 is caught by it too, nothing else\n claiming the node. -->\n <ng-content />\n <!-- The written label, drawn beside the slot rather than as its\n `ng-content` fallback. A fallback renders only while *nothing* is\n projected, and the design Canvas always projects the slot span \u2014\n empty until a Control is dropped in it \u2014 so a fallback there would\n blank the label a header is still configured with. `label` answers\n instead, which no header projecting a title sets. -->\n @if (label()) {\n <m-header\n [level]=\"level()\"\n [label]=\"label()\"\n [icon]=\"icon()\"\n [params]=\"params()\"\n [noTranslate]=\"noTranslate()\" />\n }\n @if (subText(); as sub) {\n <span class=\"section-header__sub\">{{ sub }}</span>\n }\n </div>\n <!-- A FilterGroup projected into the header row, selected by tag rather than\n by an attribute \u2014 the same shape a Section catches its `m-action` with.\n A header has room for one icon and not for a row, so a group landing\n here is squeezed by placement (ADR 0025); nothing here enforces that,\n the caller binding `[squeeze]` on the tag it projects. -->\n <div class=\"section-header__filters\">\n <ng-content select=\"m-section-filter-group\" />\n </div>\n @if (actionConfig(); as action) {\n <div class=\"section-header__action\">\n <m-button [config]=\"action\" (clicked)=\"actionClick.emit()\" />\n </div>\n }\n @if (hasMenu()) {\n <div class=\"section-header__menu\">\n <m-context-menu\n [config]=\"menu()\"\n [name]=\"menuName()\"\n [visibilityRule]=\"visibilityRule()\"\n [disableRule]=\"disableRule()\"\n [extraData]=\"extraData()\"\n (action)=\"action.emit($event)\"\n />\n </div>\n }\n</ng-template>\n\n<!-- Always the same two boxes, whether or not a `maxWidth` is in force. The\n border and the sticky backdrop live on the host and keep spanning the\n Section's full width; only this container narrows and is placed by the\n Section's `align`, so the heading lines up with the body under it. -->\n<div class=\"section-header__container\">\n <div class=\"section-header__inner\">\n <ng-container [ngTemplateOutlet]=\"body\" />\n </div>\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)}}:host{display:flex;align-items:center;gap:.5rem;min-height:var(--section-header-min-height, calc(var(--section-header-py, .5rem) * 2 + 1.25rem));border-bottom:1px solid var(--m-backdrop-border);padding:var(--section-header-py, .85rem) var(--section-px, 1rem);width:100%;grid-column:1/-1}:host(.no-border){border-bottom:none}:host(.spacing){padding:0;width:100%}.section-header__container{width:100%;min-width:0;max-width:var(--m-section-header-max-width, none);margin-inline:0 auto}:host(.box-center) .section-header__container{margin-inline:auto}:host(.box-right) .section-header__container{margin-inline:auto 0}.section-header__inner{display:flex;align-items:center;gap:.5rem;width:100%;min-width:0}.section-header__inner .section-header__title{flex:1;min-width:0;gap:.5rem}:host(.spacing) .section-header__inner{padding:1rem 1.5rem}:host(.has-sidepanel){padding-right:50px}:host(.has-sidepanel.has-menu){padding-right:50px}:host(.spacing.has-sidepanel) .section-header__inner{padding-right:calc(1.5rem + 50px)}:host(.is-sticky-enabled){position:sticky;top:0;z-index:10}:host(.is-sticky-enabled){background:color-mix(in srgb,var(--m-background) 80%,transparent);backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%)}.section-header__toggle{display:flex;flex-shrink:0}.section-header__toggle.section-header__toggle--rotate m-button{display:flex;transition:transform .3s cubic-bezier(.4,0,.2,1)}.section-header__toggle.section-header__toggle--rotate.section-header__toggle--open m-button{transform:rotate(180deg)}.section-header__title{flex:1;min-width:0;display:flex;flex-direction:column;gap:.1rem}m-header{min-width:0}.section-header__title--reverse{flex-direction:column-reverse}.section-header__sub{font-size:.8rem;color:var(--m-text-secondary);line-height:1.2}:host(.align-center){--m-header-justify: center}:host(.align-right){--m-header-justify: flex-end}:host(.has-menu){padding-right:0}:host(.spacing.has-menu) .section-header__inner{padding-right:0}.section-header__filters{display:contents}.section-header__filters m-section-filter-group{width:auto;flex-shrink:0;border-bottom:none}.section-header__back{display:flex;align-items:center;flex-shrink:0}.section-header__icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;align-self:flex-start;height:var(--m-section-header-icon-box, 1.5125rem)}.section-header__menu,.section-header__action{margin-left:auto;flex-shrink:0;display:flex;align-items:center}.section-header__action+.section-header__menu{margin-left:0}\n"] }]
10957
+ }, template: "<!-- One declaration of the row, rendered by whichever branch `spacing` picks.\n Hoisted into a template rather than written twice: an `<ng-content>` may\n appear once per selector in a component, so the duplicated copy caught\n nothing and a header projecting a title rendered it in the `spacing`\n branch alone. -->\n<ng-template #body>\n @if (accordion(); as accordionRef) {\n <div\n class=\"section-header__toggle\"\n [class.section-header__toggle--rotate]=\"toggleRotates()\"\n [class.section-header__toggle--open]=\"accordionRef.isOpen()\"\n [id]=\"accordionRef.headerId\"\n [attr.aria-expanded]=\"accordionRef.isOpen()\"\n [attr.aria-controls]=\"accordionRef.bodyId\"\n >\n <m-button\n [config]=\"{ icon: toggleIconName(), iconOnly: true, variant: 'ghost' }\"\n (clicked)=\"onToggleClick()\" />\n </div>\n }\n @if (showBack()) {\n <div class=\"section-header__back\">\n <m-button\n [config]=\"{ icon: 'chevron-left', iconOnly: true }\"\n (clicked)=\"back.emit()\" />\n </div>\n } @else if (!label() && icon(); as iconName) {\n <!-- Only where no label is written. A header with one hands the icon to\n `m-header`, which draws it inside the heading's line box and so on the\n heading's own centre line. Beside a projected title there is no such\n box to borrow, so the glyph is boxed to the level's line box here and\n centred in it \u2014 otherwise it centres against the whole title column,\n which on the Canvas is the label slot's drop rect stacked above the\n heading. -->\n <div class=\"section-header__icon\">\n <m-icon [name]=\"iconName\" />\n </div>\n }\n <div\n class=\"section-header__title\"\n [class.section-header__title--reverse]=\"reverse()\"\n >\n <!-- The title slot is the catch-all rather than a `[label]` one: every\n header already projecting a heading writes it unselected, and a\n selector here would drop that content on the floor. What the design\n page emits \u2014 `<span label>` \u2014 is caught by it too, nothing else\n claiming the node. -->\n <ng-content />\n <!-- The written label, drawn beside the slot rather than as its\n `ng-content` fallback. A fallback renders only while *nothing* is\n projected, and the design Canvas always projects the slot span \u2014\n empty until a Control is dropped in it \u2014 so a fallback there would\n blank the label a header is still configured with. `label` answers\n instead, which no header projecting a title sets. -->\n @if (label()) {\n <m-header\n [level]=\"level()\"\n [label]=\"label()\"\n [icon]=\"icon()\"\n [params]=\"params()\"\n [noTranslate]=\"noTranslate()\" />\n }\n @if (subText(); as sub) {\n <span class=\"section-header__sub\">{{ sub }}</span>\n }\n </div>\n <!-- A FilterGroup projected into the header row, selected by tag rather than\n by an attribute \u2014 the same shape a Section catches its `m-action` with.\n A header has room for one icon and not for a row, so a group landing\n here is squeezed by placement (ADR 0025); nothing here enforces that,\n the caller binding `[squeeze]` on the tag it projects. -->\n <div class=\"section-header__filters\">\n <ng-content select=\"m-section-filter-group\" />\n </div>\n @if (actionConfig(); as action) {\n <div class=\"section-header__action\">\n <m-button [config]=\"action\" (clicked)=\"actionClick.emit()\" />\n </div>\n }\n @if (hasMenu()) {\n <div class=\"section-header__menu\">\n <m-context-menu\n [config]=\"menu()\"\n [name]=\"menuName()\"\n [visibilityRule]=\"visibilityRule()\"\n [disableRule]=\"disableRule()\"\n [extraData]=\"extraData()\"\n (action)=\"action.emit($event)\"\n />\n </div>\n }\n</ng-template>\n\n<!-- Always the same two boxes, whether or not a `maxWidth` is in force. The\n border and the sticky backdrop live on the host and keep spanning the\n Section's full width; only this container narrows and is placed by the\n Section's `align`, so the heading lines up with the body under it. -->\n<div class=\"section-header__container\">\n <div class=\"section-header__inner\">\n <ng-container [ngTemplateOutlet]=\"body\" />\n </div>\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)}}:host{display:flex;align-items:center;gap:.5rem;min-height:var(--section-header-min-height, calc(var(--section-header-py, .5rem) * 2 + 1.25rem));border-bottom:1px solid var(--m-backdrop-border);padding:var(--section-header-py, .85rem) var(--section-px, 1rem);width:100%;grid-column:1/-1}:host(.no-border){border-bottom:none}:host(.spacing){padding:0;width:100%}.section-header__container{width:100%;min-width:0;max-width:var(--m-section-header-max-width, none);margin-inline:0 auto}:host(.box-center) .section-header__container{margin-inline:auto}:host(.box-right) .section-header__container{margin-inline:auto 0}.section-header__inner{display:flex;align-items:center;gap:.5rem;width:100%;min-width:0}.section-header__inner .section-header__title{flex:1;min-width:0;gap:.5rem}:host(.spacing) .section-header__inner{padding:1rem 1.5rem}:host(.has-sidepanel){padding-right:50px}:host(.has-sidepanel.has-menu){padding-right:50px}:host(.spacing.has-sidepanel) .section-header__inner{padding-right:calc(1.5rem + 50px)}:host(.is-sticky-enabled){position:sticky;top:0;z-index:10}:host(.is-sticky-enabled){background:color-mix(in srgb,var(--m-background) 80%,transparent);backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%)}.section-header__toggle{display:flex;flex-shrink:0}.section-header__toggle.section-header__toggle--rotate m-button{display:flex;transition:transform .3s cubic-bezier(.4,0,.2,1)}.section-header__toggle.section-header__toggle--rotate.section-header__toggle--open m-button{transform:rotate(180deg)}.section-header__title{flex:1;min-width:0;display:flex;flex-direction:column;gap:.1rem}m-header{min-width:0}.section-header__title--reverse{flex-direction:column-reverse}.section-header__sub{font-size:.8rem;color:var(--m-text-secondary);line-height:1.2}:host(.align-center){--m-header-justify: center}:host(.align-right){--m-header-justify: flex-end}:host(.has-menu){padding-right:0}:host(.spacing.has-menu) .section-header__inner{padding-right:0}.section-header__filters{display:contents}.section-header__filters m-section-filter-group{width:auto;flex-shrink:0;border-bottom:none}.section-header__back{display:flex;align-items:center;flex-shrink:0}.section-header__icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;align-self:flex-start;height:var(--m-section-header-icon-box, 1.5125rem)}.section-header__menu,.section-header__action{margin-left:auto;flex-shrink:0;display:flex;align-items:center}.section-header__action+.section-header__menu{margin-left:0}\n"] }]
9952
10958
  }], propDecorators: { sticky: [{ type: i0.Input, args: [{ isSignal: true, alias: "sticky", required: false }] }], level: [{ type: i0.Input, args: [{ isSignal: true, alias: "level", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], subLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "subLabel", required: false }] }], noTranslate: [{ type: i0.Input, args: [{ isSignal: true, alias: "noTranslate", required: false }] }], params: [{ type: i0.Input, args: [{ isSignal: true, alias: "params", required: false }] }], reverse: [{ type: i0.Input, args: [{ isSignal: true, alias: "reverse", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], menu: [{ type: i0.Input, args: [{ isSignal: true, alias: "menu", required: false }] }], menuName: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuName", required: false }] }], 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 }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], showBack: [{ type: i0.Input, args: [{ isSignal: true, alias: "showBack", required: false }] }], actionButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionButton", required: false }] }], actionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionLabel", required: false }] }], spacing: [{ type: i0.Input, args: [{ isSignal: true, alias: "spacing", required: false }] }], maxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxWidth", required: false }] }], actionClick: [{ type: i0.Output, args: ["actionClick"] }], action: [{ type: i0.Output, args: ["action"] }], back: [{ type: i0.Output, args: ["back"] }] } });
9953
10959
 
9954
10960
  const BACK_BTN = {
9955
- icon: 'arrow-left',
10961
+ icon: 'chevron-left',
9956
10962
  iconOnly: true,
9957
10963
  variant: 'ghost',
9958
10964
  };
@@ -9992,7 +10998,7 @@ class SectionBackComponent {
9992
10998
  <m-header [level]="3" [label]="label() ?? 'magmonium'" />
9993
10999
  }
9994
11000
  }
9995
- `, 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)}}:host{display:flex;align-items:center;gap:.75rem;min-height:var(--section-header-min-height, calc(var(--section-header-py, .5rem) * 2 + 1.25rem));border-bottom:1px solid var(--m-backdrop-border);width:100%;grid-column:1/-1}:host(.no-border){border-bottom:none}m-logo{flex-shrink:0;width:1.5rem;height:1.5rem}m-header{flex:1;min-width:0}:host>span{display:contents}:host.has-padding-x{padding-inline:var(--section-px, 1rem)}:host.has-padding-y{padding-block:var(--section-header-py, .85rem)}\n"], dependencies: [{ kind: "component", type: IconComponent, selector: "m-icon, m-one-icon", inputs: ["config", "name", "color", "size", "one", "baseUrl", "remote"], outputs: ["configChange"] }, { 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: HeaderComponent$1, selector: "m-header", inputs: ["level", "label", "icon", "actionButton", "actionLabel", "noTranslate", "params"], outputs: ["actionClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
11001
+ `, 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)}}:host{display:flex;align-items:center;gap:.25rem;min-height:var(--section-header-min-height, calc(var(--section-header-py, .5rem) * 2 + 1.25rem));border-bottom:1px solid var(--m-backdrop-border);width:100%;grid-column:1/-1;--section-back-size: .7rem;--section-back-seat: calc(var(--section-back-size) * 2.25)}:host(.no-border){border-bottom:none}m-button,m-icon{flex-shrink:0}m-button{--m-button-size: var(--section-back-size)}m-icon{display:inline-flex;justify-content:center;width:var(--section-back-seat)}m-logo{flex-shrink:0;width:1.5rem;height:1.5rem}m-header{flex:1;min-width:0}:host>span{display:contents}:host.has-padding-x{padding-inline:var(--section-px, 1rem)}:host.has-padding-y{padding-block:var(--section-header-py, .85rem)}\n"], dependencies: [{ kind: "component", type: IconComponent, selector: "m-icon, m-one-icon", inputs: ["config", "name", "color", "size", "one", "baseUrl", "remote"], outputs: ["configChange"] }, { 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: HeaderComponent$1, selector: "m-header", inputs: ["level", "label", "icon", "actionButton", "actionLabel", "noTranslate", "params"], outputs: ["actionClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
9996
11002
  }
9997
11003
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SectionBackComponent, decorators: [{
9998
11004
  type: Component,
@@ -10016,7 +11022,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
10016
11022
  '[class.has-padding-x]': 'padding() || paddingX()',
10017
11023
  '[class.has-padding-y]': 'padding() || paddingY()',
10018
11024
  '[class.no-border]': 'noBorder()',
10019
- }, 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)}}:host{display:flex;align-items:center;gap:.75rem;min-height:var(--section-header-min-height, calc(var(--section-header-py, .5rem) * 2 + 1.25rem));border-bottom:1px solid var(--m-backdrop-border);width:100%;grid-column:1/-1}:host(.no-border){border-bottom:none}m-logo{flex-shrink:0;width:1.5rem;height:1.5rem}m-header{flex:1;min-width:0}:host>span{display:contents}:host.has-padding-x{padding-inline:var(--section-px, 1rem)}:host.has-padding-y{padding-block:var(--section-header-py, .85rem)}\n"] }]
11025
+ }, 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)}}:host{display:flex;align-items:center;gap:.25rem;min-height:var(--section-header-min-height, calc(var(--section-header-py, .5rem) * 2 + 1.25rem));border-bottom:1px solid var(--m-backdrop-border);width:100%;grid-column:1/-1;--section-back-size: .7rem;--section-back-seat: calc(var(--section-back-size) * 2.25)}:host(.no-border){border-bottom:none}m-button,m-icon{flex-shrink:0}m-button{--m-button-size: var(--section-back-size)}m-icon{display:inline-flex;justify-content:center;width:var(--section-back-seat)}m-logo{flex-shrink:0;width:1.5rem;height:1.5rem}m-header{flex:1;min-width:0}:host>span{display:contents}:host.has-padding-x{padding-inline:var(--section-px, 1rem)}:host.has-padding-y{padding-block:var(--section-header-py, .85rem)}\n"] }]
10020
11026
  }], ctorParameters: () => [], propDecorators: { back: [{ type: i0.Input, args: [{ isSignal: true, alias: "back", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], html: [{ type: i0.Input, args: [{ isSignal: true, alias: "html", required: false }] }], padding: [{ type: i0.Input, args: [{ isSignal: true, alias: "padding", required: false }] }], paddingX: [{ type: i0.Input, args: [{ isSignal: true, alias: "paddingX", required: false }] }], paddingY: [{ type: i0.Input, args: [{ isSignal: true, alias: "paddingY", required: false }] }], navigate: [{ type: i0.Output, args: ["navigate"] }], contentRef: [{ type: i0.ViewChild, args: ['content', { isSignal: true }] }] } });
10021
11027
 
10022
11028
  /**
@@ -10344,6 +11350,11 @@ class ActionComponent extends ButtonGroupComponent {
10344
11350
  // consumes the Buttons dropped on a SectionAction into `[buttons]` and writes
10345
11351
  // every other setting as an attribute (ADR 0010).
10346
11352
  variant = input(...(ngDevMode ? [undefined, { debugName: "variant" }] : /* istanbul ignore next */ []));
11353
+ // A toggle's lit Button, named by a host that also moves the pick from
11354
+ // outside the bar — a shortcut, a store. It wins over the last press, so a
11355
+ // host binding it follows `clicked` back into it, the way a controlled input
11356
+ // does. Unset leaves the bar keeping its own selection.
11357
+ active = input(...(ngDevMode ? [undefined, { debugName: "active" }] : /* istanbul ignore next */ []));
10347
11358
  // Design-mode only: Button name -> the id of the Control it was folded from.
10348
11359
  // The Canvas draws a folded Button through this bar rather than as a tag of
10349
11360
  // its own, so the `render-id` its ControlLayer measures has nowhere else to
@@ -10422,6 +11433,9 @@ class ActionComponent extends ButtonGroupComponent {
10422
11433
  }
10423
11434
  if (this.resolvedVariant() !== 'toggle')
10424
11435
  return this.config()?.primary;
11436
+ const named = this.active();
11437
+ if (named && buttons.some((b) => b.name === named))
11438
+ return named;
10425
11439
  const pressed = this.pressed();
10426
11440
  if (pressed && buttons.some((b) => b.name === pressed))
10427
11441
  return pressed;
@@ -10458,10 +11472,12 @@ class ActionComponent extends ButtonGroupComponent {
10458
11472
  }
10459
11473
  return undefined;
10460
11474
  }, ...(ngDevMode ? [{ debugName: "activeSqueeze" }] : /* istanbul ignore next */ []));
10461
- // Only where the icon can carry the Button on its own — a label dropped off
10462
- // a Button with no glyph behind it leaves an empty box to press.
11475
+ // Squeezed to icons, or asked for by the Button itself (`iconOnly`). Only
11476
+ // where the icon can carry the Button on its own — a label dropped off a
11477
+ // Button with no glyph behind it leaves an empty box to press.
10463
11478
  isLabelHidden(button) {
10464
- return this.activeSqueeze() === 'icon' && !!button.icon;
11479
+ return (!!button.icon &&
11480
+ (!!button.iconOnly || this.activeSqueeze() === 'icon'));
10465
11481
  }
10466
11482
  // Folded: the Button that speaks for the bar stays out, the rest go in the
10467
11483
  // menu. Below two Buttons there is nothing to fold, so the bar is left alone.
@@ -10629,6 +11645,9 @@ class ActionComponent extends ButtonGroupComponent {
10629
11645
  // A press announces itself through `select`; this speaks only for defaults.
10630
11646
  if (this.pressed() !== undefined)
10631
11647
  return;
11648
+ // A host that names the active Button already knows which one it is.
11649
+ if (this.active() !== undefined)
11650
+ return;
10632
11651
  const name = this.selected();
10633
11652
  if (!name || name === this.announcedDefault())
10634
11653
  return;
@@ -10641,7 +11660,7 @@ class ActionComponent extends ButtonGroupComponent {
10641
11660
  this.clicked.emit(button);
10642
11661
  };
10643
11662
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ActionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10644
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: ActionComponent, isStandalone: true, selector: "m-action, m-one-action", inputs: { sticky: { classPropertyName: "sticky", publicName: "sticky", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, renderIds: { classPropertyName: "renderIds", publicName: "renderIds", isSignal: true, isRequired: false, transformFunction: null }, squeezeAt: { classPropertyName: "squeezeAt", publicName: "squeezeAt", isSignal: true, isRequired: false, transformFunction: null }, squeezeMode: { classPropertyName: "squeezeMode", publicName: "squeezeMode", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.m-action--host-sticky": "sticky()" } }, usesInheritance: true, ngImport: i0, template: "@let buttons = actionButtons();\n<!-- No `config()` guard: a bar the Design editor folded its Buttons into has no\n `button_groups/<name>.yml` behind it \u2014 they ride on `[buttons]` instead\n (ADR 0009, ADR 0010) \u2014 so what decides whether the row exists is whether\n there are Buttons in it. Empty, it draws only on the Canvas, where it is\n the drop space a Button lands on. -->\n@if (buttons.length || isDesignMode) {\n <div\n class=\"m-action\"\n [class.m-action--stuck]=\"isStuck()\"\n [class.m-action--toggle]=\"resolvedVariant() === 'toggle'\"\n [class.m-action--icon-only]=\"activeSqueeze() === 'icon'\"\n >\n @for (button of visibleButtons(); track $index) {\n <!-- A routed Button is a real link, so the browser's own affordances \u2014\n a middle-click, open in new tab, the URL on hover \u2014 reach it. A\n disabled one stays a <button>: an <a> cannot be disabled, and a\n RouterLink on one would still navigate. -->\n @let link = isDisabled(button.name) ? undefined : linkOf(button);\n @if (link) {\n <a\n class=\"m-action__btn\"\n [routerLink]=\"link\"\n [attr.data-testid]=\"(button.name || '') + '-btn'\"\n [class.active]=\"isActive(button)\"\n [attr.aria-current]=\"isActive(button) ? 'page' : null\"\n [style.--m-action-color]=\"fillColor(button)\"\n [style.--m-action-color-contrast]=\"contrastColor(button)\"\n [style.--m-action-label]=\"labelColor(button)\"\n (click)=\"select(button)\"\n >\n <ng-container\n *ngTemplateOutlet=\"buttonContent; context: { $implicit: button }\"\n />\n </a>\n } @else {\n <button\n type=\"button\"\n class=\"m-action__btn\"\n [attr.data-testid]=\"(button.name || '') + '-btn'\"\n [attr.render-id]=\"renderIds()?.[button.name ?? '']\"\n [class.active]=\"isActive(button)\"\n [style.--m-action-color]=\"fillColor(button)\"\n [style.--m-action-color-contrast]=\"contrastColor(button)\"\n [style.--m-action-label]=\"labelColor(button)\"\n [disabled]=\"isDisabled(button.name)\"\n (click)=\"select(button)\"\n >\n <ng-container\n *ngTemplateOutlet=\"buttonContent; context: { $implicit: button }\"\n />\n </button>\n }\n }\n @if (menuButtons().length) {\n <!-- The Buttons the bar could not fit. Squeezed rather than dropped:\n an action the User can still reach behind one press beats an action\n that silently stopped existing at 400px. -->\n <m-context-menu\n class=\"m-action__overflow\"\n [config]=\"squeezeMenu()\"\n [remote]=\"remote() ?? config()?.remote\"\n (action)=\"onMenuAction($event)\"\n />\n }\n @if (!buttons.length) {\n <!-- A bar with nothing in it has no box, and a slot with no box is a slot\n nothing can be dropped on \u2014 the same rect an empty projected Card is\n given (m-one-ui `.card-drop-space`). -->\n <span class=\"m-action__drop\"></span>\n }\n </div>\n}\n\n<ng-template #buttonContent let-button>\n @if (button.icon) {\n <m-icon\n [name]=\"button.icon\"\n [color]=\"iconColor(button)\"\n [remote]=\"remote() ?? config()?.remote\"\n />\n }\n @if (button.label && !isLabelHidden(button)) {\n <span class=\"m-action__label\">{{ button.label | translate }}</span>\n }\n</ng-template>\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-action,m-one-action{display:block;width:100%;grid-column:1/-1}m-action.m-action--host-sticky,m-one-action.m-action--host-sticky{position:sticky;top:0;z-index:50;background:#ffffffeb;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}.m-action{display:flex;flex-wrap:nowrap;background:transparent;width:100%;border-bottom:1px solid #f1f5f9;--m-action-color: var(--m-button-color, var(--m-one-button-color, var(--m-mm)));--m-action-color-contrast: var(--m-button-color-contrast, var(--m-one-button-color-contrast, #ffffff))}.m-action--stuck{border-bottom-color:#00000014;box-shadow:0 2px 10px #0000000f}.m-action__btn{flex:1;min-width:0;padding:1rem 2rem;border:none;background:transparent;text-decoration:none;color:var(--m-action-label, #1e293b);font-weight:300;font-size:.9rem;display:flex;align-items:center;justify-content:center;gap:.6rem;white-space:nowrap;overflow:hidden;cursor:pointer;border-right:1px solid #f1f5f9;transition:all .25s cubic-bezier(.4,0,.2,1)}.m-action__btn:last-child{border-right:none}.m-action__btn:hover{background:#f8fafc;color:var(--m-action-color)}.m-action__btn .m-icon{transition:transform .2s ease}.m-action__btn:hover .m-icon{transform:scale(1.1)}.m-action__btn:disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.m-action__btn.active{color:var(--m-action-color);font-weight:500}.m-action--toggle .m-action__btn{position:relative;filter:grayscale(100%);transition:all .25s cubic-bezier(.4,0,.2,1),filter .25s cubic-bezier(.4,0,.2,1)}.m-action--toggle .m-action__btn.active{filter:none}.m-action--toggle .m-action__btn.active:hover:not(:disabled){filter:none}.m-action--icon-only .m-action__btn{padding:1rem .5rem;gap:0}.m-action__overflow{display:flex;align-items:center;padding:0 .5rem;flex:0 0 auto}.m-action__drop{display:block;flex:1;min-height:3.5rem;margin:.5rem;border:1px dashed currentColor;border-radius:.25rem;opacity:.4;pointer-events:none}.m-action__label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}@container mag-grid (max-width: 767.98px){.m-action__btn{padding:1rem .75rem;gap:.4rem}}@container mag-grid (max-width: 575.98px){.m-action__btn{padding:.85rem .4rem;font-size:.8rem}}\n"], dependencies: [{ kind: "ngmodule", type: i0.forwardRef(() => CommonModule) }, { kind: "directive", type: i0.forwardRef(() => i1.NgTemplateOutlet), selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i0.forwardRef(() => IconComponent), selector: "m-icon, m-one-icon", inputs: ["config", "name", "color", "size", "one", "baseUrl", "remote"], outputs: ["configChange"] }, { kind: "component", type: i0.forwardRef(() => ContextMenuComponent), selector: "m-context-menu, m-one-context-menu", inputs: ["toggle", "remote", "exclude", "visibilityRule", "disableRule", "extraData", "inverted", "options"], outputs: ["toggleChange", "action"] }, { kind: "directive", type: i0.forwardRef(() => RouterLink), selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: i0.forwardRef(() => TranslatePipe), name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
11663
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: ActionComponent, isStandalone: true, selector: "m-action, m-one-action", inputs: { sticky: { classPropertyName: "sticky", publicName: "sticky", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null }, renderIds: { classPropertyName: "renderIds", publicName: "renderIds", isSignal: true, isRequired: false, transformFunction: null }, squeezeAt: { classPropertyName: "squeezeAt", publicName: "squeezeAt", isSignal: true, isRequired: false, transformFunction: null }, squeezeMode: { classPropertyName: "squeezeMode", publicName: "squeezeMode", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.m-action--host-sticky": "sticky()" } }, usesInheritance: true, ngImport: i0, template: "@let buttons = actionButtons();\n<!-- No `config()` guard: a bar the Design editor folded its Buttons into has no\n `button_groups/<name>.yml` behind it \u2014 they ride on `[buttons]` instead\n (ADR 0009, ADR 0010) \u2014 so what decides whether the row exists is whether\n there are Buttons in it. Empty, it draws only on the Canvas, where it is\n the drop space a Button lands on. -->\n@if (buttons.length || isDesignMode) {\n <div\n class=\"m-action\"\n [class.m-action--stuck]=\"isStuck()\"\n [class.m-action--toggle]=\"resolvedVariant() === 'toggle'\"\n >\n @for (button of visibleButtons(); track $index) {\n <!-- A routed Button is a real link, so the browser's own affordances \u2014\n a middle-click, open in new tab, the URL on hover \u2014 reach it. A\n disabled one stays a <button>: an <a> cannot be disabled, and a\n RouterLink on one would still navigate. -->\n @let link = isDisabled(button.name) ? undefined : linkOf(button);\n @if (link) {\n <a\n class=\"m-action__btn\"\n [routerLink]=\"link\"\n [attr.data-testid]=\"(button.name || '') + '-btn'\"\n [class.active]=\"isActive(button)\"\n [class.m-action__btn--icon-only]=\"isLabelHidden(button)\"\n [attr.aria-label]=\"isLabelHidden(button) ? (button.label | translate) : null\"\n [attr.aria-current]=\"isActive(button) ? 'page' : null\"\n [style.--m-action-color]=\"fillColor(button)\"\n [style.--m-action-color-contrast]=\"contrastColor(button)\"\n [style.--m-action-label]=\"labelColor(button)\"\n (click)=\"select(button)\"\n >\n <ng-container\n *ngTemplateOutlet=\"buttonContent; context: { $implicit: button }\"\n />\n </a>\n } @else {\n <button\n type=\"button\"\n class=\"m-action__btn\"\n [attr.data-testid]=\"(button.name || '') + '-btn'\"\n [attr.render-id]=\"renderIds()?.[button.name ?? '']\"\n [class.active]=\"isActive(button)\"\n [class.m-action__btn--icon-only]=\"isLabelHidden(button)\"\n [attr.aria-label]=\"isLabelHidden(button) ? (button.label | translate) : null\"\n [style.--m-action-color]=\"fillColor(button)\"\n [style.--m-action-color-contrast]=\"contrastColor(button)\"\n [style.--m-action-label]=\"labelColor(button)\"\n [disabled]=\"isDisabled(button.name)\"\n (click)=\"select(button)\"\n >\n <ng-container\n *ngTemplateOutlet=\"buttonContent; context: { $implicit: button }\"\n />\n </button>\n }\n }\n @if (menuButtons().length) {\n <!-- The Buttons the bar could not fit. Squeezed rather than dropped:\n an action the User can still reach behind one press beats an action\n that silently stopped existing at 400px. -->\n <m-context-menu\n class=\"m-action__overflow\"\n [config]=\"squeezeMenu()\"\n [remote]=\"remote() ?? config()?.remote\"\n (action)=\"onMenuAction($event)\"\n />\n }\n @if (!buttons.length) {\n <!-- A bar with nothing in it has no box, and a slot with no box is a slot\n nothing can be dropped on \u2014 the same rect an empty projected Card is\n given (m-one-ui `.card-drop-space`). -->\n <span class=\"m-action__drop\"></span>\n }\n </div>\n}\n\n<ng-template #buttonContent let-button>\n @if (button.icon) {\n <m-icon\n [name]=\"button.icon\"\n [color]=\"iconColor(button)\"\n [remote]=\"remote() ?? config()?.remote\"\n />\n }\n @if (button.label && !isLabelHidden(button)) {\n <span class=\"m-action__label\">{{ button.label | translate }}</span>\n }\n</ng-template>\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-action,m-one-action{display:block;width:100%;grid-column:1/-1}m-action.m-action--host-sticky,m-one-action.m-action--host-sticky{position:sticky;top:0;z-index:50;background:#ffffffeb;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}.m-action{display:flex;flex-wrap:nowrap;background:transparent;width:100%;border-bottom:1px solid #f1f5f9;--m-action-color: var(--m-button-color, var(--m-one-button-color, var(--m-mm)));--m-action-color-contrast: var(--m-button-color-contrast, var(--m-one-button-color-contrast, #ffffff))}.m-action--stuck{border-bottom-color:#00000014;box-shadow:0 2px 10px #0000000f}.m-action__btn{flex:1;min-width:0;padding:1rem 2rem;border:none;background:transparent;text-decoration:none;color:var(--m-action-label, #1e293b);font-weight:300;font-size:.9rem;display:flex;align-items:center;justify-content:center;gap:.6rem;white-space:nowrap;overflow:hidden;cursor:pointer;border-right:1px solid #f1f5f9;transition:all .25s cubic-bezier(.4,0,.2,1)}.m-action__btn:last-child{border-right:none}.m-action__btn:hover{background:#f8fafc;color:var(--m-action-color)}.m-action__btn .m-icon{transition:transform .2s ease}.m-action__btn:hover .m-icon{transform:scale(1.1)}.m-action__btn:disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.m-action__btn.active{color:var(--m-action-color);font-weight:500}.m-action__btn.m-action__btn--icon-only{padding:1rem .5rem;gap:0}.m-action--toggle .m-action__btn{position:relative;filter:grayscale(100%);transition:all .25s cubic-bezier(.4,0,.2,1),filter .25s cubic-bezier(.4,0,.2,1)}.m-action--toggle .m-action__btn.active{filter:none}.m-action--toggle .m-action__btn.active:hover:not(:disabled){filter:none}.m-action__overflow{display:flex;align-items:center;padding:0 .5rem;flex:0 0 auto}.m-action__drop{display:block;flex:1;min-height:3.5rem;margin:.5rem;border:1px dashed currentColor;border-radius:.25rem;opacity:.4;pointer-events:none}.m-action__label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}@container mag-grid (max-width: 767.98px){.m-action__btn{padding:1rem .75rem;gap:.4rem}}@container mag-grid (max-width: 575.98px){.m-action__btn{padding:.85rem .4rem;font-size:.8rem}}\n"], dependencies: [{ kind: "ngmodule", type: i0.forwardRef(() => CommonModule) }, { kind: "directive", type: i0.forwardRef(() => i1.NgTemplateOutlet), selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i0.forwardRef(() => IconComponent), selector: "m-icon, m-one-icon", inputs: ["config", "name", "color", "size", "one", "baseUrl", "remote"], outputs: ["configChange"] }, { kind: "component", type: i0.forwardRef(() => ContextMenuComponent), selector: "m-context-menu, m-one-context-menu", inputs: ["toggle", "remote", "exclude", "visibilityRule", "disableRule", "extraData", "inverted", "options"], outputs: ["toggleChange", "action"] }, { kind: "directive", type: i0.forwardRef(() => RouterLink), selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: i0.forwardRef(() => TranslatePipe), name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
10645
11664
  }
10646
11665
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ActionComponent, decorators: [{
10647
11666
  type: Component,
@@ -10653,8 +11672,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
10653
11672
  RouterLink,
10654
11673
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
10655
11674
  '[class.m-action--host-sticky]': 'sticky()',
10656
- }, template: "@let buttons = actionButtons();\n<!-- No `config()` guard: a bar the Design editor folded its Buttons into has no\n `button_groups/<name>.yml` behind it \u2014 they ride on `[buttons]` instead\n (ADR 0009, ADR 0010) \u2014 so what decides whether the row exists is whether\n there are Buttons in it. Empty, it draws only on the Canvas, where it is\n the drop space a Button lands on. -->\n@if (buttons.length || isDesignMode) {\n <div\n class=\"m-action\"\n [class.m-action--stuck]=\"isStuck()\"\n [class.m-action--toggle]=\"resolvedVariant() === 'toggle'\"\n [class.m-action--icon-only]=\"activeSqueeze() === 'icon'\"\n >\n @for (button of visibleButtons(); track $index) {\n <!-- A routed Button is a real link, so the browser's own affordances \u2014\n a middle-click, open in new tab, the URL on hover \u2014 reach it. A\n disabled one stays a <button>: an <a> cannot be disabled, and a\n RouterLink on one would still navigate. -->\n @let link = isDisabled(button.name) ? undefined : linkOf(button);\n @if (link) {\n <a\n class=\"m-action__btn\"\n [routerLink]=\"link\"\n [attr.data-testid]=\"(button.name || '') + '-btn'\"\n [class.active]=\"isActive(button)\"\n [attr.aria-current]=\"isActive(button) ? 'page' : null\"\n [style.--m-action-color]=\"fillColor(button)\"\n [style.--m-action-color-contrast]=\"contrastColor(button)\"\n [style.--m-action-label]=\"labelColor(button)\"\n (click)=\"select(button)\"\n >\n <ng-container\n *ngTemplateOutlet=\"buttonContent; context: { $implicit: button }\"\n />\n </a>\n } @else {\n <button\n type=\"button\"\n class=\"m-action__btn\"\n [attr.data-testid]=\"(button.name || '') + '-btn'\"\n [attr.render-id]=\"renderIds()?.[button.name ?? '']\"\n [class.active]=\"isActive(button)\"\n [style.--m-action-color]=\"fillColor(button)\"\n [style.--m-action-color-contrast]=\"contrastColor(button)\"\n [style.--m-action-label]=\"labelColor(button)\"\n [disabled]=\"isDisabled(button.name)\"\n (click)=\"select(button)\"\n >\n <ng-container\n *ngTemplateOutlet=\"buttonContent; context: { $implicit: button }\"\n />\n </button>\n }\n }\n @if (menuButtons().length) {\n <!-- The Buttons the bar could not fit. Squeezed rather than dropped:\n an action the User can still reach behind one press beats an action\n that silently stopped existing at 400px. -->\n <m-context-menu\n class=\"m-action__overflow\"\n [config]=\"squeezeMenu()\"\n [remote]=\"remote() ?? config()?.remote\"\n (action)=\"onMenuAction($event)\"\n />\n }\n @if (!buttons.length) {\n <!-- A bar with nothing in it has no box, and a slot with no box is a slot\n nothing can be dropped on \u2014 the same rect an empty projected Card is\n given (m-one-ui `.card-drop-space`). -->\n <span class=\"m-action__drop\"></span>\n }\n </div>\n}\n\n<ng-template #buttonContent let-button>\n @if (button.icon) {\n <m-icon\n [name]=\"button.icon\"\n [color]=\"iconColor(button)\"\n [remote]=\"remote() ?? config()?.remote\"\n />\n }\n @if (button.label && !isLabelHidden(button)) {\n <span class=\"m-action__label\">{{ button.label | translate }}</span>\n }\n</ng-template>\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-action,m-one-action{display:block;width:100%;grid-column:1/-1}m-action.m-action--host-sticky,m-one-action.m-action--host-sticky{position:sticky;top:0;z-index:50;background:#ffffffeb;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}.m-action{display:flex;flex-wrap:nowrap;background:transparent;width:100%;border-bottom:1px solid #f1f5f9;--m-action-color: var(--m-button-color, var(--m-one-button-color, var(--m-mm)));--m-action-color-contrast: var(--m-button-color-contrast, var(--m-one-button-color-contrast, #ffffff))}.m-action--stuck{border-bottom-color:#00000014;box-shadow:0 2px 10px #0000000f}.m-action__btn{flex:1;min-width:0;padding:1rem 2rem;border:none;background:transparent;text-decoration:none;color:var(--m-action-label, #1e293b);font-weight:300;font-size:.9rem;display:flex;align-items:center;justify-content:center;gap:.6rem;white-space:nowrap;overflow:hidden;cursor:pointer;border-right:1px solid #f1f5f9;transition:all .25s cubic-bezier(.4,0,.2,1)}.m-action__btn:last-child{border-right:none}.m-action__btn:hover{background:#f8fafc;color:var(--m-action-color)}.m-action__btn .m-icon{transition:transform .2s ease}.m-action__btn:hover .m-icon{transform:scale(1.1)}.m-action__btn:disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.m-action__btn.active{color:var(--m-action-color);font-weight:500}.m-action--toggle .m-action__btn{position:relative;filter:grayscale(100%);transition:all .25s cubic-bezier(.4,0,.2,1),filter .25s cubic-bezier(.4,0,.2,1)}.m-action--toggle .m-action__btn.active{filter:none}.m-action--toggle .m-action__btn.active:hover:not(:disabled){filter:none}.m-action--icon-only .m-action__btn{padding:1rem .5rem;gap:0}.m-action__overflow{display:flex;align-items:center;padding:0 .5rem;flex:0 0 auto}.m-action__drop{display:block;flex:1;min-height:3.5rem;margin:.5rem;border:1px dashed currentColor;border-radius:.25rem;opacity:.4;pointer-events:none}.m-action__label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}@container mag-grid (max-width: 767.98px){.m-action__btn{padding:1rem .75rem;gap:.4rem}}@container mag-grid (max-width: 575.98px){.m-action__btn{padding:.85rem .4rem;font-size:.8rem}}\n"] }]
10657
- }], ctorParameters: () => [], propDecorators: { sticky: [{ type: i0.Input, args: [{ isSignal: true, alias: "sticky", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], renderIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "renderIds", required: false }] }], squeezeAt: [{ type: i0.Input, args: [{ isSignal: true, alias: "squeezeAt", required: false }] }], squeezeMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "squeezeMode", required: false }] }] } });
11675
+ }, template: "@let buttons = actionButtons();\n<!-- No `config()` guard: a bar the Design editor folded its Buttons into has no\n `button_groups/<name>.yml` behind it \u2014 they ride on `[buttons]` instead\n (ADR 0009, ADR 0010) \u2014 so what decides whether the row exists is whether\n there are Buttons in it. Empty, it draws only on the Canvas, where it is\n the drop space a Button lands on. -->\n@if (buttons.length || isDesignMode) {\n <div\n class=\"m-action\"\n [class.m-action--stuck]=\"isStuck()\"\n [class.m-action--toggle]=\"resolvedVariant() === 'toggle'\"\n >\n @for (button of visibleButtons(); track $index) {\n <!-- A routed Button is a real link, so the browser's own affordances \u2014\n a middle-click, open in new tab, the URL on hover \u2014 reach it. A\n disabled one stays a <button>: an <a> cannot be disabled, and a\n RouterLink on one would still navigate. -->\n @let link = isDisabled(button.name) ? undefined : linkOf(button);\n @if (link) {\n <a\n class=\"m-action__btn\"\n [routerLink]=\"link\"\n [attr.data-testid]=\"(button.name || '') + '-btn'\"\n [class.active]=\"isActive(button)\"\n [class.m-action__btn--icon-only]=\"isLabelHidden(button)\"\n [attr.aria-label]=\"isLabelHidden(button) ? (button.label | translate) : null\"\n [attr.aria-current]=\"isActive(button) ? 'page' : null\"\n [style.--m-action-color]=\"fillColor(button)\"\n [style.--m-action-color-contrast]=\"contrastColor(button)\"\n [style.--m-action-label]=\"labelColor(button)\"\n (click)=\"select(button)\"\n >\n <ng-container\n *ngTemplateOutlet=\"buttonContent; context: { $implicit: button }\"\n />\n </a>\n } @else {\n <button\n type=\"button\"\n class=\"m-action__btn\"\n [attr.data-testid]=\"(button.name || '') + '-btn'\"\n [attr.render-id]=\"renderIds()?.[button.name ?? '']\"\n [class.active]=\"isActive(button)\"\n [class.m-action__btn--icon-only]=\"isLabelHidden(button)\"\n [attr.aria-label]=\"isLabelHidden(button) ? (button.label | translate) : null\"\n [style.--m-action-color]=\"fillColor(button)\"\n [style.--m-action-color-contrast]=\"contrastColor(button)\"\n [style.--m-action-label]=\"labelColor(button)\"\n [disabled]=\"isDisabled(button.name)\"\n (click)=\"select(button)\"\n >\n <ng-container\n *ngTemplateOutlet=\"buttonContent; context: { $implicit: button }\"\n />\n </button>\n }\n }\n @if (menuButtons().length) {\n <!-- The Buttons the bar could not fit. Squeezed rather than dropped:\n an action the User can still reach behind one press beats an action\n that silently stopped existing at 400px. -->\n <m-context-menu\n class=\"m-action__overflow\"\n [config]=\"squeezeMenu()\"\n [remote]=\"remote() ?? config()?.remote\"\n (action)=\"onMenuAction($event)\"\n />\n }\n @if (!buttons.length) {\n <!-- A bar with nothing in it has no box, and a slot with no box is a slot\n nothing can be dropped on \u2014 the same rect an empty projected Card is\n given (m-one-ui `.card-drop-space`). -->\n <span class=\"m-action__drop\"></span>\n }\n </div>\n}\n\n<ng-template #buttonContent let-button>\n @if (button.icon) {\n <m-icon\n [name]=\"button.icon\"\n [color]=\"iconColor(button)\"\n [remote]=\"remote() ?? config()?.remote\"\n />\n }\n @if (button.label && !isLabelHidden(button)) {\n <span class=\"m-action__label\">{{ button.label | translate }}</span>\n }\n</ng-template>\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-action,m-one-action{display:block;width:100%;grid-column:1/-1}m-action.m-action--host-sticky,m-one-action.m-action--host-sticky{position:sticky;top:0;z-index:50;background:#ffffffeb;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}.m-action{display:flex;flex-wrap:nowrap;background:transparent;width:100%;border-bottom:1px solid #f1f5f9;--m-action-color: var(--m-button-color, var(--m-one-button-color, var(--m-mm)));--m-action-color-contrast: var(--m-button-color-contrast, var(--m-one-button-color-contrast, #ffffff))}.m-action--stuck{border-bottom-color:#00000014;box-shadow:0 2px 10px #0000000f}.m-action__btn{flex:1;min-width:0;padding:1rem 2rem;border:none;background:transparent;text-decoration:none;color:var(--m-action-label, #1e293b);font-weight:300;font-size:.9rem;display:flex;align-items:center;justify-content:center;gap:.6rem;white-space:nowrap;overflow:hidden;cursor:pointer;border-right:1px solid #f1f5f9;transition:all .25s cubic-bezier(.4,0,.2,1)}.m-action__btn:last-child{border-right:none}.m-action__btn:hover{background:#f8fafc;color:var(--m-action-color)}.m-action__btn .m-icon{transition:transform .2s ease}.m-action__btn:hover .m-icon{transform:scale(1.1)}.m-action__btn:disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.m-action__btn.active{color:var(--m-action-color);font-weight:500}.m-action__btn.m-action__btn--icon-only{padding:1rem .5rem;gap:0}.m-action--toggle .m-action__btn{position:relative;filter:grayscale(100%);transition:all .25s cubic-bezier(.4,0,.2,1),filter .25s cubic-bezier(.4,0,.2,1)}.m-action--toggle .m-action__btn.active{filter:none}.m-action--toggle .m-action__btn.active:hover:not(:disabled){filter:none}.m-action__overflow{display:flex;align-items:center;padding:0 .5rem;flex:0 0 auto}.m-action__drop{display:block;flex:1;min-height:3.5rem;margin:.5rem;border:1px dashed currentColor;border-radius:.25rem;opacity:.4;pointer-events:none}.m-action__label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}@container mag-grid (max-width: 767.98px){.m-action__btn{padding:1rem .75rem;gap:.4rem}}@container mag-grid (max-width: 575.98px){.m-action__btn{padding:.85rem .4rem;font-size:.8rem}}\n"] }]
11676
+ }], ctorParameters: () => [], propDecorators: { sticky: [{ type: i0.Input, args: [{ isSignal: true, alias: "sticky", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], active: [{ type: i0.Input, args: [{ isSignal: true, alias: "active", required: false }] }], renderIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "renderIds", required: false }] }], squeezeAt: [{ type: i0.Input, args: [{ isSignal: true, alias: "squeezeAt", required: false }] }], squeezeMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "squeezeMode", required: false }] }] } });
10658
11677
 
10659
11678
  class BaseInputComponent {
10660
11679
  focused = input(false, ...(ngDevMode ? [{ debugName: "focused" }] : /* istanbul ignore next */ []));
@@ -14864,10 +15883,6 @@ function createMap(elems, key = 'id', elemMap = {}) {
14864
15883
  }, {}) ?? {});
14865
15884
  }
14866
15885
 
14867
- function getUniqueId() {
14868
- return Date.now().toString(36) + Math.random().toString(36).substr(2);
14869
- }
14870
-
14871
15886
  /**
14872
15887
  * Ranks items based on a numeric score and provides a sequence of ranks.
14873
15888
  */
@@ -16995,454 +18010,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
16995
18010
  args: [{ providedIn: 'root' }]
16996
18011
  }] });
16997
18012
 
16998
- const MODAL_COMPONENT = new InjectionToken('MODAL_COMPONENT');
16999
- const PANEL_COMPONENT = new InjectionToken('PANEL_COMPONENT');
17000
- const CONFIRM_COMPONENT = new InjectionToken('CONFIRM_COMPONENT');
17001
- /**
17002
- * The body an overlay opened by name is filled with — what `mModal` and
17003
- * `mSidePanel` already build by hand, reached through a token here so
17004
- * `ModalStore.openScreen` can build the same thing without importing the
17005
- * component into the store (the reason the three above are tokens).
17006
- */
17007
- const OVERLAY_BODY_COMPONENT = new InjectionToken('OVERLAY_BODY_COMPONENT');
17008
-
17009
- const MODAL_REF = new InjectionToken('MODAL_REF');
17010
- class ModalRef {
17011
- closeCallback;
17012
- changeCallback;
17013
- /** Commit a result and dismiss (single-pick, confirm, …). */
17014
- close(result) {
17015
- this.closeCallback?.(result);
17016
- }
17017
- /**
17018
- * Commit a result without dismissing. Multi-pick panels use this so each
17019
- * tick updates the field while the panel stays open.
17020
- */
17021
- change(result) {
17022
- this.changeCallback?.(result);
17023
- }
17024
- onClose(callback) {
17025
- this.closeCallback = callback;
17026
- }
17027
- onChange(callback) {
17028
- this.changeCallback = callback;
17029
- }
17030
- }
17031
-
17032
- /**
17033
- * A DockedPanel takes the viewport edge and displaces the older SidePanel inboard.
17034
- * Docking is desktop-only and requires the page to stay readable behind both panels.
17035
- * See ADR 0004.
17036
- */
17037
- const DOCK_MIN_PAGE_REMAINDER = 320;
17038
- const DOCK_TRANSITION = '300ms cubic-bezier(0.2, 0, 0, 1)';
17039
- const DEFAULT_PANEL_WIDTH = '400px';
17040
- /**
17041
- * Reads a px panel width. Any other unit is undockable — the displacement offset
17042
- * must be known before the panel exists in the DOM.
17043
- */
17044
- const parsePanelWidth = (width) => {
17045
- if (!width?.endsWith('px')) {
17046
- return undefined;
17047
- }
17048
- const value = Number.parseFloat(width);
17049
- return Number.isFinite(value) ? value : undefined;
17050
- };
17051
- /**
17052
- * A CSS length as a panel needs it. An authored width is free text — the
17053
- * Screen editor takes `400` as readily as `400px` — and a unitless number is
17054
- * not a length: the browser drops the declaration and the panel collapses to
17055
- * its content. A bare number means px, which is what every other authored
17056
- * dimension in the library already assumes; anything carrying a unit, a
17057
- * percentage or a `calc()` is passed through untouched.
17058
- */
17059
- const panelCssLength = (value) => {
17060
- const trimmed = value?.trim();
17061
- if (!trimmed)
17062
- return undefined;
17063
- return /^-?\d*\.?\d+$/.test(trimmed) ? `${trimmed}px` : trimmed;
17064
- };
17065
- const hasRoomToDock = (baseWidth, panelWidth, viewportWidth) => {
17066
- const base = parsePanelWidth(baseWidth);
17067
- const panel = parsePanelWidth(panelWidth);
17068
- if (base === undefined || panel === undefined) {
17069
- return false;
17070
- }
17071
- return viewportWidth - (base + panel) >= DOCK_MIN_PAGE_REMAINDER;
17072
- };
17073
-
17074
- const initialModalState = {
17075
- modalTriggerMap: {},
17076
- className: 'modal',
17077
- parentClassName: 'modals',
17078
- activeModal: undefined,
17079
- panelTriggerMap: {},
17080
- panelClassName: 'panel',
17081
- panelParentClassName: 'panels',
17082
- activePanel: undefined,
17083
- };
17084
- const ModalStore = signalStore({ providedIn: 'root' }, withState(initialModalState), withMethods((state, domService = inject(DomService), deviceService = inject(DeviceService)) => {
17085
- // Every modal that has gone, by id. A modal is dismissed from two places —
17086
- // its own close affordance and this store — and only one of those runs
17087
- // through a ModalRef, so a caller waiting on an answer would otherwise wait
17088
- // forever on the other.
17089
- const closed = new Subject();
17090
- const modalComp = inject(MODAL_COMPONENT);
17091
- const panelComp = inject(PANEL_COMPONENT);
17092
- const confirmComp = inject(CONFIRM_COMPONENT);
17093
- const overlayBodyComp = inject(OVERLAY_BODY_COMPONENT);
17094
- const open = (modalTrigger) => {
17095
- const id = modalTrigger.id ?? getUniqueId();
17096
- const modalComponentRef = domService.create({
17097
- component: modalComp,
17098
- className: state.className(),
17099
- id,
17100
- parentClassName: state.parentClassName(),
17101
- bindings: [
17102
- inputBinding('name', () => modalTrigger.name),
17103
- inputBinding('component', () => modalTrigger.component),
17104
- inputBinding('bindings', () => modalTrigger.bindings),
17105
- inputBinding('providers', () => modalTrigger.providers),
17106
- inputBinding('one', () => modalTrigger.one ?? false),
17107
- inputBinding('instanceId', () => id),
17108
- inputBinding('config', () => modalTrigger.config),
17109
- ],
17110
- });
17111
- patchState(state, {
17112
- modalTriggerMap: {
17113
- ...state.modalTriggerMap(),
17114
- [id]: {
17115
- ...modalTrigger,
17116
- ref: modalComponentRef,
17117
- },
17118
- },
17119
- activeModal: id,
17120
- });
17121
- return id;
17122
- };
17123
- const close = (id) => {
17124
- const modalId = id ?? state.activeModal();
17125
- const modalTriggerMap = state.modalTriggerMap();
17126
- if (!modalId) {
17127
- return;
17128
- }
17129
- // A modal that has already gone. Closing it again is what a body and its
17130
- // own close affordance both doing their job looks like (ADR 0031), and
17131
- // the state patch below would hand `activeModal` to somebody else's
17132
- // overlay, so the second call answers nothing.
17133
- if (id && !modalTriggerMap[id]) {
17134
- return;
17135
- }
17136
- domService.destroy({
17137
- componentRef: modalTriggerMap[modalId]?.ref,
17138
- parentClassName: state.parentClassName(),
17139
- id: modalId,
17140
- });
17141
- delete modalTriggerMap[modalId];
17142
- const remaining = Object.keys(modalTriggerMap);
17143
- patchState(state, {
17144
- modalTriggerMap: { ...modalTriggerMap },
17145
- activeModal: remaining.length
17146
- ? remaining[remaining.length - 1]
17147
- : undefined,
17148
- });
17149
- closed.next(modalId);
17150
- };
17151
- /**
17152
- * The panel a dock request would displace: whatever currently holds the edge.
17153
- * Docking is decided once, at open — never re-evaluated on resize (ADR 0004).
17154
- */
17155
- const resolveDockTarget = (side, width) => {
17156
- if (!deviceService.isDesktop()) {
17157
- return undefined;
17158
- }
17159
- const baseId = state.activePanel();
17160
- const base = baseId ? state.panelTriggerMap()[baseId] : undefined;
17161
- if (!baseId || !base || (base.side ?? 'right') !== side) {
17162
- return undefined;
17163
- }
17164
- const viewportWidth = typeof window === 'undefined' ? 0 : window.innerWidth;
17165
- return hasRoomToDock(base.width, width, viewportWidth)
17166
- ? baseId
17167
- : undefined;
17168
- };
17169
- const openPanel = (panelTrigger) => {
17170
- const id = panelTrigger.id ?? getUniqueId();
17171
- const side = panelTrigger.side ?? 'right';
17172
- // Authored free text, made a CSS length: a unitless `400` is dropped by
17173
- // the browser and the panel opens at the width of its own content.
17174
- const width = panelCssLength(panelTrigger.width) ?? DEFAULT_PANEL_WIDTH;
17175
- const height = panelCssLength(panelTrigger.height);
17176
- const isMobile = deviceService.isMobile();
17177
- if (panelTrigger.dock) {
17178
- const activeId = state.activePanel();
17179
- // Max two panels: a further dock request replaces the current DockedPanel,
17180
- // which restores the panel underneath to the edge before we displace it again.
17181
- if (activeId && state.panelTriggerMap()[activeId]?.dockedOver) {
17182
- closePanel(activeId);
17183
- }
17184
- }
17185
- const dockedOver = panelTrigger.dock
17186
- ? resolveDockTarget(side, width)
17187
- : undefined;
17188
- const styles = isMobile
17189
- ? {
17190
- position: 'fixed',
17191
- bottom: '0',
17192
- left: '0',
17193
- width: '100%',
17194
- height: '90%',
17195
- zIndex: '1000',
17196
- }
17197
- : {
17198
- position: 'fixed',
17199
- top: '0',
17200
- bottom: '0',
17201
- [side]: '0',
17202
- width,
17203
- zIndex: '1000',
17204
- transition: `${side} ${DOCK_TRANSITION}`,
17205
- };
17206
- const panelComponentRef = domService.create({
17207
- component: panelComp,
17208
- className: `${state.panelClassName()} panel--${side}`,
17209
- id,
17210
- parentClassName: state.panelParentClassName(),
17211
- styles,
17212
- bindings: [
17213
- inputBinding('component', () => panelTrigger.component),
17214
- inputBinding('bindings', () => panelTrigger.bindings),
17215
- inputBinding('providers', () => panelTrigger.providers),
17216
- inputBinding('side', () => side),
17217
- inputBinding('instanceId', () => id),
17218
- inputBinding('docked', () => !!state.panelTriggerMap()[id]?.dockedOver),
17219
- inputBinding('height', () => height),
17220
- inputBinding('closeProhibited', () => !!panelTrigger.closeProhibited),
17221
- ],
17222
- });
17223
- if (dockedOver) {
17224
- domService.updateStyleById({
17225
- id: dockedOver,
17226
- parentClassName: state.panelParentClassName(),
17227
- styles: { [side]: width },
17228
- });
17229
- }
17230
- patchState(state, {
17231
- panelTriggerMap: {
17232
- ...state.panelTriggerMap(),
17233
- [id]: {
17234
- ...panelTrigger,
17235
- side,
17236
- width,
17237
- dockedOver,
17238
- ref: panelComponentRef,
17239
- },
17240
- },
17241
- activePanel: id,
17242
- });
17243
- return id;
17244
- };
17245
- const closePanel = (id) => {
17246
- const panelId = id ?? state.activePanel();
17247
- const panelTriggerMap = state.panelTriggerMap();
17248
- if (!panelId) {
17249
- return;
17250
- }
17251
- // A panel that has already gone — `close`'s reason, and here it would
17252
- // also promote a DockedPanel a second time.
17253
- if (id && !panelTriggerMap[id]) {
17254
- return;
17255
- }
17256
- const closing = panelTriggerMap[panelId];
17257
- domService.destroy({
17258
- componentRef: closing?.ref,
17259
- parentClassName: state.panelParentClassName(),
17260
- id: panelId,
17261
- });
17262
- delete panelTriggerMap[panelId];
17263
- // Closing a DockedPanel returns the panel it displaced to the edge.
17264
- if (closing?.dockedOver && panelTriggerMap[closing.dockedOver]) {
17265
- domService.updateStyleById({
17266
- id: closing.dockedOver,
17267
- parentClassName: state.panelParentClassName(),
17268
- styles: { [closing.side ?? 'right']: '0' },
17269
- });
17270
- }
17271
- // Closing a displaced panel promotes its DockedPanel: already at the edge,
17272
- // so nothing moves — its seam just goes dashed -> solid.
17273
- const promotedId = Object.keys(panelTriggerMap).find((key) => panelTriggerMap[key]?.dockedOver === panelId);
17274
- if (promotedId) {
17275
- panelTriggerMap[promotedId] = {
17276
- ...panelTriggerMap[promotedId],
17277
- dockedOver: undefined,
17278
- };
17279
- }
17280
- const remaining = Object.keys(panelTriggerMap);
17281
- patchState(state, {
17282
- panelTriggerMap: { ...panelTriggerMap },
17283
- activePanel: remaining.length
17284
- ? remaining[remaining.length - 1]
17285
- : undefined,
17286
- });
17287
- };
17288
- const cleanupOnClose = rxMethod(pipe(filter((modalMap) => !Object.keys(modalMap).length), tap(() => {
17289
- domService.cleanup(state.parentClassName());
17290
- })));
17291
- const cleanupPanelsOnClose = rxMethod(pipe(filter((panelMap) => !Object.keys(panelMap).length), tap(() => {
17292
- domService.cleanup(state.panelParentClassName());
17293
- })));
17294
- /**
17295
- * The question as a value: subscribing asks it, and the single emission is
17296
- * the answer — `true` for the commit, `false` for a refusal and for a
17297
- * dismissal, which is a refusal by another route. Completes with that
17298
- * emission, so a `switchMap` over it moves on rather than holding the
17299
- * modal's answer open.
17300
- *
17301
- * Unsubscribing before it answers takes the modal away with it: the caller
17302
- * that asked is gone, and a dialog nothing is waiting on is a dialog whose
17303
- * answer lands nowhere.
17304
- */
17305
- const ask = (opts) => new Observable((subscriber) => {
17306
- const modalRef = new ModalRef();
17307
- let settled = false;
17308
- let id = '';
17309
- const settle = (result, dismiss) => {
17310
- if (settled)
17311
- return;
17312
- settled = true;
17313
- watch.unsubscribe();
17314
- if (dismiss)
17315
- close(id);
17316
- subscriber.next(result);
17317
- subscriber.complete();
17318
- };
17319
- const watch = closed
17320
- .pipe(filter((closedId) => closedId === id))
17321
- .subscribe(() => settle(false, false));
17322
- id = open({
17323
- component: confirmComp,
17324
- providers: [{ provide: MODAL_REF, useValue: modalRef }],
17325
- bindings: [
17326
- inputBinding('header', () => opts.header ?? ''),
17327
- inputBinding('body', () => opts.body ?? ''),
17328
- inputBinding('params', () => opts.params ?? {}),
17329
- inputBinding('type', () => opts.type ?? 'info'),
17330
- inputBinding('kind', () => opts.kind ?? 'yes'),
17331
- inputBinding('confirmLabel', () => opts.confirmLabel ?? ''),
17332
- inputBinding('cancelLabel', () => opts.cancelLabel ?? ''),
17333
- ],
17334
- });
17335
- modalRef.onClose((result) => settle(!!result, true));
17336
- return () => {
17337
- if (settled)
17338
- return;
17339
- settled = true;
17340
- watch.unsubscribe();
17341
- close(id);
17342
- };
17343
- });
17344
- /**
17345
- * Opens one Screen as an overlay and hands it its inputs — what a
17346
- * generated FeatureStore calls where a Control's `mModal` would be the
17347
- * drawn answer (m-one-ui OpenScreen).
17348
- *
17349
- * The same body the two directives build, reached the same way: the widget
17350
- * is loaded on first open, so nothing it names is in the initial bundle.
17351
- * Returns the overlay's own id and waits for nothing — the caller is a
17352
- * `tap` inside a request pipe, and a store that held its emission open
17353
- * until a panel closed would be answering for a gesture nobody made.
17354
- */
17355
- const openScreen = (trigger) => {
17356
- const bindings = [
17357
- inputBinding('widget', () => trigger.widget),
17358
- inputBinding('inputs', () => trigger.inputs ?? {}),
17359
- // The body binds these onto the Screen it creates (ADR 0033). A
17360
- // Screen the opener listens to nothing of hands an empty record,
17361
- // which binds nothing at all.
17362
- inputBinding('outputs', () => trigger.outputs ?? {}),
17363
- ];
17364
- // Its own ModalRef, the way each directive mints one: the body closes
17365
- // itself through this. Nothing here listens for the *result* — a store
17366
- // has nowhere to put a panel's answer — but the close dismisses, which is
17367
- // the whole of what a body opened this way can ask for (ADR 0031).
17368
- const modalRef = new ModalRef();
17369
- // What the body answered reaches the caller either way (ADR 0031): a
17370
- // `change` reports and the overlay stays, a `close` reports and then it
17371
- // goes. The order on a close is deliberate — a handler that reads the
17372
- // Screen it opened must run while that Screen is still there.
17373
- modalRef.onChange((result) => trigger.onResult?.(result));
17374
- const providers = [{ provide: MODAL_REF, useValue: modalRef }];
17375
- if (trigger.as === 'side_panel') {
17376
- const panelId = openPanel({
17377
- component: overlayBodyComp,
17378
- bindings,
17379
- providers,
17380
- side: trigger.side,
17381
- width: trigger.width,
17382
- height: trigger.height,
17383
- dock: trigger.dock,
17384
- closeProhibited: trigger.closeProhibited,
17385
- });
17386
- modalRef.onClose((result) => {
17387
- trigger.onResult?.(result);
17388
- closePanel(panelId);
17389
- });
17390
- return panelId;
17391
- }
17392
- const modalId = open({
17393
- component: overlayBodyComp,
17394
- bindings,
17395
- providers,
17396
- config: trigger.config,
17397
- });
17398
- modalRef.onClose((result) => {
17399
- trigger.onResult?.(result);
17400
- close(modalId);
17401
- });
17402
- return modalId;
17403
- };
17404
- /**
17405
- * Closes the overlay with this id, whichever kind it is — what a caller
17406
- * holding only what `openScreen` returned can say (ADR 0031). Nothing for
17407
- * an id nothing answers to, which is what a body that already closed itself
17408
- * leaves behind.
17409
- */
17410
- const dismiss = (id) => {
17411
- if (state.modalTriggerMap()[id]) {
17412
- close(id);
17413
- return;
17414
- }
17415
- if (state.panelTriggerMap()[id])
17416
- closePanel(id);
17417
- };
17418
- // The callback form, kept for every caller drawn against it. One
17419
- // implementation underneath: a refusal runs nothing, which is what an
17420
- // `onConfirm` that never fires already meant.
17421
- const confirm = (opts, onConfirm) => {
17422
- ask(opts).subscribe((result) => {
17423
- if (result)
17424
- onConfirm();
17425
- });
17426
- };
17427
- return {
17428
- open,
17429
- close,
17430
- dismiss,
17431
- ask,
17432
- confirm,
17433
- openScreen,
17434
- openPanel,
17435
- closePanel,
17436
- cleanupOnClose,
17437
- cleanupPanelsOnClose,
17438
- };
17439
- }), withHooks({
17440
- onInit({ cleanupOnClose, modalTriggerMap, cleanupPanelsOnClose, panelTriggerMap, }) {
17441
- cleanupOnClose(modalTriggerMap);
17442
- cleanupPanelsOnClose(panelTriggerMap);
17443
- },
17444
- }));
17445
-
17446
18013
  const USER_TAB_MAP = new InjectionToken('USER_TAB_MAP');
17447
18014
  const WIN_USER_TAB_HOOK = '__mag_register_user_tabs__';
17448
18015
  const WIN_USER_TAB_KEY = '__mag_user_tabs__';
@@ -17876,169 +18443,6 @@ function injectAuthenticate() {
17876
18443
  };
17877
18444
  }
17878
18445
 
17879
- class ConfirmComponent {
17880
- header = input('', ...(ngDevMode ? [{ debugName: "header" }] : /* istanbul ignore next */ []));
17881
- body = input('', ...(ngDevMode ? [{ debugName: "body" }] : /* istanbul ignore next */ []));
17882
- /**
17883
- * The MessageVariable values the two keys above name — a row's name or id the
17884
- * asker knows and the message asks about. Values and never text: they reach
17885
- * `TranslatePipe` as params rather than spliced into the key, so the message
17886
- * still resolves per language. Empty is a message with no slots, which is
17887
- * every confirmation drawn before this.
17888
- */
17889
- params = input({}, ...(ngDevMode ? [{ debugName: "params" }] : /* istanbul ignore next */ []));
17890
- type = input('info', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
17891
- /**
17892
- * Whether the question can be refused. `yes` is an acknowledgement — the one
17893
- * button commits and there is nothing else to press — and stays the default,
17894
- * which is what every ConfirmComponent drawn before this was.
17895
- */
17896
- kind = input('yes', ...(ngDevMode ? [{ debugName: "kind" }] : /* istanbul ignore next */ []));
17897
- /**
17898
- * The wording of each button, as a TranslationAsset key. Empty falls back to
17899
- * the library's own — derived from `type` for the commit, `cancel` for the
17900
- * refusal — so a caller that has nothing to say about the buttons says
17901
- * nothing.
17902
- */
17903
- confirmLabel = input('', ...(ngDevMode ? [{ debugName: "confirmLabel" }] : /* istanbul ignore next */ []));
17904
- cancelLabel = input('', ...(ngDevMode ? [{ debugName: "cancelLabel" }] : /* istanbul ignore next */ []));
17905
- #modalRef = inject(MODAL_REF);
17906
- confirmText = computed(() => {
17907
- if (this.confirmLabel())
17908
- return this.confirmLabel();
17909
- switch (this.type()) {
17910
- case 'danger':
17911
- return 'delete';
17912
- default:
17913
- return 'okay';
17914
- }
17915
- }, ...(ngDevMode ? [{ debugName: "confirmText" }] : /* istanbul ignore next */ []));
17916
- cancelText = computed(() => this.cancelLabel() || 'cancel', ...(ngDevMode ? [{ debugName: "cancelText" }] : /* istanbul ignore next */ []));
17917
- iconName = computed(() => {
17918
- switch (this.type()) {
17919
- case 'danger':
17920
- return 'trash';
17921
- case 'warning':
17922
- return 'exclamation-triangle';
17923
- case 'success':
17924
- return 'check-circle';
17925
- default:
17926
- return 'info';
17927
- }
17928
- }, ...(ngDevMode ? [{ debugName: "iconName" }] : /* istanbul ignore next */ []));
17929
- accept() {
17930
- this.#modalRef.close(true);
17931
- }
17932
- // The refusal is a result like any other, so it closes with `false` rather
17933
- // than dismissing: a caller waiting on the answer gets one either way.
17934
- decline() {
17935
- this.#modalRef.close(false);
17936
- }
17937
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ConfirmComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
17938
- 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: `
17939
- <div class="confirm confirm--{{ type() }}">
17940
- <div class="confirm__header">
17941
- <div class="confirm__icon">
17942
- <m-icon [name]="iconName()" />
17943
- </div>
17944
- @if (header()) {
17945
- <!-- The heading takes the key and its values rather than projected
17946
- text: m-header translates its own label, and a MessageVariable
17947
- fills the same way it does everywhere else. -->
17948
- <m-header [level]="3" [label]="header()" [params]="params()" />
17949
- }
17950
- </div>
17951
-
17952
- <div class="confirm__content">
17953
- @if (body()) {
17954
- <p class="confirm__body" [innerHTML]="body() | translate: params()"></p>
17955
- }
17956
- </div>
17957
-
17958
- <div class="confirm__actions">
17959
- @if (kind() === 'yes-no') {
17960
- <!-- asset: buttons/confirm_cancel.yml -->
17961
- <m-one-button name="confirm_cancel" [label]="cancelText()" (clicked)="decline()" />
17962
- }
17963
- <!-- asset: buttons/okay.yml -->
17964
- <m-one-button name="okay" [label]="confirmText()" (clicked)="accept()" />
17965
- </div>
17966
- </div>
17967
- `, 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", "icon", "actionButton", "actionLabel", "noTranslate", "params"], outputs: ["actionClick"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
17968
- }
17969
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ConfirmComponent, decorators: [{
17970
- type: Component,
17971
- args: [{ selector: 'm-confirm', imports: [ButtonComponent, IconComponent, TranslatePipe, HeaderComponent$1], template: `
17972
- <div class="confirm confirm--{{ type() }}">
17973
- <div class="confirm__header">
17974
- <div class="confirm__icon">
17975
- <m-icon [name]="iconName()" />
17976
- </div>
17977
- @if (header()) {
17978
- <!-- The heading takes the key and its values rather than projected
17979
- text: m-header translates its own label, and a MessageVariable
17980
- fills the same way it does everywhere else. -->
17981
- <m-header [level]="3" [label]="header()" [params]="params()" />
17982
- }
17983
- </div>
17984
-
17985
- <div class="confirm__content">
17986
- @if (body()) {
17987
- <p class="confirm__body" [innerHTML]="body() | translate: params()"></p>
17988
- }
17989
- </div>
17990
-
17991
- <div class="confirm__actions">
17992
- @if (kind() === 'yes-no') {
17993
- <!-- asset: buttons/confirm_cancel.yml -->
17994
- <m-one-button name="confirm_cancel" [label]="cancelText()" (clicked)="decline()" />
17995
- }
17996
- <!-- asset: buttons/okay.yml -->
17997
- <m-one-button name="okay" [label]="confirmText()" (clicked)="accept()" />
17998
- </div>
17999
- </div>
18000
- `, 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"] }]
18001
- }], 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 }] }] } });
18002
-
18003
- function injectInstallApp() {
18004
- const modalStore = inject(ModalStore);
18005
- const httpService = inject(HttpService);
18006
- return (app) => {
18007
- const appName = app.name ?? app.link ?? '';
18008
- const appId = app.id ?? '';
18009
- return new Promise((resolve, reject) => {
18010
- const modalRef = new ModalRef();
18011
- const id = modalStore.open({
18012
- component: ConfirmComponent,
18013
- providers: [{ provide: MODAL_REF, useValue: modalRef }],
18014
- bindings: [
18015
- inputBinding('header', () => `install_app_title?appName=${appName}`),
18016
- inputBinding('body', () => `install_app_body?appName=${appName}`),
18017
- inputBinding('type', () => 'info'),
18018
- ],
18019
- });
18020
- modalRef.onClose(async (confirmed) => {
18021
- modalStore.close(id);
18022
- if (!confirmed) {
18023
- reject(new Error('app_install_declined'));
18024
- return;
18025
- }
18026
- try {
18027
- const body = await firstValueFrom(httpService.post('store', ['request', appId], {}));
18028
- if (body?.relation?.type === 5) {
18029
- reject({ type: 'install_pending', appName });
18030
- return;
18031
- }
18032
- resolve();
18033
- }
18034
- catch (e) {
18035
- reject(e);
18036
- }
18037
- });
18038
- });
18039
- };
18040
- }
18041
-
18042
18446
  /**
18043
18447
  * Pre-creates signal-to-observable conversions at service instantiation time
18044
18448
  * (always outside reactive context), preventing NG0602 when interceptors run
@@ -18117,7 +18521,7 @@ class NotificationService {
18117
18521
  ...notification,
18118
18522
  timestamp: notification.timestamp ?? new Date().toISOString(),
18119
18523
  });
18120
- if (!notification.persistent) {
18524
+ if (!notification.persistent && !notification.silent) {
18121
18525
  this.scheduleAutoClose(id);
18122
18526
  }
18123
18527
  return id;
@@ -18199,7 +18603,13 @@ const tokenRefreshed$ = new Subject();
18199
18603
  // Holds the refresh token while the refresh HTTP call is in-flight.
18200
18604
  // Must be stored before clearAuth() erases it from the store.
18201
18605
  let pendingRefreshToken = null;
18202
- // Deduplicates concurrent app_access_required 403s — only one install modal at a time.
18606
+ /**
18607
+ * The header naming which App sent a request (api ADR 0007): a domain api
18608
+ * honours a Declared Permission only for the App it names.
18609
+ */
18610
+ const CALLING_APP_HEADER = 'X-Mag-App';
18611
+ // Deduplicates concurrent app_access_required / agreement_required 403s — only
18612
+ // one install or Agreement modal at a time.
18203
18613
  // Subsequent failures queue on tokenRefreshed$/authFailed$ rather than opening a second modal.
18204
18614
  const appInstallGuard = { pending: null };
18205
18615
  function getTokenizedReq(request, { auth }) {
@@ -18207,14 +18617,19 @@ function getTokenizedReq(request, { auth }) {
18207
18617
  headers: request.headers.set('Authorization', auth),
18208
18618
  });
18209
18619
  }
18210
- const mInterceptor = (request, next) => {
18620
+ const mInterceptor = (incoming, next) => {
18211
18621
  const httpService = inject(HttpService);
18212
18622
  const injector = inject(Injector);
18213
18623
  const baseUrl = httpService.getUrl();
18214
18624
  const authBaseUrl = httpService.getAuthUrl();
18215
- const isBackend = request.url.startsWith(baseUrl) || request.url.startsWith(authBaseUrl);
18625
+ const isBackend = incoming.url.startsWith(baseUrl) || incoming.url.startsWith(authBaseUrl);
18626
+ const appLink = inject(APP_LINK)();
18627
+ const request = appLink && incoming.url.startsWith(baseUrl)
18628
+ ? incoming.clone({ setHeaders: { [CALLING_APP_HEADER]: appLink } })
18629
+ : incoming;
18216
18630
  const authenticate = injectAuthenticate();
18217
18631
  const installApp = injectInstallApp();
18632
+ const agreeToApp = injectAgreeToApp();
18218
18633
  const store = inject(LOGIN_STORE);
18219
18634
  const authObs = inject(InterceptorObservables);
18220
18635
  const tokens = store?.tokens();
@@ -18259,6 +18674,23 @@ const mInterceptor = (request, next) => {
18259
18674
  const waitForToken = () => race(tokenRefreshed$.pipe(take(1), switchMap$1(() => sendWithToken())), authFailed$.pipe(take(1), switchMap$1((err) => throwError(() => err))));
18260
18675
  const on403 = (error) => {
18261
18676
  const hint = error.error?.hint;
18677
+ // The App's Declared Permissions grew since the user agreed, or they never
18678
+ // did (store ADR 0006): ask, record it, and resend.
18679
+ if (hint?.type === 'agreement_required' && hint.app) {
18680
+ actions.cancelLoading();
18681
+ if (!appInstallGuard.pending) {
18682
+ appInstallGuard.pending = agreeToApp(hint.app, hint.permissions ?? [])
18683
+ .then(() => {
18684
+ appInstallGuard.pending = null;
18685
+ tokenRefreshed$.next();
18686
+ })
18687
+ .catch(() => {
18688
+ appInstallGuard.pending = null;
18689
+ authFailed$.next(error);
18690
+ });
18691
+ }
18692
+ return waitForToken();
18693
+ }
18262
18694
  if (hint?.type === 'app_access_required' && hint.app) {
18263
18695
  actions.cancelLoading();
18264
18696
  if (!appInstallGuard.pending) {
@@ -18448,6 +18880,8 @@ class BaseRootWebComponent extends BaseWebComponent {
18448
18880
  searchGroups = inject(WC_SEARCH_GROUPS, { optional: true });
18449
18881
  /** The custom element itself: the one channel two mounts of this app do not share. */
18450
18882
  host = inject(ElementRef).nativeElement;
18883
+ ownAppLink = inject(APP_LINK);
18884
+ agreementGate = inject(AgreementGate);
18451
18885
  constructor() {
18452
18886
  super();
18453
18887
  effect(() => {
@@ -18515,6 +18949,18 @@ class BaseRootWebComponent extends BaseWebComponent {
18515
18949
  if (id && !appId)
18516
18950
  untracked(() => bindApp(id));
18517
18951
  });
18952
+ // m-remote's `appLink` is who this app is, even where the page URL names
18953
+ // the app that mounted it. Named late, so Agreement is asked here rather
18954
+ // than at init (store ADR 0006).
18955
+ effect(() => {
18956
+ const id = this.appLink();
18957
+ if (!id || id === untracked(this.ownAppLink))
18958
+ return;
18959
+ untracked(() => {
18960
+ this.ownAppLink.set(id);
18961
+ this.agreementGate.ensure(id);
18962
+ });
18963
+ });
18518
18964
  // Run initial sync when router is ready
18519
18965
  this.router.initialNavigation();
18520
18966
  const initialPath = this.extra();
@@ -18524,15 +18970,23 @@ class BaseRootWebComponent extends BaseWebComponent {
18524
18970
  });
18525
18971
  }
18526
18972
  // Report every settled route on this element, bubbling: the m-remote that
18527
- // mounted it listens there (ADR 0038), anything above still hears it.
18973
+ // mounted it listens there (ADR 0038), anything above still hears it. The
18974
+ // Nav rides along — the host routes only down to the mount, and its menu
18975
+ // stands on this app's Nav only if the app says which.
18528
18976
  const destroyRef = inject(DestroyRef);
18529
18977
  const sub = this.router.events
18530
18978
  .pipe(filter((e) => e instanceof NavigationEnd))
18531
18979
  .subscribe(({ urlAfterRedirects }) => {
18980
+ const root = this.router.routerState.snapshot.root;
18532
18981
  this.host.dispatchEvent(new CustomEvent(WC_ROUTE_CHANGED_EVENT, {
18533
18982
  bubbles: true,
18534
18983
  composed: true,
18535
- detail: { appId, path: urlAfterRedirects },
18984
+ detail: {
18985
+ appId,
18986
+ path: urlAfterRedirects,
18987
+ navId: routeNavIdOf(root),
18988
+ params: routeParamsOf(root),
18989
+ },
18536
18990
  }));
18537
18991
  });
18538
18992
  // The host moving this remote — a path binding or a menu click.
@@ -19241,7 +19695,7 @@ class SectionTableComponent extends ConfigComponent {
19241
19695
  </div>
19242
19696
  <ng-content select="m-section-pagination" />
19243
19697
  </div>
19244
- `, 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)}}.m-table{display:flex;flex-direction:column;border:1px solid var(--m-backdrop-border);border-radius:12px;overflow:clip;background:#ffffffe6;-webkit-backdrop-filter:blur(40px);backdrop-filter:blur(40px);position:relative;transition:background-color .3s ease}.m-table--flat{border:none;box-shadow:none;background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none;border-radius:0}.m-table__toolbar{position:sticky;top:0;z-index:2;display:flex;align-items:center;justify-content:space-between;padding:1.5rem var(--m-table-toolbar-padding-x, 1.25rem);border-bottom:1px solid var(--m-backdrop-border);gap:1.5rem;background:color-mix(in srgb,var(--m-background) 45%,transparent)}.m-table--flat .m-table__toolbar{background:transparent;padding-left:0;padding-right:0}.m-table__title{margin:0;font-size:1.25rem;font-weight:800;color:var(--m-text);letter-spacing:-.02em;flex:1}.m-table__search{flex:0 1 auto;display:flex;align-items:center}.m-table__search .m-input-wrapper{width:100%}.m-table__mobile-view{display:flex;flex-direction:column;gap:1rem;padding:1.25rem;flex:1;overflow:auto}.m-table__empty-mobile{padding:3rem 1.5rem;text-align:center;color:var(--m-text-tertiary);font-size:.9375rem;font-weight:500;font-style:italic;opacity:.8;background:color-mix(in srgb,var(--m-background) 20%,transparent);border-radius:12px;border:1px dashed var(--m-backdrop-border)}.m-table__wrapper{overflow:auto;flex:1}.m-table__wrapper::-webkit-scrollbar{width:6px;height:6px}.m-table__wrapper::-webkit-scrollbar-track{background:transparent}.m-table__wrapper::-webkit-scrollbar-thumb{background:var(--m-backdrop-border);border-radius:10px}.m-table__wrapper::-webkit-scrollbar-thumb:hover{background:var(--m-text-tertiary)}.m-table__table{width:100%;min-width:100%;border-collapse:separate;border-spacing:0}mark.m-table__highlight{background:var(--m-highlight);color:#000;border-radius:2px;padding:0 2px;font-weight:700;box-shadow:0 1px 4px #0003}mark.m-table__highlight .m-one-pagination{margin-left:auto;--m-button-size: 2.25rem;--m-pagination-gap: .375rem}.m-table-pagination{display:flex;align-items:center;gap:1.5rem;padding:1.25rem var(--m-table-pagination-padding-x, 1.25rem);border-top:1px solid var(--m-backdrop-border);font-size:.8125rem;flex-wrap:wrap;background:color-mix(in srgb,var(--m-background) 40%,transparent)}.m-table--flat .m-table-pagination{background:transparent;padding-left:0;padding-right:0}.m-table-pagination__size{display:flex;flex-direction:column;align-items:flex-start;gap:.35rem;color:var(--m-text-secondary);font-weight:500}.m-table-pagination__select{border:1px solid var(--m-backdrop-border);border-radius:8px;background:var(--m-backdrop-surface);color:var(--m-text);padding:.375rem .625rem;font-size:.8125rem;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);outline:none}.m-table-pagination__select:hover{background:var(--m-backdrop-glass);border-color:var(--m-mm);box-shadow:0 0 0 3px color-mix(in srgb,var(--m-mm) 10%,transparent)}.m-table-pagination__select:focus{border-color:var(--m-mm);box-shadow:0 0 0 3px color-mix(in srgb,var(--m-mm) 20%,transparent)}.m-table-filter{display:flex;flex-wrap:wrap;align-items:center;gap:10px;padding:1rem 1.25rem;background:color-mix(in srgb,var(--m-background-lite) 60%,transparent);border-bottom:1px solid var(--m-backdrop-border);box-shadow:inset 0 2px 4px #00000005;overflow-x:auto;scrollbar-width:none}.m-table-filter::-webkit-scrollbar{display:none}.m-table--flat .m-table-filter{background:transparent;padding-left:0;padding-right:0;border-bottom:none}.m-table-filter__item{display:flex;align-items:center;gap:10px;padding:.4375rem 1rem;border-radius:12px;background:var(--m-background);border:1px solid var(--m-backdrop-border);color:var(--m-text-secondary);cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);white-space:nowrap;-webkit-user-select:none;user-select:none;outline:none;font-weight:500}.m-table-filter__item:hover{border-color:var(--m-mm);color:var(--m-mm);background:var(--m-background);transform:translateY(-1px);box-shadow:0 4px 12px #0000000d}.m-table-filter__item--active{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);font-weight:600;box-shadow:0 8px 16px color-mix(in srgb,var(--m-mm) 25%,transparent)}.m-table-filter__item--active:hover{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);transform:translateY(-1px)}.m-table-filter__item--active .m-table-filter__badge{background:#fff3;color:var(--m-inverse-text);border-color:#ffffff1a}.m-table-filter__item--primary{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);font-weight:600;box-shadow:0 8px 16px color-mix(in srgb,var(--m-mm) 25%,transparent)}.m-table-filter__item--primary:hover{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);transform:translateY(-1px);box-shadow:0 10px 20px color-mix(in srgb,var(--m-mm) 30%,transparent)}.m-table-filter__item--primary .m-table-filter__badge{background:#fff3;color:var(--m-inverse-text);border-color:#ffffff1a}.m-table-filter__item--danger{border-color:var(--m-error);color:var(--m-error)}.m-table-filter__item--danger:hover{border-color:var(--m-error);color:var(--m-error);background:var(--m-backdrop-error);transform:translateY(-1px);box-shadow:0 4px 12px color-mix(in srgb,var(--m-error) 12%,transparent)}.m-table-filter__item--danger .m-table-filter__badge{background:var(--m-backdrop-error);color:var(--m-error);border-color:color-mix(in srgb,var(--m-error) 20%,transparent)}.m-table-filter__label{font-size:.8125rem;font-weight:600;letter-spacing:.01em}.m-table-filter__badge{display:inline-flex;align-items:center;justify-content:center;min-width:1.25rem;height:1.25rem;padding:0 .375rem;border-radius:100px;background:var(--m-backdrop-surface);color:var(--m-text-secondary);font-size:.6875rem;font-weight:700;border:1px solid var(--m-backdrop-border);transition:all .2s ease}.m-table-thead__th{position:sticky;top:0;z-index:10;background:color-mix(in srgb,var(--m-background) 95%,transparent);-webkit-backdrop-filter:blur(28px);backdrop-filter:blur(28px);padding:1.25rem;text-align:left;font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--m-text-tertiary);border-bottom:2px solid var(--m-backdrop-border);white-space:nowrap;transition:all .2s ease}.m-table-thead__th:hover{color:var(--m-text);background:var(--m-background)}@media(min-width:769px){.m-table-thead__th--fixed{z-index:20;background:var(--m-background)}}@media(max-width:768px){.m-table-thead__th--fixed{position:static;z-index:auto}}.m-table-thead__th--fixed{border-right:none}@media(min-width:769px){.m-table-thead__th--fixed-last{border-right:1px solid var(--m-backdrop-border)}}@media(max-width:768px){.m-table-thead__th--fixed-last{border-right:none}}.m-table-thead__th--sortable{cursor:pointer;-webkit-user-select:none;user-select:none}.m-table-thead__th--select{width:48px;min-width:48px;max-width:48px;padding:0 1rem;text-align:center}.m-table-thead__th--select input[type=checkbox]{width:1rem;height:1rem;cursor:pointer;accent-color:var(--m-mm);border-radius:3px;display:block;margin:0 auto}.m-table-thead__cell{display:flex;align-items:center;gap:.5rem}.m-table-thead__sort-icon{color:var(--m-mm);opacity:.6;transition:opacity .2s ease}.m-table-thead__th:hover .m-table-thead__sort-icon{opacity:1}.m-table-thead__menu-btn{display:flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin-left:auto;border:none;background:transparent;cursor:pointer;color:var(--m-text-tertiary);border-radius:6px;opacity:0;transition:all .15ms ease}.m-table-thead__menu-btn:hover{background:var(--m-backdrop-surface);color:var(--m-text)}.m-table-thead__th:hover .m-table-thead__menu-btn{opacity:1}.m-table-body__row{transition:background-color .3s cubic-bezier(.4,0,.2,1);position:relative}.m-table-body__row:hover{background:color-mix(in srgb,var(--m-mm) 5%,transparent)}.m-table-body__row:hover .m-table-body__cell{background:inherit}.m-table-body__cell{padding:1rem 1.25rem;font-size:.875rem;color:var(--m-text);border-bottom:1px solid var(--m-backdrop-border);white-space:nowrap;vertical-align:middle;background:transparent;transition:background-color .3s ease}.m-table-body__cell[class*=--number],.m-table-body__cell[class*=--currency],.m-table-body__cell[class*=--percent]{font-family:Inter,Roboto Mono,monospace;font-variant-numeric:tabular-nums;letter-spacing:-.01em}@media(min-width:769px){.m-table-body__cell--fixed{position:sticky;background:var(--m-background);z-index:5}}@media(max-width:768px){.m-table-body__cell--fixed{position:static;background:transparent;z-index:auto}}.m-table-body__cell--fixed{border-right:none;transition:background-color .3s ease}.m-table-body__row:hover .m-table-body__cell--fixed{background:color-mix(in srgb,var(--m-mm) 5%,var(--m-background));z-index:6}@media(min-width:769px){.m-table-body__cell--fixed-last{border-right:1px solid var(--m-backdrop-border)}}@media(max-width:768px){.m-table-body__cell--fixed-last{border-right:none}}.m-table-body__cell--context-menu{padding-top:.35rem;padding-bottom:.35rem}.m-table-body__cell--select{width:48px;min-width:48px;max-width:48px;padding:0 1rem;text-align:center}.m-table-body__cell--select input[type=checkbox],.m-table-body__cell--select input[type=radio]{width:1rem;height:1rem;cursor:pointer;accent-color:var(--m-mm);display:block;margin:0 auto}.m-table-body__input{border:none;border-bottom:2px solid var(--m-backdrop-border);background:transparent;font-size:.875rem;color:var(--m-text);padding:.25rem;outline:none;width:100%;transition:border-bottom-color .2s ease}.m-table-body__input:focus{border-bottom-color:var(--m-mm)}.m-table-body__action-btn{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;border:none;background:transparent;cursor:pointer;color:var(--m-text-tertiary);border-radius:8px;transition:all .2s ease}.m-table-body__action-btn:hover{background:var(--m-backdrop-surface);color:var(--m-text)}.m-table-body__empty{text-align:center;padding:4rem;color:var(--m-text-tertiary);font-size:1rem;font-weight:500;letter-spacing:.02em;font-style:italic;opacity:.7}.m-table-body__link{color:var(--m-mm);text-decoration:none;cursor:pointer;font-weight:600;transition:color .2s ease}.m-table-body__link:hover{text-decoration:underline;color:var(--m-mm-lite)}.m-table-body__value{padding:.25rem .5rem;border-radius:6px;font-weight:600;font-variant-numeric:tabular-nums;letter-spacing:-.01em}.m-table-body__value--positive{color:var(--m-success);background:var(--m-backdrop-success)}.m-table-body__value--negative{color:var(--m-error);background:var(--m-backdrop-error)}.m-table-body__dash{color:var(--m-text-tertiary);font-weight:400;font-style:italic;opacity:.8}.m-section-table-host{display:block;width:100%}.m-section-table__th{position:static;vertical-align:middle}.m-section-table--sticky .m-section-table__th{position:sticky;top:0}.m-section-table__heading{justify-content:var(--m-section-table-justify, flex-start);min-height:2rem}.m-section-table--compact :where(.m-section-table__th){padding:.625rem .75rem}.m-section-table--compact :where(.m-section-table__cell){padding:.5rem .75rem}.m-section-table--spacious :where(.m-section-table__th){padding:1.5rem 1.75rem}.m-section-table--spacious :where(.m-section-table__cell){padding:1.5rem 1.75rem}.m-section-table--margin{margin-block:1em}.m-section-table--border.m-table{border-top:4px solid var(--m-backdrop-border);border-bottom:2px solid var(--m-backdrop-border)}.m-section-table--zebra .m-section-table__row:nth-child(2n):not(:hover){background:color-mix(in srgb,var(--m-mm) 3%,transparent)}.m-section-table--zebra .m-section-table__row:nth-child(2n):not(:hover) .m-section-table__cell--frozen{background:color-mix(in srgb,var(--m-mm) 3%,var(--m-background))}.m-section-table__th--squeeze{position:relative;padding-right:3rem}.m-section-table__th--folded{padding-left:0;padding-right:0}.m-section-table__squeeze{position:absolute;top:50%;right:.5rem;transform:translateY(-50%);display:flex;border:1px solid var(--m-backdrop-border);border-radius:8px;background:var(--m-backdrop-surface)}.m-section-table__th--folded .m-section-table__squeeze{right:50%;transform:translate(50%,-50%)}@media(min-width:769px){.m-section-table__cell--frozen{position:sticky;z-index:5;background:var(--m-background)}}@media(min-width:769px){.m-section-table th.m-section-table__cell--frozen{z-index:20}}@media(min-width:769px){.m-section-table--sticky .m-section-table th.m-section-table__cell--frozen{z-index:21}}@media(min-width:769px){.m-section-table__cell--frozen-last{border-right:1px solid var(--m-backdrop-border)}}.m-section-table__row:hover .m-section-table__cell--frozen{background:color-mix(in srgb,var(--m-mm) 5%,var(--m-background))}.m-section-table__cell--folded{text-align:center;padding-left:0;padding-right:0}.m-section-table__content[hidden]{display:none}.m-section-table .m-section-table__cell .m-section-table__content .m-text-output-host.align-left .m-text-output{text-align:inherit}.m-section-table__dot{display:inline-block;width:.375rem;height:.375rem;border-radius:50%;background:var(--m-text-tertiary)}.m-section-table__row{cursor:default}\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: FreezeComponent, selector: "m-freeze", inputs: ["config"] }, { kind: "component", type: IconComponent, selector: "m-icon, m-one-icon", inputs: ["config", "name", "color", "size", "one", "baseUrl", "remote"], outputs: ["configChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
19698
+ `, 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)}}.m-table{display:flex;flex-direction:column;border:1px solid var(--m-backdrop-border);border-radius:12px;overflow:clip;background:#ffffffe6;-webkit-backdrop-filter:blur(40px);backdrop-filter:blur(40px);position:relative;transition:background-color .3s ease}.m-table--flat{border:none;box-shadow:none;background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none;border-radius:0}.m-table__toolbar{position:sticky;top:0;z-index:2;display:flex;align-items:center;justify-content:space-between;padding:1.5rem var(--m-table-toolbar-padding-x, 1.25rem);border-bottom:1px solid var(--m-backdrop-border);gap:1.5rem;background:color-mix(in srgb,var(--m-background) 45%,transparent)}.m-table--flat .m-table__toolbar{background:transparent;padding-left:0;padding-right:0}.m-table__title{margin:0;font-size:1.25rem;font-weight:800;color:var(--m-text);letter-spacing:-.02em;flex:1}.m-table__search{flex:0 1 auto;display:flex;align-items:center}.m-table__search .m-input-wrapper{width:100%}.m-table__mobile-view{display:flex;flex-direction:column;gap:1rem;padding:1.25rem;flex:1;overflow:auto}.m-table__empty-mobile{padding:3rem 1.5rem;text-align:center;color:var(--m-text-tertiary);font-size:.9375rem;font-weight:500;font-style:italic;opacity:.8;background:color-mix(in srgb,var(--m-background) 20%,transparent);border-radius:12px;border:1px dashed var(--m-backdrop-border)}.m-table__wrapper{overflow:auto;flex:1}.m-table__wrapper::-webkit-scrollbar{width:6px;height:6px}.m-table__wrapper::-webkit-scrollbar-track{background:transparent}.m-table__wrapper::-webkit-scrollbar-thumb{background:var(--m-backdrop-border);border-radius:10px}.m-table__wrapper::-webkit-scrollbar-thumb:hover{background:var(--m-text-tertiary)}.m-table__table{width:100%;min-width:100%;border-collapse:separate;border-spacing:0}mark.m-table__highlight{background:var(--m-highlight);color:#000;border-radius:2px;padding:0 2px;font-weight:700;box-shadow:0 1px 4px #0003}mark.m-table__highlight .m-one-pagination{margin-left:auto;--m-button-size: 2.25rem;--m-pagination-gap: .375rem}.m-table-pagination{display:flex;align-items:center;gap:1.5rem;padding:1.25rem var(--m-table-pagination-padding-x, 1.25rem);border-top:1px solid var(--m-backdrop-border);font-size:.8125rem;flex-wrap:wrap;background:color-mix(in srgb,var(--m-background) 40%,transparent)}.m-table--flat .m-table-pagination{background:transparent;padding-left:0;padding-right:0}.m-table-pagination__size{display:flex;flex-direction:column;align-items:flex-start;gap:.35rem;color:var(--m-text-secondary);font-weight:500}.m-table-pagination__select{border:1px solid var(--m-backdrop-border);border-radius:8px;background:var(--m-backdrop-surface);color:var(--m-text);padding:.375rem .625rem;font-size:.8125rem;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);outline:none}.m-table-pagination__select:hover{background:var(--m-backdrop-glass);border-color:var(--m-mm);box-shadow:0 0 0 3px color-mix(in srgb,var(--m-mm) 10%,transparent)}.m-table-pagination__select:focus{border-color:var(--m-mm);box-shadow:0 0 0 3px color-mix(in srgb,var(--m-mm) 20%,transparent)}.m-table-filter{display:flex;flex-wrap:wrap;align-items:center;gap:10px;padding:1rem 1.25rem;background:color-mix(in srgb,var(--m-background-lite) 60%,transparent);border-bottom:1px solid var(--m-backdrop-border);box-shadow:inset 0 2px 4px #00000005;overflow-x:auto;scrollbar-width:none}.m-table-filter::-webkit-scrollbar{display:none}.m-table--flat .m-table-filter{background:transparent;padding-left:0;padding-right:0;border-bottom:none}.m-table-filter__item{display:flex;align-items:center;gap:10px;padding:.4375rem 1rem;border-radius:12px;background:var(--m-background);border:1px solid var(--m-backdrop-border);color:var(--m-text-secondary);cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);white-space:nowrap;-webkit-user-select:none;user-select:none;outline:none;font-weight:500}.m-table-filter__item:hover{border-color:var(--m-mm);color:var(--m-mm);background:var(--m-background);transform:translateY(-1px);box-shadow:0 4px 12px #0000000d}.m-table-filter__item--active{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);font-weight:600;box-shadow:0 8px 16px color-mix(in srgb,var(--m-mm) 25%,transparent)}.m-table-filter__item--active:hover{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);transform:translateY(-1px)}.m-table-filter__item--active .m-table-filter__badge{background:#fff3;color:var(--m-inverse-text);border-color:#ffffff1a}.m-table-filter__item--primary{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);font-weight:600;box-shadow:0 8px 16px color-mix(in srgb,var(--m-mm) 25%,transparent)}.m-table-filter__item--primary:hover{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);transform:translateY(-1px);box-shadow:0 10px 20px color-mix(in srgb,var(--m-mm) 30%,transparent)}.m-table-filter__item--primary .m-table-filter__badge{background:#fff3;color:var(--m-inverse-text);border-color:#ffffff1a}.m-table-filter__item--danger{border-color:var(--m-error);color:var(--m-error)}.m-table-filter__item--danger:hover{border-color:var(--m-error);color:var(--m-error);background:var(--m-backdrop-error);transform:translateY(-1px);box-shadow:0 4px 12px color-mix(in srgb,var(--m-error) 12%,transparent)}.m-table-filter__item--danger .m-table-filter__badge{background:var(--m-backdrop-error);color:var(--m-error);border-color:color-mix(in srgb,var(--m-error) 20%,transparent)}.m-table-filter__label{font-size:.8125rem;font-weight:600;letter-spacing:.01em}.m-table-filter__badge{display:inline-flex;align-items:center;justify-content:center;min-width:1.25rem;height:1.25rem;padding:0 .375rem;border-radius:100px;background:var(--m-backdrop-surface);color:var(--m-text-secondary);font-size:.6875rem;font-weight:700;border:1px solid var(--m-backdrop-border);transition:all .2s ease}.m-table-thead__th{position:sticky;top:0;z-index:10;background:var(--m-table-thead-background, color-mix(in srgb, var(--m-background) 95%, transparent));-webkit-backdrop-filter:var(--m-table-thead-backdrop-filter, blur(28px));backdrop-filter:var(--m-table-thead-backdrop-filter, blur(28px));padding:1.25rem;text-align:left;font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--m-text-tertiary);border-bottom:2px solid var(--m-backdrop-border);white-space:nowrap;transition:all .2s ease}.m-table-thead__th:hover{color:var(--m-text);background:var(--m-table-thead-background, var(--m-background))}@media(min-width:769px){.m-table-thead__th--fixed{z-index:20;background:var(--m-table-thead-background, var(--m-background))}}@media(max-width:768px){.m-table-thead__th--fixed{position:static;z-index:auto}}.m-table-thead__th--fixed{border-right:none}@media(min-width:769px){.m-table-thead__th--fixed-last{border-right:1px solid var(--m-backdrop-border)}}@media(max-width:768px){.m-table-thead__th--fixed-last{border-right:none}}.m-table-thead__th--sortable{cursor:pointer;-webkit-user-select:none;user-select:none}.m-table-thead__th--select{width:48px;min-width:48px;max-width:48px;padding:0 1rem;text-align:center}.m-table-thead__th--select input[type=checkbox]{width:1rem;height:1rem;cursor:pointer;accent-color:var(--m-mm);border-radius:3px;display:block;margin:0 auto}.m-table-thead__cell{display:flex;align-items:center;gap:.5rem}.m-table-thead__sort-icon{color:var(--m-mm);opacity:.6;transition:opacity .2s ease}.m-table-thead__th:hover .m-table-thead__sort-icon{opacity:1}.m-table-thead__menu-btn{display:flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin-left:auto;border:none;background:transparent;cursor:pointer;color:var(--m-text-tertiary);border-radius:6px;opacity:0;transition:all .15ms ease}.m-table-thead__menu-btn:hover{background:var(--m-backdrop-surface);color:var(--m-text)}.m-table-thead__th:hover .m-table-thead__menu-btn{opacity:1}.m-table-body__row{transition:background-color .3s cubic-bezier(.4,0,.2,1);position:relative}.m-table-body__row:hover{background:color-mix(in srgb,var(--m-mm) 5%,transparent)}.m-table-body__row:hover .m-table-body__cell{background:inherit}.m-table-body__cell{padding:1rem 1.25rem;font-size:.875rem;color:var(--m-text);border-bottom:1px solid var(--m-backdrop-border);white-space:nowrap;vertical-align:middle;background:transparent;transition:background-color .3s ease}.m-table-body__cell[class*=--number],.m-table-body__cell[class*=--currency],.m-table-body__cell[class*=--percent]{font-family:Inter,Roboto Mono,monospace;font-variant-numeric:tabular-nums;letter-spacing:-.01em}@media(min-width:769px){.m-table-body__cell--fixed{position:sticky;background:var(--m-background);z-index:5}}@media(max-width:768px){.m-table-body__cell--fixed{position:static;background:transparent;z-index:auto}}.m-table-body__cell--fixed{border-right:none;transition:background-color .3s ease}.m-table-body__row:hover .m-table-body__cell--fixed{background:color-mix(in srgb,var(--m-mm) 5%,var(--m-background));z-index:6}@media(min-width:769px){.m-table-body__cell--fixed-last{border-right:1px solid var(--m-backdrop-border)}}@media(max-width:768px){.m-table-body__cell--fixed-last{border-right:none}}.m-table-body__cell--context-menu{padding-top:.35rem;padding-bottom:.35rem}.m-table-body__cell--select{width:48px;min-width:48px;max-width:48px;padding:0 1rem;text-align:center}.m-table-body__cell--select input[type=checkbox],.m-table-body__cell--select input[type=radio]{width:1rem;height:1rem;cursor:pointer;accent-color:var(--m-mm);display:block;margin:0 auto}.m-table-body__input{border:none;border-bottom:2px solid var(--m-backdrop-border);background:transparent;font-size:.875rem;color:var(--m-text);padding:.25rem;outline:none;width:100%;transition:border-bottom-color .2s ease}.m-table-body__input:focus{border-bottom-color:var(--m-mm)}.m-table-body__action-btn{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;border:none;background:transparent;cursor:pointer;color:var(--m-text-tertiary);border-radius:8px;transition:all .2s ease}.m-table-body__action-btn:hover{background:var(--m-backdrop-surface);color:var(--m-text)}.m-table-body__empty{text-align:center;padding:4rem;color:var(--m-text-tertiary);font-size:1rem;font-weight:500;letter-spacing:.02em;font-style:italic;opacity:.7}.m-table-body__link{color:var(--m-mm);text-decoration:none;cursor:pointer;font-weight:600;transition:color .2s ease}.m-table-body__link:hover{text-decoration:underline;color:var(--m-mm-lite)}.m-table-body__value{padding:.25rem .5rem;border-radius:6px;font-weight:600;font-variant-numeric:tabular-nums;letter-spacing:-.01em}.m-table-body__value--positive{color:var(--m-success);background:var(--m-backdrop-success)}.m-table-body__value--negative{color:var(--m-error);background:var(--m-backdrop-error)}.m-table-body__dash{color:var(--m-text-tertiary);font-weight:400;font-style:italic;opacity:.8}.m-section-table-host{display:block;width:100%}.m-section-table__th{position:static;vertical-align:middle}.m-section-table--sticky .m-section-table__th{position:sticky;top:0}.m-section-table__heading{justify-content:var(--m-section-table-justify, flex-start);min-height:2rem}.m-section-table--compact :where(.m-section-table__th){padding:.625rem .75rem}.m-section-table--compact :where(.m-section-table__cell){padding:.5rem .75rem}.m-section-table--spacious :where(.m-section-table__th){padding:1.5rem 1.75rem}.m-section-table--spacious :where(.m-section-table__cell){padding:1.5rem 1.75rem}.m-section-table--margin{margin-block:1em}.m-section-table--border.m-table{border-top:4px solid var(--m-backdrop-border);border-bottom:2px solid var(--m-backdrop-border)}.m-section-table--zebra .m-section-table__row:nth-child(2n):not(:hover){background:color-mix(in srgb,var(--m-mm) 3%,transparent)}.m-section-table--zebra .m-section-table__row:nth-child(2n):not(:hover) .m-section-table__cell--frozen{background:color-mix(in srgb,var(--m-mm) 3%,var(--m-background))}.m-section-table__th--squeeze{position:relative;padding-right:3rem}.m-section-table__th--folded{padding-left:0;padding-right:0}.m-section-table__squeeze{position:absolute;top:50%;right:.5rem;transform:translateY(-50%);display:flex;border:1px solid var(--m-backdrop-border);border-radius:8px;background:var(--m-backdrop-surface)}.m-section-table__th--folded .m-section-table__squeeze{right:50%;transform:translate(50%,-50%)}@media(min-width:769px){.m-section-table__cell--frozen{position:sticky;z-index:5;background:var(--m-background)}}@media(min-width:769px){.m-section-table th.m-section-table__cell--frozen{z-index:20}}@media(min-width:769px){.m-section-table--sticky .m-section-table th.m-section-table__cell--frozen{z-index:21}}@media(min-width:769px){.m-section-table__cell--frozen-last{border-right:1px solid var(--m-backdrop-border)}}.m-section-table__row:hover .m-section-table__cell--frozen{background:color-mix(in srgb,var(--m-mm) 5%,var(--m-background))}.m-section-table__cell--folded{text-align:center;padding-left:0;padding-right:0}.m-section-table__content[hidden]{display:none}.m-section-table .m-section-table__cell .m-section-table__content .m-text-output-host.align-left .m-text-output{text-align:inherit}.m-section-table__dot{display:inline-block;width:.375rem;height:.375rem;border-radius:50%;background:var(--m-text-tertiary)}.m-section-table__row{cursor:default}\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: FreezeComponent, selector: "m-freeze", inputs: ["config"] }, { kind: "component", type: IconComponent, selector: "m-icon, m-one-icon", inputs: ["config", "name", "color", "size", "one", "baseUrl", "remote"], outputs: ["configChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
19245
19699
  }
19246
19700
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SectionTableComponent, decorators: [{
19247
19701
  type: Component,
@@ -19335,7 +19789,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
19335
19789
  };
19336
19790
  },
19337
19791
  },
19338
- ], 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-table{display:flex;flex-direction:column;border:1px solid var(--m-backdrop-border);border-radius:12px;overflow:clip;background:#ffffffe6;-webkit-backdrop-filter:blur(40px);backdrop-filter:blur(40px);position:relative;transition:background-color .3s ease}.m-table--flat{border:none;box-shadow:none;background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none;border-radius:0}.m-table__toolbar{position:sticky;top:0;z-index:2;display:flex;align-items:center;justify-content:space-between;padding:1.5rem var(--m-table-toolbar-padding-x, 1.25rem);border-bottom:1px solid var(--m-backdrop-border);gap:1.5rem;background:color-mix(in srgb,var(--m-background) 45%,transparent)}.m-table--flat .m-table__toolbar{background:transparent;padding-left:0;padding-right:0}.m-table__title{margin:0;font-size:1.25rem;font-weight:800;color:var(--m-text);letter-spacing:-.02em;flex:1}.m-table__search{flex:0 1 auto;display:flex;align-items:center}.m-table__search .m-input-wrapper{width:100%}.m-table__mobile-view{display:flex;flex-direction:column;gap:1rem;padding:1.25rem;flex:1;overflow:auto}.m-table__empty-mobile{padding:3rem 1.5rem;text-align:center;color:var(--m-text-tertiary);font-size:.9375rem;font-weight:500;font-style:italic;opacity:.8;background:color-mix(in srgb,var(--m-background) 20%,transparent);border-radius:12px;border:1px dashed var(--m-backdrop-border)}.m-table__wrapper{overflow:auto;flex:1}.m-table__wrapper::-webkit-scrollbar{width:6px;height:6px}.m-table__wrapper::-webkit-scrollbar-track{background:transparent}.m-table__wrapper::-webkit-scrollbar-thumb{background:var(--m-backdrop-border);border-radius:10px}.m-table__wrapper::-webkit-scrollbar-thumb:hover{background:var(--m-text-tertiary)}.m-table__table{width:100%;min-width:100%;border-collapse:separate;border-spacing:0}mark.m-table__highlight{background:var(--m-highlight);color:#000;border-radius:2px;padding:0 2px;font-weight:700;box-shadow:0 1px 4px #0003}mark.m-table__highlight .m-one-pagination{margin-left:auto;--m-button-size: 2.25rem;--m-pagination-gap: .375rem}.m-table-pagination{display:flex;align-items:center;gap:1.5rem;padding:1.25rem var(--m-table-pagination-padding-x, 1.25rem);border-top:1px solid var(--m-backdrop-border);font-size:.8125rem;flex-wrap:wrap;background:color-mix(in srgb,var(--m-background) 40%,transparent)}.m-table--flat .m-table-pagination{background:transparent;padding-left:0;padding-right:0}.m-table-pagination__size{display:flex;flex-direction:column;align-items:flex-start;gap:.35rem;color:var(--m-text-secondary);font-weight:500}.m-table-pagination__select{border:1px solid var(--m-backdrop-border);border-radius:8px;background:var(--m-backdrop-surface);color:var(--m-text);padding:.375rem .625rem;font-size:.8125rem;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);outline:none}.m-table-pagination__select:hover{background:var(--m-backdrop-glass);border-color:var(--m-mm);box-shadow:0 0 0 3px color-mix(in srgb,var(--m-mm) 10%,transparent)}.m-table-pagination__select:focus{border-color:var(--m-mm);box-shadow:0 0 0 3px color-mix(in srgb,var(--m-mm) 20%,transparent)}.m-table-filter{display:flex;flex-wrap:wrap;align-items:center;gap:10px;padding:1rem 1.25rem;background:color-mix(in srgb,var(--m-background-lite) 60%,transparent);border-bottom:1px solid var(--m-backdrop-border);box-shadow:inset 0 2px 4px #00000005;overflow-x:auto;scrollbar-width:none}.m-table-filter::-webkit-scrollbar{display:none}.m-table--flat .m-table-filter{background:transparent;padding-left:0;padding-right:0;border-bottom:none}.m-table-filter__item{display:flex;align-items:center;gap:10px;padding:.4375rem 1rem;border-radius:12px;background:var(--m-background);border:1px solid var(--m-backdrop-border);color:var(--m-text-secondary);cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);white-space:nowrap;-webkit-user-select:none;user-select:none;outline:none;font-weight:500}.m-table-filter__item:hover{border-color:var(--m-mm);color:var(--m-mm);background:var(--m-background);transform:translateY(-1px);box-shadow:0 4px 12px #0000000d}.m-table-filter__item--active{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);font-weight:600;box-shadow:0 8px 16px color-mix(in srgb,var(--m-mm) 25%,transparent)}.m-table-filter__item--active:hover{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);transform:translateY(-1px)}.m-table-filter__item--active .m-table-filter__badge{background:#fff3;color:var(--m-inverse-text);border-color:#ffffff1a}.m-table-filter__item--primary{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);font-weight:600;box-shadow:0 8px 16px color-mix(in srgb,var(--m-mm) 25%,transparent)}.m-table-filter__item--primary:hover{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);transform:translateY(-1px);box-shadow:0 10px 20px color-mix(in srgb,var(--m-mm) 30%,transparent)}.m-table-filter__item--primary .m-table-filter__badge{background:#fff3;color:var(--m-inverse-text);border-color:#ffffff1a}.m-table-filter__item--danger{border-color:var(--m-error);color:var(--m-error)}.m-table-filter__item--danger:hover{border-color:var(--m-error);color:var(--m-error);background:var(--m-backdrop-error);transform:translateY(-1px);box-shadow:0 4px 12px color-mix(in srgb,var(--m-error) 12%,transparent)}.m-table-filter__item--danger .m-table-filter__badge{background:var(--m-backdrop-error);color:var(--m-error);border-color:color-mix(in srgb,var(--m-error) 20%,transparent)}.m-table-filter__label{font-size:.8125rem;font-weight:600;letter-spacing:.01em}.m-table-filter__badge{display:inline-flex;align-items:center;justify-content:center;min-width:1.25rem;height:1.25rem;padding:0 .375rem;border-radius:100px;background:var(--m-backdrop-surface);color:var(--m-text-secondary);font-size:.6875rem;font-weight:700;border:1px solid var(--m-backdrop-border);transition:all .2s ease}.m-table-thead__th{position:sticky;top:0;z-index:10;background:color-mix(in srgb,var(--m-background) 95%,transparent);-webkit-backdrop-filter:blur(28px);backdrop-filter:blur(28px);padding:1.25rem;text-align:left;font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--m-text-tertiary);border-bottom:2px solid var(--m-backdrop-border);white-space:nowrap;transition:all .2s ease}.m-table-thead__th:hover{color:var(--m-text);background:var(--m-background)}@media(min-width:769px){.m-table-thead__th--fixed{z-index:20;background:var(--m-background)}}@media(max-width:768px){.m-table-thead__th--fixed{position:static;z-index:auto}}.m-table-thead__th--fixed{border-right:none}@media(min-width:769px){.m-table-thead__th--fixed-last{border-right:1px solid var(--m-backdrop-border)}}@media(max-width:768px){.m-table-thead__th--fixed-last{border-right:none}}.m-table-thead__th--sortable{cursor:pointer;-webkit-user-select:none;user-select:none}.m-table-thead__th--select{width:48px;min-width:48px;max-width:48px;padding:0 1rem;text-align:center}.m-table-thead__th--select input[type=checkbox]{width:1rem;height:1rem;cursor:pointer;accent-color:var(--m-mm);border-radius:3px;display:block;margin:0 auto}.m-table-thead__cell{display:flex;align-items:center;gap:.5rem}.m-table-thead__sort-icon{color:var(--m-mm);opacity:.6;transition:opacity .2s ease}.m-table-thead__th:hover .m-table-thead__sort-icon{opacity:1}.m-table-thead__menu-btn{display:flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin-left:auto;border:none;background:transparent;cursor:pointer;color:var(--m-text-tertiary);border-radius:6px;opacity:0;transition:all .15ms ease}.m-table-thead__menu-btn:hover{background:var(--m-backdrop-surface);color:var(--m-text)}.m-table-thead__th:hover .m-table-thead__menu-btn{opacity:1}.m-table-body__row{transition:background-color .3s cubic-bezier(.4,0,.2,1);position:relative}.m-table-body__row:hover{background:color-mix(in srgb,var(--m-mm) 5%,transparent)}.m-table-body__row:hover .m-table-body__cell{background:inherit}.m-table-body__cell{padding:1rem 1.25rem;font-size:.875rem;color:var(--m-text);border-bottom:1px solid var(--m-backdrop-border);white-space:nowrap;vertical-align:middle;background:transparent;transition:background-color .3s ease}.m-table-body__cell[class*=--number],.m-table-body__cell[class*=--currency],.m-table-body__cell[class*=--percent]{font-family:Inter,Roboto Mono,monospace;font-variant-numeric:tabular-nums;letter-spacing:-.01em}@media(min-width:769px){.m-table-body__cell--fixed{position:sticky;background:var(--m-background);z-index:5}}@media(max-width:768px){.m-table-body__cell--fixed{position:static;background:transparent;z-index:auto}}.m-table-body__cell--fixed{border-right:none;transition:background-color .3s ease}.m-table-body__row:hover .m-table-body__cell--fixed{background:color-mix(in srgb,var(--m-mm) 5%,var(--m-background));z-index:6}@media(min-width:769px){.m-table-body__cell--fixed-last{border-right:1px solid var(--m-backdrop-border)}}@media(max-width:768px){.m-table-body__cell--fixed-last{border-right:none}}.m-table-body__cell--context-menu{padding-top:.35rem;padding-bottom:.35rem}.m-table-body__cell--select{width:48px;min-width:48px;max-width:48px;padding:0 1rem;text-align:center}.m-table-body__cell--select input[type=checkbox],.m-table-body__cell--select input[type=radio]{width:1rem;height:1rem;cursor:pointer;accent-color:var(--m-mm);display:block;margin:0 auto}.m-table-body__input{border:none;border-bottom:2px solid var(--m-backdrop-border);background:transparent;font-size:.875rem;color:var(--m-text);padding:.25rem;outline:none;width:100%;transition:border-bottom-color .2s ease}.m-table-body__input:focus{border-bottom-color:var(--m-mm)}.m-table-body__action-btn{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;border:none;background:transparent;cursor:pointer;color:var(--m-text-tertiary);border-radius:8px;transition:all .2s ease}.m-table-body__action-btn:hover{background:var(--m-backdrop-surface);color:var(--m-text)}.m-table-body__empty{text-align:center;padding:4rem;color:var(--m-text-tertiary);font-size:1rem;font-weight:500;letter-spacing:.02em;font-style:italic;opacity:.7}.m-table-body__link{color:var(--m-mm);text-decoration:none;cursor:pointer;font-weight:600;transition:color .2s ease}.m-table-body__link:hover{text-decoration:underline;color:var(--m-mm-lite)}.m-table-body__value{padding:.25rem .5rem;border-radius:6px;font-weight:600;font-variant-numeric:tabular-nums;letter-spacing:-.01em}.m-table-body__value--positive{color:var(--m-success);background:var(--m-backdrop-success)}.m-table-body__value--negative{color:var(--m-error);background:var(--m-backdrop-error)}.m-table-body__dash{color:var(--m-text-tertiary);font-weight:400;font-style:italic;opacity:.8}.m-section-table-host{display:block;width:100%}.m-section-table__th{position:static;vertical-align:middle}.m-section-table--sticky .m-section-table__th{position:sticky;top:0}.m-section-table__heading{justify-content:var(--m-section-table-justify, flex-start);min-height:2rem}.m-section-table--compact :where(.m-section-table__th){padding:.625rem .75rem}.m-section-table--compact :where(.m-section-table__cell){padding:.5rem .75rem}.m-section-table--spacious :where(.m-section-table__th){padding:1.5rem 1.75rem}.m-section-table--spacious :where(.m-section-table__cell){padding:1.5rem 1.75rem}.m-section-table--margin{margin-block:1em}.m-section-table--border.m-table{border-top:4px solid var(--m-backdrop-border);border-bottom:2px solid var(--m-backdrop-border)}.m-section-table--zebra .m-section-table__row:nth-child(2n):not(:hover){background:color-mix(in srgb,var(--m-mm) 3%,transparent)}.m-section-table--zebra .m-section-table__row:nth-child(2n):not(:hover) .m-section-table__cell--frozen{background:color-mix(in srgb,var(--m-mm) 3%,var(--m-background))}.m-section-table__th--squeeze{position:relative;padding-right:3rem}.m-section-table__th--folded{padding-left:0;padding-right:0}.m-section-table__squeeze{position:absolute;top:50%;right:.5rem;transform:translateY(-50%);display:flex;border:1px solid var(--m-backdrop-border);border-radius:8px;background:var(--m-backdrop-surface)}.m-section-table__th--folded .m-section-table__squeeze{right:50%;transform:translate(50%,-50%)}@media(min-width:769px){.m-section-table__cell--frozen{position:sticky;z-index:5;background:var(--m-background)}}@media(min-width:769px){.m-section-table th.m-section-table__cell--frozen{z-index:20}}@media(min-width:769px){.m-section-table--sticky .m-section-table th.m-section-table__cell--frozen{z-index:21}}@media(min-width:769px){.m-section-table__cell--frozen-last{border-right:1px solid var(--m-backdrop-border)}}.m-section-table__row:hover .m-section-table__cell--frozen{background:color-mix(in srgb,var(--m-mm) 5%,var(--m-background))}.m-section-table__cell--folded{text-align:center;padding-left:0;padding-right:0}.m-section-table__content[hidden]{display:none}.m-section-table .m-section-table__cell .m-section-table__content .m-text-output-host.align-left .m-text-output{text-align:inherit}.m-section-table__dot{display:inline-block;width:.375rem;height:.375rem;border-radius:50%;background:var(--m-text-tertiary)}.m-section-table__row{cursor:default}\n"] }]
19792
+ ], 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-table{display:flex;flex-direction:column;border:1px solid var(--m-backdrop-border);border-radius:12px;overflow:clip;background:#ffffffe6;-webkit-backdrop-filter:blur(40px);backdrop-filter:blur(40px);position:relative;transition:background-color .3s ease}.m-table--flat{border:none;box-shadow:none;background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none;border-radius:0}.m-table__toolbar{position:sticky;top:0;z-index:2;display:flex;align-items:center;justify-content:space-between;padding:1.5rem var(--m-table-toolbar-padding-x, 1.25rem);border-bottom:1px solid var(--m-backdrop-border);gap:1.5rem;background:color-mix(in srgb,var(--m-background) 45%,transparent)}.m-table--flat .m-table__toolbar{background:transparent;padding-left:0;padding-right:0}.m-table__title{margin:0;font-size:1.25rem;font-weight:800;color:var(--m-text);letter-spacing:-.02em;flex:1}.m-table__search{flex:0 1 auto;display:flex;align-items:center}.m-table__search .m-input-wrapper{width:100%}.m-table__mobile-view{display:flex;flex-direction:column;gap:1rem;padding:1.25rem;flex:1;overflow:auto}.m-table__empty-mobile{padding:3rem 1.5rem;text-align:center;color:var(--m-text-tertiary);font-size:.9375rem;font-weight:500;font-style:italic;opacity:.8;background:color-mix(in srgb,var(--m-background) 20%,transparent);border-radius:12px;border:1px dashed var(--m-backdrop-border)}.m-table__wrapper{overflow:auto;flex:1}.m-table__wrapper::-webkit-scrollbar{width:6px;height:6px}.m-table__wrapper::-webkit-scrollbar-track{background:transparent}.m-table__wrapper::-webkit-scrollbar-thumb{background:var(--m-backdrop-border);border-radius:10px}.m-table__wrapper::-webkit-scrollbar-thumb:hover{background:var(--m-text-tertiary)}.m-table__table{width:100%;min-width:100%;border-collapse:separate;border-spacing:0}mark.m-table__highlight{background:var(--m-highlight);color:#000;border-radius:2px;padding:0 2px;font-weight:700;box-shadow:0 1px 4px #0003}mark.m-table__highlight .m-one-pagination{margin-left:auto;--m-button-size: 2.25rem;--m-pagination-gap: .375rem}.m-table-pagination{display:flex;align-items:center;gap:1.5rem;padding:1.25rem var(--m-table-pagination-padding-x, 1.25rem);border-top:1px solid var(--m-backdrop-border);font-size:.8125rem;flex-wrap:wrap;background:color-mix(in srgb,var(--m-background) 40%,transparent)}.m-table--flat .m-table-pagination{background:transparent;padding-left:0;padding-right:0}.m-table-pagination__size{display:flex;flex-direction:column;align-items:flex-start;gap:.35rem;color:var(--m-text-secondary);font-weight:500}.m-table-pagination__select{border:1px solid var(--m-backdrop-border);border-radius:8px;background:var(--m-backdrop-surface);color:var(--m-text);padding:.375rem .625rem;font-size:.8125rem;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);outline:none}.m-table-pagination__select:hover{background:var(--m-backdrop-glass);border-color:var(--m-mm);box-shadow:0 0 0 3px color-mix(in srgb,var(--m-mm) 10%,transparent)}.m-table-pagination__select:focus{border-color:var(--m-mm);box-shadow:0 0 0 3px color-mix(in srgb,var(--m-mm) 20%,transparent)}.m-table-filter{display:flex;flex-wrap:wrap;align-items:center;gap:10px;padding:1rem 1.25rem;background:color-mix(in srgb,var(--m-background-lite) 60%,transparent);border-bottom:1px solid var(--m-backdrop-border);box-shadow:inset 0 2px 4px #00000005;overflow-x:auto;scrollbar-width:none}.m-table-filter::-webkit-scrollbar{display:none}.m-table--flat .m-table-filter{background:transparent;padding-left:0;padding-right:0;border-bottom:none}.m-table-filter__item{display:flex;align-items:center;gap:10px;padding:.4375rem 1rem;border-radius:12px;background:var(--m-background);border:1px solid var(--m-backdrop-border);color:var(--m-text-secondary);cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);white-space:nowrap;-webkit-user-select:none;user-select:none;outline:none;font-weight:500}.m-table-filter__item:hover{border-color:var(--m-mm);color:var(--m-mm);background:var(--m-background);transform:translateY(-1px);box-shadow:0 4px 12px #0000000d}.m-table-filter__item--active{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);font-weight:600;box-shadow:0 8px 16px color-mix(in srgb,var(--m-mm) 25%,transparent)}.m-table-filter__item--active:hover{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);transform:translateY(-1px)}.m-table-filter__item--active .m-table-filter__badge{background:#fff3;color:var(--m-inverse-text);border-color:#ffffff1a}.m-table-filter__item--primary{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);font-weight:600;box-shadow:0 8px 16px color-mix(in srgb,var(--m-mm) 25%,transparent)}.m-table-filter__item--primary:hover{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);transform:translateY(-1px);box-shadow:0 10px 20px color-mix(in srgb,var(--m-mm) 30%,transparent)}.m-table-filter__item--primary .m-table-filter__badge{background:#fff3;color:var(--m-inverse-text);border-color:#ffffff1a}.m-table-filter__item--danger{border-color:var(--m-error);color:var(--m-error)}.m-table-filter__item--danger:hover{border-color:var(--m-error);color:var(--m-error);background:var(--m-backdrop-error);transform:translateY(-1px);box-shadow:0 4px 12px color-mix(in srgb,var(--m-error) 12%,transparent)}.m-table-filter__item--danger .m-table-filter__badge{background:var(--m-backdrop-error);color:var(--m-error);border-color:color-mix(in srgb,var(--m-error) 20%,transparent)}.m-table-filter__label{font-size:.8125rem;font-weight:600;letter-spacing:.01em}.m-table-filter__badge{display:inline-flex;align-items:center;justify-content:center;min-width:1.25rem;height:1.25rem;padding:0 .375rem;border-radius:100px;background:var(--m-backdrop-surface);color:var(--m-text-secondary);font-size:.6875rem;font-weight:700;border:1px solid var(--m-backdrop-border);transition:all .2s ease}.m-table-thead__th{position:sticky;top:0;z-index:10;background:var(--m-table-thead-background, color-mix(in srgb, var(--m-background) 95%, transparent));-webkit-backdrop-filter:var(--m-table-thead-backdrop-filter, blur(28px));backdrop-filter:var(--m-table-thead-backdrop-filter, blur(28px));padding:1.25rem;text-align:left;font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--m-text-tertiary);border-bottom:2px solid var(--m-backdrop-border);white-space:nowrap;transition:all .2s ease}.m-table-thead__th:hover{color:var(--m-text);background:var(--m-table-thead-background, var(--m-background))}@media(min-width:769px){.m-table-thead__th--fixed{z-index:20;background:var(--m-table-thead-background, var(--m-background))}}@media(max-width:768px){.m-table-thead__th--fixed{position:static;z-index:auto}}.m-table-thead__th--fixed{border-right:none}@media(min-width:769px){.m-table-thead__th--fixed-last{border-right:1px solid var(--m-backdrop-border)}}@media(max-width:768px){.m-table-thead__th--fixed-last{border-right:none}}.m-table-thead__th--sortable{cursor:pointer;-webkit-user-select:none;user-select:none}.m-table-thead__th--select{width:48px;min-width:48px;max-width:48px;padding:0 1rem;text-align:center}.m-table-thead__th--select input[type=checkbox]{width:1rem;height:1rem;cursor:pointer;accent-color:var(--m-mm);border-radius:3px;display:block;margin:0 auto}.m-table-thead__cell{display:flex;align-items:center;gap:.5rem}.m-table-thead__sort-icon{color:var(--m-mm);opacity:.6;transition:opacity .2s ease}.m-table-thead__th:hover .m-table-thead__sort-icon{opacity:1}.m-table-thead__menu-btn{display:flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin-left:auto;border:none;background:transparent;cursor:pointer;color:var(--m-text-tertiary);border-radius:6px;opacity:0;transition:all .15ms ease}.m-table-thead__menu-btn:hover{background:var(--m-backdrop-surface);color:var(--m-text)}.m-table-thead__th:hover .m-table-thead__menu-btn{opacity:1}.m-table-body__row{transition:background-color .3s cubic-bezier(.4,0,.2,1);position:relative}.m-table-body__row:hover{background:color-mix(in srgb,var(--m-mm) 5%,transparent)}.m-table-body__row:hover .m-table-body__cell{background:inherit}.m-table-body__cell{padding:1rem 1.25rem;font-size:.875rem;color:var(--m-text);border-bottom:1px solid var(--m-backdrop-border);white-space:nowrap;vertical-align:middle;background:transparent;transition:background-color .3s ease}.m-table-body__cell[class*=--number],.m-table-body__cell[class*=--currency],.m-table-body__cell[class*=--percent]{font-family:Inter,Roboto Mono,monospace;font-variant-numeric:tabular-nums;letter-spacing:-.01em}@media(min-width:769px){.m-table-body__cell--fixed{position:sticky;background:var(--m-background);z-index:5}}@media(max-width:768px){.m-table-body__cell--fixed{position:static;background:transparent;z-index:auto}}.m-table-body__cell--fixed{border-right:none;transition:background-color .3s ease}.m-table-body__row:hover .m-table-body__cell--fixed{background:color-mix(in srgb,var(--m-mm) 5%,var(--m-background));z-index:6}@media(min-width:769px){.m-table-body__cell--fixed-last{border-right:1px solid var(--m-backdrop-border)}}@media(max-width:768px){.m-table-body__cell--fixed-last{border-right:none}}.m-table-body__cell--context-menu{padding-top:.35rem;padding-bottom:.35rem}.m-table-body__cell--select{width:48px;min-width:48px;max-width:48px;padding:0 1rem;text-align:center}.m-table-body__cell--select input[type=checkbox],.m-table-body__cell--select input[type=radio]{width:1rem;height:1rem;cursor:pointer;accent-color:var(--m-mm);display:block;margin:0 auto}.m-table-body__input{border:none;border-bottom:2px solid var(--m-backdrop-border);background:transparent;font-size:.875rem;color:var(--m-text);padding:.25rem;outline:none;width:100%;transition:border-bottom-color .2s ease}.m-table-body__input:focus{border-bottom-color:var(--m-mm)}.m-table-body__action-btn{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;border:none;background:transparent;cursor:pointer;color:var(--m-text-tertiary);border-radius:8px;transition:all .2s ease}.m-table-body__action-btn:hover{background:var(--m-backdrop-surface);color:var(--m-text)}.m-table-body__empty{text-align:center;padding:4rem;color:var(--m-text-tertiary);font-size:1rem;font-weight:500;letter-spacing:.02em;font-style:italic;opacity:.7}.m-table-body__link{color:var(--m-mm);text-decoration:none;cursor:pointer;font-weight:600;transition:color .2s ease}.m-table-body__link:hover{text-decoration:underline;color:var(--m-mm-lite)}.m-table-body__value{padding:.25rem .5rem;border-radius:6px;font-weight:600;font-variant-numeric:tabular-nums;letter-spacing:-.01em}.m-table-body__value--positive{color:var(--m-success);background:var(--m-backdrop-success)}.m-table-body__value--negative{color:var(--m-error);background:var(--m-backdrop-error)}.m-table-body__dash{color:var(--m-text-tertiary);font-weight:400;font-style:italic;opacity:.8}.m-section-table-host{display:block;width:100%}.m-section-table__th{position:static;vertical-align:middle}.m-section-table--sticky .m-section-table__th{position:sticky;top:0}.m-section-table__heading{justify-content:var(--m-section-table-justify, flex-start);min-height:2rem}.m-section-table--compact :where(.m-section-table__th){padding:.625rem .75rem}.m-section-table--compact :where(.m-section-table__cell){padding:.5rem .75rem}.m-section-table--spacious :where(.m-section-table__th){padding:1.5rem 1.75rem}.m-section-table--spacious :where(.m-section-table__cell){padding:1.5rem 1.75rem}.m-section-table--margin{margin-block:1em}.m-section-table--border.m-table{border-top:4px solid var(--m-backdrop-border);border-bottom:2px solid var(--m-backdrop-border)}.m-section-table--zebra .m-section-table__row:nth-child(2n):not(:hover){background:color-mix(in srgb,var(--m-mm) 3%,transparent)}.m-section-table--zebra .m-section-table__row:nth-child(2n):not(:hover) .m-section-table__cell--frozen{background:color-mix(in srgb,var(--m-mm) 3%,var(--m-background))}.m-section-table__th--squeeze{position:relative;padding-right:3rem}.m-section-table__th--folded{padding-left:0;padding-right:0}.m-section-table__squeeze{position:absolute;top:50%;right:.5rem;transform:translateY(-50%);display:flex;border:1px solid var(--m-backdrop-border);border-radius:8px;background:var(--m-backdrop-surface)}.m-section-table__th--folded .m-section-table__squeeze{right:50%;transform:translate(50%,-50%)}@media(min-width:769px){.m-section-table__cell--frozen{position:sticky;z-index:5;background:var(--m-background)}}@media(min-width:769px){.m-section-table th.m-section-table__cell--frozen{z-index:20}}@media(min-width:769px){.m-section-table--sticky .m-section-table th.m-section-table__cell--frozen{z-index:21}}@media(min-width:769px){.m-section-table__cell--frozen-last{border-right:1px solid var(--m-backdrop-border)}}.m-section-table__row:hover .m-section-table__cell--frozen{background:color-mix(in srgb,var(--m-mm) 5%,var(--m-background))}.m-section-table__cell--folded{text-align:center;padding-left:0;padding-right:0}.m-section-table__content[hidden]{display:none}.m-section-table .m-section-table__cell .m-section-table__content .m-text-output-host.align-left .m-text-output{text-align:inherit}.m-section-table__dot{display:inline-block;width:.375rem;height:.375rem;border-radius:50%;background:var(--m-text-tertiary)}.m-section-table__row{cursor:default}\n"] }]
19339
19793
  }], ctorParameters: () => [], propDecorators: { sticky: [{ type: i0.Input, args: [{ isSignal: true, alias: "sticky", required: false }] }], margin: [{ type: i0.Input, args: [{ isSignal: true, alias: "margin", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], tableInitialized: [{ type: i0.Output, args: ["tableInitialized"] }], headings: [{ type: i0.ViewChildren, args: ['heading', { isSignal: true }] }] } });
19340
19794
 
19341
19795
  /**
@@ -22536,7 +22990,7 @@ class WrapperInputComponent extends ConfigComponent {
22536
22990
  break;
22537
22991
  }
22538
22992
  case InputType.TOGGLE: {
22539
- const { ToggleInputComponent } = await import('./magmonium-one-toggle-atjxl_R_.mjs');
22993
+ const { ToggleInputComponent } = await import('./magmonium-one-toggle-DXiBGDPh.mjs');
22540
22994
  this.createDynamicComponent(seq, ToggleInputComponent, [], true);
22541
22995
  break;
22542
22996
  }
@@ -22548,12 +23002,12 @@ class WrapperInputComponent extends ConfigComponent {
22548
23002
  break;
22549
23003
  }
22550
23004
  case InputType.PASSWORD: {
22551
- const { PasswordInputComponent } = await import('./magmonium-one-password-yXiSYlMS.mjs');
23005
+ const { PasswordInputComponent } = await import('./magmonium-one-password-B4R18v54.mjs');
22552
23006
  this.createDynamicComponent(seq, PasswordInputComponent);
22553
23007
  break;
22554
23008
  }
22555
23009
  case InputType.OTP: {
22556
- const { OtpInputComponent } = await import('./magmonium-one-otp-B-NBB6PF.mjs');
23010
+ const { OtpInputComponent } = await import('./magmonium-one-otp-Cq5Hfnh_.mjs');
22557
23011
  this.createDynamicComponent(seq, OtpInputComponent);
22558
23012
  break;
22559
23013
  }
@@ -24260,7 +24714,7 @@ class FileUploadInputComponent extends BaseInputComponent {
24260
24714
  const modalStore = this.modalStore;
24261
24715
  if (!modalStore)
24262
24716
  return undefined;
24263
- const { ImageEditorComponent } = await import('./magmonium-one-image-editor-CurYe_Mb.mjs');
24717
+ const { ImageEditorComponent } = await import('./magmonium-one-image-editor-CqTVP7Li.mjs');
24264
24718
  const ratio = String(this.config()?.ratio ?? '');
24265
24719
  return new Promise((resolve) => {
24266
24720
  const modalRef = new ModalRef();
@@ -27136,6 +27590,8 @@ class RemoteComponent {
27136
27590
  mountedLink;
27137
27591
  /** The first report after each mount replaces: boot redirects leave no entry. */
27138
27592
  reported = false;
27593
+ /** The next report replaces rather than pushes — a move asked to (`move`). */
27594
+ replaceNext = false;
27139
27595
  /** The remote's own last word on where it stands, never echoed back to it. */
27140
27596
  lastReported;
27141
27597
  lastSent;
@@ -27302,11 +27758,13 @@ class RemoteComponent {
27302
27758
  * A menu click: unlike a path binding the host URL does not hold it yet, so
27303
27759
  * the report that follows is a move to write, not an echo to drop.
27304
27760
  */
27305
- move = (path) => {
27761
+ move = (path, options) => {
27762
+ this.replaceNext = !!options?.replaceUrl;
27306
27763
  this.loadedElement?.dispatchEvent(new CustomEvent(WC_NAVIGATE_EVENT, { detail: { path } }));
27307
27764
  };
27308
27765
  onReport = (event) => {
27309
- const raw = event.detail?.path;
27766
+ const detail = event.detail;
27767
+ const raw = detail?.path;
27310
27768
  if (raw === undefined)
27311
27769
  return;
27312
27770
  const path = raw.replace(/^\//, '');
@@ -27320,6 +27778,13 @@ class RemoteComponent {
27320
27778
  if (isBootRedirect(this.bootPending, sent, path))
27321
27779
  return;
27322
27780
  this.bootPending = false;
27781
+ // Where the remote stands as a Nav, echo or not: the host routes only down
27782
+ // to the mount, and a Back the host drove still moved the remote's Nav. A
27783
+ // remote built before it reported one leaves the mount standing on its root.
27784
+ if (this.registeredName)
27785
+ this.navRef?.setMountRoute?.(this.registeredName, detail.navId
27786
+ ? { navId: detail.navId, params: detail.params ?? {} }
27787
+ : undefined);
27323
27788
  this.lastReported = path;
27324
27789
  this.lastSent = undefined;
27325
27790
  if (echo && this.reported)
@@ -27328,8 +27793,9 @@ class RemoteComponent {
27328
27793
  const out = untracked(() => this.out());
27329
27794
  const target = out ? out(path, link) : path;
27330
27795
  const url = this.url();
27331
- const replace = !this.reported;
27796
+ const replace = !this.reported || this.replaceNext;
27332
27797
  this.reported = true;
27798
+ this.replaceNext = false;
27333
27799
  const keys = queryKeysOf(target);
27334
27800
  const dropped = this.queryKeys.filter((k) => !keys.includes(k));
27335
27801
  this.queryKeys = keys;
@@ -29189,7 +29655,7 @@ class TableHeaderComponent {
29189
29655
  }
29190
29656
  </tr>
29191
29657
  </thead>
29192
- `, 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)}}.m-table-thead__th{position:sticky;top:0;z-index:10;background:color-mix(in srgb,var(--m-background) 95%,transparent);-webkit-backdrop-filter:blur(28px);backdrop-filter:blur(28px);padding:1.25rem;text-align:left;font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--m-text-tertiary);border-bottom:2px solid var(--m-backdrop-border);white-space:nowrap;transition:all .2s ease}.m-table-thead__th:hover{color:var(--m-text);background:var(--m-background)}@media(min-width:769px){.m-table-thead__th--fixed{z-index:20;background:var(--m-background)}}@media(max-width:768px){.m-table-thead__th--fixed{position:static;z-index:auto}}.m-table-thead__th--fixed{border-right:none}@media(min-width:769px){.m-table-thead__th--fixed-last{border-right:1px solid var(--m-backdrop-border)}}@media(max-width:768px){.m-table-thead__th--fixed-last{border-right:none}}.m-table-thead__th--sortable{cursor:pointer;-webkit-user-select:none;user-select:none}.m-table-thead__th--select{width:48px;min-width:48px;max-width:48px;padding:0 1rem;text-align:center}.m-table-thead__th--select input[type=checkbox]{width:1rem;height:1rem;cursor:pointer;accent-color:var(--m-mm);border-radius:3px;display:block;margin:0 auto}.m-table-thead__cell{display:flex;align-items:center;gap:.5rem}.m-table-thead__sort-icon{color:var(--m-mm);opacity:.6;transition:opacity .2s ease}.m-table-thead__th:hover .m-table-thead__sort-icon{opacity:1}.m-table-thead__menu-btn{display:flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin-left:auto;border:none;background:transparent;cursor:pointer;color:var(--m-text-tertiary);border-radius:6px;opacity:0;transition:all .15ms ease}.m-table-thead__menu-btn:hover{background:var(--m-backdrop-surface);color:var(--m-text)}.m-table-thead__th:hover .m-table-thead__menu-btn{opacity:1}\n"], dependencies: [{ kind: "component", type: CheckboxInputComponent, selector: "m-checkbox", inputs: ["checked", "config", "required", "disabled", "invalid", "touched", "focused", "errors"], outputs: ["checkedChange", "touchedChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
29658
+ `, 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)}}.m-table-thead__th{position:sticky;top:0;z-index:10;background:var(--m-table-thead-background, color-mix(in srgb, var(--m-background) 95%, transparent));-webkit-backdrop-filter:var(--m-table-thead-backdrop-filter, blur(28px));backdrop-filter:var(--m-table-thead-backdrop-filter, blur(28px));padding:1.25rem;text-align:left;font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--m-text-tertiary);border-bottom:2px solid var(--m-backdrop-border);white-space:nowrap;transition:all .2s ease}.m-table-thead__th:hover{color:var(--m-text);background:var(--m-table-thead-background, var(--m-background))}@media(min-width:769px){.m-table-thead__th--fixed{z-index:20;background:var(--m-table-thead-background, var(--m-background))}}@media(max-width:768px){.m-table-thead__th--fixed{position:static;z-index:auto}}.m-table-thead__th--fixed{border-right:none}@media(min-width:769px){.m-table-thead__th--fixed-last{border-right:1px solid var(--m-backdrop-border)}}@media(max-width:768px){.m-table-thead__th--fixed-last{border-right:none}}.m-table-thead__th--sortable{cursor:pointer;-webkit-user-select:none;user-select:none}.m-table-thead__th--select{width:48px;min-width:48px;max-width:48px;padding:0 1rem;text-align:center}.m-table-thead__th--select input[type=checkbox]{width:1rem;height:1rem;cursor:pointer;accent-color:var(--m-mm);border-radius:3px;display:block;margin:0 auto}.m-table-thead__cell{display:flex;align-items:center;gap:.5rem}.m-table-thead__sort-icon{color:var(--m-mm);opacity:.6;transition:opacity .2s ease}.m-table-thead__th:hover .m-table-thead__sort-icon{opacity:1}.m-table-thead__menu-btn{display:flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin-left:auto;border:none;background:transparent;cursor:pointer;color:var(--m-text-tertiary);border-radius:6px;opacity:0;transition:all .15ms ease}.m-table-thead__menu-btn:hover{background:var(--m-backdrop-surface);color:var(--m-text)}.m-table-thead__th:hover .m-table-thead__menu-btn{opacity:1}\n"], dependencies: [{ kind: "component", type: CheckboxInputComponent, selector: "m-checkbox", inputs: ["checked", "config", "required", "disabled", "invalid", "touched", "focused", "errors"], outputs: ["checkedChange", "touchedChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
29193
29659
  }
29194
29660
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TableHeaderComponent, decorators: [{
29195
29661
  type: Component,
@@ -29242,7 +29708,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
29242
29708
  }
29243
29709
  </tr>
29244
29710
  </thead>
29245
- `, 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)}}.m-table-thead__th{position:sticky;top:0;z-index:10;background:color-mix(in srgb,var(--m-background) 95%,transparent);-webkit-backdrop-filter:blur(28px);backdrop-filter:blur(28px);padding:1.25rem;text-align:left;font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--m-text-tertiary);border-bottom:2px solid var(--m-backdrop-border);white-space:nowrap;transition:all .2s ease}.m-table-thead__th:hover{color:var(--m-text);background:var(--m-background)}@media(min-width:769px){.m-table-thead__th--fixed{z-index:20;background:var(--m-background)}}@media(max-width:768px){.m-table-thead__th--fixed{position:static;z-index:auto}}.m-table-thead__th--fixed{border-right:none}@media(min-width:769px){.m-table-thead__th--fixed-last{border-right:1px solid var(--m-backdrop-border)}}@media(max-width:768px){.m-table-thead__th--fixed-last{border-right:none}}.m-table-thead__th--sortable{cursor:pointer;-webkit-user-select:none;user-select:none}.m-table-thead__th--select{width:48px;min-width:48px;max-width:48px;padding:0 1rem;text-align:center}.m-table-thead__th--select input[type=checkbox]{width:1rem;height:1rem;cursor:pointer;accent-color:var(--m-mm);border-radius:3px;display:block;margin:0 auto}.m-table-thead__cell{display:flex;align-items:center;gap:.5rem}.m-table-thead__sort-icon{color:var(--m-mm);opacity:.6;transition:opacity .2s ease}.m-table-thead__th:hover .m-table-thead__sort-icon{opacity:1}.m-table-thead__menu-btn{display:flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin-left:auto;border:none;background:transparent;cursor:pointer;color:var(--m-text-tertiary);border-radius:6px;opacity:0;transition:all .15ms ease}.m-table-thead__menu-btn:hover{background:var(--m-backdrop-surface);color:var(--m-text)}.m-table-thead__th:hover .m-table-thead__menu-btn{opacity:1}\n"] }]
29711
+ `, 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)}}.m-table-thead__th{position:sticky;top:0;z-index:10;background:var(--m-table-thead-background, color-mix(in srgb, var(--m-background) 95%, transparent));-webkit-backdrop-filter:var(--m-table-thead-backdrop-filter, blur(28px));backdrop-filter:var(--m-table-thead-backdrop-filter, blur(28px));padding:1.25rem;text-align:left;font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--m-text-tertiary);border-bottom:2px solid var(--m-backdrop-border);white-space:nowrap;transition:all .2s ease}.m-table-thead__th:hover{color:var(--m-text);background:var(--m-table-thead-background, var(--m-background))}@media(min-width:769px){.m-table-thead__th--fixed{z-index:20;background:var(--m-table-thead-background, var(--m-background))}}@media(max-width:768px){.m-table-thead__th--fixed{position:static;z-index:auto}}.m-table-thead__th--fixed{border-right:none}@media(min-width:769px){.m-table-thead__th--fixed-last{border-right:1px solid var(--m-backdrop-border)}}@media(max-width:768px){.m-table-thead__th--fixed-last{border-right:none}}.m-table-thead__th--sortable{cursor:pointer;-webkit-user-select:none;user-select:none}.m-table-thead__th--select{width:48px;min-width:48px;max-width:48px;padding:0 1rem;text-align:center}.m-table-thead__th--select input[type=checkbox]{width:1rem;height:1rem;cursor:pointer;accent-color:var(--m-mm);border-radius:3px;display:block;margin:0 auto}.m-table-thead__cell{display:flex;align-items:center;gap:.5rem}.m-table-thead__sort-icon{color:var(--m-mm);opacity:.6;transition:opacity .2s ease}.m-table-thead__th:hover .m-table-thead__sort-icon{opacity:1}.m-table-thead__menu-btn{display:flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin-left:auto;border:none;background:transparent;cursor:pointer;color:var(--m-text-tertiary);border-radius:6px;opacity:0;transition:all .15ms ease}.m-table-thead__menu-btn:hover{background:var(--m-backdrop-surface);color:var(--m-text)}.m-table-thead__th:hover .m-table-thead__menu-btn{opacity:1}\n"] }]
29246
29712
  }], propDecorators: { visibleColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "visibleColumns", required: false }] }], fixedCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "fixedCount", required: false }] }], fixedOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "fixedOffset", required: false }] }], sortState: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortState", required: false }] }], sortClick: [{ type: i0.Output, args: ["sortClick"] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], allSelected: [{ type: i0.Input, args: [{ isSignal: true, alias: "allSelected", required: false }] }], someSelected: [{ type: i0.Input, args: [{ isSignal: true, alias: "someSelected", required: false }] }], selectAll: [{ type: i0.Output, args: ["selectAll"] }] } });
29247
29713
 
29248
29714
  class TableUserCellComponent {
@@ -31304,7 +31770,7 @@ class TreeGridComponent extends ConfigComponent {
31304
31770
  </table>
31305
31771
  </div>
31306
31772
  </div>
31307
- `, 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)}}.m-table{display:flex;flex-direction:column;border:1px solid var(--m-backdrop-border);border-radius:12px;overflow:clip;background:#ffffffe6;-webkit-backdrop-filter:blur(40px);backdrop-filter:blur(40px);position:relative;transition:background-color .3s ease}.m-table--flat{border:none;box-shadow:none;background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none;border-radius:0}.m-table__toolbar{position:sticky;top:0;z-index:2;display:flex;align-items:center;justify-content:space-between;padding:1.5rem var(--m-table-toolbar-padding-x, 1.25rem);border-bottom:1px solid var(--m-backdrop-border);gap:1.5rem;background:color-mix(in srgb,var(--m-background) 45%,transparent)}.m-table--flat .m-table__toolbar{background:transparent;padding-left:0;padding-right:0}.m-table__title{margin:0;font-size:1.25rem;font-weight:800;color:var(--m-text);letter-spacing:-.02em;flex:1}.m-table__search{flex:0 1 auto;display:flex;align-items:center}.m-table__search .m-input-wrapper{width:100%}.m-table__mobile-view{display:flex;flex-direction:column;gap:1rem;padding:1.25rem;flex:1;overflow:auto}.m-table__empty-mobile{padding:3rem 1.5rem;text-align:center;color:var(--m-text-tertiary);font-size:.9375rem;font-weight:500;font-style:italic;opacity:.8;background:color-mix(in srgb,var(--m-background) 20%,transparent);border-radius:12px;border:1px dashed var(--m-backdrop-border)}.m-table__wrapper{overflow:auto;flex:1}.m-table__wrapper::-webkit-scrollbar{width:6px;height:6px}.m-table__wrapper::-webkit-scrollbar-track{background:transparent}.m-table__wrapper::-webkit-scrollbar-thumb{background:var(--m-backdrop-border);border-radius:10px}.m-table__wrapper::-webkit-scrollbar-thumb:hover{background:var(--m-text-tertiary)}.m-table__table{width:100%;min-width:100%;border-collapse:separate;border-spacing:0}mark.m-table__highlight{background:var(--m-highlight);color:#000;border-radius:2px;padding:0 2px;font-weight:700;box-shadow:0 1px 4px #0003}mark.m-table__highlight .m-one-pagination{margin-left:auto;--m-button-size: 2.25rem;--m-pagination-gap: .375rem}.m-table-pagination{display:flex;align-items:center;gap:1.5rem;padding:1.25rem var(--m-table-pagination-padding-x, 1.25rem);border-top:1px solid var(--m-backdrop-border);font-size:.8125rem;flex-wrap:wrap;background:color-mix(in srgb,var(--m-background) 40%,transparent)}.m-table--flat .m-table-pagination{background:transparent;padding-left:0;padding-right:0}.m-table-pagination__size{display:flex;flex-direction:column;align-items:flex-start;gap:.35rem;color:var(--m-text-secondary);font-weight:500}.m-table-pagination__select{border:1px solid var(--m-backdrop-border);border-radius:8px;background:var(--m-backdrop-surface);color:var(--m-text);padding:.375rem .625rem;font-size:.8125rem;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);outline:none}.m-table-pagination__select:hover{background:var(--m-backdrop-glass);border-color:var(--m-mm);box-shadow:0 0 0 3px color-mix(in srgb,var(--m-mm) 10%,transparent)}.m-table-pagination__select:focus{border-color:var(--m-mm);box-shadow:0 0 0 3px color-mix(in srgb,var(--m-mm) 20%,transparent)}.m-table-filter{display:flex;flex-wrap:wrap;align-items:center;gap:10px;padding:1rem 1.25rem;background:color-mix(in srgb,var(--m-background-lite) 60%,transparent);border-bottom:1px solid var(--m-backdrop-border);box-shadow:inset 0 2px 4px #00000005;overflow-x:auto;scrollbar-width:none}.m-table-filter::-webkit-scrollbar{display:none}.m-table--flat .m-table-filter{background:transparent;padding-left:0;padding-right:0;border-bottom:none}.m-table-filter__item{display:flex;align-items:center;gap:10px;padding:.4375rem 1rem;border-radius:12px;background:var(--m-background);border:1px solid var(--m-backdrop-border);color:var(--m-text-secondary);cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);white-space:nowrap;-webkit-user-select:none;user-select:none;outline:none;font-weight:500}.m-table-filter__item:hover{border-color:var(--m-mm);color:var(--m-mm);background:var(--m-background);transform:translateY(-1px);box-shadow:0 4px 12px #0000000d}.m-table-filter__item--active{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);font-weight:600;box-shadow:0 8px 16px color-mix(in srgb,var(--m-mm) 25%,transparent)}.m-table-filter__item--active:hover{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);transform:translateY(-1px)}.m-table-filter__item--active .m-table-filter__badge{background:#fff3;color:var(--m-inverse-text);border-color:#ffffff1a}.m-table-filter__item--primary{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);font-weight:600;box-shadow:0 8px 16px color-mix(in srgb,var(--m-mm) 25%,transparent)}.m-table-filter__item--primary:hover{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);transform:translateY(-1px);box-shadow:0 10px 20px color-mix(in srgb,var(--m-mm) 30%,transparent)}.m-table-filter__item--primary .m-table-filter__badge{background:#fff3;color:var(--m-inverse-text);border-color:#ffffff1a}.m-table-filter__item--danger{border-color:var(--m-error);color:var(--m-error)}.m-table-filter__item--danger:hover{border-color:var(--m-error);color:var(--m-error);background:var(--m-backdrop-error);transform:translateY(-1px);box-shadow:0 4px 12px color-mix(in srgb,var(--m-error) 12%,transparent)}.m-table-filter__item--danger .m-table-filter__badge{background:var(--m-backdrop-error);color:var(--m-error);border-color:color-mix(in srgb,var(--m-error) 20%,transparent)}.m-table-filter__label{font-size:.8125rem;font-weight:600;letter-spacing:.01em}.m-table-filter__badge{display:inline-flex;align-items:center;justify-content:center;min-width:1.25rem;height:1.25rem;padding:0 .375rem;border-radius:100px;background:var(--m-backdrop-surface);color:var(--m-text-secondary);font-size:.6875rem;font-weight:700;border:1px solid var(--m-backdrop-border);transition:all .2s ease}.m-table-thead__th{position:sticky;top:0;z-index:10;background:color-mix(in srgb,var(--m-background) 95%,transparent);-webkit-backdrop-filter:blur(28px);backdrop-filter:blur(28px);padding:1.25rem;text-align:left;font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--m-text-tertiary);border-bottom:2px solid var(--m-backdrop-border);white-space:nowrap;transition:all .2s ease}.m-table-thead__th:hover{color:var(--m-text);background:var(--m-background)}@media(min-width:769px){.m-table-thead__th--fixed{z-index:20;background:var(--m-background)}}@media(max-width:768px){.m-table-thead__th--fixed{position:static;z-index:auto}}.m-table-thead__th--fixed{border-right:none}@media(min-width:769px){.m-table-thead__th--fixed-last{border-right:1px solid var(--m-backdrop-border)}}@media(max-width:768px){.m-table-thead__th--fixed-last{border-right:none}}.m-table-thead__th--sortable{cursor:pointer;-webkit-user-select:none;user-select:none}.m-table-thead__th--select{width:48px;min-width:48px;max-width:48px;padding:0 1rem;text-align:center}.m-table-thead__th--select input[type=checkbox]{width:1rem;height:1rem;cursor:pointer;accent-color:var(--m-mm);border-radius:3px;display:block;margin:0 auto}.m-table-thead__cell{display:flex;align-items:center;gap:.5rem}.m-table-thead__sort-icon{color:var(--m-mm);opacity:.6;transition:opacity .2s ease}.m-table-thead__th:hover .m-table-thead__sort-icon{opacity:1}.m-table-thead__menu-btn{display:flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin-left:auto;border:none;background:transparent;cursor:pointer;color:var(--m-text-tertiary);border-radius:6px;opacity:0;transition:all .15ms ease}.m-table-thead__menu-btn:hover{background:var(--m-backdrop-surface);color:var(--m-text)}.m-table-thead__th:hover .m-table-thead__menu-btn{opacity:1}.m-table-body__row{transition:background-color .3s cubic-bezier(.4,0,.2,1);position:relative}.m-table-body__row:hover{background:color-mix(in srgb,var(--m-mm) 5%,transparent)}.m-table-body__row:hover .m-table-body__cell{background:inherit}.m-table-body__cell{padding:1rem 1.25rem;font-size:.875rem;color:var(--m-text);border-bottom:1px solid var(--m-backdrop-border);white-space:nowrap;vertical-align:middle;background:transparent;transition:background-color .3s ease}.m-table-body__cell[class*=--number],.m-table-body__cell[class*=--currency],.m-table-body__cell[class*=--percent]{font-family:Inter,Roboto Mono,monospace;font-variant-numeric:tabular-nums;letter-spacing:-.01em}@media(min-width:769px){.m-table-body__cell--fixed{position:sticky;background:var(--m-background);z-index:5}}@media(max-width:768px){.m-table-body__cell--fixed{position:static;background:transparent;z-index:auto}}.m-table-body__cell--fixed{border-right:none;transition:background-color .3s ease}.m-table-body__row:hover .m-table-body__cell--fixed{background:color-mix(in srgb,var(--m-mm) 5%,var(--m-background));z-index:6}@media(min-width:769px){.m-table-body__cell--fixed-last{border-right:1px solid var(--m-backdrop-border)}}@media(max-width:768px){.m-table-body__cell--fixed-last{border-right:none}}.m-table-body__cell--context-menu{padding-top:.35rem;padding-bottom:.35rem}.m-table-body__cell--select{width:48px;min-width:48px;max-width:48px;padding:0 1rem;text-align:center}.m-table-body__cell--select input[type=checkbox],.m-table-body__cell--select input[type=radio]{width:1rem;height:1rem;cursor:pointer;accent-color:var(--m-mm);display:block;margin:0 auto}.m-table-body__input{border:none;border-bottom:2px solid var(--m-backdrop-border);background:transparent;font-size:.875rem;color:var(--m-text);padding:.25rem;outline:none;width:100%;transition:border-bottom-color .2s ease}.m-table-body__input:focus{border-bottom-color:var(--m-mm)}.m-table-body__action-btn{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;border:none;background:transparent;cursor:pointer;color:var(--m-text-tertiary);border-radius:8px;transition:all .2s ease}.m-table-body__action-btn:hover{background:var(--m-backdrop-surface);color:var(--m-text)}.m-table-body__empty{text-align:center;padding:4rem;color:var(--m-text-tertiary);font-size:1rem;font-weight:500;letter-spacing:.02em;font-style:italic;opacity:.7}.m-table-body__link{color:var(--m-mm);text-decoration:none;cursor:pointer;font-weight:600;transition:color .2s ease}.m-table-body__link:hover{text-decoration:underline;color:var(--m-mm-lite)}.m-table-body__value{padding:.25rem .5rem;border-radius:6px;font-weight:600;font-variant-numeric:tabular-nums;letter-spacing:-.01em}.m-table-body__value--positive{color:var(--m-success);background:var(--m-backdrop-success)}.m-table-body__value--negative{color:var(--m-error);background:var(--m-backdrop-error)}.m-table-body__dash{color:var(--m-text-tertiary);font-weight:400;font-style:italic;opacity:.8}.m-tree-grid{--m-tree-grid-icon: .75rem}.m-tree-grid .m-table-thead__th,.m-tree-grid .m-table-body__cell{padding:.375rem .5rem}.m-tree-grid .m-table-thead__th{font-size:.6875rem;letter-spacing:.06em;border-bottom-width:1px}.m-tree-grid__tree-cell{display:flex;align-items:center;gap:0;min-width:0}.m-tree-grid__indent{flex:0 0 auto;width:calc(var(--m-tree-grid-depth, 0) * var(--m-tree-grid-indent, var(--m-tree-grid-icon)))}.m-tree-grid__toggle{flex:0 0 auto;width:var(--m-tree-grid-icon);height:var(--m-tree-grid-icon);display:inline-flex;align-items:center;justify-content:center}.m-tree-grid__toggle m-button{--m-button-size: .333rem}.m-tree-grid__toggle-spacer{width:var(--m-tree-grid-icon);height:var(--m-tree-grid-icon);flex:0 0 auto}.m-tree-grid__lead-icon{flex:0 0 auto;display:inline-flex;align-items:center;margin-left:.125rem;opacity:.75}.m-tree-grid__lead-icon m-icon{--m-icon-size: .75rem}.m-tree-grid__label{min-width:0;margin-left:.25rem;overflow:hidden;text-overflow:ellipsis;font-size:.875em;line-height:1.25}.m-tree-grid .m-table-body__row{cursor:pointer}.m-tree-grid .m-table-body__row--selected{background:color-mix(in srgb,var(--m-mm) 12%,transparent)}.m-tree-grid .m-table__toolbar{padding:.5rem;background:var(--m-background)}.m-tree-grid .m-table__search{flex:1 1 auto;width:100%}.m-tree-grid .m-table__search m-input-wrapper,.m-tree-grid .m-table__search .m-input-wrapper{width:100%}.m-tree-grid__match{background:var(--m-highlight);padding:0;color:inherit;border-radius:2px}\n"], dependencies: [{ kind: "component", type: TableHeaderComponent, selector: "m-table-header", inputs: ["visibleColumns", "fixedCount", "fixedOffset", "sortState", "selectable", "allSelected", "someSelected"], outputs: ["sortClick", "selectAll"] }, { kind: "component", type: FreezeComponent, selector: "m-freeze", inputs: ["config"] }, { 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: HeaderComponent$1, selector: "m-header", inputs: ["level", "label", "icon", "actionButton", "actionLabel", "noTranslate", "params"], outputs: ["actionClick"] }, { kind: "component", type: IconComponent, selector: "m-icon, m-one-icon", inputs: ["config", "name", "color", "size", "one", "baseUrl", "remote"], outputs: ["configChange"] }, { kind: "component", type: ContextMenuComponent, selector: "m-context-menu, m-one-context-menu", inputs: ["toggle", "remote", "exclude", "visibilityRule", "disableRule", "extraData", "inverted", "options"], outputs: ["toggleChange", "action"] }, { kind: "component", type: WrapperInputComponent, selector: "m-input-wrapper", inputs: ["remote", "value", "readonly", "state", "focused", "form", "options", "dir", "element", "data", "template", "placeholder", "aclResolver", "formValues"], outputs: ["valueChange", "stateChange", "act", "fieldKey", "fieldType"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
31773
+ `, 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)}}.m-table{display:flex;flex-direction:column;border:1px solid var(--m-backdrop-border);border-radius:12px;overflow:clip;background:#ffffffe6;-webkit-backdrop-filter:blur(40px);backdrop-filter:blur(40px);position:relative;transition:background-color .3s ease}.m-table--flat{border:none;box-shadow:none;background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none;border-radius:0}.m-table__toolbar{position:sticky;top:0;z-index:2;display:flex;align-items:center;justify-content:space-between;padding:1.5rem var(--m-table-toolbar-padding-x, 1.25rem);border-bottom:1px solid var(--m-backdrop-border);gap:1.5rem;background:color-mix(in srgb,var(--m-background) 45%,transparent)}.m-table--flat .m-table__toolbar{background:transparent;padding-left:0;padding-right:0}.m-table__title{margin:0;font-size:1.25rem;font-weight:800;color:var(--m-text);letter-spacing:-.02em;flex:1}.m-table__search{flex:0 1 auto;display:flex;align-items:center}.m-table__search .m-input-wrapper{width:100%}.m-table__mobile-view{display:flex;flex-direction:column;gap:1rem;padding:1.25rem;flex:1;overflow:auto}.m-table__empty-mobile{padding:3rem 1.5rem;text-align:center;color:var(--m-text-tertiary);font-size:.9375rem;font-weight:500;font-style:italic;opacity:.8;background:color-mix(in srgb,var(--m-background) 20%,transparent);border-radius:12px;border:1px dashed var(--m-backdrop-border)}.m-table__wrapper{overflow:auto;flex:1}.m-table__wrapper::-webkit-scrollbar{width:6px;height:6px}.m-table__wrapper::-webkit-scrollbar-track{background:transparent}.m-table__wrapper::-webkit-scrollbar-thumb{background:var(--m-backdrop-border);border-radius:10px}.m-table__wrapper::-webkit-scrollbar-thumb:hover{background:var(--m-text-tertiary)}.m-table__table{width:100%;min-width:100%;border-collapse:separate;border-spacing:0}mark.m-table__highlight{background:var(--m-highlight);color:#000;border-radius:2px;padding:0 2px;font-weight:700;box-shadow:0 1px 4px #0003}mark.m-table__highlight .m-one-pagination{margin-left:auto;--m-button-size: 2.25rem;--m-pagination-gap: .375rem}.m-table-pagination{display:flex;align-items:center;gap:1.5rem;padding:1.25rem var(--m-table-pagination-padding-x, 1.25rem);border-top:1px solid var(--m-backdrop-border);font-size:.8125rem;flex-wrap:wrap;background:color-mix(in srgb,var(--m-background) 40%,transparent)}.m-table--flat .m-table-pagination{background:transparent;padding-left:0;padding-right:0}.m-table-pagination__size{display:flex;flex-direction:column;align-items:flex-start;gap:.35rem;color:var(--m-text-secondary);font-weight:500}.m-table-pagination__select{border:1px solid var(--m-backdrop-border);border-radius:8px;background:var(--m-backdrop-surface);color:var(--m-text);padding:.375rem .625rem;font-size:.8125rem;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);outline:none}.m-table-pagination__select:hover{background:var(--m-backdrop-glass);border-color:var(--m-mm);box-shadow:0 0 0 3px color-mix(in srgb,var(--m-mm) 10%,transparent)}.m-table-pagination__select:focus{border-color:var(--m-mm);box-shadow:0 0 0 3px color-mix(in srgb,var(--m-mm) 20%,transparent)}.m-table-filter{display:flex;flex-wrap:wrap;align-items:center;gap:10px;padding:1rem 1.25rem;background:color-mix(in srgb,var(--m-background-lite) 60%,transparent);border-bottom:1px solid var(--m-backdrop-border);box-shadow:inset 0 2px 4px #00000005;overflow-x:auto;scrollbar-width:none}.m-table-filter::-webkit-scrollbar{display:none}.m-table--flat .m-table-filter{background:transparent;padding-left:0;padding-right:0;border-bottom:none}.m-table-filter__item{display:flex;align-items:center;gap:10px;padding:.4375rem 1rem;border-radius:12px;background:var(--m-background);border:1px solid var(--m-backdrop-border);color:var(--m-text-secondary);cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);white-space:nowrap;-webkit-user-select:none;user-select:none;outline:none;font-weight:500}.m-table-filter__item:hover{border-color:var(--m-mm);color:var(--m-mm);background:var(--m-background);transform:translateY(-1px);box-shadow:0 4px 12px #0000000d}.m-table-filter__item--active{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);font-weight:600;box-shadow:0 8px 16px color-mix(in srgb,var(--m-mm) 25%,transparent)}.m-table-filter__item--active:hover{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);transform:translateY(-1px)}.m-table-filter__item--active .m-table-filter__badge{background:#fff3;color:var(--m-inverse-text);border-color:#ffffff1a}.m-table-filter__item--primary{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);font-weight:600;box-shadow:0 8px 16px color-mix(in srgb,var(--m-mm) 25%,transparent)}.m-table-filter__item--primary:hover{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);transform:translateY(-1px);box-shadow:0 10px 20px color-mix(in srgb,var(--m-mm) 30%,transparent)}.m-table-filter__item--primary .m-table-filter__badge{background:#fff3;color:var(--m-inverse-text);border-color:#ffffff1a}.m-table-filter__item--danger{border-color:var(--m-error);color:var(--m-error)}.m-table-filter__item--danger:hover{border-color:var(--m-error);color:var(--m-error);background:var(--m-backdrop-error);transform:translateY(-1px);box-shadow:0 4px 12px color-mix(in srgb,var(--m-error) 12%,transparent)}.m-table-filter__item--danger .m-table-filter__badge{background:var(--m-backdrop-error);color:var(--m-error);border-color:color-mix(in srgb,var(--m-error) 20%,transparent)}.m-table-filter__label{font-size:.8125rem;font-weight:600;letter-spacing:.01em}.m-table-filter__badge{display:inline-flex;align-items:center;justify-content:center;min-width:1.25rem;height:1.25rem;padding:0 .375rem;border-radius:100px;background:var(--m-backdrop-surface);color:var(--m-text-secondary);font-size:.6875rem;font-weight:700;border:1px solid var(--m-backdrop-border);transition:all .2s ease}.m-table-thead__th{position:sticky;top:0;z-index:10;background:var(--m-table-thead-background, color-mix(in srgb, var(--m-background) 95%, transparent));-webkit-backdrop-filter:var(--m-table-thead-backdrop-filter, blur(28px));backdrop-filter:var(--m-table-thead-backdrop-filter, blur(28px));padding:1.25rem;text-align:left;font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--m-text-tertiary);border-bottom:2px solid var(--m-backdrop-border);white-space:nowrap;transition:all .2s ease}.m-table-thead__th:hover{color:var(--m-text);background:var(--m-table-thead-background, var(--m-background))}@media(min-width:769px){.m-table-thead__th--fixed{z-index:20;background:var(--m-table-thead-background, var(--m-background))}}@media(max-width:768px){.m-table-thead__th--fixed{position:static;z-index:auto}}.m-table-thead__th--fixed{border-right:none}@media(min-width:769px){.m-table-thead__th--fixed-last{border-right:1px solid var(--m-backdrop-border)}}@media(max-width:768px){.m-table-thead__th--fixed-last{border-right:none}}.m-table-thead__th--sortable{cursor:pointer;-webkit-user-select:none;user-select:none}.m-table-thead__th--select{width:48px;min-width:48px;max-width:48px;padding:0 1rem;text-align:center}.m-table-thead__th--select input[type=checkbox]{width:1rem;height:1rem;cursor:pointer;accent-color:var(--m-mm);border-radius:3px;display:block;margin:0 auto}.m-table-thead__cell{display:flex;align-items:center;gap:.5rem}.m-table-thead__sort-icon{color:var(--m-mm);opacity:.6;transition:opacity .2s ease}.m-table-thead__th:hover .m-table-thead__sort-icon{opacity:1}.m-table-thead__menu-btn{display:flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin-left:auto;border:none;background:transparent;cursor:pointer;color:var(--m-text-tertiary);border-radius:6px;opacity:0;transition:all .15ms ease}.m-table-thead__menu-btn:hover{background:var(--m-backdrop-surface);color:var(--m-text)}.m-table-thead__th:hover .m-table-thead__menu-btn{opacity:1}.m-table-body__row{transition:background-color .3s cubic-bezier(.4,0,.2,1);position:relative}.m-table-body__row:hover{background:color-mix(in srgb,var(--m-mm) 5%,transparent)}.m-table-body__row:hover .m-table-body__cell{background:inherit}.m-table-body__cell{padding:1rem 1.25rem;font-size:.875rem;color:var(--m-text);border-bottom:1px solid var(--m-backdrop-border);white-space:nowrap;vertical-align:middle;background:transparent;transition:background-color .3s ease}.m-table-body__cell[class*=--number],.m-table-body__cell[class*=--currency],.m-table-body__cell[class*=--percent]{font-family:Inter,Roboto Mono,monospace;font-variant-numeric:tabular-nums;letter-spacing:-.01em}@media(min-width:769px){.m-table-body__cell--fixed{position:sticky;background:var(--m-background);z-index:5}}@media(max-width:768px){.m-table-body__cell--fixed{position:static;background:transparent;z-index:auto}}.m-table-body__cell--fixed{border-right:none;transition:background-color .3s ease}.m-table-body__row:hover .m-table-body__cell--fixed{background:color-mix(in srgb,var(--m-mm) 5%,var(--m-background));z-index:6}@media(min-width:769px){.m-table-body__cell--fixed-last{border-right:1px solid var(--m-backdrop-border)}}@media(max-width:768px){.m-table-body__cell--fixed-last{border-right:none}}.m-table-body__cell--context-menu{padding-top:.35rem;padding-bottom:.35rem}.m-table-body__cell--select{width:48px;min-width:48px;max-width:48px;padding:0 1rem;text-align:center}.m-table-body__cell--select input[type=checkbox],.m-table-body__cell--select input[type=radio]{width:1rem;height:1rem;cursor:pointer;accent-color:var(--m-mm);display:block;margin:0 auto}.m-table-body__input{border:none;border-bottom:2px solid var(--m-backdrop-border);background:transparent;font-size:.875rem;color:var(--m-text);padding:.25rem;outline:none;width:100%;transition:border-bottom-color .2s ease}.m-table-body__input:focus{border-bottom-color:var(--m-mm)}.m-table-body__action-btn{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;border:none;background:transparent;cursor:pointer;color:var(--m-text-tertiary);border-radius:8px;transition:all .2s ease}.m-table-body__action-btn:hover{background:var(--m-backdrop-surface);color:var(--m-text)}.m-table-body__empty{text-align:center;padding:4rem;color:var(--m-text-tertiary);font-size:1rem;font-weight:500;letter-spacing:.02em;font-style:italic;opacity:.7}.m-table-body__link{color:var(--m-mm);text-decoration:none;cursor:pointer;font-weight:600;transition:color .2s ease}.m-table-body__link:hover{text-decoration:underline;color:var(--m-mm-lite)}.m-table-body__value{padding:.25rem .5rem;border-radius:6px;font-weight:600;font-variant-numeric:tabular-nums;letter-spacing:-.01em}.m-table-body__value--positive{color:var(--m-success);background:var(--m-backdrop-success)}.m-table-body__value--negative{color:var(--m-error);background:var(--m-backdrop-error)}.m-table-body__dash{color:var(--m-text-tertiary);font-weight:400;font-style:italic;opacity:.8}.m-tree-grid{--m-tree-grid-icon: .75rem}.m-tree-grid .m-table-thead__th,.m-tree-grid .m-table-body__cell{padding:.375rem .5rem}.m-tree-grid{--m-table-thead-background: transparent;--m-table-thead-backdrop-filter: none}.m-tree-grid .m-table-thead__th{font-size:.6875rem;letter-spacing:.06em;border-bottom-width:1px}.m-tree-grid__tree-cell{display:flex;align-items:center;gap:0;min-width:0}.m-tree-grid__indent{flex:0 0 auto;width:calc(var(--m-tree-grid-depth, 0) * var(--m-tree-grid-indent, var(--m-tree-grid-icon)))}.m-tree-grid__toggle{flex:0 0 auto;width:var(--m-tree-grid-icon);height:var(--m-tree-grid-icon);display:inline-flex;align-items:center;justify-content:center}.m-tree-grid__toggle m-button{--m-button-size: .333rem}.m-tree-grid__toggle-spacer{width:var(--m-tree-grid-icon);height:var(--m-tree-grid-icon);flex:0 0 auto}.m-tree-grid__lead-icon{flex:0 0 auto;display:inline-flex;align-items:center;margin-left:.125rem;opacity:.75}.m-tree-grid__lead-icon m-icon{--m-icon-size: .75rem}.m-tree-grid__label{min-width:0;margin-left:.25rem;overflow:hidden;text-overflow:ellipsis;font-size:.875em;line-height:1.25}.m-tree-grid .m-table-body__row{cursor:pointer}.m-tree-grid .m-table-body__row--selected{background:color-mix(in srgb,var(--m-mm) 12%,transparent)}.m-tree-grid .m-table__toolbar{padding:.5rem;background:transparent}.m-tree-grid .m-table__search{flex:1 1 auto;width:100%}.m-tree-grid .m-table__search m-input-wrapper,.m-tree-grid .m-table__search .m-input-wrapper{width:100%}.m-tree-grid__match{background:var(--m-highlight);padding:0;color:inherit;border-radius:2px}\n"], dependencies: [{ kind: "component", type: TableHeaderComponent, selector: "m-table-header", inputs: ["visibleColumns", "fixedCount", "fixedOffset", "sortState", "selectable", "allSelected", "someSelected"], outputs: ["sortClick", "selectAll"] }, { kind: "component", type: FreezeComponent, selector: "m-freeze", inputs: ["config"] }, { 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: HeaderComponent$1, selector: "m-header", inputs: ["level", "label", "icon", "actionButton", "actionLabel", "noTranslate", "params"], outputs: ["actionClick"] }, { kind: "component", type: IconComponent, selector: "m-icon, m-one-icon", inputs: ["config", "name", "color", "size", "one", "baseUrl", "remote"], outputs: ["configChange"] }, { kind: "component", type: ContextMenuComponent, selector: "m-context-menu, m-one-context-menu", inputs: ["toggle", "remote", "exclude", "visibilityRule", "disableRule", "extraData", "inverted", "options"], outputs: ["toggleChange", "action"] }, { kind: "component", type: WrapperInputComponent, selector: "m-input-wrapper", inputs: ["remote", "value", "readonly", "state", "focused", "form", "options", "dir", "element", "data", "template", "placeholder", "aclResolver", "formValues"], outputs: ["valueChange", "stateChange", "act", "fieldKey", "fieldType"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
31308
31774
  }
31309
31775
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TreeGridComponent, decorators: [{
31310
31776
  type: Component,
@@ -31585,7 +32051,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
31585
32051
  </table>
31586
32052
  </div>
31587
32053
  </div>
31588
- `, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, 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-table{display:flex;flex-direction:column;border:1px solid var(--m-backdrop-border);border-radius:12px;overflow:clip;background:#ffffffe6;-webkit-backdrop-filter:blur(40px);backdrop-filter:blur(40px);position:relative;transition:background-color .3s ease}.m-table--flat{border:none;box-shadow:none;background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none;border-radius:0}.m-table__toolbar{position:sticky;top:0;z-index:2;display:flex;align-items:center;justify-content:space-between;padding:1.5rem var(--m-table-toolbar-padding-x, 1.25rem);border-bottom:1px solid var(--m-backdrop-border);gap:1.5rem;background:color-mix(in srgb,var(--m-background) 45%,transparent)}.m-table--flat .m-table__toolbar{background:transparent;padding-left:0;padding-right:0}.m-table__title{margin:0;font-size:1.25rem;font-weight:800;color:var(--m-text);letter-spacing:-.02em;flex:1}.m-table__search{flex:0 1 auto;display:flex;align-items:center}.m-table__search .m-input-wrapper{width:100%}.m-table__mobile-view{display:flex;flex-direction:column;gap:1rem;padding:1.25rem;flex:1;overflow:auto}.m-table__empty-mobile{padding:3rem 1.5rem;text-align:center;color:var(--m-text-tertiary);font-size:.9375rem;font-weight:500;font-style:italic;opacity:.8;background:color-mix(in srgb,var(--m-background) 20%,transparent);border-radius:12px;border:1px dashed var(--m-backdrop-border)}.m-table__wrapper{overflow:auto;flex:1}.m-table__wrapper::-webkit-scrollbar{width:6px;height:6px}.m-table__wrapper::-webkit-scrollbar-track{background:transparent}.m-table__wrapper::-webkit-scrollbar-thumb{background:var(--m-backdrop-border);border-radius:10px}.m-table__wrapper::-webkit-scrollbar-thumb:hover{background:var(--m-text-tertiary)}.m-table__table{width:100%;min-width:100%;border-collapse:separate;border-spacing:0}mark.m-table__highlight{background:var(--m-highlight);color:#000;border-radius:2px;padding:0 2px;font-weight:700;box-shadow:0 1px 4px #0003}mark.m-table__highlight .m-one-pagination{margin-left:auto;--m-button-size: 2.25rem;--m-pagination-gap: .375rem}.m-table-pagination{display:flex;align-items:center;gap:1.5rem;padding:1.25rem var(--m-table-pagination-padding-x, 1.25rem);border-top:1px solid var(--m-backdrop-border);font-size:.8125rem;flex-wrap:wrap;background:color-mix(in srgb,var(--m-background) 40%,transparent)}.m-table--flat .m-table-pagination{background:transparent;padding-left:0;padding-right:0}.m-table-pagination__size{display:flex;flex-direction:column;align-items:flex-start;gap:.35rem;color:var(--m-text-secondary);font-weight:500}.m-table-pagination__select{border:1px solid var(--m-backdrop-border);border-radius:8px;background:var(--m-backdrop-surface);color:var(--m-text);padding:.375rem .625rem;font-size:.8125rem;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);outline:none}.m-table-pagination__select:hover{background:var(--m-backdrop-glass);border-color:var(--m-mm);box-shadow:0 0 0 3px color-mix(in srgb,var(--m-mm) 10%,transparent)}.m-table-pagination__select:focus{border-color:var(--m-mm);box-shadow:0 0 0 3px color-mix(in srgb,var(--m-mm) 20%,transparent)}.m-table-filter{display:flex;flex-wrap:wrap;align-items:center;gap:10px;padding:1rem 1.25rem;background:color-mix(in srgb,var(--m-background-lite) 60%,transparent);border-bottom:1px solid var(--m-backdrop-border);box-shadow:inset 0 2px 4px #00000005;overflow-x:auto;scrollbar-width:none}.m-table-filter::-webkit-scrollbar{display:none}.m-table--flat .m-table-filter{background:transparent;padding-left:0;padding-right:0;border-bottom:none}.m-table-filter__item{display:flex;align-items:center;gap:10px;padding:.4375rem 1rem;border-radius:12px;background:var(--m-background);border:1px solid var(--m-backdrop-border);color:var(--m-text-secondary);cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);white-space:nowrap;-webkit-user-select:none;user-select:none;outline:none;font-weight:500}.m-table-filter__item:hover{border-color:var(--m-mm);color:var(--m-mm);background:var(--m-background);transform:translateY(-1px);box-shadow:0 4px 12px #0000000d}.m-table-filter__item--active{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);font-weight:600;box-shadow:0 8px 16px color-mix(in srgb,var(--m-mm) 25%,transparent)}.m-table-filter__item--active:hover{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);transform:translateY(-1px)}.m-table-filter__item--active .m-table-filter__badge{background:#fff3;color:var(--m-inverse-text);border-color:#ffffff1a}.m-table-filter__item--primary{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);font-weight:600;box-shadow:0 8px 16px color-mix(in srgb,var(--m-mm) 25%,transparent)}.m-table-filter__item--primary:hover{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);transform:translateY(-1px);box-shadow:0 10px 20px color-mix(in srgb,var(--m-mm) 30%,transparent)}.m-table-filter__item--primary .m-table-filter__badge{background:#fff3;color:var(--m-inverse-text);border-color:#ffffff1a}.m-table-filter__item--danger{border-color:var(--m-error);color:var(--m-error)}.m-table-filter__item--danger:hover{border-color:var(--m-error);color:var(--m-error);background:var(--m-backdrop-error);transform:translateY(-1px);box-shadow:0 4px 12px color-mix(in srgb,var(--m-error) 12%,transparent)}.m-table-filter__item--danger .m-table-filter__badge{background:var(--m-backdrop-error);color:var(--m-error);border-color:color-mix(in srgb,var(--m-error) 20%,transparent)}.m-table-filter__label{font-size:.8125rem;font-weight:600;letter-spacing:.01em}.m-table-filter__badge{display:inline-flex;align-items:center;justify-content:center;min-width:1.25rem;height:1.25rem;padding:0 .375rem;border-radius:100px;background:var(--m-backdrop-surface);color:var(--m-text-secondary);font-size:.6875rem;font-weight:700;border:1px solid var(--m-backdrop-border);transition:all .2s ease}.m-table-thead__th{position:sticky;top:0;z-index:10;background:color-mix(in srgb,var(--m-background) 95%,transparent);-webkit-backdrop-filter:blur(28px);backdrop-filter:blur(28px);padding:1.25rem;text-align:left;font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--m-text-tertiary);border-bottom:2px solid var(--m-backdrop-border);white-space:nowrap;transition:all .2s ease}.m-table-thead__th:hover{color:var(--m-text);background:var(--m-background)}@media(min-width:769px){.m-table-thead__th--fixed{z-index:20;background:var(--m-background)}}@media(max-width:768px){.m-table-thead__th--fixed{position:static;z-index:auto}}.m-table-thead__th--fixed{border-right:none}@media(min-width:769px){.m-table-thead__th--fixed-last{border-right:1px solid var(--m-backdrop-border)}}@media(max-width:768px){.m-table-thead__th--fixed-last{border-right:none}}.m-table-thead__th--sortable{cursor:pointer;-webkit-user-select:none;user-select:none}.m-table-thead__th--select{width:48px;min-width:48px;max-width:48px;padding:0 1rem;text-align:center}.m-table-thead__th--select input[type=checkbox]{width:1rem;height:1rem;cursor:pointer;accent-color:var(--m-mm);border-radius:3px;display:block;margin:0 auto}.m-table-thead__cell{display:flex;align-items:center;gap:.5rem}.m-table-thead__sort-icon{color:var(--m-mm);opacity:.6;transition:opacity .2s ease}.m-table-thead__th:hover .m-table-thead__sort-icon{opacity:1}.m-table-thead__menu-btn{display:flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin-left:auto;border:none;background:transparent;cursor:pointer;color:var(--m-text-tertiary);border-radius:6px;opacity:0;transition:all .15ms ease}.m-table-thead__menu-btn:hover{background:var(--m-backdrop-surface);color:var(--m-text)}.m-table-thead__th:hover .m-table-thead__menu-btn{opacity:1}.m-table-body__row{transition:background-color .3s cubic-bezier(.4,0,.2,1);position:relative}.m-table-body__row:hover{background:color-mix(in srgb,var(--m-mm) 5%,transparent)}.m-table-body__row:hover .m-table-body__cell{background:inherit}.m-table-body__cell{padding:1rem 1.25rem;font-size:.875rem;color:var(--m-text);border-bottom:1px solid var(--m-backdrop-border);white-space:nowrap;vertical-align:middle;background:transparent;transition:background-color .3s ease}.m-table-body__cell[class*=--number],.m-table-body__cell[class*=--currency],.m-table-body__cell[class*=--percent]{font-family:Inter,Roboto Mono,monospace;font-variant-numeric:tabular-nums;letter-spacing:-.01em}@media(min-width:769px){.m-table-body__cell--fixed{position:sticky;background:var(--m-background);z-index:5}}@media(max-width:768px){.m-table-body__cell--fixed{position:static;background:transparent;z-index:auto}}.m-table-body__cell--fixed{border-right:none;transition:background-color .3s ease}.m-table-body__row:hover .m-table-body__cell--fixed{background:color-mix(in srgb,var(--m-mm) 5%,var(--m-background));z-index:6}@media(min-width:769px){.m-table-body__cell--fixed-last{border-right:1px solid var(--m-backdrop-border)}}@media(max-width:768px){.m-table-body__cell--fixed-last{border-right:none}}.m-table-body__cell--context-menu{padding-top:.35rem;padding-bottom:.35rem}.m-table-body__cell--select{width:48px;min-width:48px;max-width:48px;padding:0 1rem;text-align:center}.m-table-body__cell--select input[type=checkbox],.m-table-body__cell--select input[type=radio]{width:1rem;height:1rem;cursor:pointer;accent-color:var(--m-mm);display:block;margin:0 auto}.m-table-body__input{border:none;border-bottom:2px solid var(--m-backdrop-border);background:transparent;font-size:.875rem;color:var(--m-text);padding:.25rem;outline:none;width:100%;transition:border-bottom-color .2s ease}.m-table-body__input:focus{border-bottom-color:var(--m-mm)}.m-table-body__action-btn{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;border:none;background:transparent;cursor:pointer;color:var(--m-text-tertiary);border-radius:8px;transition:all .2s ease}.m-table-body__action-btn:hover{background:var(--m-backdrop-surface);color:var(--m-text)}.m-table-body__empty{text-align:center;padding:4rem;color:var(--m-text-tertiary);font-size:1rem;font-weight:500;letter-spacing:.02em;font-style:italic;opacity:.7}.m-table-body__link{color:var(--m-mm);text-decoration:none;cursor:pointer;font-weight:600;transition:color .2s ease}.m-table-body__link:hover{text-decoration:underline;color:var(--m-mm-lite)}.m-table-body__value{padding:.25rem .5rem;border-radius:6px;font-weight:600;font-variant-numeric:tabular-nums;letter-spacing:-.01em}.m-table-body__value--positive{color:var(--m-success);background:var(--m-backdrop-success)}.m-table-body__value--negative{color:var(--m-error);background:var(--m-backdrop-error)}.m-table-body__dash{color:var(--m-text-tertiary);font-weight:400;font-style:italic;opacity:.8}.m-tree-grid{--m-tree-grid-icon: .75rem}.m-tree-grid .m-table-thead__th,.m-tree-grid .m-table-body__cell{padding:.375rem .5rem}.m-tree-grid .m-table-thead__th{font-size:.6875rem;letter-spacing:.06em;border-bottom-width:1px}.m-tree-grid__tree-cell{display:flex;align-items:center;gap:0;min-width:0}.m-tree-grid__indent{flex:0 0 auto;width:calc(var(--m-tree-grid-depth, 0) * var(--m-tree-grid-indent, var(--m-tree-grid-icon)))}.m-tree-grid__toggle{flex:0 0 auto;width:var(--m-tree-grid-icon);height:var(--m-tree-grid-icon);display:inline-flex;align-items:center;justify-content:center}.m-tree-grid__toggle m-button{--m-button-size: .333rem}.m-tree-grid__toggle-spacer{width:var(--m-tree-grid-icon);height:var(--m-tree-grid-icon);flex:0 0 auto}.m-tree-grid__lead-icon{flex:0 0 auto;display:inline-flex;align-items:center;margin-left:.125rem;opacity:.75}.m-tree-grid__lead-icon m-icon{--m-icon-size: .75rem}.m-tree-grid__label{min-width:0;margin-left:.25rem;overflow:hidden;text-overflow:ellipsis;font-size:.875em;line-height:1.25}.m-tree-grid .m-table-body__row{cursor:pointer}.m-tree-grid .m-table-body__row--selected{background:color-mix(in srgb,var(--m-mm) 12%,transparent)}.m-tree-grid .m-table__toolbar{padding:.5rem;background:var(--m-background)}.m-tree-grid .m-table__search{flex:1 1 auto;width:100%}.m-tree-grid .m-table__search m-input-wrapper,.m-tree-grid .m-table__search .m-input-wrapper{width:100%}.m-tree-grid__match{background:var(--m-highlight);padding:0;color:inherit;border-radius:2px}\n"] }]
32054
+ `, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, 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-table{display:flex;flex-direction:column;border:1px solid var(--m-backdrop-border);border-radius:12px;overflow:clip;background:#ffffffe6;-webkit-backdrop-filter:blur(40px);backdrop-filter:blur(40px);position:relative;transition:background-color .3s ease}.m-table--flat{border:none;box-shadow:none;background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none;border-radius:0}.m-table__toolbar{position:sticky;top:0;z-index:2;display:flex;align-items:center;justify-content:space-between;padding:1.5rem var(--m-table-toolbar-padding-x, 1.25rem);border-bottom:1px solid var(--m-backdrop-border);gap:1.5rem;background:color-mix(in srgb,var(--m-background) 45%,transparent)}.m-table--flat .m-table__toolbar{background:transparent;padding-left:0;padding-right:0}.m-table__title{margin:0;font-size:1.25rem;font-weight:800;color:var(--m-text);letter-spacing:-.02em;flex:1}.m-table__search{flex:0 1 auto;display:flex;align-items:center}.m-table__search .m-input-wrapper{width:100%}.m-table__mobile-view{display:flex;flex-direction:column;gap:1rem;padding:1.25rem;flex:1;overflow:auto}.m-table__empty-mobile{padding:3rem 1.5rem;text-align:center;color:var(--m-text-tertiary);font-size:.9375rem;font-weight:500;font-style:italic;opacity:.8;background:color-mix(in srgb,var(--m-background) 20%,transparent);border-radius:12px;border:1px dashed var(--m-backdrop-border)}.m-table__wrapper{overflow:auto;flex:1}.m-table__wrapper::-webkit-scrollbar{width:6px;height:6px}.m-table__wrapper::-webkit-scrollbar-track{background:transparent}.m-table__wrapper::-webkit-scrollbar-thumb{background:var(--m-backdrop-border);border-radius:10px}.m-table__wrapper::-webkit-scrollbar-thumb:hover{background:var(--m-text-tertiary)}.m-table__table{width:100%;min-width:100%;border-collapse:separate;border-spacing:0}mark.m-table__highlight{background:var(--m-highlight);color:#000;border-radius:2px;padding:0 2px;font-weight:700;box-shadow:0 1px 4px #0003}mark.m-table__highlight .m-one-pagination{margin-left:auto;--m-button-size: 2.25rem;--m-pagination-gap: .375rem}.m-table-pagination{display:flex;align-items:center;gap:1.5rem;padding:1.25rem var(--m-table-pagination-padding-x, 1.25rem);border-top:1px solid var(--m-backdrop-border);font-size:.8125rem;flex-wrap:wrap;background:color-mix(in srgb,var(--m-background) 40%,transparent)}.m-table--flat .m-table-pagination{background:transparent;padding-left:0;padding-right:0}.m-table-pagination__size{display:flex;flex-direction:column;align-items:flex-start;gap:.35rem;color:var(--m-text-secondary);font-weight:500}.m-table-pagination__select{border:1px solid var(--m-backdrop-border);border-radius:8px;background:var(--m-backdrop-surface);color:var(--m-text);padding:.375rem .625rem;font-size:.8125rem;font-weight:600;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);outline:none}.m-table-pagination__select:hover{background:var(--m-backdrop-glass);border-color:var(--m-mm);box-shadow:0 0 0 3px color-mix(in srgb,var(--m-mm) 10%,transparent)}.m-table-pagination__select:focus{border-color:var(--m-mm);box-shadow:0 0 0 3px color-mix(in srgb,var(--m-mm) 20%,transparent)}.m-table-filter{display:flex;flex-wrap:wrap;align-items:center;gap:10px;padding:1rem 1.25rem;background:color-mix(in srgb,var(--m-background-lite) 60%,transparent);border-bottom:1px solid var(--m-backdrop-border);box-shadow:inset 0 2px 4px #00000005;overflow-x:auto;scrollbar-width:none}.m-table-filter::-webkit-scrollbar{display:none}.m-table--flat .m-table-filter{background:transparent;padding-left:0;padding-right:0;border-bottom:none}.m-table-filter__item{display:flex;align-items:center;gap:10px;padding:.4375rem 1rem;border-radius:12px;background:var(--m-background);border:1px solid var(--m-backdrop-border);color:var(--m-text-secondary);cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);white-space:nowrap;-webkit-user-select:none;user-select:none;outline:none;font-weight:500}.m-table-filter__item:hover{border-color:var(--m-mm);color:var(--m-mm);background:var(--m-background);transform:translateY(-1px);box-shadow:0 4px 12px #0000000d}.m-table-filter__item--active{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);font-weight:600;box-shadow:0 8px 16px color-mix(in srgb,var(--m-mm) 25%,transparent)}.m-table-filter__item--active:hover{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);transform:translateY(-1px)}.m-table-filter__item--active .m-table-filter__badge{background:#fff3;color:var(--m-inverse-text);border-color:#ffffff1a}.m-table-filter__item--primary{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);font-weight:600;box-shadow:0 8px 16px color-mix(in srgb,var(--m-mm) 25%,transparent)}.m-table-filter__item--primary:hover{background:var(--m-mm);border-color:var(--m-mm);color:var(--m-inverse-text);transform:translateY(-1px);box-shadow:0 10px 20px color-mix(in srgb,var(--m-mm) 30%,transparent)}.m-table-filter__item--primary .m-table-filter__badge{background:#fff3;color:var(--m-inverse-text);border-color:#ffffff1a}.m-table-filter__item--danger{border-color:var(--m-error);color:var(--m-error)}.m-table-filter__item--danger:hover{border-color:var(--m-error);color:var(--m-error);background:var(--m-backdrop-error);transform:translateY(-1px);box-shadow:0 4px 12px color-mix(in srgb,var(--m-error) 12%,transparent)}.m-table-filter__item--danger .m-table-filter__badge{background:var(--m-backdrop-error);color:var(--m-error);border-color:color-mix(in srgb,var(--m-error) 20%,transparent)}.m-table-filter__label{font-size:.8125rem;font-weight:600;letter-spacing:.01em}.m-table-filter__badge{display:inline-flex;align-items:center;justify-content:center;min-width:1.25rem;height:1.25rem;padding:0 .375rem;border-radius:100px;background:var(--m-backdrop-surface);color:var(--m-text-secondary);font-size:.6875rem;font-weight:700;border:1px solid var(--m-backdrop-border);transition:all .2s ease}.m-table-thead__th{position:sticky;top:0;z-index:10;background:var(--m-table-thead-background, color-mix(in srgb, var(--m-background) 95%, transparent));-webkit-backdrop-filter:var(--m-table-thead-backdrop-filter, blur(28px));backdrop-filter:var(--m-table-thead-backdrop-filter, blur(28px));padding:1.25rem;text-align:left;font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--m-text-tertiary);border-bottom:2px solid var(--m-backdrop-border);white-space:nowrap;transition:all .2s ease}.m-table-thead__th:hover{color:var(--m-text);background:var(--m-table-thead-background, var(--m-background))}@media(min-width:769px){.m-table-thead__th--fixed{z-index:20;background:var(--m-table-thead-background, var(--m-background))}}@media(max-width:768px){.m-table-thead__th--fixed{position:static;z-index:auto}}.m-table-thead__th--fixed{border-right:none}@media(min-width:769px){.m-table-thead__th--fixed-last{border-right:1px solid var(--m-backdrop-border)}}@media(max-width:768px){.m-table-thead__th--fixed-last{border-right:none}}.m-table-thead__th--sortable{cursor:pointer;-webkit-user-select:none;user-select:none}.m-table-thead__th--select{width:48px;min-width:48px;max-width:48px;padding:0 1rem;text-align:center}.m-table-thead__th--select input[type=checkbox]{width:1rem;height:1rem;cursor:pointer;accent-color:var(--m-mm);border-radius:3px;display:block;margin:0 auto}.m-table-thead__cell{display:flex;align-items:center;gap:.5rem}.m-table-thead__sort-icon{color:var(--m-mm);opacity:.6;transition:opacity .2s ease}.m-table-thead__th:hover .m-table-thead__sort-icon{opacity:1}.m-table-thead__menu-btn{display:flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin-left:auto;border:none;background:transparent;cursor:pointer;color:var(--m-text-tertiary);border-radius:6px;opacity:0;transition:all .15ms ease}.m-table-thead__menu-btn:hover{background:var(--m-backdrop-surface);color:var(--m-text)}.m-table-thead__th:hover .m-table-thead__menu-btn{opacity:1}.m-table-body__row{transition:background-color .3s cubic-bezier(.4,0,.2,1);position:relative}.m-table-body__row:hover{background:color-mix(in srgb,var(--m-mm) 5%,transparent)}.m-table-body__row:hover .m-table-body__cell{background:inherit}.m-table-body__cell{padding:1rem 1.25rem;font-size:.875rem;color:var(--m-text);border-bottom:1px solid var(--m-backdrop-border);white-space:nowrap;vertical-align:middle;background:transparent;transition:background-color .3s ease}.m-table-body__cell[class*=--number],.m-table-body__cell[class*=--currency],.m-table-body__cell[class*=--percent]{font-family:Inter,Roboto Mono,monospace;font-variant-numeric:tabular-nums;letter-spacing:-.01em}@media(min-width:769px){.m-table-body__cell--fixed{position:sticky;background:var(--m-background);z-index:5}}@media(max-width:768px){.m-table-body__cell--fixed{position:static;background:transparent;z-index:auto}}.m-table-body__cell--fixed{border-right:none;transition:background-color .3s ease}.m-table-body__row:hover .m-table-body__cell--fixed{background:color-mix(in srgb,var(--m-mm) 5%,var(--m-background));z-index:6}@media(min-width:769px){.m-table-body__cell--fixed-last{border-right:1px solid var(--m-backdrop-border)}}@media(max-width:768px){.m-table-body__cell--fixed-last{border-right:none}}.m-table-body__cell--context-menu{padding-top:.35rem;padding-bottom:.35rem}.m-table-body__cell--select{width:48px;min-width:48px;max-width:48px;padding:0 1rem;text-align:center}.m-table-body__cell--select input[type=checkbox],.m-table-body__cell--select input[type=radio]{width:1rem;height:1rem;cursor:pointer;accent-color:var(--m-mm);display:block;margin:0 auto}.m-table-body__input{border:none;border-bottom:2px solid var(--m-backdrop-border);background:transparent;font-size:.875rem;color:var(--m-text);padding:.25rem;outline:none;width:100%;transition:border-bottom-color .2s ease}.m-table-body__input:focus{border-bottom-color:var(--m-mm)}.m-table-body__action-btn{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;border:none;background:transparent;cursor:pointer;color:var(--m-text-tertiary);border-radius:8px;transition:all .2s ease}.m-table-body__action-btn:hover{background:var(--m-backdrop-surface);color:var(--m-text)}.m-table-body__empty{text-align:center;padding:4rem;color:var(--m-text-tertiary);font-size:1rem;font-weight:500;letter-spacing:.02em;font-style:italic;opacity:.7}.m-table-body__link{color:var(--m-mm);text-decoration:none;cursor:pointer;font-weight:600;transition:color .2s ease}.m-table-body__link:hover{text-decoration:underline;color:var(--m-mm-lite)}.m-table-body__value{padding:.25rem .5rem;border-radius:6px;font-weight:600;font-variant-numeric:tabular-nums;letter-spacing:-.01em}.m-table-body__value--positive{color:var(--m-success);background:var(--m-backdrop-success)}.m-table-body__value--negative{color:var(--m-error);background:var(--m-backdrop-error)}.m-table-body__dash{color:var(--m-text-tertiary);font-weight:400;font-style:italic;opacity:.8}.m-tree-grid{--m-tree-grid-icon: .75rem}.m-tree-grid .m-table-thead__th,.m-tree-grid .m-table-body__cell{padding:.375rem .5rem}.m-tree-grid{--m-table-thead-background: transparent;--m-table-thead-backdrop-filter: none}.m-tree-grid .m-table-thead__th{font-size:.6875rem;letter-spacing:.06em;border-bottom-width:1px}.m-tree-grid__tree-cell{display:flex;align-items:center;gap:0;min-width:0}.m-tree-grid__indent{flex:0 0 auto;width:calc(var(--m-tree-grid-depth, 0) * var(--m-tree-grid-indent, var(--m-tree-grid-icon)))}.m-tree-grid__toggle{flex:0 0 auto;width:var(--m-tree-grid-icon);height:var(--m-tree-grid-icon);display:inline-flex;align-items:center;justify-content:center}.m-tree-grid__toggle m-button{--m-button-size: .333rem}.m-tree-grid__toggle-spacer{width:var(--m-tree-grid-icon);height:var(--m-tree-grid-icon);flex:0 0 auto}.m-tree-grid__lead-icon{flex:0 0 auto;display:inline-flex;align-items:center;margin-left:.125rem;opacity:.75}.m-tree-grid__lead-icon m-icon{--m-icon-size: .75rem}.m-tree-grid__label{min-width:0;margin-left:.25rem;overflow:hidden;text-overflow:ellipsis;font-size:.875em;line-height:1.25}.m-tree-grid .m-table-body__row{cursor:pointer}.m-tree-grid .m-table-body__row--selected{background:color-mix(in srgb,var(--m-mm) 12%,transparent)}.m-tree-grid .m-table__toolbar{padding:.5rem;background:transparent}.m-tree-grid .m-table__search{flex:1 1 auto;width:100%}.m-tree-grid .m-table__search m-input-wrapper,.m-tree-grid .m-table__search .m-input-wrapper{width:100%}.m-tree-grid__match{background:var(--m-highlight);padding:0;color:inherit;border-radius:2px}\n"] }]
31589
32055
  }], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }, { type: i0.Output, args: ["configChange"] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }, { type: i0.Output, args: ["dataChange"] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], indentRem: [{ type: i0.Input, args: [{ isSignal: true, alias: "indentRem", required: false }] }], keyIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyIndex", required: false }] }], selectedKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedKey", required: false }] }, { type: i0.Output, args: ["selectedKeyChange"] }], rowToggled: [{ type: i0.Output, args: ["rowToggled"] }], loadChildren: [{ type: i0.Output, args: ["loadChildren"] }], rowSelected: [{ type: i0.Output, args: ["rowSelected"] }], menuAction: [{ type: i0.Output, args: ["menuAction"] }], cellClicked: [{ type: i0.Output, args: ["cellClicked"] }], searchChanged: [{ type: i0.Output, args: ["searchChanged"] }] } });
31590
32056
 
31591
32057
  const CHART_WIDTH = 300;
@@ -33217,9 +33683,14 @@ function provideModalComponents() {
33217
33683
  ]);
33218
33684
  }
33219
33685
 
33686
+ /** Where the recent queries are held (CONTEXT.md HeldValue). */
33687
+ const RECENT_KEY = 'search.recent';
33688
+ /** Recent queries kept — enough to pick from, not a history. */
33689
+ const RECENT_SEARCH_LIMIT = 8;
33220
33690
  const initialState$1 = {
33221
33691
  query: '',
33222
33692
  sourceResults: {},
33693
+ recent: [],
33223
33694
  };
33224
33695
  const SearchStore = signalStore({ providedIn: 'root' }, withState(initialState$1), withComputed(({ query, sourceResults }) => ({
33225
33696
  groupedResults: computed(() => Object.values(sourceResults()).filter((g) => g.items.length > 0)),
@@ -33227,11 +33698,30 @@ const SearchStore = signalStore({ providedIn: 'root' }, withState(initialState$1
33227
33698
  hasQuery: computed(() => query().trim().length > 0),
33228
33699
  })), withMethods((store) => {
33229
33700
  const searchQuery = inject(SEARCH_QUERY, { optional: true });
33701
+ const storage = inject(StorageService);
33230
33702
  return {
33231
33703
  updateQuery: (query) => {
33232
33704
  patchState(store, { query });
33233
33705
  searchQuery?.set(query);
33234
33706
  },
33707
+ /**
33708
+ * Keeps the current query as a recent one — called when a User follows
33709
+ * a hit, so only a search that found something is kept, never each
33710
+ * keystroke on the way to it. Moves a repeat to the front.
33711
+ */
33712
+ rememberQuery: () => {
33713
+ const query = store.query().trim();
33714
+ if (!query)
33715
+ return;
33716
+ const recent = [
33717
+ query,
33718
+ ...store
33719
+ .recent()
33720
+ .filter((q) => q.toLowerCase() !== query.toLowerCase()),
33721
+ ].slice(0, RECENT_SEARCH_LIMIT);
33722
+ patchState(store, { recent });
33723
+ storage.setHeld(RECENT_KEY, recent);
33724
+ },
33235
33725
  clearQuery: () => {
33236
33726
  patchState(store, { query: '', sourceResults: {} });
33237
33727
  searchQuery?.set('');
@@ -33257,6 +33747,9 @@ const SearchStore = signalStore({ providedIn: 'root' }, withState(initialState$1
33257
33747
  const injector = inject(Injector);
33258
33748
  return {
33259
33749
  onInit() {
33750
+ patchState(store, {
33751
+ recent: injector.get(StorageService).getHeld(RECENT_KEY) ?? [],
33752
+ });
33260
33753
  const sq = injector.get(SEARCH_QUERY, null);
33261
33754
  if (sq) {
33262
33755
  effect(() => {
@@ -33661,23 +34154,89 @@ const navTailMatcher = (prefix, name) => (segments) => {
33661
34154
  return { consumed: segments, posParams };
33662
34155
  };
33663
34156
 
34157
+ // What one entry and its chevron take on the line, at the trail's size. An
34158
+ // estimate rather than a measurement: labels are clipped to fit anyway, so the
34159
+ // guess only decides how many ancestors are worth drawing at all.
34160
+ const ENTRY_PX = 96;
34161
+ // Unmeasured (SSR, jsdom) the trail has no width to fold against, so a long
34162
+ // one still folds rather than running off the line.
34163
+ const UNMEASURED_FIT = 4;
34164
+ // The root entry and the one nearest the page are the two worth keeping.
34165
+ const MIN_FIT = 2;
33664
34166
  class NavTrailComponent {
33665
34167
  config = input.required(...(ngDevMode ? [{ debugName: "config" }] : /* istanbul ignore next */ []));
33666
34168
  Size = Size;
33667
34169
  themeStore = inject(ThemeStore);
33668
34170
  navStore = inject(NavStore);
34171
+ el = inject(ElementRef);
34172
+ destroyRef = inject(DestroyRef);
34173
+ doc = inject(DOCUMENT);
33669
34174
  headerColor = computed(() => this.themeStore.color()?.mm ?? '#fff', ...(ngDevMode ? [{ debugName: "headerColor" }] : /* istanbul ignore next */ []));
33670
34175
  fromUrl = computed(() => !!this.navStore.id(), ...(ngDevMode ? [{ debugName: "fromUrl" }] : /* istanbul ignore next */ []));
34176
+ // The trail's own width, measured rather than queried: the header is
34177
+ // routinely the width of a docked panel, not the window (ADR 0001).
34178
+ width = signal(undefined, ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
34179
+ fit = computed(() => {
34180
+ const width = this.width();
34181
+ if (width === undefined)
34182
+ return UNMEASURED_FIT;
34183
+ return Math.max(MIN_FIT, Math.floor(width / ENTRY_PX));
34184
+ }, ...(ngDevMode ? [{ debugName: "fit" }] : /* istanbul ignore next */ []));
34185
+ // Folded from the middle: the root anchors where the trail starts and the
34186
+ // nearest ancestors say where the User stands, so it is the ones between
34187
+ // that go behind the overflow.
34188
+ fold = computed(() => {
34189
+ const trail = this.config();
34190
+ const fit = this.fit();
34191
+ if (trail.length <= fit)
34192
+ return { shown: trail, hidden: [] };
34193
+ const tail = Math.max(1, fit - 1);
34194
+ return {
34195
+ shown: [trail[0], ...trail.slice(-tail)],
34196
+ hidden: trail.slice(1, trail.length - tail),
34197
+ };
34198
+ }, ...(ngDevMode ? [{ debugName: "fold" }] : /* istanbul ignore next */ []));
34199
+ shown = computed(() => this.fold().shown, ...(ngDevMode ? [{ debugName: "shown" }] : /* istanbul ignore next */ []));
34200
+ hidden = computed(() => this.fold().hidden, ...(ngDevMode ? [{ debugName: "hidden" }] : /* istanbul ignore next */ []));
34201
+ // No `nav` on the rows: the menu would follow it and move the User, where a
34202
+ // trail entry only Browses. The press comes back through `onOverflow`.
34203
+ overflowMenu = computed(() => ({
34204
+ align: 'left',
34205
+ icon: { name: 'more' },
34206
+ options: [
34207
+ this.hidden().map((entry) => ({
34208
+ id: entry.id,
34209
+ label: entry.label,
34210
+ icon: entry.icon,
34211
+ })),
34212
+ ],
34213
+ }), ...(ngDevMode ? [{ debugName: "overflowMenu" }] : /* istanbul ignore next */ []));
34214
+ constructor() {
34215
+ afterNextRender(() => {
34216
+ if (typeof ResizeObserver === 'undefined')
34217
+ return;
34218
+ const observer = new ResizeObserver(([entry]) => this.width.set(entry.contentRect.width));
34219
+ observer.observe(this.el.nativeElement);
34220
+ this.destroyRef.onDestroy(() => observer.disconnect());
34221
+ });
34222
+ }
33671
34223
  /**
33672
34224
  * Moves the panel onto the entry's Nav and leaves the Address, and the Page
33673
34225
  * behind the panel, where they are (CONTEXT.md Browse).
33674
34226
  */
33675
34227
  browse = (navId, params) => this.navStore.browse(navId, params);
34228
+ onOverflow(item) {
34229
+ const entry = this.hidden().find((e) => e.id === item.id);
34230
+ if (entry?.nav)
34231
+ this.browse(entry.nav, entry.navParams);
34232
+ else if (entry?.href)
34233
+ this.doc.location.assign(entry.href);
34234
+ }
33676
34235
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: NavTrailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
33677
34236
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: NavTrailComponent, isStandalone: true, selector: "m-nav-trail", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "m-nav-trail" }, ngImport: i0, template: `
33678
34237
  @if (config(); as trail) {
33679
34238
  <nav class="nav-trail">
33680
- @for (item of trail; track item.id; let i = $index; let last = $last) {
34239
+ @for (item of shown(); track item.id; let i = $index; let last = $last) {
33681
34240
  <div class="trail-item" [style.animation-delay.ms]="i * 50">
33682
34241
  @if (item.nav; as nav) {
33683
34242
  <!-- Browses: the trail moves the panel, never the User. -->
@@ -33685,13 +34244,14 @@ class NavTrailComponent {
33685
34244
  class="trail-link"
33686
34245
  role="button"
33687
34246
  tabindex="0"
34247
+ [attr.title]="item.label | translate"
33688
34248
  (click)="browse(nav, item.navParams)"
33689
34249
  (keydown.enter)="browse(nav, item.navParams)"
33690
34250
  >
33691
34251
  {{ item.label | translate }}
33692
34252
  </a>
33693
34253
  } @else if (item.href; as href) {
33694
- <a [href]="href" class="trail-link">
34254
+ <a [href]="href" class="trail-link" [attr.title]="item.label | translate">
33695
34255
  {{ item.label | translate }}
33696
34256
  </a>
33697
34257
  }
@@ -33701,17 +34261,26 @@ class NavTrailComponent {
33701
34261
  </div>
33702
34262
  }
33703
34263
  </div>
34264
+ @if (i === 0 && hidden().length) {
34265
+ <!-- The ancestors the line could not fit, one press away. -->
34266
+ <div class="trail-item trail-item--overflow">
34267
+ <m-context-menu [config]="overflowMenu()" (action)="onOverflow($event)" />
34268
+ <div class="trail-separator">
34269
+ <m-icon name="chevron-right" />
34270
+ </div>
34271
+ </div>
34272
+ }
33704
34273
  }
33705
34274
  </nav>
33706
34275
  }
33707
- `, 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)}}.m-nav-trail{display:block;flex:1;min-width:0}.nav-trail{display:flex;align-items:center;gap:.6rem;font-size:.725rem;letter-spacing:.04em;color:var(--m-text-tertiary);-webkit-user-select:none;user-select:none;font-weight:600}.trail-item{display:flex;align-items:center;gap:.6rem;animation:slide-in-trail .5s cubic-bezier(.16,1,.3,1)}.trail-link{color:inherit;text-decoration:none;padding:.25rem .6rem;border-radius:6px;transition:all .3s cubic-bezier(.16,1,.3,1);cursor:pointer;white-space:nowrap}.trail-link:hover{color:var(--m-mm);background:color-mix(in srgb,var(--m-mm) 6%,transparent);transform:translateY(-1px)}.trail-link:active{transform:scale(.96) translateY(0)}.trail-separator{display:flex;align-items:center;justify-content:center;opacity:.35;color:var(--m-text-tertiary);pointer-events:none;font-size:.625rem}.trail-separator .m-icon{--m-icon-size: .625rem;display:flex;align-items:center;justify-content:center}@keyframes slide-in-trail{0%{opacity:0;transform:translate(-10px)}to{opacity:1;transform:translate(0)}}\n"], dependencies: [{ kind: "component", type: IconComponent, selector: "m-icon, m-one-icon", inputs: ["config", "name", "color", "size", "one", "baseUrl", "remote"], outputs: ["configChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
34276
+ `, 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)}}.m-nav-trail{display:block;flex:1;min-width:0}.nav-trail{display:flex;flex-wrap:nowrap;align-items:center;min-width:0;gap:.125rem;font-size:.725rem;letter-spacing:.04em;color:var(--m-text-tertiary);-webkit-user-select:none;user-select:none;font-weight:600}.trail-item{display:flex;align-items:center;gap:.125rem;min-width:0;flex:0 3 auto;animation:slide-in-trail .5s cubic-bezier(.16,1,.3,1)}.trail-item:last-child{flex-shrink:1}.trail-item:last-child .trail-link{color:var(--m-text-secondary)}.trail-item--overflow{flex-shrink:0;--m-button-size: .7rem}.trail-link{display:block;min-width:2rem;max-width:12rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:inherit;text-decoration:none;padding:.125rem .375rem;border-radius:4px;transition:all .3s cubic-bezier(.16,1,.3,1);cursor:pointer}.trail-link:hover{color:var(--m-mm);background:color-mix(in srgb,var(--m-mm) 6%,transparent)}.trail-link:active{transform:scale(.96)}.trail-separator{display:flex;flex-shrink:0;align-items:center;justify-content:center;opacity:.35;color:var(--m-text-tertiary);pointer-events:none;font-size:.625rem}.trail-separator .m-icon{--m-icon-size: .625rem;display:flex;align-items:center;justify-content:center}@keyframes slide-in-trail{0%{opacity:0;transform:translate(-10px)}to{opacity:1;transform:translate(0)}}\n"], dependencies: [{ kind: "component", type: IconComponent, selector: "m-icon, m-one-icon", inputs: ["config", "name", "color", "size", "one", "baseUrl", "remote"], outputs: ["configChange"] }, { kind: "component", type: ContextMenuComponent, selector: "m-context-menu, m-one-context-menu", inputs: ["toggle", "remote", "exclude", "visibilityRule", "disableRule", "extraData", "inverted", "options"], outputs: ["toggleChange", "action"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
33708
34277
  }
33709
34278
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: NavTrailComponent, decorators: [{
33710
34279
  type: Component,
33711
34280
  args: [{ selector: 'm-nav-trail', template: `
33712
34281
  @if (config(); as trail) {
33713
34282
  <nav class="nav-trail">
33714
- @for (item of trail; track item.id; let i = $index; let last = $last) {
34283
+ @for (item of shown(); track item.id; let i = $index; let last = $last) {
33715
34284
  <div class="trail-item" [style.animation-delay.ms]="i * 50">
33716
34285
  @if (item.nav; as nav) {
33717
34286
  <!-- Browses: the trail moves the panel, never the User. -->
@@ -33719,13 +34288,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
33719
34288
  class="trail-link"
33720
34289
  role="button"
33721
34290
  tabindex="0"
34291
+ [attr.title]="item.label | translate"
33722
34292
  (click)="browse(nav, item.navParams)"
33723
34293
  (keydown.enter)="browse(nav, item.navParams)"
33724
34294
  >
33725
34295
  {{ item.label | translate }}
33726
34296
  </a>
33727
34297
  } @else if (item.href; as href) {
33728
- <a [href]="href" class="trail-link">
34298
+ <a [href]="href" class="trail-link" [attr.title]="item.label | translate">
33729
34299
  {{ item.label | translate }}
33730
34300
  </a>
33731
34301
  }
@@ -33735,13 +34305,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
33735
34305
  </div>
33736
34306
  }
33737
34307
  </div>
34308
+ @if (i === 0 && hidden().length) {
34309
+ <!-- The ancestors the line could not fit, one press away. -->
34310
+ <div class="trail-item trail-item--overflow">
34311
+ <m-context-menu [config]="overflowMenu()" (action)="onOverflow($event)" />
34312
+ <div class="trail-separator">
34313
+ <m-icon name="chevron-right" />
34314
+ </div>
34315
+ </div>
34316
+ }
33738
34317
  }
33739
34318
  </nav>
33740
34319
  }
33741
- `, imports: [TranslatePipe, IconComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: {
34320
+ `, imports: [TranslatePipe, IconComponent, ContextMenuComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: {
33742
34321
  class: 'm-nav-trail',
33743
- }, 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-nav-trail{display:block;flex:1;min-width:0}.nav-trail{display:flex;align-items:center;gap:.6rem;font-size:.725rem;letter-spacing:.04em;color:var(--m-text-tertiary);-webkit-user-select:none;user-select:none;font-weight:600}.trail-item{display:flex;align-items:center;gap:.6rem;animation:slide-in-trail .5s cubic-bezier(.16,1,.3,1)}.trail-link{color:inherit;text-decoration:none;padding:.25rem .6rem;border-radius:6px;transition:all .3s cubic-bezier(.16,1,.3,1);cursor:pointer;white-space:nowrap}.trail-link:hover{color:var(--m-mm);background:color-mix(in srgb,var(--m-mm) 6%,transparent);transform:translateY(-1px)}.trail-link:active{transform:scale(.96) translateY(0)}.trail-separator{display:flex;align-items:center;justify-content:center;opacity:.35;color:var(--m-text-tertiary);pointer-events:none;font-size:.625rem}.trail-separator .m-icon{--m-icon-size: .625rem;display:flex;align-items:center;justify-content:center}@keyframes slide-in-trail{0%{opacity:0;transform:translate(-10px)}to{opacity:1;transform:translate(0)}}\n"] }]
33744
- }], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }] } });
34322
+ }, 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-nav-trail{display:block;flex:1;min-width:0}.nav-trail{display:flex;flex-wrap:nowrap;align-items:center;min-width:0;gap:.125rem;font-size:.725rem;letter-spacing:.04em;color:var(--m-text-tertiary);-webkit-user-select:none;user-select:none;font-weight:600}.trail-item{display:flex;align-items:center;gap:.125rem;min-width:0;flex:0 3 auto;animation:slide-in-trail .5s cubic-bezier(.16,1,.3,1)}.trail-item:last-child{flex-shrink:1}.trail-item:last-child .trail-link{color:var(--m-text-secondary)}.trail-item--overflow{flex-shrink:0;--m-button-size: .7rem}.trail-link{display:block;min-width:2rem;max-width:12rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:inherit;text-decoration:none;padding:.125rem .375rem;border-radius:4px;transition:all .3s cubic-bezier(.16,1,.3,1);cursor:pointer}.trail-link:hover{color:var(--m-mm);background:color-mix(in srgb,var(--m-mm) 6%,transparent)}.trail-link:active{transform:scale(.96)}.trail-separator{display:flex;flex-shrink:0;align-items:center;justify-content:center;opacity:.35;color:var(--m-text-tertiary);pointer-events:none;font-size:.625rem}.trail-separator .m-icon{--m-icon-size: .625rem;display:flex;align-items:center;justify-content:center}@keyframes slide-in-trail{0%{opacity:0;transform:translate(-10px)}to{opacity:1;transform:translate(0)}}\n"] }]
34323
+ }], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }] } });
33745
34324
 
33746
34325
  class SearchPanelComponent {
33747
34326
  searchStore = inject(SearchStore);
@@ -33749,9 +34328,31 @@ class SearchPanelComponent {
33749
34328
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: SearchPanelComponent, isStandalone: true, selector: "m-search-panel", ngImport: i0, template: `
33750
34329
  <div class="search-panel">
33751
34330
  @if (!searchStore.hasQuery()) {
33752
- <div class="search-panel__empty">
33753
- {{ 'type-to-search' | translate }}
33754
- </div>
34331
+ @if (searchStore.recent().length) {
34332
+ <div class="search-panel__group">
34333
+ <span class="search-panel__source-label">{{
34334
+ 'recent-searches' | translate
34335
+ }}</span>
34336
+ <!-- mousedown kept from the input, so picking a recent query
34337
+ leaves the search bar open with that query in it. -->
34338
+ @for (query of searchStore.recent(); track query) {
34339
+ <a
34340
+ class="search-panel__result"
34341
+ role="button"
34342
+ tabindex="0"
34343
+ (mousedown)="$event.preventDefault()"
34344
+ (click)="searchStore.updateQuery(query)"
34345
+ (keydown.enter)="searchStore.updateQuery(query)"
34346
+ >
34347
+ <span class="search-panel__result-title">{{ query }}</span>
34348
+ </a>
34349
+ }
34350
+ </div>
34351
+ } @else {
34352
+ <div class="search-panel__empty">
34353
+ {{ 'type-to-search' | translate }}
34354
+ </div>
34355
+ }
33755
34356
  } @else if (!searchStore.hasResults()) {
33756
34357
  <div class="search-panel__empty">{{ 'no-results-found' | translate }}</div>
33757
34358
  } @else {
@@ -33761,7 +34362,11 @@ class SearchPanelComponent {
33761
34362
  group.label | translate
33762
34363
  }}</span>
33763
34364
  @for (result of group.items; track result.id) {
33764
- <a class="search-panel__result" [routerLink]="result.url ?? '/'">
34365
+ <a
34366
+ class="search-panel__result"
34367
+ [routerLink]="result.url ?? '/'"
34368
+ (click)="searchStore.rememberQuery()"
34369
+ >
33765
34370
  @if (result.img) {
33766
34371
  <div class="search-panel__result-img">
33767
34372
  <m-img [src]="result.img" [alt]="result.title" />
@@ -33790,9 +34395,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
33790
34395
  args: [{ selector: 'm-search-panel', changeDetection: ChangeDetectionStrategy.OnPush, imports: [RouterLink, ImgComponent, TranslatePipe], template: `
33791
34396
  <div class="search-panel">
33792
34397
  @if (!searchStore.hasQuery()) {
33793
- <div class="search-panel__empty">
33794
- {{ 'type-to-search' | translate }}
33795
- </div>
34398
+ @if (searchStore.recent().length) {
34399
+ <div class="search-panel__group">
34400
+ <span class="search-panel__source-label">{{
34401
+ 'recent-searches' | translate
34402
+ }}</span>
34403
+ <!-- mousedown kept from the input, so picking a recent query
34404
+ leaves the search bar open with that query in it. -->
34405
+ @for (query of searchStore.recent(); track query) {
34406
+ <a
34407
+ class="search-panel__result"
34408
+ role="button"
34409
+ tabindex="0"
34410
+ (mousedown)="$event.preventDefault()"
34411
+ (click)="searchStore.updateQuery(query)"
34412
+ (keydown.enter)="searchStore.updateQuery(query)"
34413
+ >
34414
+ <span class="search-panel__result-title">{{ query }}</span>
34415
+ </a>
34416
+ }
34417
+ </div>
34418
+ } @else {
34419
+ <div class="search-panel__empty">
34420
+ {{ 'type-to-search' | translate }}
34421
+ </div>
34422
+ }
33796
34423
  } @else if (!searchStore.hasResults()) {
33797
34424
  <div class="search-panel__empty">{{ 'no-results-found' | translate }}</div>
33798
34425
  } @else {
@@ -33802,7 +34429,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
33802
34429
  group.label | translate
33803
34430
  }}</span>
33804
34431
  @for (result of group.items; track result.id) {
33805
- <a class="search-panel__result" [routerLink]="result.url ?? '/'">
34432
+ <a
34433
+ class="search-panel__result"
34434
+ [routerLink]="result.url ?? '/'"
34435
+ (click)="searchStore.rememberQuery()"
34436
+ >
33806
34437
  @if (result.img) {
33807
34438
  <div class="search-panel__result-img">
33808
34439
  <m-img [src]="result.img" [alt]="result.title" />
@@ -33830,8 +34461,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
33830
34461
  class NavHeaderComponent {
33831
34462
  _navStore = inject(NavStore);
33832
34463
  _searchStore = inject(SearchStore);
33833
- _isUser = computed(() => this._navStore.id() === `${ROOT_NAV$1}_user`, ...(ngDevMode ? [{ debugName: "_isUser" }] : /* istanbul ignore next */ []));
33834
- _isSearch = computed(() => this._navStore.id() === `${ROOT_NAV$1}_search`, ...(ngDevMode ? [{ debugName: "_isSearch" }] : /* istanbul ignore next */ []));
34464
+ // Asked of the panel that answered, not of the Address: opened over any page
34465
+ // but root, the Address is anchored there (`<page>_search`), and it is the
34466
+ // root-anchored Platform panel behind it that is showing.
34467
+ _isUser = computed(() => this._navStore.panelNavId() === `${ROOT_NAV$1}_user`, ...(ngDevMode ? [{ debugName: "_isUser" }] : /* istanbul ignore next */ []));
34468
+ _isSearch = computed(() => this._navStore.panelNavId() === `${ROOT_NAV$1}_search`, ...(ngDevMode ? [{ debugName: "_isSearch" }] : /* istanbul ignore next */ []));
33835
34469
  _hasParent = computed(() => this._navStore.breadcrumb().header?.id !== ROOT_NAV$1, ...(ngDevMode ? [{ debugName: "_hasParent" }] : /* istanbul ignore next */ []));
33836
34470
  _trail = computed(() => {
33837
34471
  const trail = this._navStore.breadcrumb().trail;
@@ -34296,8 +34930,8 @@ class NavComponent {
34296
34930
  return {
34297
34931
  icon: showArrow
34298
34932
  ? isMobileOrTablet
34299
- ? 'arrow-down'
34300
- : 'arrow-left'
34933
+ ? 'chevron-down'
34934
+ : 'chevron-left'
34301
34935
  : 'menu',
34302
34936
  variant: 'ghost',
34303
34937
  iconOnly: true,
@@ -34603,13 +35237,19 @@ class NotificationElementComponent {
34603
35237
  // --- Handlers ---
34604
35238
  /** The whole row is the affordance: reading it marks it read, and one
34605
35239
  * carrying an `onClick` runs it — which is how a notification becomes the
34606
- * way to what it is about (`Notification.onClick`). */
35240
+ * way to what it is about (`Notification.onClick`). A highlight has done
35241
+ * its job once the User acts on the row it marked. */
34607
35242
  onActivate() {
34608
35243
  const notification = this.notification();
34609
35244
  if (!notification)
34610
35245
  return;
34611
35246
  if (!notification.read)
34612
35247
  this.markAsRead();
35248
+ if (notification.highlighted) {
35249
+ this.#notificationStore.updateNotification(notification.id, {
35250
+ highlighted: false,
35251
+ });
35252
+ }
34613
35253
  notification.onClick?.();
34614
35254
  }
34615
35255
  markAsRead() {
@@ -34656,6 +35296,7 @@ class NotificationElementComponent {
34656
35296
  class="notification-item"
34657
35297
  [class.notification-item--unread]="!notification()?.read"
34658
35298
  [class.notification-item--popup]="autoClose()"
35299
+ [class.notification-item--highlighted]="notification()?.highlighted"
34659
35300
  role="button"
34660
35301
  tabindex="0"
34661
35302
  (click)="onActivate()"
@@ -34716,9 +35357,10 @@ class NotificationElementComponent {
34716
35357
 
34717
35358
  @if (notification()?.type === NotificationType.PROGRESS) {
34718
35359
  <div class="notification-item__body">
34719
- <m-header [level]="4">
34720
- {{ notification()?.title | translate }}
34721
- </m-header>
35360
+ <!-- Through label, not projected: m-header projects default
35361
+ content into its last level's slot only, so a level-4 title
35362
+ drew blank. -->
35363
+ <m-header [level]="4" [label]="notification()?.title" />
34722
35364
  <div class="notification-item__progress-bar">
34723
35365
  <div
34724
35366
  class="notification-item__progress-fill"
@@ -34729,9 +35371,7 @@ class NotificationElementComponent {
34729
35371
  </div>
34730
35372
  } @else {
34731
35373
  <div class="notification-item__body">
34732
- <m-header [level]="4">
34733
- {{ notification()?.title | translate }}
34734
- </m-header>
35374
+ <m-header [level]="4" [label]="notification()?.title" />
34735
35375
  @if (notification()?.body?.text) {
34736
35376
  <p class="notification-item__description">
34737
35377
  {{ notification()?.body?.text | translate }}
@@ -34745,10 +35385,25 @@ class NotificationElementComponent {
34745
35385
  <m-button-group [name]="buttons" />
34746
35386
  </div>
34747
35387
  }
35388
+
35389
+ @if (notification()?.actions?.length) {
35390
+ <div class="notification-item__actions">
35391
+ @for (action of notification()?.actions; track $index) {
35392
+ <!-- Same stop as dismiss: an action is not a click on the row. -->
35393
+ <m-one-button
35394
+ variant="ghost"
35395
+ [label]="action.label"
35396
+ noTranslate="true"
35397
+ (click)="$event.stopPropagation()"
35398
+ (clicked)="action.run()"
35399
+ />
35400
+ }
35401
+ </div>
35402
+ }
34748
35403
  }
34749
35404
  </div>
34750
35405
  </div>
34751
- `, 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)}}.notification-item{position:relative;display:flex;gap:1rem;padding:1.25rem 1.5rem;transition:background .2s ease;cursor:pointer;border-bottom:1px solid #f0f0f0}.notification-item:last-child{border-bottom:none}.notification-item:hover{background:#00000005}.notification-item--unread .notification-item__user{font-weight:800;color:#1a1a1a}.notification-item--popup{background:#fff;border-radius:1rem;box-shadow:0 10px 30px #00000014,0 4px 12px #0000000a;border:1px solid rgba(0,0,0,.05);margin-bottom:.75rem;width:24rem;max-width:90vw;pointer-events:auto;padding:1rem 1.25rem;gap:.75rem}.notification-item--popup:has(.notification-item__status-icon.success){background:linear-gradient(135deg,#f8fff9,#fff)}.notification-item--popup:has(.notification-item__status-icon.error){background:linear-gradient(135deg,snow,#fff)}.notification-item--popup:has(.notification-item__status-icon.warning){background:linear-gradient(135deg,#fffcf5,#fff)}.notification-item--popup:has(.notification-item__status-icon.info){background:linear-gradient(135deg,#f5faff,#fff)}.notification-item--popup .notification-item__avatar{width:2.25rem;height:2.25rem}.notification-item--popup .notification-item__status-icon{width:1rem;height:1rem;font-size:.5rem}.notification-item--popup .notification-item__title{font-size:.8125rem}.notification-item--popup .notification-item__description{font-size:.75rem}.notification-item__avatar-container{position:relative;flex-shrink:0}.notification-item__avatar{width:2.75rem;height:2.75rem;border-radius:50%;overflow:hidden;background:#f0f0f0;display:flex;align-items:center;justify-content:center}.notification-item__avatar img{width:100%;height:100%;object-fit:cover}.notification-item__avatar-fallback{font-size:1rem;font-weight:700;color:#666}.notification-item__status-icon{position:absolute;bottom:-2px;right:-2px;width:1.25rem;height:1.25rem;border-radius:50%;background:#fff;display:flex;align-items:center;justify-content:center;font-size:.625rem;font-weight:800;color:#fff;box-shadow:0 2px 4px #0000001a;border:2px solid white}.notification-item__status-icon.success{background:#4caf50}.notification-item__status-icon.error{background:#f44336}.notification-item__status-icon.warning{background:#ff9800}.notification-item__status-icon.info{background:#2196f3}.notification-item__status-icon:not([class*=\" \"]){background:#9c27b0}.notification-item__content{flex:1;display:flex;flex-direction:column;gap:.125rem;min-width:0}.notification-item__header{display:flex;justify-content:space-between;align-items:center}.notification-item__meta{display:flex;align-items:center;gap:.5rem;font-size:.8125rem;color:#666}.notification-item__user{font-weight:700;color:#1a1a1a}.notification-item__time{color:#999;font-weight:500}.notification-item__dot{width:.5rem;height:.5rem;border-radius:50%;background:#4caf50;flex-shrink:0}.notification-item__body{display:flex;flex-direction:column;gap:.125rem}.notification-item__title{font-size:.875rem;font-weight:600;color:#1a1a1a;margin:0;line-height:1.4}.notification-item__description{font-size:.8125rem;line-height:1.5;color:#666;margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.notification-item__header-actions{display:flex;align-items:center;gap:1rem;margin-right:-.5rem}.notification-item__header-actions .m-button{--m-button-size: .75rem;--m-button-color: #999;opacity:.6}.notification-item__header-actions .m-button:hover{opacity:1}.notification-item__actions{display:flex;gap:.75rem;margin-top:.75rem}.notification-item--popup .notification-item__actions{margin-top:1rem;gap:1.5rem;--m-button-background: transparent;--m-button-padding: 0;--m-button-size: .875rem}.notification-item--popup .notification-item__actions .m-button{color:#3f51b5;font-weight:700}.notification-item--popup .notification-item__actions .m-button:hover{text-decoration:underline;opacity:.8}.notification-item--popup .notification-item__actions .m-button:last-child{color:#666}.notification-item__action{padding:.625rem 1.5rem;border-radius:.625rem;font-size:.8125rem;font-weight:700;border:none;cursor:pointer;transition:all .2s ease}.notification-item__action--reject{background:#f0f0f0;color:#1a1a1a}.notification-item__action--reject:hover{background:#e5e5e5}.notification-item__action--approve{background:#1a1a1a;color:#fff}.notification-item__action--approve:hover{background:#333}.notification-item__action{padding:.375rem .75rem;border-radius:.5rem;font-size:.75rem;font-weight:700;border:1px solid transparent;cursor:pointer;transition:all .2s ease}.notification-item__action--reject{background:var(--m-frame);color:var(--m-text-secondary)}.notification-item__action--reject:hover{background:var(--m-border)}.notification-item__action--approve{background:var(--m-mm);color:#fff}.notification-item__action--approve:hover{background:var(--m-mm-dark)}.notification-item__progress-bar{width:100%;height:6px;background:#00000014;border-radius:100px;overflow:hidden;position:relative;margin-top:.5rem}.notification-item__progress-fill{height:100%;border-radius:100px;background-image:linear-gradient(90deg,var(--saffron, var(--m-mm)) 0%,rgba(255,255,255,.6) 50%,var(--saffron, var(--m-mm)) 100%);background-size:200% 100%;animation:notification-shimmer 1.5s infinite linear;transition:width .3s ease-out}.notification-item__percentage{font-size:.75rem;color:#666;align-self:flex-end;font-weight:600;margin-top:.25rem}@keyframes notification-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}\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: ButtonGroupComponent, selector: "m-button-group, m-one-button-group", inputs: ["buttons", "names", "exclude", "vertical", "size"], outputs: ["clicked"] }, { kind: "component", type: HeaderComponent$1, selector: "m-header", inputs: ["level", "label", "icon", "actionButton", "actionLabel", "noTranslate", "params"], outputs: ["actionClick"] }, { kind: "component", type: ImgComponent, selector: "m-img", inputs: ["src", "data", "dataType", "alt", "priority", "fill", "width", "height", "remote", "ngSrcset", "sizes"] }, { kind: "pipe", type: TimeAgoPipe, name: "timeAgo" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
35406
+ `, 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)}}.notification-item{position:relative;display:flex;gap:1rem;padding:1.25rem 1.5rem;transition:background .2s ease;cursor:pointer;border-bottom:1px solid #f0f0f0}.notification-item:last-child{border-bottom:none}.notification-item:hover{background:#00000005}.notification-item--unread .notification-item__user{font-weight:800;color:#1a1a1a}.notification-item--highlighted{background:var(--m-warning-lite);box-shadow:inset 0 0 0 2px var(--m-warning)}.notification-item--highlighted:has(.notification-item__status-icon.error){background:var(--m-error-light);box-shadow:inset 0 0 0 2px var(--m-error)}.notification-item--highlighted:hover{background:var(--m-warning-lite)}.notification-item--highlighted:has(.notification-item__status-icon.error):hover{background:var(--m-error-light)}.notification-item--popup{background:#fff;border-radius:1rem;box-shadow:0 10px 30px #00000014,0 4px 12px #0000000a;border:1px solid rgba(0,0,0,.05);margin-bottom:.75rem;width:24rem;max-width:90vw;pointer-events:auto;padding:1rem 1.25rem;gap:.75rem}.notification-item--popup:has(.notification-item__status-icon.success){background:linear-gradient(135deg,#f8fff9,#fff)}.notification-item--popup:has(.notification-item__status-icon.error){background:linear-gradient(135deg,snow,#fff)}.notification-item--popup:has(.notification-item__status-icon.warning){background:linear-gradient(135deg,#fffcf5,#fff)}.notification-item--popup:has(.notification-item__status-icon.info){background:linear-gradient(135deg,#f5faff,#fff)}.notification-item--popup .notification-item__avatar{width:2.25rem;height:2.25rem}.notification-item--popup .notification-item__status-icon{width:1rem;height:1rem;font-size:.5rem}.notification-item--popup .notification-item__title{font-size:.8125rem}.notification-item--popup .notification-item__description{font-size:.75rem}.notification-item__avatar-container{position:relative;flex-shrink:0}.notification-item__avatar{width:2.75rem;height:2.75rem;border-radius:50%;overflow:hidden;background:#f0f0f0;display:flex;align-items:center;justify-content:center}.notification-item__avatar img{width:100%;height:100%;object-fit:cover}.notification-item__avatar-fallback{font-size:1rem;font-weight:700;color:#666}.notification-item__status-icon{position:absolute;bottom:-2px;right:-2px;width:1.25rem;height:1.25rem;border-radius:50%;background:#fff;display:flex;align-items:center;justify-content:center;font-size:.625rem;font-weight:800;color:#fff;box-shadow:0 2px 4px #0000001a;border:2px solid white}.notification-item__status-icon.success{background:#4caf50}.notification-item__status-icon.error{background:#f44336}.notification-item__status-icon.warning{background:#ff9800}.notification-item__status-icon.info{background:#2196f3}.notification-item__status-icon:not([class*=\" \"]){background:#9c27b0}.notification-item__content{flex:1;display:flex;flex-direction:column;gap:.125rem;min-width:0}.notification-item__header{display:flex;justify-content:space-between;align-items:center}.notification-item__meta{display:flex;align-items:center;gap:.5rem;font-size:.8125rem;color:#666}.notification-item__user{font-weight:700;color:#1a1a1a}.notification-item__time{color:#999;font-weight:500}.notification-item__dot{width:.5rem;height:.5rem;border-radius:50%;background:#4caf50;flex-shrink:0}.notification-item__body{display:flex;flex-direction:column;gap:.125rem}.notification-item__title{font-size:.875rem;font-weight:600;color:#1a1a1a;margin:0;line-height:1.4}.notification-item__description{font-size:.8125rem;line-height:1.5;color:#666;margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.notification-item__header-actions{display:flex;align-items:center;gap:1rem;margin-right:-.5rem}.notification-item__header-actions .m-button{--m-button-size: .75rem;--m-button-color: #999;opacity:.6}.notification-item__header-actions .m-button:hover{opacity:1}.notification-item__actions{display:flex;gap:.75rem;margin-top:.75rem}.notification-item--popup .notification-item__actions{margin-top:1rem;gap:1.5rem;--m-button-background: transparent;--m-button-padding: 0;--m-button-size: .875rem}.notification-item--popup .notification-item__actions .m-button{color:#3f51b5;font-weight:700}.notification-item--popup .notification-item__actions .m-button:hover{text-decoration:underline;opacity:.8}.notification-item--popup .notification-item__actions .m-button:last-child{color:#666}.notification-item__action{padding:.625rem 1.5rem;border-radius:.625rem;font-size:.8125rem;font-weight:700;border:none;cursor:pointer;transition:all .2s ease}.notification-item__action--reject{background:#f0f0f0;color:#1a1a1a}.notification-item__action--reject:hover{background:#e5e5e5}.notification-item__action--approve{background:#1a1a1a;color:#fff}.notification-item__action--approve:hover{background:#333}.notification-item__action{padding:.375rem .75rem;border-radius:.5rem;font-size:.75rem;font-weight:700;border:1px solid transparent;cursor:pointer;transition:all .2s ease}.notification-item__action--reject{background:var(--m-frame);color:var(--m-text-secondary)}.notification-item__action--reject:hover{background:var(--m-border)}.notification-item__action--approve{background:var(--m-mm);color:#fff}.notification-item__action--approve:hover{background:var(--m-mm-dark)}.notification-item__progress-bar{width:100%;height:6px;background:#00000014;border-radius:100px;overflow:hidden;position:relative;margin-top:.5rem}.notification-item__progress-fill{height:100%;border-radius:100px;background-image:linear-gradient(90deg,var(--saffron, var(--m-mm)) 0%,rgba(255,255,255,.6) 50%,var(--saffron, var(--m-mm)) 100%);background-size:200% 100%;animation:notification-shimmer 1.5s infinite linear;transition:width .3s ease-out}.notification-item__percentage{font-size:.75rem;color:#666;align-self:flex-end;font-weight:600;margin-top:.25rem}@keyframes notification-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}\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: ButtonGroupComponent, selector: "m-button-group, m-one-button-group", inputs: ["buttons", "names", "exclude", "vertical", "size"], outputs: ["clicked"] }, { kind: "component", type: HeaderComponent$1, selector: "m-header", inputs: ["level", "label", "icon", "actionButton", "actionLabel", "noTranslate", "params"], outputs: ["actionClick"] }, { kind: "component", type: ImgComponent, selector: "m-img", inputs: ["src", "data", "dataType", "alt", "priority", "fill", "width", "height", "remote", "ngSrcset", "sizes"] }, { kind: "pipe", type: TimeAgoPipe, name: "timeAgo" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
34752
35407
  }
34753
35408
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: NotificationElementComponent, decorators: [{
34754
35409
  type: Component,
@@ -34757,6 +35412,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
34757
35412
  class="notification-item"
34758
35413
  [class.notification-item--unread]="!notification()?.read"
34759
35414
  [class.notification-item--popup]="autoClose()"
35415
+ [class.notification-item--highlighted]="notification()?.highlighted"
34760
35416
  role="button"
34761
35417
  tabindex="0"
34762
35418
  (click)="onActivate()"
@@ -34817,9 +35473,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
34817
35473
 
34818
35474
  @if (notification()?.type === NotificationType.PROGRESS) {
34819
35475
  <div class="notification-item__body">
34820
- <m-header [level]="4">
34821
- {{ notification()?.title | translate }}
34822
- </m-header>
35476
+ <!-- Through label, not projected: m-header projects default
35477
+ content into its last level's slot only, so a level-4 title
35478
+ drew blank. -->
35479
+ <m-header [level]="4" [label]="notification()?.title" />
34823
35480
  <div class="notification-item__progress-bar">
34824
35481
  <div
34825
35482
  class="notification-item__progress-fill"
@@ -34830,9 +35487,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
34830
35487
  </div>
34831
35488
  } @else {
34832
35489
  <div class="notification-item__body">
34833
- <m-header [level]="4">
34834
- {{ notification()?.title | translate }}
34835
- </m-header>
35490
+ <m-header [level]="4" [label]="notification()?.title" />
34836
35491
  @if (notification()?.body?.text) {
34837
35492
  <p class="notification-item__description">
34838
35493
  {{ notification()?.body?.text | translate }}
@@ -34846,10 +35501,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
34846
35501
  <m-button-group [name]="buttons" />
34847
35502
  </div>
34848
35503
  }
35504
+
35505
+ @if (notification()?.actions?.length) {
35506
+ <div class="notification-item__actions">
35507
+ @for (action of notification()?.actions; track $index) {
35508
+ <!-- Same stop as dismiss: an action is not a click on the row. -->
35509
+ <m-one-button
35510
+ variant="ghost"
35511
+ [label]="action.label"
35512
+ noTranslate="true"
35513
+ (click)="$event.stopPropagation()"
35514
+ (clicked)="action.run()"
35515
+ />
35516
+ }
35517
+ </div>
35518
+ }
34849
35519
  }
34850
35520
  </div>
34851
35521
  </div>
34852
- `, 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)}}.notification-item{position:relative;display:flex;gap:1rem;padding:1.25rem 1.5rem;transition:background .2s ease;cursor:pointer;border-bottom:1px solid #f0f0f0}.notification-item:last-child{border-bottom:none}.notification-item:hover{background:#00000005}.notification-item--unread .notification-item__user{font-weight:800;color:#1a1a1a}.notification-item--popup{background:#fff;border-radius:1rem;box-shadow:0 10px 30px #00000014,0 4px 12px #0000000a;border:1px solid rgba(0,0,0,.05);margin-bottom:.75rem;width:24rem;max-width:90vw;pointer-events:auto;padding:1rem 1.25rem;gap:.75rem}.notification-item--popup:has(.notification-item__status-icon.success){background:linear-gradient(135deg,#f8fff9,#fff)}.notification-item--popup:has(.notification-item__status-icon.error){background:linear-gradient(135deg,snow,#fff)}.notification-item--popup:has(.notification-item__status-icon.warning){background:linear-gradient(135deg,#fffcf5,#fff)}.notification-item--popup:has(.notification-item__status-icon.info){background:linear-gradient(135deg,#f5faff,#fff)}.notification-item--popup .notification-item__avatar{width:2.25rem;height:2.25rem}.notification-item--popup .notification-item__status-icon{width:1rem;height:1rem;font-size:.5rem}.notification-item--popup .notification-item__title{font-size:.8125rem}.notification-item--popup .notification-item__description{font-size:.75rem}.notification-item__avatar-container{position:relative;flex-shrink:0}.notification-item__avatar{width:2.75rem;height:2.75rem;border-radius:50%;overflow:hidden;background:#f0f0f0;display:flex;align-items:center;justify-content:center}.notification-item__avatar img{width:100%;height:100%;object-fit:cover}.notification-item__avatar-fallback{font-size:1rem;font-weight:700;color:#666}.notification-item__status-icon{position:absolute;bottom:-2px;right:-2px;width:1.25rem;height:1.25rem;border-radius:50%;background:#fff;display:flex;align-items:center;justify-content:center;font-size:.625rem;font-weight:800;color:#fff;box-shadow:0 2px 4px #0000001a;border:2px solid white}.notification-item__status-icon.success{background:#4caf50}.notification-item__status-icon.error{background:#f44336}.notification-item__status-icon.warning{background:#ff9800}.notification-item__status-icon.info{background:#2196f3}.notification-item__status-icon:not([class*=\" \"]){background:#9c27b0}.notification-item__content{flex:1;display:flex;flex-direction:column;gap:.125rem;min-width:0}.notification-item__header{display:flex;justify-content:space-between;align-items:center}.notification-item__meta{display:flex;align-items:center;gap:.5rem;font-size:.8125rem;color:#666}.notification-item__user{font-weight:700;color:#1a1a1a}.notification-item__time{color:#999;font-weight:500}.notification-item__dot{width:.5rem;height:.5rem;border-radius:50%;background:#4caf50;flex-shrink:0}.notification-item__body{display:flex;flex-direction:column;gap:.125rem}.notification-item__title{font-size:.875rem;font-weight:600;color:#1a1a1a;margin:0;line-height:1.4}.notification-item__description{font-size:.8125rem;line-height:1.5;color:#666;margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.notification-item__header-actions{display:flex;align-items:center;gap:1rem;margin-right:-.5rem}.notification-item__header-actions .m-button{--m-button-size: .75rem;--m-button-color: #999;opacity:.6}.notification-item__header-actions .m-button:hover{opacity:1}.notification-item__actions{display:flex;gap:.75rem;margin-top:.75rem}.notification-item--popup .notification-item__actions{margin-top:1rem;gap:1.5rem;--m-button-background: transparent;--m-button-padding: 0;--m-button-size: .875rem}.notification-item--popup .notification-item__actions .m-button{color:#3f51b5;font-weight:700}.notification-item--popup .notification-item__actions .m-button:hover{text-decoration:underline;opacity:.8}.notification-item--popup .notification-item__actions .m-button:last-child{color:#666}.notification-item__action{padding:.625rem 1.5rem;border-radius:.625rem;font-size:.8125rem;font-weight:700;border:none;cursor:pointer;transition:all .2s ease}.notification-item__action--reject{background:#f0f0f0;color:#1a1a1a}.notification-item__action--reject:hover{background:#e5e5e5}.notification-item__action--approve{background:#1a1a1a;color:#fff}.notification-item__action--approve:hover{background:#333}.notification-item__action{padding:.375rem .75rem;border-radius:.5rem;font-size:.75rem;font-weight:700;border:1px solid transparent;cursor:pointer;transition:all .2s ease}.notification-item__action--reject{background:var(--m-frame);color:var(--m-text-secondary)}.notification-item__action--reject:hover{background:var(--m-border)}.notification-item__action--approve{background:var(--m-mm);color:#fff}.notification-item__action--approve:hover{background:var(--m-mm-dark)}.notification-item__progress-bar{width:100%;height:6px;background:#00000014;border-radius:100px;overflow:hidden;position:relative;margin-top:.5rem}.notification-item__progress-fill{height:100%;border-radius:100px;background-image:linear-gradient(90deg,var(--saffron, var(--m-mm)) 0%,rgba(255,255,255,.6) 50%,var(--saffron, var(--m-mm)) 100%);background-size:200% 100%;animation:notification-shimmer 1.5s infinite linear;transition:width .3s ease-out}.notification-item__percentage{font-size:.75rem;color:#666;align-self:flex-end;font-weight:600;margin-top:.25rem}@keyframes notification-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}\n"] }]
35522
+ `, 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)}}.notification-item{position:relative;display:flex;gap:1rem;padding:1.25rem 1.5rem;transition:background .2s ease;cursor:pointer;border-bottom:1px solid #f0f0f0}.notification-item:last-child{border-bottom:none}.notification-item:hover{background:#00000005}.notification-item--unread .notification-item__user{font-weight:800;color:#1a1a1a}.notification-item--highlighted{background:var(--m-warning-lite);box-shadow:inset 0 0 0 2px var(--m-warning)}.notification-item--highlighted:has(.notification-item__status-icon.error){background:var(--m-error-light);box-shadow:inset 0 0 0 2px var(--m-error)}.notification-item--highlighted:hover{background:var(--m-warning-lite)}.notification-item--highlighted:has(.notification-item__status-icon.error):hover{background:var(--m-error-light)}.notification-item--popup{background:#fff;border-radius:1rem;box-shadow:0 10px 30px #00000014,0 4px 12px #0000000a;border:1px solid rgba(0,0,0,.05);margin-bottom:.75rem;width:24rem;max-width:90vw;pointer-events:auto;padding:1rem 1.25rem;gap:.75rem}.notification-item--popup:has(.notification-item__status-icon.success){background:linear-gradient(135deg,#f8fff9,#fff)}.notification-item--popup:has(.notification-item__status-icon.error){background:linear-gradient(135deg,snow,#fff)}.notification-item--popup:has(.notification-item__status-icon.warning){background:linear-gradient(135deg,#fffcf5,#fff)}.notification-item--popup:has(.notification-item__status-icon.info){background:linear-gradient(135deg,#f5faff,#fff)}.notification-item--popup .notification-item__avatar{width:2.25rem;height:2.25rem}.notification-item--popup .notification-item__status-icon{width:1rem;height:1rem;font-size:.5rem}.notification-item--popup .notification-item__title{font-size:.8125rem}.notification-item--popup .notification-item__description{font-size:.75rem}.notification-item__avatar-container{position:relative;flex-shrink:0}.notification-item__avatar{width:2.75rem;height:2.75rem;border-radius:50%;overflow:hidden;background:#f0f0f0;display:flex;align-items:center;justify-content:center}.notification-item__avatar img{width:100%;height:100%;object-fit:cover}.notification-item__avatar-fallback{font-size:1rem;font-weight:700;color:#666}.notification-item__status-icon{position:absolute;bottom:-2px;right:-2px;width:1.25rem;height:1.25rem;border-radius:50%;background:#fff;display:flex;align-items:center;justify-content:center;font-size:.625rem;font-weight:800;color:#fff;box-shadow:0 2px 4px #0000001a;border:2px solid white}.notification-item__status-icon.success{background:#4caf50}.notification-item__status-icon.error{background:#f44336}.notification-item__status-icon.warning{background:#ff9800}.notification-item__status-icon.info{background:#2196f3}.notification-item__status-icon:not([class*=\" \"]){background:#9c27b0}.notification-item__content{flex:1;display:flex;flex-direction:column;gap:.125rem;min-width:0}.notification-item__header{display:flex;justify-content:space-between;align-items:center}.notification-item__meta{display:flex;align-items:center;gap:.5rem;font-size:.8125rem;color:#666}.notification-item__user{font-weight:700;color:#1a1a1a}.notification-item__time{color:#999;font-weight:500}.notification-item__dot{width:.5rem;height:.5rem;border-radius:50%;background:#4caf50;flex-shrink:0}.notification-item__body{display:flex;flex-direction:column;gap:.125rem}.notification-item__title{font-size:.875rem;font-weight:600;color:#1a1a1a;margin:0;line-height:1.4}.notification-item__description{font-size:.8125rem;line-height:1.5;color:#666;margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.notification-item__header-actions{display:flex;align-items:center;gap:1rem;margin-right:-.5rem}.notification-item__header-actions .m-button{--m-button-size: .75rem;--m-button-color: #999;opacity:.6}.notification-item__header-actions .m-button:hover{opacity:1}.notification-item__actions{display:flex;gap:.75rem;margin-top:.75rem}.notification-item--popup .notification-item__actions{margin-top:1rem;gap:1.5rem;--m-button-background: transparent;--m-button-padding: 0;--m-button-size: .875rem}.notification-item--popup .notification-item__actions .m-button{color:#3f51b5;font-weight:700}.notification-item--popup .notification-item__actions .m-button:hover{text-decoration:underline;opacity:.8}.notification-item--popup .notification-item__actions .m-button:last-child{color:#666}.notification-item__action{padding:.625rem 1.5rem;border-radius:.625rem;font-size:.8125rem;font-weight:700;border:none;cursor:pointer;transition:all .2s ease}.notification-item__action--reject{background:#f0f0f0;color:#1a1a1a}.notification-item__action--reject:hover{background:#e5e5e5}.notification-item__action--approve{background:#1a1a1a;color:#fff}.notification-item__action--approve:hover{background:#333}.notification-item__action{padding:.375rem .75rem;border-radius:.5rem;font-size:.75rem;font-weight:700;border:1px solid transparent;cursor:pointer;transition:all .2s ease}.notification-item__action--reject{background:var(--m-frame);color:var(--m-text-secondary)}.notification-item__action--reject:hover{background:var(--m-border)}.notification-item__action--approve{background:var(--m-mm);color:#fff}.notification-item__action--approve:hover{background:var(--m-mm-dark)}.notification-item__progress-bar{width:100%;height:6px;background:#00000014;border-radius:100px;overflow:hidden;position:relative;margin-top:.5rem}.notification-item__progress-fill{height:100%;border-radius:100px;background-image:linear-gradient(90deg,var(--saffron, var(--m-mm)) 0%,rgba(255,255,255,.6) 50%,var(--saffron, var(--m-mm)) 100%);background-size:200% 100%;animation:notification-shimmer 1.5s infinite linear;transition:width .3s ease-out}.notification-item__percentage{font-size:.75rem;color:#666;align-self:flex-end;font-weight:600;margin-top:.25rem}@keyframes notification-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}\n"] }]
34853
35523
  }], propDecorators: { notification: [{ type: i0.Input, args: [{ isSignal: true, alias: "notification", required: false }] }], autoClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoClose", required: false }] }], actionClicked: [{ type: i0.Output, args: ["actionClicked"] }] } });
34854
35524
 
34855
35525
  class NotificationPopupComponent {
@@ -35690,10 +36360,13 @@ class NotificationWidgetComponent {
35690
36360
  displayNotifications = computed(() => {
35691
36361
  const tab = this.activeTab();
35692
36362
  const all = this.#notificationStore.allNotifications();
35693
- if (tab === 'unread') {
35694
- return all.filter((n) => !n.read);
35695
- }
35696
- return all;
36363
+ const shown = tab === 'unread' ? all.filter((n) => !n.read) : all;
36364
+ // Highlighted rows are why the tray was just opened — first, whatever
36365
+ // their age, each group keeping the store's order.
36366
+ return [
36367
+ ...shown.filter((n) => n.highlighted),
36368
+ ...shown.filter((n) => !n.highlighted),
36369
+ ];
35697
36370
  }, ...(ngDevMode ? [{ debugName: "displayNotifications" }] : /* istanbul ignore next */ []));
35698
36371
  unreadCount = computed(() => this.#notificationStore.unreadCount(), ...(ngDevMode ? [{ debugName: "unreadCount" }] : /* istanbul ignore next */ []));
35699
36372
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: NotificationWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -36820,22 +37493,17 @@ const providePlatformNavWidgets = () => provideNavWidgets(platformNavWidgets());
36820
37493
  function provideAppContext() {
36821
37494
  const navStore = inject(NavStore);
36822
37495
  const authStore = inject(AuthStore);
36823
- const httpService = inject(HttpService);
37496
+ const agreementGate = inject(AgreementGate);
36824
37497
  const relationType = signal(null, ...(ngDevMode ? [{ debugName: "relationType" }] : /* istanbul ignore next */ []));
36825
37498
  effect(() => {
36826
37499
  const appLink = navStore.appLink();
36827
37500
  const isLoggedIn = authStore.isLoggedIn();
37501
+ agreementGate.revision();
36828
37502
  if (appLink && isLoggedIn) {
36829
- httpService
36830
- .get('store', ['app', appLink, 'relation'])
36831
- .subscribe({
36832
- next: (response) => {
36833
- relationType.set(response.type);
36834
- },
36835
- error: () => {
36836
- relationType.set(null);
36837
- },
36838
- });
37503
+ // The same read the init Agreement step made, so it is fetched once.
37504
+ // A reply for an app the host has since left is dropped.
37505
+ const current = () => untracked(navStore.appLink) === appLink;
37506
+ agreementGate.view(appLink).then((view) => current() && relationType.set(view.type), () => current() && relationType.set(null));
36839
37507
  }
36840
37508
  else {
36841
37509
  relationType.set(null);
@@ -36869,6 +37537,12 @@ function provideMagWcConfig(options) {
36869
37537
  },
36870
37538
  },
36871
37539
  provideZonelessChangeDetection(),
37540
+ {
37541
+ // The `/app/<link>` a host mounts it under, until m-remote hands the
37542
+ // `appLink` input down (BaseRootWebComponent) — init reads it first.
37543
+ provide: APP_LINK,
37544
+ useFactory: () => signal(window.location.pathname.match(/^\/app\/([^/]+)/)?.[1]),
37545
+ },
36872
37546
  // `always` rather than the default `emptyOnly`: a child route rendered in
36873
37547
  // a parent Page's RouterOutlet declares its own component, so without it
36874
37548
  // Angular hands the child none of the parent's `:params` and
@@ -37046,6 +37720,7 @@ function provideMagAppConfig(options) {
37046
37720
  provideMurlUrlSerializer(),
37047
37721
  provideZonelessChangeDetection(),
37048
37722
  provideAnimations(),
37723
+ { provide: APP_LINK, useValue: signal(options.appLink) },
37049
37724
  provideHttpClient(withFetch(), withInterceptors([mInterceptor])),
37050
37725
  provideAppInitializer(initMagmoniumApp({
37051
37726
  backend: options.backend,
@@ -37144,6 +37819,7 @@ function bootstrapMagApp(routesOrOptions, maybeOptions) {
37144
37819
  backend: options.backend,
37145
37820
  authUrl: options.authUrl,
37146
37821
  socketUrl: options.socketUrl,
37822
+ appLink: options.appLink,
37147
37823
  routes: finalRoutes,
37148
37824
  providers: options.providers,
37149
37825
  });
@@ -37170,6 +37846,13 @@ function bootstrapMagApp(routesOrOptions, maybeOptions) {
37170
37846
  if (wcConfig?.app) {
37171
37847
  navStore.setWcConfig(wcConfig.app, wcConfig);
37172
37848
  navStore.setAppLink(wcConfig.app);
37849
+ // A bootstrap naming no appLink learns it only now, after init
37850
+ // — so Agreement is asked here instead (store ADR 0006).
37851
+ const appLink = appRef.injector.get(APP_LINK);
37852
+ if (!appLink()) {
37853
+ appLink.set(wcConfig.app);
37854
+ appRef.injector.get(AgreementGate).ensure(wcConfig.app);
37855
+ }
37173
37856
  }
37174
37857
  else if (options.appLink) {
37175
37858
  navStore.setAppLink(options.appLink);
@@ -39655,5 +40338,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
39655
40338
  * Generated bundle index. Do not edit.
39656
40339
  */
39657
40340
 
39658
- export { ClipboardService as $, ACCESS_DOMAINS as A, ButtonComponent as B, Assets as C, AuthActivityPageComponent as D, AuthApiService as E, AuthStore as F, AutosizeDirective as G, HeaderComponent$1 as H, InputType as I, BadgeComponent as J, BandingComponent as K, LabelComponent as L, MODAL_REF as M, BaseArrayInputComponent as N, BaseRootWebComponent as O, BaseWebComponent as P, ButtonGroupComponent as Q, RangeInputComponent as R, COMPONENT_INPUT_REGISTRY as S, TranslatePipe as T, CardComponent as U, CardWrapperComponent as V, CarouselComponent as W, ChartComponent as X, ChatBubbleComponent as Y, CheckboxInputComponent as Z, ClearableInputComponent as _, MIN_ZOOM as a, ImgComponent as a$, ColComponent as a0, ColorPickerInputComponent as a1, CommentItemComponent as a2, CommentsApiService as a3, CommentsComponent as a4, CommentsStore as a5, CompactNumberPipe as a6, ComponentInputComponent as a7, ComponentStepperComponent as a8, ConfigComponent as a9, Domain as aA, DotGridComponent as aB, DragListDirective as aC, DragListItemDirective as aD, DraggableDirective as aE, DropdownInputComponent as aF, FILTER_GROUP_CONTEXT as aG, FILTER_RANGE_MODES as aH, FILTER_VARIANTS as aI, FLEX_VARIANTS as aJ, FOLDER_PICK_LISTENER as aK, FORM_ASSET_FOLDER as aL, FileService as aM, FileUploadDirective as aN, FileUploadInputComponent as aO, FlexComponent as aP, FlexItemComponent as aQ, FormGroupComponent as aR, FrameComponent as aS, FreezeService as aT, GRID_BREAKPOINTS as aU, GetNavService as aV, HighlightDirective as aW, HttpService as aX, ICON_SOURCE as aY, IS_SIDE_PANEL as aZ, IconComponent as a_, ConfirmComponent as aa, ContextMenuComponent as ab, CustomIconClass as ac, CustomIconEditComponent as ad, DEFAULT_DENIAL as ae, DEFAULT_DOC_DENSITY as af, DEFAULT_DOC_VARIANT as ag, DEFAULT_FILTER_RANGE_MODE as ah, DEFAULT_FILTER_VARIANT as ai, DEFAULT_NAV_PARAM as aj, DEFAULT_NAV_SEGMENT as ak, DEFAULT_SIZE as al, DOCK_MIN_PAGE_REMAINDER as am, DOCS_FOLDER as an, DOC_ACTION_ICONS as ao, DOC_DENSITIES as ap, DOC_EDIT_ACTIONS as aq, DOC_TOOLBAR_GROUPS as ar, DOC_VARIANTS as as, DashboardCardComponent as at, DateInputComponent as au, DatePickerComponent as av, DeviceService as aw, DocComponent as ax, DocEditorComponent as ay, DomService as az, MAX_ZOOM as b, PercentagePipe as b$, InstrumentScoreComponent as b0, InterceptorObservables as b1, JumbotronComponent as b2, KeyValueComponent as b3, LAYOUT_ASSET_FOLDER as b4, LOGIN_COMPONENT as b5, LOGIN_STORE as b6, LanguageComponent as b7, ListComponent as b8, LogoComponent as b9, NavDetailsComponent as bA, NavHeaderComponent as bB, NavMenuComponent as bC, NavStore as bD, NavTrailComponent as bE, NothingComponent as bF, NotificationElementComponent as bG, NotificationGroupComponent as bH, NotificationPopupComponent as bI, NotificationService as bJ, NotificationStore as bK, NotificationType as bL, NotificationWidgetComponent as bM, ONE_ASSET_BASE_URL as bN, OPTIONS_SOURCE as bO, OVERLAY_WIDGETS as bP, OneApp as bQ, OptionsSourceDirective as bR, OverlayBodyComponent as bS, OverlayRef as bT, OverlayService as bU, PLATFORM_BUTTON_NAV_IDS as bV, PLATFORM_EXTENSIBLE_NAV_IDS as bW, PLATFORM_NAV_MAP as bX, PLATFORM_ROOT_CHILDREN as bY, PaginationComponent as bZ, PanelComponent as b_, MAG_SOCKET_EVENT as ba, MHeroColorDirective as bb, MHeroComponent as bc, MODAL_STORE_REF as bd, MOUNT_STATIC_SEGMENT as be, MOUNT_TOKEN as bf, MRefDirective as bg, MStepComponent as bh, MURL_PARAM as bi, MURL_SEP as bj, ManifestEnrichmentService as bk, MenuComponent as bl, ModalDirective as bm, ModalRef as bn, ModalStore as bo, MoneyPipe as bp, MultiRangeInputComponent as bq, MurlUrlSerializer as br, NAV_DEFAULT_MURL as bs, NAV_ID_SEP as bt, NAV_MAIN_BUTTONS as bu, NAV_SEGMENT_RE as bv, NAV_STORE_REF as bw, NAV_WC_COMPONENTS as bx, NAV_WIDGET_MAP as by, NavComponent as bz, cropRect as c, SocketStore as c$, PlaygroundComponent as c0, PositionDirective as c1, PwaInstallComponent as c2, REMOTE_PAGE_RELOAD as c3, ROOT_NAV$1 as c4, RadioGroupComponent as c5, RadioInputComponent as c6, RatingInputComponent as c7, ReactiveElementComponent as c8, RemoteComponent as c9, SectionFilterGroupComponent as cA, SectionFilterMenuComponent as cB, SectionFilterPanelComponent as cC, SectionFilterRangePanelComponent as cD, SectionFooterComponent as cE, SectionFormComponent as cF, SectionFormItemComponent as cG, SectionHeaderComponent as cH, SectionHeroComponent as cI, SectionPaginationComponent as cJ, SectionSearchComponent as cK, SectionStepperComponent as cL, SectionTableCellComponent as cM, SectionTableComponent as cN, SectionTableRowComponent as cO, SectionTableSortPipe as cP, SectionTabsComponent as cQ, SectionToggleComponent as cR, SectionToggleItemDirective as cS, SelectableCardInputComponent as cT, SelectorDirective as cU, SettingsSearchBarComponent as cV, SettingsSearchService as cW, ShapeComponent as cX, SharedStoreRegistry as cY, SidePanelDirective as cZ, Size as c_, RemoteLoaderService as ca, ResizeElementComponent as cb, RouteContainer as cc, RowComponent as cd, SEARCH_QUERY as ce, SEARCH_RESULTS_EVENT as cf, SECTION_ACCORDION_GROUP as cg, SECTION_FORM_CONTEXT as ch, SECTION_TABLE_VARIANTS as ci, SHARED_ICONS as cj, SIZE_CONTEXT as ck, ScoreComponent as cl, ScrollComponent as cm, ScrollService as cn, SearchPanelComponent as co, SearchStore as cp, SearchUserPanelComponent as cq, SectionAccordionDirective as cr, SectionAccordionGroupDirective as cs, SectionBackComponent as ct, SectionBadgesComponent as cu, SectionButtonGroupComponent as cv, SectionCardComponent as cw, SectionCarouselComponent as cx, SectionComponent as cy, SectionFilterComponent as cz, drawFramed as d, childNavId as d$, SortComponent as d0, StatComponent as d1, StepComponent as d2, StepperComponent as d3, StepsComponent as d4, StorageService as d5, StrokeLinecap as d6, StrokeLinejoin as d7, SummaryComponent as d8, SvgGeneratorComponent as d9, UserApiService as dA, UserAvatarComponent as dB, UserComponent as dC, UserNavComponent as dD, UserSettingsComponent as dE, UserStore as dF, WC_BUNDLE as dG, WC_NAVIGATE_EVENT as dH, WC_ROUTE_CHANGED_EVENT as dI, WC_SEARCH_GROUPS as dJ, WIN_USER_TAB_HOOK as dK, WIN_USER_TAB_KEY as dL, WatermarkComponent as dM, WcRouterStore as dN, WrapperInputComponent as dO, anchorNavId as dP, applyColorsToElement as dQ, applyDocEdit as dR, assetOptions as dS, bootstrapMagApp as dT, bootstrapPwaInstall as dU, buildWcBaseUrl as dV, calculateLuminance as dW, calculateRanks as dX, cellText as dY, checkDoc as dZ, checkFilterCondition as d_, SvgGeneratorService as da, SvgService as db, TOTAL_COLUMNS as dc, TRANSLATION_SOURCE as dd, TableComponent as de, TechnicalMeterComponent as df, TextInputComponent as dg, TextareaInputComponent as dh, ThemeComponent as di, ThemeDataService as dj, ThemeService as dk, ThemeStore as dl, TimeAgoPipe as dm, TimelineComponent as dn, ToggleButtonComponent as dp, ToggleInputComponent as dq, ToggleRadioInputComponent as dr, ToolTipDirective as ds, TooltipComponent as dt, TranslateService as du, TreeGridComponent as dv, URL_SEP as dw, USER_STORE_REF as dx, USER_TAB_MAP as dy, UniverseComponent as dz, encodeFramed as e, isExtensiblePlatformNavId as e$, claimDenial as e0, classListSignal as e1, coerceSize as e2, cornerEdge as e3, cornerSide as e4, createMap as e5, createPlatformNavMap as e6, definedWcTierOf as e7, deriveAvatarGradient as e8, deriveContrastColor as e9, flattenTreeGridRows as eA, formatBadgeCount as eB, fullName as eC, generateClipPath as eD, generateTransform as eE, getClassList as eF, getProperty as eG, getScrollParent as eH, getTierFromPreviewPath as eI, getTreeGridRow as eJ, getUniqueId as eK, getValue as eL, hasErrorComputed as eM, hexToRgb as eN, hslToRgb$1 as eO, initMagmoniumApp as eP, initialNotificationState as eQ, initialState$2 as eR, initials as eS, injectAuthenticate as eT, injectDefaultDenial as eU, injectInstallApp as eV, injectParentSize as eW, injectScrollSticky as eX, isBootRedirect as eY, isButtonName as eZ, isCancelledComputed as e_, deriveOppositeColor as ea, derivePropertyName as eb, docActionKey as ec, docAssetCandidates as ed, docProblemKey as ee, docRemotePath as ef, emailValidation as eg, evaluate as eh, evaluateBool as ei, fieldBoolean as ej, fieldNumber as ek, fieldString as el, filterHoldsList as em, filterHoldsOneBound as en, filterHoldsOptions as eo, filterHoldsRange as ep, filterList as eq, filterNumber as er, filterNumberList as es, filterOne as et, filterPanelOf as eu, filterPanelWidth as ev, filterRange as ew, filterTreeGridRows as ex, filterValueList as ey, filterValues as ez, clampFraming as f, provideModalComponents as f$, isJson as f0, isLoadingComputed as f1, isLocalhost as f2, isNavInstanceConfig as f3, isNavMenuConfig as f4, isNavRowsConfig as f5, isNavVisibilityConfig as f6, isPlatformNavId as f7, isSize as f8, isTierPreview as f9, navIdChain as fA, navIdFor as fB, navIdSegment as fC, navIdToRoutePath as fD, navIdToSegments as fE, navParamOf as fF, navTailMatcher as fG, navToId as fH, navVisibilityGuard as fI, nextSectionTableSort as fJ, normalizeAssetOptions as fK, offsetOfLine as fL, parentNavId as fM, parseAddress as fN, parseColor as fO, parseMountPattern as fP, parsePatternNames as fQ, patternValidation as fR, patternsValidation as fS, permissionRefusal as fT, platformNavWidgets as fU, privateGuard as fV, processImageToSvg as fW, provideAppContext as fX, provideMagAppConfig as fY, provideMagWcConfig as fZ, provideMagWcRoutes as f_, isUrlLocalhost as fa, isValidNavId as fb, isValidNavSegment as fc, isWebComponent as fd, linkToId as fe, linkToNav as ff, loadingActions as fg, mInterceptor as fh, manualValidation as fi, matchFieldValidation as fj, matchMount as fk, maxLengthValidation as fl, maxValidation as fm, mergePlatformNav as fn, mergeUnique as fo, mergeUniqueBy as fp, mergeUniqueWith as fq, minAgeValidation as fr, minLengthValidation as fs, minValidation as ft, miniMarkToHtml as fu, mountFor as fv, mountPatternProblem as fw, mountPatternText as fx, mountSegmentOf as fy, mountTokenOf as fz, BaseInputComponent as g, provideMurlUrlSerializer as g0, provideNavWidgets as g1, provideOverlayWidgets as g2, providePlatformNavWidgets as g3, provideSearch as g4, provideSizeContext as g5, provideUserTabs as g6, publicGuard as g7, readFieldPatterns as g8, recordDefinedWcTier as g9, toAttrBool as gA, toAttrNumber as gB, toCssLength as gC, toHostNavId as gD, toLength$1 as gE, toLocalNavId as gF, toggleTreeGridRow as gG, unfetchedPlatformNav as gH, ungroupedDocActions as gI, urlValidation as gJ, wcTierOf as gK, remoteOutletRoute as ga, renderAddress as gb, renderDocument as gc, requiredValidation as gd, resolveConfigAsset as ge, resolveIconSize as gf, resolvePallet as gg, resolvePatternRules as gh, resolveSize as gi, rgbToHex as gj, rgbToHsl as gk, rowHasChildren as gl, samePatterns as gm, sectionTableColumnId as gn, sectionTableColumnWidths as go, sectionTableFrozenCount as gp, segmentsToNavId as gq, setProperty as gr, setTreeGridChildren as gs, setWcTier as gt, settingsWidgets as gu, shouldShowBadge as gv, sortSectionTableRows as gw, splitNavId as gx, splitOnMatch as gy, stringToColor as gz, BaseTextInputComponent as h, initialFraming as i, TextOutputComponent as j, IS_DESIGN_MODE as k, APP_CONTEXT_REF as l, ASSET_BASE_URL as m, AccordionBodyDirective as n, outputSize as o, parseRatio as p, AccordionComponent as q, renameForType as r, AccordionGroupComponent as s, ActionComponent as t, AnimatedGraphsComponent as u, AppCardComponent as v, AppRelationType as w, AppTileComponent as x, AssetStore as y, AssetUrlPipe as z };
39659
- //# sourceMappingURL=magmonium-one-magmonium-one-Dr2fBHOB.mjs.map
40341
+ export { CheckboxInputComponent as $, ACCESS_DOMAINS as A, ButtonComponent as B, AssetUrlPipe as C, Assets as D, AuthActivityPageComponent as E, AuthApiService as F, AuthStore as G, HeaderComponent$1 as H, InputType as I, AutosizeDirective as J, BadgeComponent as K, LabelComponent as L, MODAL_REF as M, BandingComponent as N, BaseArrayInputComponent as O, BaseRootWebComponent as P, BaseWebComponent as Q, RangeInputComponent as R, ButtonGroupComponent as S, TranslatePipe as T, CALLING_APP_HEADER as U, COMPONENT_INPUT_REGISTRY as V, CardComponent as W, CardWrapperComponent as X, CarouselComponent as Y, ChartComponent as Z, ChatBubbleComponent as _, MIN_ZOOM as a, IS_SIDE_PANEL as a$, ClearableInputComponent as a0, ClipboardService as a1, ColComponent as a2, ColorPickerInputComponent as a3, CommentItemComponent as a4, CommentsApiService as a5, CommentsComponent as a6, CommentsStore as a7, CompactNumberPipe as a8, ComponentInputComponent as a9, DocEditorComponent as aA, DomService as aB, Domain as aC, DotGridComponent as aD, DragListDirective as aE, DragListItemDirective as aF, DraggableDirective as aG, DropdownInputComponent as aH, FILTER_GROUP_CONTEXT as aI, FILTER_RANGE_MODES as aJ, FILTER_VARIANTS as aK, FLEX_VARIANTS as aL, FOLDER_PICK_LISTENER as aM, FORM_ASSET_FOLDER as aN, FileService as aO, FileUploadDirective as aP, FileUploadInputComponent as aQ, FlexComponent as aR, FlexItemComponent as aS, FormGroupComponent as aT, FrameComponent as aU, FreezeService as aV, GRID_BREAKPOINTS as aW, GetNavService as aX, HighlightDirective as aY, HttpService as aZ, ICON_SOURCE as a_, ComponentStepperComponent as aa, ConfigComponent as ab, ConfirmComponent as ac, ContextMenuComponent as ad, CustomIconClass as ae, CustomIconEditComponent as af, DEFAULT_DENIAL as ag, DEFAULT_DOC_DENSITY as ah, DEFAULT_DOC_VARIANT as ai, DEFAULT_FILTER_RANGE_MODE as aj, DEFAULT_FILTER_VARIANT as ak, DEFAULT_NAV_PARAM as al, DEFAULT_NAV_SEGMENT as am, DEFAULT_SIZE as an, DOCK_MIN_PAGE_REMAINDER as ao, DOCS_FOLDER as ap, DOC_ACTION_ICONS as aq, DOC_DENSITIES as ar, DOC_EDIT_ACTIONS as as, DOC_TOOLBAR_GROUPS as at, DOC_VARIANTS as au, DashboardCardComponent as av, DateInputComponent as aw, DatePickerComponent as ax, DeviceService as ay, DocComponent as az, MAX_ZOOM as b, PaginationComponent as b$, IconComponent as b0, ImgComponent as b1, InstrumentScoreComponent as b2, InterceptorObservables as b3, JumbotronComponent as b4, KeyValueComponent as b5, LAYOUT_ASSET_FOLDER as b6, LOGIN_COMPONENT as b7, LOGIN_STORE as b8, LanguageComponent as b9, NAV_WIDGET_MAP as bA, NavComponent as bB, NavDetailsComponent as bC, NavHeaderComponent as bD, NavMenuComponent as bE, NavStore as bF, NavTrailComponent as bG, NothingComponent as bH, NotificationElementComponent as bI, NotificationGroupComponent as bJ, NotificationPopupComponent as bK, NotificationService as bL, NotificationStore as bM, NotificationType as bN, NotificationWidgetComponent as bO, ONE_ASSET_BASE_URL as bP, OPTIONS_SOURCE as bQ, OVERLAY_WIDGETS as bR, OneApp as bS, OptionsSourceDirective as bT, OverlayBodyComponent as bU, OverlayRef as bV, OverlayService as bW, PLATFORM_BUTTON_NAV_IDS as bX, PLATFORM_EXTENSIBLE_NAV_IDS as bY, PLATFORM_NAV_MAP as bZ, PLATFORM_ROOT_CHILDREN as b_, ListComponent as ba, LogoComponent as bb, MAG_SOCKET_EVENT as bc, MHeroColorDirective as bd, MHeroComponent as be, MODAL_STORE_REF as bf, MOUNT_STATIC_SEGMENT as bg, MOUNT_TOKEN as bh, MRefDirective as bi, MStepComponent as bj, MURL_PARAM as bk, MURL_SEP as bl, ManifestEnrichmentService as bm, MenuComponent as bn, ModalDirective as bo, ModalRef as bp, ModalStore as bq, MoneyPipe as br, MultiRangeInputComponent as bs, MurlUrlSerializer as bt, NAV_DEFAULT_MURL as bu, NAV_ID_SEP as bv, NAV_MAIN_BUTTONS as bw, NAV_SEGMENT_RE as bx, NAV_STORE_REF as by, NAV_WC_COMPONENTS as bz, cropRect as c, SharedStoreRegistry as c$, PanelComponent as c0, PercentagePipe as c1, PlaygroundComponent as c2, PositionDirective as c3, PwaInstallComponent as c4, RECENT_SEARCH_LIMIT as c5, REMOTE_PAGE_RELOAD as c6, ROOT_NAV$1 as c7, RadioGroupComponent as c8, RadioInputComponent as c9, SectionCarouselComponent as cA, SectionComponent as cB, SectionFilterComponent as cC, SectionFilterGroupComponent as cD, SectionFilterMenuComponent as cE, SectionFilterPanelComponent as cF, SectionFilterRangePanelComponent as cG, SectionFooterComponent as cH, SectionFormComponent as cI, SectionFormItemComponent as cJ, SectionHeaderComponent as cK, SectionHeroComponent as cL, SectionPaginationComponent as cM, SectionSearchComponent as cN, SectionStepperComponent as cO, SectionTableCellComponent as cP, SectionTableComponent as cQ, SectionTableRowComponent as cR, SectionTableSortPipe as cS, SectionTabsComponent as cT, SectionToggleComponent as cU, SectionToggleItemDirective as cV, SelectableCardInputComponent as cW, SelectorDirective as cX, SettingsSearchBarComponent as cY, SettingsSearchService as cZ, ShapeComponent as c_, RatingInputComponent as ca, ReactiveElementComponent as cb, RemoteComponent as cc, RemoteLoaderService as cd, ResizeElementComponent as ce, RouteContainer as cf, RowComponent as cg, SEARCH_QUERY as ch, SEARCH_RESULTS_EVENT as ci, SECTION_ACCORDION_GROUP as cj, SECTION_FORM_CONTEXT as ck, SECTION_TABLE_VARIANTS as cl, SHARED_ICONS as cm, SIZE_CONTEXT as cn, ScoreComponent as co, ScrollComponent as cp, ScrollService as cq, SearchPanelComponent as cr, SearchStore as cs, SearchUserPanelComponent as ct, SectionAccordionDirective as cu, SectionAccordionGroupDirective as cv, SectionBackComponent as cw, SectionBadgesComponent as cx, SectionButtonGroupComponent as cy, SectionCardComponent as cz, drawFramed as d, cellText as d$, SidePanelDirective as d0, Size as d1, SocketStore as d2, SortComponent as d3, StatComponent as d4, StepComponent as d5, StepperComponent as d6, StepsComponent as d7, StorageService as d8, StrokeLinecap as d9, USER_STORE_REF as dA, USER_TAB_MAP as dB, UniverseComponent as dC, UserApiService as dD, UserAvatarComponent as dE, UserComponent as dF, UserNavComponent as dG, UserSettingsComponent as dH, UserStore as dI, WC_BUNDLE as dJ, WC_NAVIGATE_EVENT as dK, WC_ROUTE_CHANGED_EVENT as dL, WC_SEARCH_GROUPS as dM, WIN_USER_TAB_HOOK as dN, WIN_USER_TAB_KEY as dO, WatermarkComponent as dP, WcRouterStore as dQ, WrapperInputComponent as dR, anchorNavId as dS, applyColorsToElement as dT, applyDocEdit as dU, assetOptions as dV, bootstrapMagApp as dW, bootstrapPwaInstall as dX, buildWcBaseUrl as dY, calculateLuminance as dZ, calculateRanks as d_, StrokeLinejoin as da, SummaryComponent as db, SvgGeneratorComponent as dc, SvgGeneratorService as dd, SvgService as de, TOTAL_COLUMNS as df, TRANSLATION_SOURCE as dg, TableComponent as dh, TechnicalMeterComponent as di, TextInputComponent as dj, TextareaInputComponent as dk, ThemeComponent as dl, ThemeDataService as dm, ThemeService as dn, ThemeStore as dp, TimeAgoPipe as dq, TimelineComponent as dr, ToggleButtonComponent as ds, ToggleInputComponent as dt, ToggleRadioInputComponent as du, ToolTipDirective as dv, TooltipComponent as dw, TranslateService as dx, TreeGridComponent as dy, URL_SEP as dz, encodeFramed as e, isBootRedirect as e$, checkDoc as e0, checkFilterCondition as e1, childNavId as e2, claimDenial as e3, classListSignal as e4, coerceSize as e5, cornerEdge as e6, cornerSide as e7, createMap as e8, createPlatformNavMap as e9, filterTreeGridRows as eA, filterValueList as eB, filterValues as eC, flattenTreeGridRows as eD, formatBadgeCount as eE, fullName as eF, generateClipPath as eG, generateTransform as eH, getClassList as eI, getProperty as eJ, getScrollParent as eK, getTierFromPreviewPath as eL, getTreeGridRow as eM, getUniqueId as eN, getValue as eO, hasErrorComputed as eP, hexToRgb as eQ, hslToRgb$1 as eR, initMagmoniumApp as eS, initialNotificationState as eT, initialState$2 as eU, initials as eV, injectAuthenticate as eW, injectDefaultDenial as eX, injectInstallApp as eY, injectParentSize as eZ, injectScrollSticky as e_, definedWcTierOf as ea, deriveAvatarGradient as eb, deriveContrastColor as ec, deriveOppositeColor as ed, derivePropertyName as ee, docActionKey as ef, docAssetCandidates as eg, docProblemKey as eh, docRemotePath as ei, emailValidation as ej, evaluate as ek, evaluateBool as el, fieldBoolean as em, fieldNumber as en, fieldString as eo, filterHoldsList as ep, filterHoldsOneBound as eq, filterHoldsOptions as er, filterHoldsRange as es, filterList as et, filterNumber as eu, filterNumberList as ev, filterOne as ew, filterPanelOf as ex, filterPanelWidth as ey, filterRange as ez, clampFraming as f, provideMagAppConfig as f$, isButtonName as f0, isCancelledComputed as f1, isExtensiblePlatformNavId as f2, isJson as f3, isLoadingComputed as f4, isLocalhost as f5, isNavInstanceConfig as f6, isNavMenuConfig as f7, isNavRowsConfig as f8, isNavVisibilityConfig as f9, mountPatternText as fA, mountSegmentOf as fB, mountTokenOf as fC, navIdChain as fD, navIdFor as fE, navIdSegment as fF, navIdToRoutePath as fG, navIdToSegments as fH, navParamOf as fI, navTailMatcher as fJ, navToId as fK, navVisibilityGuard as fL, nextSectionTableSort as fM, normalizeAssetOptions as fN, offsetOfLine as fO, parentNavId as fP, parseAddress as fQ, parseColor as fR, parseMountPattern as fS, parsePatternNames as fT, patternValidation as fU, patternsValidation as fV, permissionRefusal as fW, platformNavWidgets as fX, privateGuard as fY, processImageToSvg as fZ, provideAppContext as f_, isPlatformNavId as fa, isSize as fb, isTierPreview as fc, isUrlLocalhost as fd, isValidNavId as fe, isValidNavSegment as ff, isWebComponent as fg, linkToId as fh, linkToNav as fi, loadingActions as fj, mInterceptor as fk, manualValidation as fl, matchFieldValidation as fm, matchMount as fn, maxLengthValidation as fo, maxValidation as fp, mergePlatformNav as fq, mergeUnique as fr, mergeUniqueBy as fs, mergeUniqueWith as ft, minAgeValidation as fu, minLengthValidation as fv, minValidation as fw, miniMarkToHtml as fx, mountFor as fy, mountPatternProblem as fz, BaseInputComponent as g, provideMagWcConfig as g0, provideMagWcRoutes as g1, provideModalComponents as g2, provideMurlUrlSerializer as g3, provideNavWidgets as g4, provideOverlayWidgets as g5, providePlatformNavWidgets as g6, provideSearch as g7, provideSizeContext as g8, provideUserTabs as g9, splitNavId as gA, splitOnMatch as gB, stringToColor as gC, tailRouteOf as gD, toAttrBool as gE, toAttrNumber as gF, toCssLength as gG, toHostNavId as gH, toLength$1 as gI, toLocalNavId as gJ, toggleTreeGridRow as gK, unfetchedPlatformNav as gL, ungroupedDocActions as gM, urlValidation as gN, wcTierOf as gO, publicGuard as ga, readFieldPatterns as gb, recordDefinedWcTier as gc, remoteOutletRoute as gd, renderAddress as ge, renderDocument as gf, requiredValidation as gg, resolveConfigAsset as gh, resolveIconSize as gi, resolvePallet as gj, resolvePatternRules as gk, resolveSize as gl, rgbToHex as gm, rgbToHsl as gn, rowHasChildren as go, samePatterns as gp, sectionTableColumnId as gq, sectionTableColumnWidths as gr, sectionTableFrozenCount as gs, segmentsToNavId as gt, setProperty as gu, setTreeGridChildren as gv, setWcTier as gw, settingsWidgets as gx, shouldShowBadge as gy, sortSectionTableRows as gz, BaseTextInputComponent as h, initialFraming as i, TextOutputComponent as j, IS_DESIGN_MODE as k, APP_CONTEXT_REF as l, APP_LINK as m, ASSET_BASE_URL as n, outputSize as o, parseRatio as p, AccordionBodyDirective as q, renameForType as r, AccordionComponent as s, AccordionGroupComponent as t, ActionComponent as u, AnimatedGraphsComponent as v, AppCardComponent as w, AppRelationType as x, AppTileComponent as y, AssetStore as z };
40342
+ //# sourceMappingURL=magmonium-one-magmonium-one-DCRM0N5X.mjs.map