@magmonium/one 0.2.79 → 0.2.81

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, inject, Injectable, signal, computed, DestroyRef, DOCUMENT, ApplicationRef, RendererFactory2, createComponent, EnvironmentInjector, Pipe, ChangeDetectorRef, untracked, ElementRef, afterNextRender, input, ChangeDetectionStrategy, Component, effect, Injector, reflectComponentType, model, HostListener, Renderer2, Directive, output, viewChild, ViewEncapsulation, forwardRef, contentChild, TemplateRef, ViewContainerRef, inputBinding, outputBinding, linkedSignal, afterRenderEffect, runInInjectionContext, Input, booleanAttribute, HostAttributeToken, EventEmitter, Output, ViewChild, ContentChild, provideZonelessChangeDetection, makeEnvironmentProviders, HostBinding, provideAppInitializer, provideBrowserGlobalErrorListeners, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
3
3
  import { HttpClient, HttpParams, provideHttpClient, withFetch, withInterceptors } from '@angular/common/http';
4
- import { firstValueFrom, of, tap, catchError, throwError, shareReplay, finalize, map, forkJoin, Observable, pipe, interval, fromEvent, switchMap as switchMap$1, filter, EMPTY, Subject, combineLatest, race, take, from } from 'rxjs';
4
+ import { firstValueFrom, of, tap, catchError, throwError, shareReplay, finalize, map, forkJoin, Observable, pipe, interval, fromEvent, switchMap as switchMap$1, filter, EMPTY, Subject, combineLatest, race, take, from, 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';
@@ -10,7 +10,7 @@ import { io } from 'socket.io-client';
10
10
  import { DefaultUrlSerializer, UrlSerializer, Router, NavigationEnd, RouterModule, RouterLink, provideRouter, withComponentInputBinding, withRouterConfig, RouterOutlet } from '@angular/router';
11
11
  import * as i1 from '@angular/common';
12
12
  import { APP_BASE_HREF, Location, NgOptimizedImage, IMAGE_LOADER, NgTemplateOutlet, CommonModule, NgComponentOutlet, DecimalPipe, NgClass, DatePipe, NgStyle } from '@angular/common';
13
- import { FormField, email, required, minLength, maxLength, min, max, validate, apply, form } from '@angular/forms/signals';
13
+ import { FormField, email, required, validate, minLength, maxLength, min, max, apply, form } from '@angular/forms/signals';
14
14
  import { createCustomElement } from '@angular/elements';
15
15
  import { bootstrapApplication, DomSanitizer } from '@angular/platform-browser';
16
16
  import { provideAnimations } from '@angular/platform-browser/animations';
@@ -3479,6 +3479,9 @@ function isNavRowsConfig(entry) {
3479
3479
  function isNavInstanceConfig(entry) {
3480
3480
  return typeof entry === 'object' && 'navInstance' in entry;
3481
3481
  }
3482
+ function isNavVisibilityConfig(entry) {
3483
+ return typeof entry === 'object' && 'navVisible' in entry;
3484
+ }
3482
3485
  /**
3483
3486
  * Multi-provided, and resolved **last-wins**: the library provides its own
3484
3487
  * Platform Nav panels first so an app registering at the same NavId replaces
@@ -3696,6 +3699,13 @@ const unfetchedPlatformNav = (navId) => {
3696
3699
  : undefined;
3697
3700
  };
3698
3701
 
3702
+ /**
3703
+ * No Nav hidden — the shape every caller predating [NavVisibilityConfig] still
3704
+ * has. Frozen and shared rather than minted per call: the default sits on four
3705
+ * signatures, and a fresh Set on each would make two calls with the same
3706
+ * arguments produce values a memo could not tell apart.
3707
+ */
3708
+ const EMPTY_HIDDEN = new Set();
3699
3709
  const emptyResult = () => ({
3700
3710
  breadcrumb: { header: { label: '', id: '' }, trail: [] },
3701
3711
  navMenus: [],
@@ -3824,9 +3834,20 @@ const drawsRows = (childId, dynamicRows) => {
3824
3834
  const resolved = dynamicRows[childId];
3825
3835
  return !!resolved && (resolved.rows.length > 0 || !!resolved.loading);
3826
3836
  };
3827
- const menuChildIds = (navId, navMap, dynamicRows = {}, instances = {}) => childIdsOf(navId, navMap).flatMap((childId) => {
3837
+ const menuChildIds = (navId, navMap, dynamicRows = {}, instances = {},
3838
+ // NavIds a NavVisibilityConfig answered no — or has not answered yet — for.
3839
+ // A set rather than a predicate: the answers are resolved once per read of
3840
+ // the widget maps, and this walk is called from four places that would
3841
+ // otherwise each resolve them again.
3842
+ hidden = EMPTY_HIDDEN) => childIdsOf(navId, navMap).flatMap((childId) => {
3843
+ // Hidden first, and before the Default Nav descent: a hidden parent takes
3844
+ // its children with it, which is the same cascade the route guard walks —
3845
+ // a row spliced out of a panel whose children still listed beneath it
3846
+ // would be the panel that looks correct and is not.
3847
+ if (hidden.has(childId))
3848
+ return [];
3828
3849
  if (isDefaultNav(childId))
3829
- return menuChildIds(childId, navMap, dynamicRows, instances);
3850
+ return menuChildIds(childId, navMap, dynamicRows, instances, hidden);
3830
3851
  if (navMap[childId]?.presentation === 'dynamic') {
3831
3852
  if (drawsRows(childId, dynamicRows))
3832
3853
  return [childId];
@@ -3847,10 +3868,10 @@ const menuChildIds = (navId, navMap, dynamicRows = {}, instances = {}) => childI
3847
3868
  * list the User moved through and the row they are on is the one marked
3848
3869
  * active. Root is the floor: its own children are the last list there is.
3849
3870
  */
3850
- const navMenuOwnerId = (navId, navMap, hasOwnContent = false, dynamicRows = {}, instances = {}) => {
3871
+ const navMenuOwnerId = (navId, navMap, hasOwnContent = false, dynamicRows = {}, instances = {}, hidden = EMPTY_HIDDEN) => {
3851
3872
  const visible = visibleNavId(navId);
3852
3873
  if (visible === ROOT_NAV$1 ||
3853
- menuChildIds(visible, navMap, dynamicRows, instances).length) {
3874
+ menuChildIds(visible, navMap, dynamicRows, instances, hidden).length) {
3854
3875
  return visible;
3855
3876
  }
3856
3877
  // A panel that answers with a widget of its own keeps its own title —
@@ -3865,7 +3886,7 @@ const navMenuOwnerId = (navId, navMap, hasOwnContent = false, dynamicRows = {},
3865
3886
  // than the one we are on — a mistitled empty panel is worse than a titled one.
3866
3887
  for (let ancestor = parentNavId(visible); ancestor; ancestor = parentNavId(ancestor)) {
3867
3888
  const owner = visibleNavId(ancestor);
3868
- if (menuChildIds(owner, navMap, dynamicRows, instances).length)
3889
+ if (menuChildIds(owner, navMap, dynamicRows, instances, hidden).length)
3869
3890
  return owner;
3870
3891
  if (owner === ROOT_NAV$1)
3871
3892
  break;
@@ -3885,7 +3906,7 @@ const navMenuOwnerId = (navId, navMap, hasOwnContent = false, dynamicRows = {},
3885
3906
  * falling through to the static siblings around it would show a panel that
3886
3907
  * looks correct and is not.
3887
3908
  */
3888
- const buildNavMenus = (navId, navMap, anchor, dynamicRows = {}, routeParams, instances = {}) => menuChildIds(navId, navMap, dynamicRows, instances).flatMap((childId) => {
3909
+ const buildNavMenus = (navId, navMap, anchor, dynamicRows = {}, routeParams, instances = {}, hidden = EMPTY_HIDDEN) => menuChildIds(navId, navMap, dynamicRows, instances, hidden).flatMap((childId) => {
3889
3910
  const nav = navMap[childId];
3890
3911
  const resolved = nav && dynamicRows[childId];
3891
3912
  // The instances above this row, whether it is a row of its own or one of
@@ -3913,7 +3934,7 @@ const mergeTrail = (derived, override, derivedHeader) => {
3913
3934
  return { trail, header: override.header ?? derivedHeader };
3914
3935
  };
3915
3936
  function deriveBreadcrumb(params) {
3916
- const { navId, navMap, anchor, breadcrumb, navMenu, hasOwnContent, dynamicRows, routeParams, instances, } = params;
3937
+ const { navId, navMap, anchor, breadcrumb, navMenu, hasOwnContent, dynamicRows, routeParams, instances, hidden = EMPTY_HIDDEN, } = params;
3917
3938
  if (!navId)
3918
3939
  return emptyResult();
3919
3940
  /**
@@ -3962,7 +3983,7 @@ function deriveBreadcrumb(params) {
3962
3983
  // The header and the trail belong to whichever Nav owns the menu below them:
3963
3984
  // on a leaf that is the parent, so the User reads the list they are in with
3964
3985
  // their own row marked, rather than a title over an empty panel.
3965
- const ownerId = navMenuOwnerId(navId, navMap, hasOwnContent, dynamicRows, instances);
3986
+ const ownerId = navMenuOwnerId(navId, navMap, hasOwnContent, dynamicRows, instances, hidden);
3966
3987
  // An emitted breadcrumb names the panel it was emitted for. Once the panel
3967
3988
  // has been handed up to an ancestor it is no longer that panel, so the
3968
3989
  // override would title the ancestor's list after the leaf we left.
@@ -3992,7 +4013,7 @@ function deriveBreadcrumb(params) {
3992
4013
  breadcrumb: { trail, header },
3993
4014
  navMenus: navMenu?.length && ownPanel
3994
4015
  ? navMenu
3995
- : buildNavMenus(ownerId, navMap, anchor, dynamicRows, routeParams, instances),
4016
+ : buildNavMenus(ownerId, navMap, anchor, dynamicRows, routeParams, instances, hidden),
3996
4017
  };
3997
4018
  }
3998
4019
 
@@ -4100,6 +4121,7 @@ const initialState$3 = {
4100
4121
  keepPanelOnPathChange: false,
4101
4122
  panelPushed: false,
4102
4123
  navScrolledDown: false,
4124
+ visibilityAnswers: {},
4103
4125
  remoteWidgets: {},
4104
4126
  navMap: createPlatformNavMap(),
4105
4127
  wcConfigMap: {},
@@ -4130,6 +4152,18 @@ const routeParamsOf = (root) => {
4130
4152
  }
4131
4153
  return params;
4132
4154
  };
4155
+ /**
4156
+ * A gate's answer is remembered against the parameters it was asked with, not
4157
+ * against the NavId alone: one gate asked about book `a` and book `b` is two
4158
+ * questions, and remembering only the last would carry `a`'s answer into `b`'s
4159
+ * panel. Sorted so two records with the same pairs key alike whatever order the
4160
+ * Router built them in.
4161
+ */
4162
+ const visibilityKey = (navId, params) => `${navId}|${Object.keys(params)
4163
+ .sort()
4164
+ .map((name) => `${name}=${params[name]}`)
4165
+ .join('&')}`;
4166
+ const isPromise$1 = (value) => typeof value?.then === 'function';
4133
4167
  const murlOf = (root) => {
4134
4168
  const raw = root.queryParams?.[MURL_PARAM];
4135
4169
  return typeof raw === 'string' ? raw.split(MURL_SEP).filter(Boolean) : [];
@@ -4268,6 +4302,94 @@ const NavStore = signalStore({ providedIn: 'root' }, withState(initialState$3),
4268
4302
  }
4269
4303
  return out;
4270
4304
  }, ...(ngDevMode ? [{ debugName: "dynamicInstances" }] : /* istanbul ignore next */ []));
4305
+ /**
4306
+ * Every registered gate, asked once, with the answer left exactly as it
4307
+ * came back — boolean, `undefined`, or a promise.
4308
+ *
4309
+ * One computed rather than one per consumer: `navVisible` is called here
4310
+ * and nowhere else, so an async gate mints one promise per change of the
4311
+ * signals it reads rather than one per reader.
4312
+ *
4313
+ * Walks the whole map for the reason `dynamicRows` does: a gate may sit on
4314
+ * a Nav the open panel never descends into, and reading each registration
4315
+ * here is what makes the menu recompute when the store behind it fills.
4316
+ */
4317
+ const visibilityReads = computed(() => {
4318
+ const params = store.routeParams();
4319
+ const out = [];
4320
+ for (const nav of Object.values(store.navMap())) {
4321
+ const hit = entryAt(nav.navId);
4322
+ if (!hit || !isNavVisibilityConfig(hit.entry))
4323
+ continue;
4324
+ out.push({
4325
+ navId: nav.navId,
4326
+ key: visibilityKey(nav.navId, params),
4327
+ answer: hit.entry.navVisible(params),
4328
+ });
4329
+ }
4330
+ return out;
4331
+ }, ...(ngDevMode ? [{ debugName: "visibilityReads" }] : /* istanbul ignore next */ []));
4332
+ /**
4333
+ * The load each registered gate offers, paired with the key it answers
4334
+ * under. Exposed rather than fired here for the reason `instanceLoaders`
4335
+ * is: calling a store method from inside a `computed` writes state during a
4336
+ * read.
4337
+ *
4338
+ * Every gate with a load is listed, not only the ones currently answering
4339
+ * `undefined`. What it names is a CacheMethod — state first, HTTP on a miss
4340
+ * — so firing it warm costs a state read, where gating on the answer being
4341
+ * missing would make the trigger depend on the thing it triggers.
4342
+ */
4343
+ const visibilityLoaders = computed(() => {
4344
+ const params = store.routeParams();
4345
+ const out = [];
4346
+ for (const nav of Object.values(store.navMap())) {
4347
+ const hit = entryAt(nav.navId);
4348
+ if (!hit || !isNavVisibilityConfig(hit.entry))
4349
+ continue;
4350
+ const load = hit.entry.navVisibleLoad;
4351
+ if (!load)
4352
+ continue;
4353
+ out.push({ key: visibilityKey(nav.navId, params), params, load });
4354
+ }
4355
+ return out;
4356
+ }, ...(ngDevMode ? [{ debugName: "visibilityLoaders" }] : /* istanbul ignore next */ []));
4357
+ /**
4358
+ * The promises nothing has resolved yet. Exposed rather than awaited here:
4359
+ * awaiting inside a `computed` would write state during a read, which is
4360
+ * the same reason `instanceLoaders` hands its calls out instead of firing
4361
+ * them. The hook below settles them.
4362
+ */
4363
+ const visibilityPending = computed(() => {
4364
+ const settled = store.visibilityAnswers();
4365
+ return visibilityReads()
4366
+ .filter((read) => isPromise$1(read.answer) && !(read.key in settled))
4367
+ .map((read) => ({
4368
+ key: read.key,
4369
+ answer: read.answer,
4370
+ }));
4371
+ }, ...(ngDevMode ? [{ debugName: "visibilityPending" }] : /* istanbul ignore next */ []));
4372
+ /**
4373
+ * Every Nav a gate currently takes out of the menu — one that answered
4374
+ * `false`, one that has not answered at all, and one still asking.
4375
+ *
4376
+ * The unresolved cases hide, which is the half that is not symmetric: a row
4377
+ * flashed in while its gate was still asking leaks the existence of the
4378
+ * thing the gate was written to hide, where a row that appears a tick late
4379
+ * costs nothing. The route guard reads the same registrations and parts
4380
+ * ways here — it *waits*, a Router being able to hold a navigation where a
4381
+ * panel cannot hold a render (nav-visibility-guard.ts).
4382
+ */
4383
+ const hiddenNavIds = computed(() => {
4384
+ const settled = store.visibilityAnswers();
4385
+ const out = new Set();
4386
+ for (const read of visibilityReads()) {
4387
+ const answer = isPromise$1(read.answer) ? settled[read.key] : read.answer;
4388
+ if (answer !== true)
4389
+ out.add(read.navId);
4390
+ }
4391
+ return out;
4392
+ }, ...(ngDevMode ? [{ debugName: "hiddenNavIds" }] : /* istanbul ignore next */ []));
4271
4393
  /**
4272
4394
  * The load each registered NavInstanceSource offers, paired with the value
4273
4395
  * of the parameter it resolves. Exposed rather than fired here: calling a
@@ -4342,7 +4464,8 @@ const NavStore = signalStore({ providedIn: 'root' }, withState(initialState$3),
4342
4464
  const map = store.navMap();
4343
4465
  const candidates = widgetNavIds();
4344
4466
  const rows = dynamicRows();
4345
- return (candidates.find((c) => menuChildIds(c, map, rows, dynamicInstances()).length) ??
4467
+ return (candidates.find((c) => menuChildIds(c, map, rows, dynamicInstances(), hiddenNavIds())
4468
+ .length) ??
4346
4469
  // A leaf nothing is registered for is still a Nav the tree knows, and
4347
4470
  // that is where the panel belongs: `|settings|app` with no widget hands
4348
4471
  // the panel back to *settings*, whose row it is, rather than climbing
@@ -4360,6 +4483,7 @@ const NavStore = signalStore({ providedIn: 'root' }, withState(initialState$3),
4360
4483
  anchor: { navId: store.routeNavId() ?? ROOT_NAV$1, path: store.path() },
4361
4484
  dynamicRows: dynamicRows(),
4362
4485
  instances: dynamicInstances(),
4486
+ hidden: hiddenNavIds(),
4363
4487
  routeParams: store.routeParams(),
4364
4488
  breadcrumb: menuConfig?.breadcramb?.() ??
4365
4489
  (typeof widgetConfig?.breadcramb === 'function'
@@ -4406,6 +4530,9 @@ const NavStore = signalStore({ providedIn: 'root' }, withState(initialState$3),
4406
4530
  currentWcConfig,
4407
4531
  resolvedNavMenuConfig,
4408
4532
  instanceLoaders,
4533
+ hiddenNavIds,
4534
+ visibilityPending,
4535
+ visibilityLoaders,
4409
4536
  };
4410
4537
  }), withMethods((store) => {
4411
4538
  const getNavService = inject(GetNavService);
@@ -4632,6 +4759,61 @@ const NavStore = signalStore({ providedIn: 'root' }, withState(initialState$3),
4632
4759
  * would never refresh a name that has gone stale, and would make the
4633
4760
  * trigger depend on the thing it triggers.
4634
4761
  */
4762
+ /**
4763
+ * Settles each async gate once and remembers what it said.
4764
+ *
4765
+ * Keyed by NavId *and* parameters, so moving from book `a` to book `b`
4766
+ * asks again while moving between two pages under `a` does not. In
4767
+ * flight is tracked separately from settled: a promise that has not
4768
+ * come back yet must not be re-asked on every recompute, and it is not
4769
+ * in `visibilityAnswers` to say so.
4770
+ */
4771
+ /**
4772
+ * Fires each gate's CacheMethod once per NavId + parameters, so a cold
4773
+ * deep link fills the state the gate reads. Keyed the same way the
4774
+ * answers are: moving from app `a` to app `b` loads again, moving
4775
+ * between two pages under `a` does not.
4776
+ */
4777
+ const loadedFor = new Set();
4778
+ effect(() => {
4779
+ const loaders = store.visibilityLoaders();
4780
+ untracked(() => {
4781
+ for (const { key, params, load } of loaders) {
4782
+ if (loadedFor.has(key))
4783
+ continue;
4784
+ loadedFor.add(key);
4785
+ load(params);
4786
+ }
4787
+ });
4788
+ });
4789
+ const askedFor = new Set();
4790
+ effect(() => {
4791
+ const pending = store.visibilityPending();
4792
+ untracked(() => {
4793
+ for (const { key, answer } of pending) {
4794
+ if (askedFor.has(key))
4795
+ continue;
4796
+ askedFor.add(key);
4797
+ answer
4798
+ .then((allowed) => patchState(store, (state) => ({
4799
+ visibilityAnswers: {
4800
+ ...state.visibilityAnswers,
4801
+ [key]: allowed === true,
4802
+ },
4803
+ })))
4804
+ // A gate that threw is a gate that did not say yes. Closed
4805
+ // rather than open: the failure mode of the other direction is
4806
+ // showing a row the User may not be allowed to have, which is
4807
+ // the thing the gate exists to prevent.
4808
+ .catch(() => patchState(store, (state) => ({
4809
+ visibilityAnswers: {
4810
+ ...state.visibilityAnswers,
4811
+ [key]: false,
4812
+ },
4813
+ })));
4814
+ }
4815
+ });
4816
+ });
4635
4817
  const firedFor = new Map();
4636
4818
  effect(() => {
4637
4819
  const loaders = store.instanceLoaders();
@@ -6765,6 +6947,16 @@ class SectionFormItemComponent extends ConfigComponent {
6765
6947
  isCheckboxVisible = input(...(ngDevMode ? [undefined, { debugName: "isCheckboxVisible" }] : /* istanbul ignore next */ []));
6766
6948
  enlarge = input(...(ngDevMode ? [undefined, { debugName: "enlarge" }] : /* istanbul ignore next */ []));
6767
6949
  optionsAsset = input(...(ngDevMode ? [undefined, { debugName: "optionsAsset" }] : /* istanbul ignore next */ []));
6950
+ // A `file` Field's settings. `accept` is one comma-separated scalar, the
6951
+ // spelling the native attribute already takes, so it rides on the tag the way
6952
+ // `patterns` does below rather than as a list (ADR 0010).
6953
+ accept = input(...(ngDevMode ? [undefined, { debugName: "accept" }] : /* istanbul ignore next */ []));
6954
+ maxSize = input(...(ngDevMode ? [undefined, { debugName: "maxSize" }] : /* istanbul ignore next */ []));
6955
+ dropZone = input(...(ngDevMode ? [undefined, { debugName: "dropZone" }] : /* istanbul ignore next */ []));
6956
+ readAs = input(...(ngDevMode ? [undefined, { debugName: "readAs" }] : /* istanbul ignore next */ []));
6957
+ editor = input(...(ngDevMode ? [undefined, { debugName: "editor" }] : /* istanbul ignore next */ []));
6958
+ ratio = input(...(ngDevMode ? [undefined, { debugName: "ratio" }] : /* istanbul ignore next */ []));
6959
+ width = input(...(ngDevMode ? [undefined, { debugName: "width" }] : /* istanbul ignore next */ []));
6768
6960
  // The shapes this Field's value may take, named on the tag the way every
6769
6961
  // other setting is (ADR 0010). One scalar rather than a list: the names are
6770
6962
  // comma-separated and resolved into rules here, so the markup says which
@@ -6819,6 +7011,13 @@ class SectionFormItemComponent extends ConfigComponent {
6819
7011
  put('iconOnly', toAttrBool(this.iconOnly()));
6820
7012
  put('isCheckboxVisible', toAttrBool(this.isCheckboxVisible()));
6821
7013
  put('enlarge', toAttrBool(this.enlarge()));
7014
+ put('accept', this.accept());
7015
+ put('maxSize', toAttrNumber(this.maxSize()));
7016
+ put('dropZone', toAttrBool(this.dropZone()));
7017
+ put('readAs', this.readAs());
7018
+ put('editor', toAttrBool(this.editor()));
7019
+ put('ratio', this.ratio());
7020
+ put('width', toAttrNumber(this.width()));
6822
7021
  // An OptionsSource on the tag outranks the asset's own key, and the plain
6823
7022
  // attribute outranks both — same order every other key follows.
6824
7023
  put('optionsAsset', this.optionsAsset() ?? this.optionsSource?.name());
@@ -7033,7 +7232,7 @@ class SectionFormItemComponent extends ConfigComponent {
7033
7232
  break;
7034
7233
  }
7035
7234
  case InputType.TOGGLE: {
7036
- const { ToggleInputComponent } = await import('./magmonium-one-toggle-DBQMTJ6O.mjs');
7235
+ const { ToggleInputComponent } = await import('./magmonium-one-toggle-DL3lH7Xo.mjs');
7037
7236
  this.createDynamicComponent(seq, ToggleInputComponent, [], true);
7038
7237
  break;
7039
7238
  }
@@ -7045,12 +7244,12 @@ class SectionFormItemComponent extends ConfigComponent {
7045
7244
  break;
7046
7245
  }
7047
7246
  case InputType.PASSWORD: {
7048
- const { PasswordInputComponent } = await import('./magmonium-one-password-rGcfKu8z.mjs');
7247
+ const { PasswordInputComponent } = await import('./magmonium-one-password-7gmB_RWb.mjs');
7049
7248
  this.createDynamicComponent(seq, PasswordInputComponent);
7050
7249
  break;
7051
7250
  }
7052
7251
  case InputType.OTP: {
7053
- const { OtpInputComponent } = await import('./magmonium-one-otp-T4eYO6SM.mjs');
7252
+ const { OtpInputComponent } = await import('./magmonium-one-otp-B-oUlDWY.mjs');
7054
7253
  this.createDynamicComponent(seq, OtpInputComponent);
7055
7254
  break;
7056
7255
  }
@@ -7122,6 +7321,12 @@ class SectionFormItemComponent extends ConfigComponent {
7122
7321
  ]);
7123
7322
  break;
7124
7323
  }
7324
+ case InputType.FILE:
7325
+ case InputType.FOLDER: {
7326
+ const { FileUploadInputComponent } = await Promise.resolve().then(function () { return fileUploadInput; });
7327
+ this.createDynamicComponent(seq, FileUploadInputComponent);
7328
+ break;
7329
+ }
7125
7330
  default: {
7126
7331
  const { TextInputComponent } = await Promise.resolve().then(function () { return text; });
7127
7332
  this.createDynamicComponent(seq, TextInputComponent);
@@ -7134,7 +7339,7 @@ class SectionFormItemComponent extends ConfigComponent {
7134
7339
  }
7135
7340
  };
7136
7341
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SectionFormItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7137
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: SectionFormItemComponent, isStandalone: true, selector: "m-section-form-item, m-one-section-form-item", inputs: { span: { classPropertyName: "span", publicName: "span", isSignal: true, isRequired: false, transformFunction: null }, labelOrientation: { classPropertyName: "labelOrientation", publicName: "labelOrientation", isSignal: true, isRequired: false, transformFunction: null }, gap: { classPropertyName: "gap", publicName: "gap", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, focused: { classPropertyName: "focused", publicName: "focused", isSignal: true, isRequired: false, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, dir: { classPropertyName: "dir", publicName: "dir", isSignal: true, isRequired: false, transformFunction: null }, element: { classPropertyName: "element", publicName: "element", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, template: { classPropertyName: "template", publicName: "template", isSignal: true, isRequired: false, transformFunction: null }, aclResolver: { classPropertyName: "aclResolver", publicName: "aclResolver", isSignal: true, isRequired: false, transformFunction: null }, formValues: { classPropertyName: "formValues", publicName: "formValues", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, params: { classPropertyName: "params", publicName: "params", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, prefix: { classPropertyName: "prefix", publicName: "prefix", isSignal: true, isRequired: false, transformFunction: null }, suffix: { classPropertyName: "suffix", publicName: "suffix", isSignal: true, isRequired: false, transformFunction: null }, button: { classPropertyName: "button", publicName: "button", isSignal: true, isRequired: false, transformFunction: null }, buttonAction: { classPropertyName: "buttonAction", publicName: "buttonAction", isSignal: true, isRequired: false, transformFunction: null }, buttonAcl: { classPropertyName: "buttonAcl", publicName: "buttonAcl", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, acl: { classPropertyName: "acl", publicName: "acl", isSignal: true, isRequired: false, transformFunction: null }, testid: { classPropertyName: "testid", publicName: "testid", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, length: { classPropertyName: "length", publicName: "length", isSignal: true, isRequired: false, transformFunction: null }, debounce: { classPropertyName: "debounce", publicName: "debounce", isSignal: true, isRequired: false, transformFunction: null }, dateFormat: { classPropertyName: "dateFormat", publicName: "dateFormat", isSignal: true, isRequired: false, transformFunction: null }, searchLabel: { classPropertyName: "searchLabel", publicName: "searchLabel", isSignal: true, isRequired: false, transformFunction: null }, vertical: { classPropertyName: "vertical", publicName: "vertical", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, multiSelect: { classPropertyName: "multiSelect", publicName: "multiSelect", isSignal: true, isRequired: false, transformFunction: null }, equalWidth: { classPropertyName: "equalWidth", publicName: "equalWidth", isSignal: true, isRequired: false, transformFunction: null }, iconOnly: { classPropertyName: "iconOnly", publicName: "iconOnly", isSignal: true, isRequired: false, transformFunction: null }, isCheckboxVisible: { classPropertyName: "isCheckboxVisible", publicName: "isCheckboxVisible", isSignal: true, isRequired: false, transformFunction: null }, enlarge: { classPropertyName: "enlarge", publicName: "enlarge", isSignal: true, isRequired: false, transformFunction: null }, optionsAsset: { classPropertyName: "optionsAsset", publicName: "optionsAsset", isSignal: true, isRequired: false, transformFunction: null }, patterns: { classPropertyName: "patterns", publicName: "patterns", isSignal: true, isRequired: false, transformFunction: null }, patternMessage: { classPropertyName: "patternMessage", publicName: "patternMessage", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", act: "act", fieldKey: "fieldKey" }, host: { properties: { "class": "spanClass()", "style.display": "isVisible() ? null : \"none\"" } }, queries: [{ propertyName: "projectedTemplate", first: true, predicate: (TemplateRef), descendants: true, isSignal: true }], viewQueries: [{ propertyName: "dynamicInput", first: true, predicate: ["dynamicInput"], descendants: true, read: ViewContainerRef, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
7342
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: SectionFormItemComponent, isStandalone: true, selector: "m-section-form-item, m-one-section-form-item", inputs: { span: { classPropertyName: "span", publicName: "span", isSignal: true, isRequired: false, transformFunction: null }, labelOrientation: { classPropertyName: "labelOrientation", publicName: "labelOrientation", isSignal: true, isRequired: false, transformFunction: null }, gap: { classPropertyName: "gap", publicName: "gap", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, focused: { classPropertyName: "focused", publicName: "focused", isSignal: true, isRequired: false, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, dir: { classPropertyName: "dir", publicName: "dir", isSignal: true, isRequired: false, transformFunction: null }, element: { classPropertyName: "element", publicName: "element", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, template: { classPropertyName: "template", publicName: "template", isSignal: true, isRequired: false, transformFunction: null }, aclResolver: { classPropertyName: "aclResolver", publicName: "aclResolver", isSignal: true, isRequired: false, transformFunction: null }, formValues: { classPropertyName: "formValues", publicName: "formValues", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, params: { classPropertyName: "params", publicName: "params", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, prefix: { classPropertyName: "prefix", publicName: "prefix", isSignal: true, isRequired: false, transformFunction: null }, suffix: { classPropertyName: "suffix", publicName: "suffix", isSignal: true, isRequired: false, transformFunction: null }, button: { classPropertyName: "button", publicName: "button", isSignal: true, isRequired: false, transformFunction: null }, buttonAction: { classPropertyName: "buttonAction", publicName: "buttonAction", isSignal: true, isRequired: false, transformFunction: null }, buttonAcl: { classPropertyName: "buttonAcl", publicName: "buttonAcl", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, acl: { classPropertyName: "acl", publicName: "acl", isSignal: true, isRequired: false, transformFunction: null }, testid: { classPropertyName: "testid", publicName: "testid", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, length: { classPropertyName: "length", publicName: "length", isSignal: true, isRequired: false, transformFunction: null }, debounce: { classPropertyName: "debounce", publicName: "debounce", isSignal: true, isRequired: false, transformFunction: null }, dateFormat: { classPropertyName: "dateFormat", publicName: "dateFormat", isSignal: true, isRequired: false, transformFunction: null }, searchLabel: { classPropertyName: "searchLabel", publicName: "searchLabel", isSignal: true, isRequired: false, transformFunction: null }, vertical: { classPropertyName: "vertical", publicName: "vertical", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, multiSelect: { classPropertyName: "multiSelect", publicName: "multiSelect", isSignal: true, isRequired: false, transformFunction: null }, equalWidth: { classPropertyName: "equalWidth", publicName: "equalWidth", isSignal: true, isRequired: false, transformFunction: null }, iconOnly: { classPropertyName: "iconOnly", publicName: "iconOnly", isSignal: true, isRequired: false, transformFunction: null }, isCheckboxVisible: { classPropertyName: "isCheckboxVisible", publicName: "isCheckboxVisible", isSignal: true, isRequired: false, transformFunction: null }, enlarge: { classPropertyName: "enlarge", publicName: "enlarge", isSignal: true, isRequired: false, transformFunction: null }, optionsAsset: { classPropertyName: "optionsAsset", publicName: "optionsAsset", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, maxSize: { classPropertyName: "maxSize", publicName: "maxSize", isSignal: true, isRequired: false, transformFunction: null }, dropZone: { classPropertyName: "dropZone", publicName: "dropZone", isSignal: true, isRequired: false, transformFunction: null }, readAs: { classPropertyName: "readAs", publicName: "readAs", isSignal: true, isRequired: false, transformFunction: null }, editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: false, transformFunction: null }, ratio: { classPropertyName: "ratio", publicName: "ratio", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, patterns: { classPropertyName: "patterns", publicName: "patterns", isSignal: true, isRequired: false, transformFunction: null }, patternMessage: { classPropertyName: "patternMessage", publicName: "patternMessage", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", act: "act", fieldKey: "fieldKey" }, host: { properties: { "class": "spanClass()", "style.display": "isVisible() ? null : \"none\"" } }, queries: [{ propertyName: "projectedTemplate", first: true, predicate: (TemplateRef), descendants: true, isSignal: true }], viewQueries: [{ propertyName: "dynamicInput", first: true, predicate: ["dynamicInput"], descendants: true, read: ViewContainerRef, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
7138
7343
  <div
7139
7344
  [class]="itemClass()"
7140
7345
  [style.--sfi-gap.px]="gap()"
@@ -7167,7 +7372,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
7167
7372
  '[class]': 'spanClass()',
7168
7373
  '[style.display]': 'isVisible() ? null : "none"',
7169
7374
  }, 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:block;flex:1 1 100%;min-width:0}.section-form-item{display:flex;flex-direction:column;gap:var(--sfi-gap, .5em );min-width:0;width:100%}.section-form-item.--horizontal{flex-direction:row;align-items:center}.section-form-item.--horizontal .section-form-item__input{flex:1;min-width:0}.section-form-item.--vertical{flex-direction:column}.section-form-item.--vertical .section-form-item__input{width:100%}.section-form-item__input{display:flex;flex-direction:column;min-width:0;width:100%}.section-form-item__input>*{width:100%}\n"] }]
7170
- }], ctorParameters: () => [], propDecorators: { span: [{ type: i0.Input, args: [{ isSignal: true, alias: "span", required: false }] }], labelOrientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelOrientation", required: false }] }], gap: [{ type: i0.Input, args: [{ isSignal: true, alias: "gap", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], focused: [{ type: i0.Input, args: [{ isSignal: true, alias: "focused", required: false }] }], form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], element: [{ type: i0.Input, args: [{ isSignal: true, alias: "element", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], template: [{ type: i0.Input, args: [{ isSignal: true, alias: "template", required: false }] }], projectedTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => TemplateRef), { isSignal: true }] }], aclResolver: [{ type: i0.Input, args: [{ isSignal: true, alias: "aclResolver", required: false }] }], formValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "formValues", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], params: [{ type: i0.Input, args: [{ isSignal: true, alias: "params", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], prefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefix", required: false }] }], suffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffix", required: false }] }], button: [{ type: i0.Input, args: [{ isSignal: true, alias: "button", required: false }] }], buttonAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonAction", required: false }] }], buttonAcl: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonAcl", required: false }] }], maxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxWidth", required: false }] }], acl: [{ type: i0.Input, args: [{ isSignal: true, alias: "acl", required: false }] }], testid: [{ type: i0.Input, args: [{ isSignal: true, alias: "testid", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], length: [{ type: i0.Input, args: [{ isSignal: true, alias: "length", required: false }] }], debounce: [{ type: i0.Input, args: [{ isSignal: true, alias: "debounce", required: false }] }], dateFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFormat", required: false }] }], searchLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchLabel", required: false }] }], vertical: [{ type: i0.Input, args: [{ isSignal: true, alias: "vertical", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], multiSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiSelect", required: false }] }], equalWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "equalWidth", required: false }] }], iconOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnly", required: false }] }], isCheckboxVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "isCheckboxVisible", required: false }] }], enlarge: [{ type: i0.Input, args: [{ isSignal: true, alias: "enlarge", required: false }] }], optionsAsset: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionsAsset", required: false }] }], patterns: [{ type: i0.Input, args: [{ isSignal: true, alias: "patterns", required: false }] }], patternMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "patternMessage", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], act: [{ type: i0.Output, args: ["act"] }], fieldKey: [{ type: i0.Output, args: ["fieldKey"] }], dynamicInput: [{ type: i0.ViewChild, args: ['dynamicInput', { ...{ read: ViewContainerRef }, isSignal: true }] }] } });
7375
+ }], ctorParameters: () => [], propDecorators: { span: [{ type: i0.Input, args: [{ isSignal: true, alias: "span", required: false }] }], labelOrientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelOrientation", required: false }] }], gap: [{ type: i0.Input, args: [{ isSignal: true, alias: "gap", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], focused: [{ type: i0.Input, args: [{ isSignal: true, alias: "focused", required: false }] }], form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], element: [{ type: i0.Input, args: [{ isSignal: true, alias: "element", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], template: [{ type: i0.Input, args: [{ isSignal: true, alias: "template", required: false }] }], projectedTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => TemplateRef), { isSignal: true }] }], aclResolver: [{ type: i0.Input, args: [{ isSignal: true, alias: "aclResolver", required: false }] }], formValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "formValues", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], params: [{ type: i0.Input, args: [{ isSignal: true, alias: "params", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], prefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefix", required: false }] }], suffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffix", required: false }] }], button: [{ type: i0.Input, args: [{ isSignal: true, alias: "button", required: false }] }], buttonAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonAction", required: false }] }], buttonAcl: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonAcl", required: false }] }], maxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxWidth", required: false }] }], acl: [{ type: i0.Input, args: [{ isSignal: true, alias: "acl", required: false }] }], testid: [{ type: i0.Input, args: [{ isSignal: true, alias: "testid", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], length: [{ type: i0.Input, args: [{ isSignal: true, alias: "length", required: false }] }], debounce: [{ type: i0.Input, args: [{ isSignal: true, alias: "debounce", required: false }] }], dateFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFormat", required: false }] }], searchLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchLabel", required: false }] }], vertical: [{ type: i0.Input, args: [{ isSignal: true, alias: "vertical", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], multiSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiSelect", required: false }] }], equalWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "equalWidth", required: false }] }], iconOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnly", required: false }] }], isCheckboxVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "isCheckboxVisible", required: false }] }], enlarge: [{ type: i0.Input, args: [{ isSignal: true, alias: "enlarge", required: false }] }], optionsAsset: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionsAsset", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], maxSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSize", required: false }] }], dropZone: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropZone", required: false }] }], readAs: [{ type: i0.Input, args: [{ isSignal: true, alias: "readAs", required: false }] }], editor: [{ type: i0.Input, args: [{ isSignal: true, alias: "editor", required: false }] }], ratio: [{ type: i0.Input, args: [{ isSignal: true, alias: "ratio", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], patterns: [{ type: i0.Input, args: [{ isSignal: true, alias: "patterns", required: false }] }], patternMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "patternMessage", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], act: [{ type: i0.Output, args: ["act"] }], fieldKey: [{ type: i0.Output, args: ["fieldKey"] }], dynamicInput: [{ type: i0.ViewChild, args: ['dynamicInput', { ...{ read: ViewContainerRef }, isSignal: true }] }] } });
7171
7376
 
7172
7377
  function formatDate(date, format) {
7173
7378
  if (!date) {
@@ -7219,9 +7424,19 @@ function isValidDateString(dateString, format) {
7219
7424
  const emailValidation = (schemaPath) => email(schemaPath, {
7220
7425
  message: 'not-a-valid-email',
7221
7426
  });
7222
- const requiredValidation = (s, paths) => paths.forEach((path) => required(s[path], {
7223
- message: 'this-field-is-required',
7224
- }));
7427
+ const requiredValidation = (s, paths) => paths.forEach((path) => {
7428
+ required(s[path], {
7429
+ message: 'this-field-is-required',
7430
+ });
7431
+ // `required` counts an empty list as a value. A multiselect or a `file`
7432
+ // Field holding `multiple` files is empty at `[]`, so that is refused too.
7433
+ validate(s[path], (ctx) => {
7434
+ const value = ctx.value();
7435
+ return Array.isArray(value) && value.length === 0
7436
+ ? { kind: 'required', message: 'this-field-is-required' }
7437
+ : null;
7438
+ });
7439
+ });
7225
7440
  const minLengthValidation = (s, paths, len) => paths.forEach((path) => minLength(s[path], len, {
7226
7441
  message: `min-length?len=${len}`,
7227
7442
  }));
@@ -16843,7 +17058,7 @@ class AuthActivityPageComponent {
16843
17058
  wrongPassword: this.authStore.wrongPassword,
16844
17059
  });
16845
17060
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AuthActivityPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
16846
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AuthActivityPageComponent, isStandalone: true, selector: "m-auth-activity", ngImport: i0, template: "<m-section>\n <m-flex direction=\"column\" justify=\"center\" alignItems=\"center\" gap=\"2em\" minHeight=\"400px\">\n <m-logo color=\"mm\" width=\"5em\" padding=\"10px\" variant=\"grained\" />\n @if (authStore.variant().busy) {\n <m-icon color=\"mm\" size=\"4em\" name=\"loading-bars\" [one]=\"true\" />\n } @else if (!authStore.variant().identity_exiest && !authStore.variant().many_identifications) {\n <m-text-output [noTranslate]=\"false\" label=\"welcome-to-app?app=Magmonium\" />\n <m-section-form\n minWidth=\"320px\"\n maxWidth=\"320px\"\n label=\"e-mail\"\n subtitle=\"type-text\"\n [data]=\"emailData!\"\n (submitted)=\"authStore.patch({ email: $event.email }); authStore.createAuthEmail({ identity: $event.email })\"\n >\n <m-section-form-item\n name=\"email\"\n patterns=\"email\"\n type=\"text\"\n label=\"e-mail\"\n placeholder=\"type-text\"\n [required]=\"true\"\n />\n <m-button\n label=\"next\"\n icon=\"chevron-right\"\n isSubmit\n [isRightIcon]=\"true\"\n color=\"mm\"\n [fullWidth]=\"true\"\n variant=\"primary\"\n />\n </m-section-form>\n } @else if (!authStore.variant().identity_exiest && authStore.variant().many_identifications) {\n <m-text-output [noTranslate]=\"false\" label=\"welcome-to-app?app=Magmonium\" />\n <m-section-form\n minWidth=\"320px\"\n maxWidth=\"320px\"\n label=\"e-mail\"\n subtitle=\"type-text\"\n (dataChange)=\"selectUserCard($event.user)\"\n >\n <m-section-form-item\n name=\"user\"\n [span]=\"1\"\n patterns=\"email\"\n type=\"selectable_card\"\n label=\"select-user\"\n placeholder=\"type-text\"\n [required]=\"true\"\n [multiSelect]=\"false\"\n [vertical]=\"true\"\n [isCheckboxVisible]=\"false\"\n [data]=\"userCards()\"\n >\n <ng-template let-item=\"row\" let-index=\"index\">\n <m-user [firstName]=\"item.firstName\" [lastName]=\"item.lastName\">\n <m-text-output [label]=\"item.identity\" noTranslate />\n </m-user>\n </ng-template>\n </m-section-form-item>\n <m-section-button-group [fullWidth]=\"true\">\n <m-button\n label=\"or-try-new-user\"\n icon=\"chevron-left\"\n color=\"mm\"\n [fullWidth]=\"true\"\n variant=\"primary\"\n (clicked)=\"authStore.patch({ identity: undefined, email: undefined })\"\n />\n </m-section-button-group>\n </m-section-form>\n } @else if (authStore.variant().with_show_term && !authStore.variant().create_new_user) {\n <m-section-form\n minWidth=\"320px\"\n maxWidth=\"320px\"\n label=\"e-mail\"\n subtitle=\"type-text\"\n align=\"center\"\n (submitted)=\"authStore.createSignUpOtp()\"\n >\n <m-text-output\n align=\"center\"\n variant=\"footer\"\n label=\"by-signing-in-you-agree-to-magmonium-s-terms-of-service-terms-and-acknowledge-our-privacy-policy-privacy\"\n [params]=\"activityTranslateParams()\"\n />\n <m-section-form-item name=\"field_1\" type=\"checkbox\" label=\"i-agree\" placeholder=\"type-text\" [required]=\"true\" />\n <m-button\n label=\"confirm\"\n icon=\"check\"\n isSubmit\n [isRightIcon]=\"true\"\n color=\"success\"\n [fullWidth]=\"true\"\n variant=\"primary\"\n />\n <m-section-button-group [fullWidth]=\"true\">\n <m-button\n label=\"back\"\n icon=\"chevron-left\"\n color=\"mm\"\n variant=\"ghost\"\n (clicked)=\"\n authStore.patch({\n identity: undefined,\n otp: undefined,\n otpCounter: undefined,\n registerNewUser: undefined,\n resetPassword: undefined,\n showTerms: undefined,\n signUp: undefined,\n })\n \"\n />\n </m-section-button-group>\n </m-section-form>\n } @else if (authStore.variant().with_otp && authStore.variant().create_new_user) {\n <m-section-form\n minWidth=\"320px\"\n maxWidth=\"320px\"\n label=\"e-mail\"\n subtitle=\"type-text\"\n align=\"center\"\n [data]=\"eMailData!\"\n (submitted)=\"authStore.updateAuthOtp({ code: $event.otp })\"\n >\n <m-section-form-item\n name=\"otp\"\n type=\"one-time-password\"\n label=\"one-time-password\"\n placeholder=\"type-text\"\n [required]=\"true\"\n />\n <m-button\n label=\"next\"\n icon=\"chevron-right\"\n isSubmit\n [isRightIcon]=\"true\"\n color=\"mm\"\n [fullWidth]=\"true\"\n variant=\"primary\"\n />\n <m-section-button-group [fullWidth]=\"true\">\n <m-button\n label=\"resend\"\n icon=\"corner-left-up\"\n color=\"mm\"\n variant=\"ghost\"\n (clicked)=\"authStore.createAuthOtp()\"\n />\n <m-button\n label=\"back\"\n icon=\"chevron-left\"\n color=\"mm\"\n variant=\"ghost\"\n (clicked)=\"\n authStore.patch({\n identity: undefined,\n otp: undefined,\n otpCounter: undefined,\n registerNewUser: undefined,\n resetPassword: undefined,\n showTerms: undefined,\n signUp: undefined,\n })\n \"\n />\n </m-section-button-group>\n </m-section-form>\n } @else if (\n authStore.variant().identity_exiest && !authStore.variant().reset_password && !authStore.variant().create_new_user\n ) {\n <m-section-form\n minWidth=\"320px\"\n maxWidth=\"320px\"\n label=\"e-mail\"\n subtitle=\"type-text\"\n align=\"center\"\n [validation]=\"signInValidation\"\n [data]=\"signInData!\"\n (formInitialized)=\"authStore.patch({ wrongPassword: undefined })\"\n (submitted)=\"authStore.updateAuthPassword({ password: btoa($event.password) })\"\n >\n <m-text-output label=\"signing-in-as\" [params]=\"activityTranslateParams()\" />\n <m-section-form-item\n name=\"password\"\n type=\"password\"\n label=\"password\"\n placeholder=\"type-text\"\n [required]=\"true\"\n />\n <m-button\n label=\"sign-in\"\n icon=\"check\"\n isSubmit\n [isRightIcon]=\"true\"\n color=\"success\"\n [fullWidth]=\"true\"\n variant=\"primary\"\n />\n <m-section-button-group [fullWidth]=\"true\">\n <m-button\n label=\"back\"\n icon=\"chevron-left\"\n color=\"mm\"\n variant=\"ghost\"\n (clicked)=\"authStore.patch({ identity: undefined })\"\n />\n <m-button\n label=\"reset\"\n icon=\"chevron-right\"\n [isRightIcon]=\"true\"\n color=\"textSecondary\"\n variant=\"ghost\"\n (clicked)=\"authStore.createAuthOtp()\"\n />\n </m-section-button-group>\n </m-section-form>\n } @else if (authStore.variant().reset_password && authStore.variant().with_otp) {\n <m-section-form\n minWidth=\"320px\"\n maxWidth=\"320px\"\n label=\"e-mail\"\n subtitle=\"type-text\"\n align=\"center\"\n [validation]=\"passwordValidation\"\n [data]=\"passwordData!\"\n (submitted)=\"authStore.createAuthPassword({ password: $event.confirm, code: $event.code })\"\n >\n <m-section-form-item\n name=\"code\"\n type=\"one-time-password\"\n label=\"one-time-password\"\n placeholder=\"type-text\"\n [required]=\"true\"\n />\n <m-section-button-group [fullWidth]=\"true\">\n <m-button\n label=\"resend\"\n icon=\"corner-left-up\"\n color=\"mm\"\n variant=\"ghost\"\n (clicked)=\"authStore.createAuthOtp()\"\n />\n </m-section-button-group>\n <m-section-form-item\n name=\"password\"\n type=\"password\"\n label=\"new-password\"\n placeholder=\"type-text\"\n [required]=\"true\"\n />\n <m-section-form-item\n name=\"confirm\"\n type=\"password\"\n label=\"confirm-password\"\n placeholder=\"type-text\"\n [required]=\"true\"\n />\n <m-button\n label=\"reset\"\n icon=\"check\"\n isSubmit\n [isRightIcon]=\"true\"\n color=\"mm\"\n [fullWidth]=\"true\"\n variant=\"primary\"\n />\n </m-section-form>\n } @else if (authStore.variant().create_new_user && authStore.variant().identity_exiest) {\n <m-section-form\n minWidth=\"320px\"\n maxWidth=\"320px\"\n label=\"e-mail\"\n subtitle=\"type-text\"\n align=\"center\"\n [data]=\"signupData!\"\n (submitted)=\"\n authStore.createAuthSignup({\n firstName: $event.firstname,\n lastName: $event.lastname,\n dob: $event.dob,\n sex: $event.sex,\n password: btoa($event.password),\n })\n \"\n >\n <m-text-output label=\"signing-up-as\" [params]=\"activityTranslateParams()\" />\n <m-section-form-item\n name=\"firstname\"\n type=\"text\"\n label=\"first-name\"\n placeholder=\"type-text\"\n [required]=\"true\"\n />\n <m-section-form-item name=\"lastname\" type=\"text\" label=\"last-name\" placeholder=\"type-text\" [required]=\"true\" />\n <m-section-form-item name=\"dob\" type=\"date\" label=\"date-of-birth\" placeholder=\"type-text\" [required]=\"true\" />\n <m-section-form-item\n name=\"sex\"\n type=\"toggle_radio\"\n label=\"sex\"\n placeholder=\"type-text\"\n [required]=\"true\"\n value=\"male\"\n mOptions=\"sex\"\n />\n <m-section-form-item\n name=\"password\"\n type=\"password\"\n label=\"password\"\n placeholder=\"type-text\"\n [required]=\"true\"\n />\n <m-section-form-item\n name=\"repassword\"\n type=\"password\"\n label=\"confirm-password\"\n placeholder=\"type-text\"\n [required]=\"true\"\n />\n <m-button\n label=\"sign-up\"\n icon=\"check\"\n isSubmit\n [isRightIcon]=\"true\"\n color=\"success\"\n [fullWidth]=\"true\"\n variant=\"primary\"\n />\n <m-section-button-group [fullWidth]=\"true\">\n <m-button\n label=\"back\"\n icon=\"chevron-left\"\n color=\"mm\"\n variant=\"ghost\"\n (clicked)=\"\n authStore.patch({\n identity: undefined,\n otp: undefined,\n otpCounter: undefined,\n registerNewUser: undefined,\n resetPassword: undefined,\n showTerms: undefined,\n signUp: undefined,\n })\n \"\n />\n </m-section-button-group>\n </m-section-form>\n }\n </m-flex>\n</m-section>\n", styles: [":host{display:block;width:100%;box-sizing:border-box;padding-block:clamp(1.5rem,6vh,4rem)}\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: FlexComponent, selector: "m-flex", inputs: ["direction", "justify", "alignItems", "variant", "gap", "padding", "paddingX", "paddingY", "wrap", "inline", "fullHeight", "minHeight", "minWidth", "maxHeight", "maxWidth"] }, { kind: "component", type: IconComponent, selector: "m-icon, m-one-icon", inputs: ["config", "name", "color", "size", "one", "baseUrl", "remote"], outputs: ["configChange"] }, { kind: "component", type: LogoComponent, selector: "m-logo", inputs: ["animation", "alive", "variant", "interactive", "width", "padding", "border", "color"] }, { kind: "directive", type: OptionsSourceDirective, selector: "[mOptions]", inputs: ["mOptions"] }, { kind: "component", type: SectionButtonGroupComponent, selector: "m-section-button-group", inputs: ["vertical", "align", "variant", "size", "fullWidth"] }, { kind: "component", type: SectionComponent, selector: "m-section", inputs: ["variant", "maxWidth", "heightMode", "maxHeight", "height", "align", "alignX", "alignY", "size"], outputs: ["inView"] }, { kind: "component", type: SectionFormComponent, selector: "m-section-form, m-one-section-form", inputs: ["variant", "maxWidth", "heightMode", "maxHeight", "height", "align", "size", "autofocus", "data", "validation", "disabled", "fieldConfigs", "fieldRenderIds"], outputs: ["dataChange", "submitted", "formInitialized"] }, { kind: "component", type: SectionFormItemComponent, selector: "m-section-form-item, m-one-section-form-item", inputs: ["span", "labelOrientation", "gap", "readonly", "focused", "form", "options", "dir", "element", "data", "template", "aclResolver", "formValues", "type", "label", "placeholder", "params", "required", "disabled", "icon", "prefix", "suffix", "button", "buttonAction", "buttonAcl", "maxWidth", "acl", "testid", "color", "variant", "min", "max", "step", "length", "debounce", "dateFormat", "searchLabel", "vertical", "multiple", "multiSelect", "equalWidth", "iconOnly", "isCheckboxVisible", "enlarge", "optionsAsset", "patterns", "patternMessage", "value"], outputs: ["valueChange", "act", "fieldKey"] }, { kind: "component", type: TextOutputComponent, selector: "m-text-output", inputs: ["config", "align", "variant", "color", "fontWeight", "label", "noTranslate", "params"], outputs: ["configChange", "clicked"] }, { kind: "component", type: UserComponent, selector: "m-user", inputs: ["id", "user", "firstName", "lastName", "profilePic"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
17061
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AuthActivityPageComponent, isStandalone: true, selector: "m-auth-activity", ngImport: i0, template: "<m-section>\n <m-flex direction=\"column\" justify=\"center\" alignItems=\"center\" gap=\"2em\" minHeight=\"400px\">\n <m-logo color=\"mm\" width=\"5em\" padding=\"10px\" variant=\"grained\" />\n @if (authStore.variant().busy) {\n <m-icon color=\"mm\" size=\"4em\" name=\"loading-bars\" [one]=\"true\" />\n } @else if (!authStore.variant().identity_exiest && !authStore.variant().many_identifications) {\n <m-text-output [noTranslate]=\"false\" label=\"welcome-to-app?app=Magmonium\" />\n <m-section-form\n minWidth=\"320px\"\n maxWidth=\"320px\"\n label=\"e-mail\"\n subtitle=\"type-text\"\n [data]=\"emailData!\"\n (submitted)=\"authStore.patch({ email: $event.email }); authStore.createAuthEmail({ identity: $event.email })\"\n >\n <m-section-form-item\n name=\"email\"\n patterns=\"email\"\n type=\"text\"\n label=\"e-mail\"\n placeholder=\"type-text\"\n [required]=\"true\"\n />\n <m-button\n label=\"next\"\n icon=\"chevron-right\"\n isSubmit\n [isRightIcon]=\"true\"\n color=\"mm\"\n [fullWidth]=\"true\"\n variant=\"primary\"\n />\n </m-section-form>\n } @else if (!authStore.variant().identity_exiest && authStore.variant().many_identifications) {\n <m-text-output [noTranslate]=\"false\" label=\"welcome-to-app?app=Magmonium\" />\n <m-section-form\n minWidth=\"320px\"\n maxWidth=\"320px\"\n label=\"e-mail\"\n subtitle=\"type-text\"\n (dataChange)=\"selectUserCard($event.user)\"\n >\n <m-section-form-item\n name=\"user\"\n [span]=\"1\"\n patterns=\"email\"\n type=\"selectable_card\"\n label=\"select-user\"\n placeholder=\"type-text\"\n [required]=\"true\"\n [multiSelect]=\"false\"\n [vertical]=\"true\"\n [isCheckboxVisible]=\"false\"\n [data]=\"userCards()\"\n >\n <ng-template let-item=\"row\" let-index=\"index\">\n <m-user [firstName]=\"item.firstName\" [lastName]=\"item.lastName\">\n <m-text-output [label]=\"item.identity\" noTranslate />\n </m-user>\n </ng-template>\n </m-section-form-item>\n <m-section-button-group [fullWidth]=\"true\">\n <m-button\n label=\"or-try-new-user\"\n icon=\"chevron-left\"\n color=\"mm\"\n [fullWidth]=\"true\"\n variant=\"primary\"\n (clicked)=\"authStore.patch({ identity: undefined, email: undefined })\"\n />\n </m-section-button-group>\n </m-section-form>\n } @else if (authStore.variant().with_show_term && !authStore.variant().create_new_user) {\n <m-section-form\n minWidth=\"320px\"\n maxWidth=\"320px\"\n label=\"e-mail\"\n subtitle=\"type-text\"\n align=\"center\"\n (submitted)=\"authStore.createSignUpOtp()\"\n >\n <m-text-output\n align=\"center\"\n variant=\"footer\"\n label=\"by-signing-in-you-agree-to-magmonium-s-terms-of-service-terms-and-acknowledge-our-privacy-policy-privacy\"\n [params]=\"activityTranslateParams()\"\n />\n <m-section-form-item name=\"field_1\" type=\"checkbox\" label=\"i-agree\" placeholder=\"type-text\" [required]=\"true\" />\n <m-button\n label=\"confirm\"\n icon=\"check\"\n isSubmit\n [isRightIcon]=\"true\"\n color=\"success\"\n [fullWidth]=\"true\"\n variant=\"primary\"\n />\n <m-section-button-group [fullWidth]=\"true\">\n <m-button\n label=\"back\"\n icon=\"chevron-left\"\n color=\"mm\"\n variant=\"ghost\"\n (clicked)=\"\n authStore.patch({\n identity: undefined,\n otp: undefined,\n otpCounter: undefined,\n registerNewUser: undefined,\n resetPassword: undefined,\n showTerms: undefined,\n signUp: undefined,\n })\n \"\n />\n </m-section-button-group>\n </m-section-form>\n } @else if (authStore.variant().with_otp && authStore.variant().create_new_user) {\n <m-section-form\n minWidth=\"320px\"\n maxWidth=\"320px\"\n label=\"e-mail\"\n subtitle=\"type-text\"\n align=\"center\"\n [data]=\"eMailData!\"\n (submitted)=\"authStore.updateAuthOtp({ code: $event.otp })\"\n >\n <m-section-form-item\n name=\"otp\"\n type=\"one-time-password\"\n label=\"one-time-password\"\n placeholder=\"type-text\"\n [required]=\"true\"\n />\n <m-button\n label=\"next\"\n icon=\"chevron-right\"\n isSubmit\n [isRightIcon]=\"true\"\n color=\"mm\"\n [fullWidth]=\"true\"\n variant=\"primary\"\n />\n <m-section-button-group [fullWidth]=\"true\">\n <m-button\n label=\"resend\"\n icon=\"corner-left-up\"\n color=\"mm\"\n variant=\"ghost\"\n (clicked)=\"authStore.createAuthOtp()\"\n />\n <m-button\n label=\"back\"\n icon=\"chevron-left\"\n color=\"mm\"\n variant=\"ghost\"\n (clicked)=\"\n authStore.patch({\n identity: undefined,\n otp: undefined,\n otpCounter: undefined,\n registerNewUser: undefined,\n resetPassword: undefined,\n showTerms: undefined,\n signUp: undefined,\n })\n \"\n />\n </m-section-button-group>\n </m-section-form>\n } @else if (\n authStore.variant().identity_exiest && !authStore.variant().reset_password && !authStore.variant().create_new_user\n ) {\n <m-section-form\n minWidth=\"320px\"\n maxWidth=\"320px\"\n label=\"e-mail\"\n subtitle=\"type-text\"\n align=\"center\"\n [validation]=\"signInValidation\"\n [data]=\"signInData!\"\n (formInitialized)=\"authStore.patch({ wrongPassword: undefined })\"\n (submitted)=\"authStore.updateAuthPassword({ password: btoa($event.password) })\"\n >\n <m-text-output label=\"signing-in-as\" [params]=\"activityTranslateParams()\" />\n <m-section-form-item\n name=\"password\"\n type=\"password\"\n label=\"password\"\n placeholder=\"type-text\"\n [required]=\"true\"\n />\n <m-button\n label=\"sign-in\"\n icon=\"check\"\n isSubmit\n [isRightIcon]=\"true\"\n color=\"success\"\n [fullWidth]=\"true\"\n variant=\"primary\"\n />\n <m-section-button-group [fullWidth]=\"true\">\n <m-button\n label=\"back\"\n icon=\"chevron-left\"\n color=\"mm\"\n variant=\"ghost\"\n (clicked)=\"authStore.patch({ identity: undefined })\"\n />\n <m-button\n label=\"reset\"\n icon=\"chevron-right\"\n [isRightIcon]=\"true\"\n color=\"textSecondary\"\n variant=\"ghost\"\n (clicked)=\"authStore.createAuthOtp()\"\n />\n </m-section-button-group>\n </m-section-form>\n } @else if (authStore.variant().reset_password && authStore.variant().with_otp) {\n <m-section-form\n minWidth=\"320px\"\n maxWidth=\"320px\"\n label=\"e-mail\"\n subtitle=\"type-text\"\n align=\"center\"\n [validation]=\"passwordValidation\"\n [data]=\"passwordData!\"\n (submitted)=\"authStore.createAuthPassword({ password: $event.confirm, code: $event.code })\"\n >\n <m-section-form-item\n name=\"code\"\n type=\"one-time-password\"\n label=\"one-time-password\"\n placeholder=\"type-text\"\n [required]=\"true\"\n />\n <m-section-button-group [fullWidth]=\"true\">\n <m-button\n label=\"resend\"\n icon=\"corner-left-up\"\n color=\"mm\"\n variant=\"ghost\"\n (clicked)=\"authStore.createAuthOtp()\"\n />\n </m-section-button-group>\n <m-section-form-item\n name=\"password\"\n type=\"password\"\n label=\"new-password\"\n placeholder=\"type-text\"\n [required]=\"true\"\n />\n <m-section-form-item\n name=\"confirm\"\n type=\"password\"\n label=\"confirm-password\"\n placeholder=\"type-text\"\n [required]=\"true\"\n />\n <m-button\n label=\"reset\"\n icon=\"check\"\n isSubmit\n [isRightIcon]=\"true\"\n color=\"mm\"\n [fullWidth]=\"true\"\n variant=\"primary\"\n />\n </m-section-form>\n } @else if (authStore.variant().create_new_user && authStore.variant().identity_exiest) {\n <m-section-form\n minWidth=\"320px\"\n maxWidth=\"320px\"\n label=\"e-mail\"\n subtitle=\"type-text\"\n align=\"center\"\n [data]=\"signupData!\"\n (submitted)=\"\n authStore.createAuthSignup({\n firstName: $event.firstname,\n lastName: $event.lastname,\n dob: $event.dob,\n sex: $event.sex,\n password: btoa($event.password),\n })\n \"\n >\n <m-text-output label=\"signing-up-as\" [params]=\"activityTranslateParams()\" />\n <m-section-form-item\n name=\"firstname\"\n type=\"text\"\n label=\"first-name\"\n placeholder=\"type-text\"\n [required]=\"true\"\n />\n <m-section-form-item name=\"lastname\" type=\"text\" label=\"last-name\" placeholder=\"type-text\" [required]=\"true\" />\n <m-section-form-item name=\"dob\" type=\"date\" label=\"date-of-birth\" placeholder=\"type-text\" [required]=\"true\" />\n <m-section-form-item\n name=\"sex\"\n type=\"toggle_radio\"\n label=\"sex\"\n placeholder=\"type-text\"\n [required]=\"true\"\n value=\"male\"\n mOptions=\"sex\"\n />\n <m-section-form-item\n name=\"password\"\n type=\"password\"\n label=\"password\"\n placeholder=\"type-text\"\n [required]=\"true\"\n />\n <m-section-form-item\n name=\"repassword\"\n type=\"password\"\n label=\"confirm-password\"\n placeholder=\"type-text\"\n [required]=\"true\"\n />\n <m-button\n label=\"sign-up\"\n icon=\"check\"\n isSubmit\n [isRightIcon]=\"true\"\n color=\"success\"\n [fullWidth]=\"true\"\n variant=\"primary\"\n />\n <m-section-button-group [fullWidth]=\"true\">\n <m-button\n label=\"back\"\n icon=\"chevron-left\"\n color=\"mm\"\n variant=\"ghost\"\n (clicked)=\"\n authStore.patch({\n identity: undefined,\n otp: undefined,\n otpCounter: undefined,\n registerNewUser: undefined,\n resetPassword: undefined,\n showTerms: undefined,\n signUp: undefined,\n })\n \"\n />\n </m-section-button-group>\n </m-section-form>\n }\n </m-flex>\n</m-section>\n", styles: [":host{display:block;width:100%;box-sizing:border-box;padding-block:clamp(1.5rem,6vh,4rem)}\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: FlexComponent, selector: "m-flex", inputs: ["direction", "justify", "alignItems", "variant", "gap", "padding", "paddingX", "paddingY", "wrap", "inline", "fullHeight", "minHeight", "minWidth", "maxHeight", "maxWidth"] }, { kind: "component", type: IconComponent, selector: "m-icon, m-one-icon", inputs: ["config", "name", "color", "size", "one", "baseUrl", "remote"], outputs: ["configChange"] }, { kind: "component", type: LogoComponent, selector: "m-logo", inputs: ["animation", "alive", "variant", "interactive", "width", "padding", "border", "color"] }, { kind: "directive", type: OptionsSourceDirective, selector: "[mOptions]", inputs: ["mOptions"] }, { kind: "component", type: SectionButtonGroupComponent, selector: "m-section-button-group", inputs: ["vertical", "align", "variant", "size", "fullWidth"] }, { kind: "component", type: SectionComponent, selector: "m-section", inputs: ["variant", "maxWidth", "heightMode", "maxHeight", "height", "align", "alignX", "alignY", "size"], outputs: ["inView"] }, { kind: "component", type: SectionFormComponent, selector: "m-section-form, m-one-section-form", inputs: ["variant", "maxWidth", "heightMode", "maxHeight", "height", "align", "size", "autofocus", "data", "validation", "disabled", "fieldConfigs", "fieldRenderIds"], outputs: ["dataChange", "submitted", "formInitialized"] }, { kind: "component", type: SectionFormItemComponent, selector: "m-section-form-item, m-one-section-form-item", inputs: ["span", "labelOrientation", "gap", "readonly", "focused", "form", "options", "dir", "element", "data", "template", "aclResolver", "formValues", "type", "label", "placeholder", "params", "required", "disabled", "icon", "prefix", "suffix", "button", "buttonAction", "buttonAcl", "maxWidth", "acl", "testid", "color", "variant", "min", "max", "step", "length", "debounce", "dateFormat", "searchLabel", "vertical", "multiple", "multiSelect", "equalWidth", "iconOnly", "isCheckboxVisible", "enlarge", "optionsAsset", "accept", "maxSize", "dropZone", "readAs", "editor", "ratio", "width", "patterns", "patternMessage", "value"], outputs: ["valueChange", "act", "fieldKey"] }, { kind: "component", type: TextOutputComponent, selector: "m-text-output", inputs: ["config", "align", "variant", "color", "fontWeight", "label", "noTranslate", "params"], outputs: ["configChange", "clicked"] }, { kind: "component", type: UserComponent, selector: "m-user", inputs: ["id", "user", "firstName", "lastName", "profilePic"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
16847
17062
  }
16848
17063
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AuthActivityPageComponent, decorators: [{
16849
17064
  type: Component,
@@ -20937,7 +21152,7 @@ class WrapperInputComponent extends ConfigComponent {
20937
21152
  break;
20938
21153
  }
20939
21154
  case InputType.TOGGLE: {
20940
- const { ToggleInputComponent } = await import('./magmonium-one-toggle-DBQMTJ6O.mjs');
21155
+ const { ToggleInputComponent } = await import('./magmonium-one-toggle-DL3lH7Xo.mjs');
20941
21156
  this.createDynamicComponent(seq, ToggleInputComponent, [], true);
20942
21157
  break;
20943
21158
  }
@@ -20949,12 +21164,12 @@ class WrapperInputComponent extends ConfigComponent {
20949
21164
  break;
20950
21165
  }
20951
21166
  case InputType.PASSWORD: {
20952
- const { PasswordInputComponent } = await import('./magmonium-one-password-rGcfKu8z.mjs');
21167
+ const { PasswordInputComponent } = await import('./magmonium-one-password-7gmB_RWb.mjs');
20953
21168
  this.createDynamicComponent(seq, PasswordInputComponent);
20954
21169
  break;
20955
21170
  }
20956
21171
  case InputType.OTP: {
20957
- const { OtpInputComponent } = await import('./magmonium-one-otp-T4eYO6SM.mjs');
21172
+ const { OtpInputComponent } = await import('./magmonium-one-otp-B-oUlDWY.mjs');
20958
21173
  this.createDynamicComponent(seq, OtpInputComponent);
20959
21174
  break;
20960
21175
  }
@@ -22120,25 +22335,365 @@ function truncateMiddlePath(path, maxLength = 48) {
22120
22335
  return trimmed.slice(0, headLen) + '...' + trimmed.slice(-tailLen);
22121
22336
  }
22122
22337
 
22123
- class FileUploadInputComponent extends BaseTextInputComponent {
22338
+ /**
22339
+ * A Field's `accept` as a list. On a tag it is one comma-separated scalar — the
22340
+ * spelling the native `accept` attribute already uses (ADR 0010) — and in a
22341
+ * `fields/<name>.yml` a list, so both arrive here.
22342
+ */
22343
+ const parseAccept = (accept) => {
22344
+ const parts = typeof accept === 'string' ? accept.split(',') : accept ?? [];
22345
+ return parts.map((part) => part.trim().toLowerCase()).filter(Boolean);
22346
+ };
22347
+ /**
22348
+ * A Field's `accept` as the text it shows in place of a placeholder: `.png`
22349
+ * reads `PNG`, `image/*` reads `IMAGE`, `image/svg+xml` reads `SVG`. Entries
22350
+ * that read alike are shown once, and the rest are joined with ` / `.
22351
+ */
22352
+ const formatAccept = (accept) => {
22353
+ const names = accept
22354
+ .filter((rule) => rule !== '*' && rule !== '*/*')
22355
+ .map((rule) => {
22356
+ if (rule.startsWith('.'))
22357
+ return rule.slice(1);
22358
+ const [type, subtype = ''] = rule.split('/');
22359
+ return subtype === '*' || !subtype ? type : subtype.split('+')[0];
22360
+ })
22361
+ .map((name) => name.toUpperCase());
22362
+ return [...new Set(names)].join(' / ');
22363
+ };
22364
+ /** A file name's extension, lower-cased and without its dot; empty if none. */
22365
+ const fileExtension = (name) => {
22366
+ const dot = name.lastIndexOf('.');
22367
+ return dot > 0 ? name.slice(dot + 1).toLowerCase() : '';
22368
+ };
22369
+ const ICON_BY_EXTENSION = {
22370
+ png: 'file-image',
22371
+ jpg: 'file-image',
22372
+ jpeg: 'file-image',
22373
+ gif: 'file-image',
22374
+ webp: 'file-image',
22375
+ svg: 'file-image',
22376
+ csv: 'file-data',
22377
+ json: 'file-data',
22378
+ xlsx: 'file-data',
22379
+ html: 'file-markup',
22380
+ xml: 'file-markup',
22381
+ css: 'file-style',
22382
+ sass: 'file-style',
22383
+ scss: 'file-style',
22384
+ js: 'file-code',
22385
+ ts: 'file-code',
22386
+ };
22387
+ /** The `file-*` icon a tile draws for a file it has no preview of. */
22388
+ const fileIcon = (name) => ICON_BY_EXTENSION[fileExtension(name)] ?? 'file-text';
22389
+ /** Mirrors the picker's own matching: `.ext`, `type/*` or an exact MIME type. */
22390
+ const fileMatchesAccept = (file, accept) => {
22391
+ if (!accept.length)
22392
+ return true;
22393
+ const name = file.name.toLowerCase();
22394
+ const mime = (file.type ?? '').toLowerCase();
22395
+ return accept.some((rule) => {
22396
+ if (rule === '*' || rule === '*/*')
22397
+ return true;
22398
+ if (rule.startsWith('.'))
22399
+ return name.endsWith(rule);
22400
+ if (rule.endsWith('/*'))
22401
+ return mime.startsWith(rule.slice(0, -1));
22402
+ return mime === rule;
22403
+ });
22404
+ };
22405
+ /**
22406
+ * Splits picked or dropped files into the ones the Field keeps and the ones it
22407
+ * reports. A drop never passes the native picker, so this is where `accept` and
22408
+ * `maxSize` are enforced rather than merely suggested (CONTEXT.md DropZone).
22409
+ */
22410
+ const screenFiles = (files, accept, maxSize) => {
22411
+ const accepted = [];
22412
+ const rejected = [];
22413
+ for (const file of files) {
22414
+ if (!fileMatchesAccept(file, accept)) {
22415
+ rejected.push({ name: file.name, reason: 'type' });
22416
+ }
22417
+ else if (maxSize && file.size > maxSize) {
22418
+ rejected.push({ name: file.name, reason: 'size' });
22419
+ }
22420
+ else {
22421
+ accepted.push(file);
22422
+ }
22423
+ }
22424
+ return { accepted, rejected };
22425
+ };
22426
+ const sameFile = (a, b) => a.name === b.name && a.size === b.size && a.lastModified === b.lastModified;
22427
+ /** Appends `incoming` to `current`, skipping a file already held. */
22428
+ const mergeFiles = (current, incoming) => incoming.reduce((held, file) => held.some((existing) => sameFile(existing, file))
22429
+ ? held
22430
+ : [...held, file], [...current]);
22431
+ const UNITS = ['B', 'KB', 'MB', 'GB'];
22432
+ const formatFileSize = (bytes) => {
22433
+ let size = bytes;
22434
+ let unit = 0;
22435
+ while (size >= 1024 && unit < UNITS.length - 1) {
22436
+ size /= 1024;
22437
+ unit++;
22438
+ }
22439
+ const figure = unit === 0 || size >= 10 ? Math.round(size) : size.toFixed(1);
22440
+ return `${figure} ${UNITS[unit]}`;
22441
+ };
22442
+
22443
+ const MIN_ZOOM = 1;
22444
+ const MAX_ZOOM = 4;
22445
+ /** Only raster images a canvas decodes everywhere enter the ImageEditor. */
22446
+ const EDITABLE_TYPES = ['image/png', 'image/jpeg', 'image/webp'];
22447
+ const isEditableImage = (file) => EDITABLE_TYPES.includes(file.type.toLowerCase());
22448
+ /** `'16:9'` as `16 / 9`; undefined for anything but two positive figures. */
22449
+ const parseRatio = (ratio) => {
22450
+ if (typeof ratio !== 'string')
22451
+ return undefined;
22452
+ const match = /^\s*(\d+(?:\.\d+)?)\s*:\s*(\d+(?:\.\d+)?)\s*$/.exec(ratio);
22453
+ if (!match)
22454
+ return undefined;
22455
+ const width = Number(match[1]);
22456
+ const height = Number(match[2]);
22457
+ return width > 0 && height > 0 ? width / height : undefined;
22458
+ };
22459
+ /**
22460
+ * The exact pixels an edited image comes out at: the Field's `width`, and the
22461
+ * height its `ratio` derives. Undefined when either is missing or malformed —
22462
+ * a Field without both has no ImageEditor.
22463
+ */
22464
+ const outputSize = (ratio, width) => {
22465
+ const aspect = parseRatio(ratio);
22466
+ const pixels = Math.round(Number(width));
22467
+ if (!aspect || !Number.isFinite(pixels) || pixels < 1)
22468
+ return undefined;
22469
+ return { width: pixels, height: Math.max(1, Math.round(pixels / aspect)) };
22470
+ };
22471
+ /** The largest box of this aspect that fits inside the image. */
22472
+ const coverCrop = (image, aspect) => image.width / image.height > aspect
22473
+ ? { width: image.height * aspect, height: image.height }
22474
+ : { width: image.width, height: image.width / aspect };
22475
+ const initialFraming = (image) => ({
22476
+ cx: image.width / 2,
22477
+ cy: image.height / 2,
22478
+ zoom: MIN_ZOOM,
22479
+ });
22480
+ const clamp$1 = (value, min, max) => Math.min(max, Math.max(min, value));
22481
+ /**
22482
+ * The framing pulled back inside the picture: zoom between the cover fit and
22483
+ * MAX_ZOOM, and the centre far enough in that the box never shows past an edge.
22484
+ */
22485
+ const clampFraming = (image, aspect, framing) => {
22486
+ const zoom = clamp$1(framing.zoom, MIN_ZOOM, MAX_ZOOM);
22487
+ const cover = coverCrop(image, aspect);
22488
+ const halfW = cover.width / zoom / 2;
22489
+ const halfH = cover.height / zoom / 2;
22490
+ return {
22491
+ zoom,
22492
+ cx: clamp$1(framing.cx, halfW, image.width - halfW),
22493
+ cy: clamp$1(framing.cy, halfH, image.height - halfH),
22494
+ };
22495
+ };
22496
+ /** The part of the source the box holds, in source pixels. */
22497
+ const cropRect = (image, aspect, framing) => {
22498
+ const { cx, cy, zoom } = clampFraming(image, aspect, framing);
22499
+ const cover = coverCrop(image, aspect);
22500
+ const width = cover.width / zoom;
22501
+ const height = cover.height / zoom;
22502
+ return { x: cx - width / 2, y: cy - height / 2, width, height };
22503
+ };
22504
+ /** `avatar.png` holding a WebP is `avatar.webp`. */
22505
+ const renameForType = (name, type) => {
22506
+ const extension = type === 'image/jpeg' ? 'jpg' : type.split('/')[1] ?? 'bin';
22507
+ const dot = name.lastIndexOf('.');
22508
+ const base = dot > 0 ? name.slice(0, dot) : name;
22509
+ return `${base}.${extension}`;
22510
+ };
22511
+ const createCanvas = (size) => {
22512
+ const canvas = document.createElement('canvas');
22513
+ canvas.width = Math.max(1, Math.round(size.width));
22514
+ canvas.height = Math.max(1, Math.round(size.height));
22515
+ return canvas;
22516
+ };
22517
+ const smoothContext = (canvas) => {
22518
+ const context = canvas.getContext('2d');
22519
+ if (!context)
22520
+ throw new Error('2d canvas unavailable');
22521
+ context.imageSmoothingEnabled = true;
22522
+ context.imageSmoothingQuality = 'high';
22523
+ return context;
22524
+ };
22525
+ /**
22526
+ * The crop drawn at exactly `output` pixels. A shrink past half is taken in
22527
+ * halving steps — one pass that drops more than every other pixel aliases —
22528
+ * and a grow is one smoothed pass.
22529
+ */
22530
+ const drawFramed = (source, rect, output) => {
22531
+ let from = source;
22532
+ let area = rect;
22533
+ while (area.width >= output.width * 2 &&
22534
+ area.height >= output.height * 2) {
22535
+ const step = createCanvas({
22536
+ width: area.width / 2,
22537
+ height: area.height / 2,
22538
+ });
22539
+ smoothContext(step).drawImage(from, area.x, area.y, area.width, area.height, 0, 0, step.width, step.height);
22540
+ from = step;
22541
+ area = { x: 0, y: 0, width: step.width, height: step.height };
22542
+ }
22543
+ const canvas = createCanvas(output);
22544
+ smoothContext(canvas).drawImage(from, area.x, area.y, area.width, area.height, 0, 0, canvas.width, canvas.height);
22545
+ return canvas;
22546
+ };
22547
+ const ENCODE_QUALITY = 0.9;
22548
+ const toBlob = (canvas, type) => new Promise((resolve) => canvas.toBlob(resolve, type, ENCODE_QUALITY));
22549
+ const hasTransparency = (canvas) => {
22550
+ const { data } = smoothContext(canvas).getImageData(0, 0, canvas.width, canvas.height);
22551
+ for (let i = 3; i < data.length; i += 4) {
22552
+ if (data[i] < 255)
22553
+ return true;
22554
+ }
22555
+ return false;
22556
+ };
22557
+ /**
22558
+ * WebP, the smallest file at this quality. A browser that cannot encode WebP
22559
+ * hands back a PNG under the WebP request without saying so, so the blob's own
22560
+ * type is what is checked: then an opaque picture goes JPEG and one with
22561
+ * transparency PNG, the smallest that keeps what it shows.
22562
+ */
22563
+ const encodeFramed = async (canvas) => {
22564
+ const webp = await toBlob(canvas, 'image/webp');
22565
+ if (webp?.type === 'image/webp')
22566
+ return webp;
22567
+ const type = hasTransparency(canvas) ? 'image/png' : 'image/jpeg';
22568
+ const fallback = await toBlob(canvas, type);
22569
+ if (!fallback)
22570
+ throw new Error('canvas encode failed');
22571
+ return fallback;
22572
+ };
22573
+
22574
+ const isTrue = (value) => value === true || value === 'true';
22575
+ class FileUploadInputComponent extends BaseInputComponent {
22124
22576
  config = input(...(ngDevMode ? [undefined, { debugName: "config" }] : /* istanbul ignore next */ []));
22577
+ value = model();
22125
22578
  files = inject(FileService);
22579
+ translate = inject(TranslateService);
22126
22580
  folderPickListener = inject(FOLDER_PICK_LISTENER, {
22127
22581
  optional: true,
22128
22582
  });
22129
- /** File name shown on the button after a file pick. */
22130
- pickedLabel = signal('', ...(ngDevMode ? [{ debugName: "pickedLabel" }] : /* istanbul ignore next */ []));
22131
- syncPickedLabel = effect(() => {
22132
- if (!this.value()) {
22133
- this.pickedLabel.set('');
22134
- }
22135
- }, ...(ngDevMode ? [{ debugName: "syncPickedLabel" }] : /* istanbul ignore next */ []));
22583
+ modalStore = inject(MODAL_STORE_REF, { optional: true });
22584
+ /**
22585
+ * Names of what `readAs: text` read, and of a folder picked. The value holds
22586
+ * the text or the folder's name, so the file names survive only here.
22587
+ */
22588
+ pickedNames = signal([], ...(ngDevMode ? [{ debugName: "pickedNames" }] : /* istanbul ignore next */ []));
22589
+ rejections = signal([], ...(ngDevMode ? [{ debugName: "rejections" }] : /* istanbul ignore next */ []));
22590
+ isDragging = signal(false, ...(ngDevMode ? [{ debugName: "isDragging" }] : /* istanbul ignore next */ []));
22591
+ // A value emptied from outside — a FormReset, a model reseeded — takes the
22592
+ // names read into it along, and the complaints about the last pick with them.
22593
+ syncPickedNames = effect(() => {
22594
+ if (this.isEmpty(this.value())) {
22595
+ this.pickedNames.set([]);
22596
+ this.rejections.set([]);
22597
+ }
22598
+ }, ...(ngDevMode ? [{ debugName: "syncPickedNames" }] : /* istanbul ignore next */ []));
22136
22599
  isFolderMode = computed(() => this.config()?.type === InputType.FOLDER ||
22137
22600
  this.config()?.mode === 'folder', ...(ngDevMode ? [{ debugName: "isFolderMode" }] : /* istanbul ignore next */ []));
22601
+ isMultiple = computed(() => !this.isFolderMode() && isTrue(this.config()?.multiple), ...(ngDevMode ? [{ debugName: "isMultiple" }] : /* istanbul ignore next */ []));
22602
+ hasDropZone = computed(() => !this.isFolderMode() && isTrue(this.config()?.dropZone), ...(ngDevMode ? [{ debugName: "hasDropZone" }] : /* istanbul ignore next */ []));
22603
+ readsText = computed(() => this.config()?.readAs === 'text', ...(ngDevMode ? [{ debugName: "readsText" }] : /* istanbul ignore next */ []));
22604
+ accept = computed(() => parseAccept(this.config()?.accept), ...(ngDevMode ? [{ debugName: "accept" }] : /* istanbul ignore next */ []));
22605
+ /**
22606
+ * The pixels the ImageEditor frames to, or undefined when this Field has no
22607
+ * ImageEditor: `editor` off, `ratio` or `width` missing, a text read or a
22608
+ * folder — none of which hold a picture to frame.
22609
+ */
22610
+ editorSize = computed(() => {
22611
+ const fieldConfig = this.config();
22612
+ if (!isTrue(fieldConfig?.editor))
22613
+ return undefined;
22614
+ if (this.isFolderMode() || this.readsText())
22615
+ return undefined;
22616
+ return outputSize(fieldConfig?.ratio, fieldConfig?.width);
22617
+ }, ...(ngDevMode ? [{ debugName: "editorSize" }] : /* istanbul ignore next */ []));
22618
+ maxSize = computed(() => {
22619
+ const size = Number(this.config()?.maxSize);
22620
+ return Number.isFinite(size) && size > 0 ? size : undefined;
22621
+ }, ...(ngDevMode ? [{ debugName: "maxSize" }] : /* istanbul ignore next */ []));
22622
+ isLocked = computed(() => {
22623
+ const fieldConfig = this.config();
22624
+ return (isTrue(this.disabled()) ||
22625
+ isTrue(this.readonly()) ||
22626
+ isTrue(fieldConfig?.disabled) ||
22627
+ isTrue(fieldConfig?.readonly));
22628
+ }, ...(ngDevMode ? [{ debugName: "isLocked" }] : /* istanbul ignore next */ []));
22629
+ /** Object URLs of the previews on show, keyed by what the value holds. */
22630
+ previews = new Map();
22631
+ heldFiles = computed(() => {
22632
+ const value = this.value();
22633
+ if (this.readsText()) {
22634
+ const texts = Array.isArray(value) ? value : [value];
22635
+ return this.pickedNames().map((name, index) => {
22636
+ const text = texts[index];
22637
+ // Only an SVG's text is still an image; any other read is not.
22638
+ const preview = typeof text === 'string' && fileExtension(name) === 'svg'
22639
+ ? this.previewFor(text, () => new Blob([text], { type: 'image/svg+xml' }))
22640
+ : undefined;
22641
+ return this.toHeld(name, text, preview);
22642
+ });
22643
+ }
22644
+ const list = Array.isArray(value) ? value : value ? [value] : [];
22645
+ return list
22646
+ .filter((item) => item instanceof File)
22647
+ .map((file) => this.toHeld(file.name, file, file.type.startsWith('image/')
22648
+ ? this.previewFor(file, () => file)
22649
+ : undefined));
22650
+ }, ...(ngDevMode ? [{ debugName: "heldFiles" }] : /* istanbul ignore next */ []));
22651
+ // A preview outlives its file only until the file leaves the value.
22652
+ releasePreviews = effect(() => {
22653
+ const held = new Set(this.heldFiles().map((file) => file.source));
22654
+ for (const [source, url] of this.previews) {
22655
+ if (held.has(source))
22656
+ continue;
22657
+ URL.revokeObjectURL(url);
22658
+ this.previews.delete(source);
22659
+ }
22660
+ }, ...(ngDevMode ? [{ debugName: "releasePreviews" }] : /* istanbul ignore next */ []));
22661
+ releaseAllPreviews = inject(DestroyRef).onDestroy(() => {
22662
+ this.previews.forEach((url) => URL.revokeObjectURL(url));
22663
+ this.previews.clear();
22664
+ });
22665
+ /** A `file` Field has no placeholder: it names the types it takes instead. */
22666
+ acceptLabel = computed(() => formatAccept(this.accept()), ...(ngDevMode ? [{ debugName: "acceptLabel" }] : /* istanbul ignore next */ []));
22667
+ dropPlaceholder = computed(() => this.acceptLabel() || this.translate.translate('drop-files-or-click'), ...(ngDevMode ? [{ debugName: "dropPlaceholder" }] : /* istanbul ignore next */ []));
22668
+ removeButton = computed(() => ({
22669
+ label: 'remove-file',
22670
+ icon: 'x',
22671
+ iconOnly: true,
22672
+ variant: 'ghost',
22673
+ one: true,
22674
+ type: 'button',
22675
+ disabled: this.isLocked(),
22676
+ }), ...(ngDevMode ? [{ debugName: "removeButton" }] : /* istanbul ignore next */ []));
22677
+ rejectionMessages = computed(() => {
22678
+ const max = formatFileSize(this.maxSize() ?? 0);
22679
+ return this.rejections().map((rejection) => {
22680
+ if (rejection.reason === 'size') {
22681
+ return {
22682
+ key: 'file-too-large',
22683
+ params: { name: rejection.name, max },
22684
+ };
22685
+ }
22686
+ if (rejection.reason === 'unreadable') {
22687
+ return { key: 'image-not-readable', params: { name: rejection.name } };
22688
+ }
22689
+ return { key: 'file-type-not-allowed', params: { name: rejection.name } };
22690
+ });
22691
+ }, ...(ngDevMode ? [{ debugName: "rejectionMessages" }] : /* istanbul ignore next */ []));
22138
22692
  buttonConfig = computed(() => {
22139
22693
  const fieldConfig = this.config();
22140
22694
  if (this.isFolderMode()) {
22141
- const folderPath = this.value()?.trim() ?? '';
22695
+ const value = this.value();
22696
+ const folderPath = typeof value === 'string' ? value.trim() : '';
22142
22697
  const hasFolderSelection = !!folderPath;
22143
22698
  const placeholder = fieldConfig?.placeholder ?? 'select-folder';
22144
22699
  return {
@@ -22155,71 +22710,246 @@ class FileUploadInputComponent extends BaseTextInputComponent {
22155
22710
  type: 'button',
22156
22711
  icon: hasFolderSelection ? undefined : fieldConfig?.icon ?? 'folder',
22157
22712
  fullWidth: hasFolderSelection,
22158
- disabled: this.disabled() === true ||
22159
- this.disabled() + '' === 'true' ||
22160
- fieldConfig?.disabled === true ||
22161
- fieldConfig?.disabled + '' === 'true' ||
22713
+ disabled: isTrue(this.disabled()) ||
22714
+ isTrue(fieldConfig?.disabled) ||
22162
22715
  !this.files.folderPickSupported(),
22163
22716
  };
22164
22717
  }
22165
- const label = this.pickedLabel();
22166
- const hasFileSelection = !!this.value()?.trim();
22718
+ // What is picked is drawn beneath the button as tiles, so the button keeps
22719
+ // naming the types it takes.
22720
+ const value = this.value();
22721
+ const fallbackLabel = !this.isMultiple() &&
22722
+ !this.heldFiles().length &&
22723
+ typeof value === 'string' &&
22724
+ value.trim()
22725
+ ? value
22726
+ : '';
22727
+ const label = fallbackLabel || this.acceptLabel();
22167
22728
  return {
22168
- label: label || (hasFileSelection ? this.value() : fieldConfig?.placeholder),
22169
- noTranslate: !!label || hasFileSelection,
22729
+ label: label || 'choose-file',
22730
+ noTranslate: !!label,
22170
22731
  variant: 'secondary',
22171
22732
  one: true,
22172
22733
  // In-Field trigger, not the form's submit — otherwise it greys out
22173
22734
  // whenever the form is invalid.
22174
22735
  type: 'button',
22175
- icon: label || hasFileSelection ? undefined : fieldConfig?.icon ?? 'upload',
22736
+ icon: label ? undefined : fieldConfig?.icon ?? 'upload',
22176
22737
  fullWidth: true,
22177
- disabled: this.disabled() === true ||
22178
- this.disabled() + '' === 'true' ||
22179
- fieldConfig?.disabled === true ||
22180
- fieldConfig?.disabled + '' === 'true',
22738
+ disabled: isTrue(this.disabled()) || isTrue(fieldConfig?.disabled),
22181
22739
  };
22182
22740
  }, ...(ngDevMode ? [{ debugName: "buttonConfig" }] : /* istanbul ignore next */ []));
22183
22741
  openPicker = () => {
22184
- const fieldConfig = this.config();
22185
- const isDisabled = this.disabled() === true ||
22186
- this.disabled() + '' === 'true' ||
22187
- fieldConfig?.disabled === true ||
22188
- fieldConfig?.disabled + '' === 'true';
22189
- const isReadonly = this.readonly() === true ||
22190
- this.readonly() + '' === 'true' ||
22191
- fieldConfig?.readonly === true ||
22192
- fieldConfig?.readonly + '' === 'true';
22193
- if (isDisabled || isReadonly)
22742
+ if (this.isLocked())
22194
22743
  return;
22195
22744
  if (this.isFolderMode()) {
22196
22745
  void this.pickFolder();
22197
22746
  return;
22198
22747
  }
22199
- void this.pickFile();
22748
+ void this.pickFiles();
22200
22749
  };
22201
- pickFile = async () => {
22202
- const fieldConfig = this.config();
22750
+ onSpace = (event) => {
22751
+ event.preventDefault();
22752
+ this.openPicker();
22753
+ };
22754
+ onDragOver = (event) => {
22755
+ event.preventDefault();
22756
+ if (this.isLocked())
22757
+ return;
22758
+ if (event.dataTransfer)
22759
+ event.dataTransfer.dropEffect = 'copy';
22760
+ this.isDragging.set(true);
22761
+ };
22762
+ onDrop = (event) => {
22763
+ event.preventDefault();
22764
+ this.isDragging.set(false);
22765
+ if (this.isLocked())
22766
+ return;
22767
+ const dropped = Array.from(event.dataTransfer?.files ?? []);
22768
+ // One file for a single Field: the first dropped, the rest ignored, the way
22769
+ // the picker itself would have refused a second selection.
22770
+ void this.take(this.isMultiple() ? dropped : dropped.slice(0, 1));
22771
+ };
22772
+ removeAt = (index, event) => {
22773
+ // Inside the DropZone the removal would otherwise also open the picker.
22774
+ event.stopPropagation();
22775
+ if (this.isLocked())
22776
+ return;
22777
+ this.rejections.set([]);
22778
+ const value = this.value();
22779
+ if (this.isMultiple() && Array.isArray(value)) {
22780
+ const next = [...value];
22781
+ next.splice(index, 1);
22782
+ this.pickedNames.update((names) => names.filter((_, i) => i !== index));
22783
+ this.setValue(next);
22784
+ return;
22785
+ }
22786
+ this.pickedNames.set([]);
22787
+ this.setValue(undefined);
22788
+ };
22789
+ pickFiles = async () => {
22203
22790
  const { files } = await this.files.getFiles({
22204
- accept: fieldConfig?.accept,
22791
+ accept: this.accept(),
22792
+ multiple: this.isMultiple(),
22205
22793
  });
22206
- const file = files[0];
22207
- if (!file)
22794
+ await this.take(files);
22795
+ };
22796
+ take = async (incoming) => {
22797
+ if (!incoming.length)
22208
22798
  return;
22209
- const text = await file.text();
22210
- this.pickedLabel.set(file.name);
22211
- this.setValue(text);
22799
+ const { accepted, rejected } = await this.screen(incoming);
22800
+ this.rejections.set(rejected);
22801
+ if (!accepted.length) {
22802
+ this.touched.set(true);
22803
+ return;
22804
+ }
22805
+ if (this.readsText()) {
22806
+ const texts = await Promise.all(accepted.map((file) => file.text()));
22807
+ const names = accepted.map((file) => file.name);
22808
+ if (this.isMultiple()) {
22809
+ const current = this.value();
22810
+ this.pickedNames.update((held) => [...held, ...names]);
22811
+ const held = Array.isArray(current) ? current : [];
22812
+ this.setValue([...held, ...texts]);
22813
+ }
22814
+ else {
22815
+ this.pickedNames.set(names.slice(0, 1));
22816
+ this.setValue(texts[0]);
22817
+ }
22818
+ return;
22819
+ }
22820
+ if (this.isMultiple()) {
22821
+ const current = this.value();
22822
+ const held = Array.isArray(current)
22823
+ ? current.filter((item) => item instanceof File)
22824
+ : [];
22825
+ this.setValue(mergeFiles(held, accepted));
22826
+ }
22827
+ else {
22828
+ this.setValue(accepted[0]);
22829
+ }
22830
+ };
22831
+ /**
22832
+ * The files this Field keeps. Without an ImageEditor, `accept` and `maxSize`
22833
+ * in one pass. With one, each raster image is framed first and the size limit
22834
+ * judged on what the framing produced, since that is what gets uploaded.
22835
+ */
22836
+ screen = async (incoming) => {
22837
+ const size = this.editorSize();
22838
+ if (!size || !this.modalStore) {
22839
+ return screenFiles(incoming, this.accept(), this.maxSize());
22840
+ }
22841
+ const typed = screenFiles(incoming, this.accept(), undefined);
22842
+ const edited = [];
22843
+ const rejected = [...typed.rejected];
22844
+ // One ImageEditor at a time, in pick order. A cancel drops that image only.
22845
+ for (const file of typed.accepted) {
22846
+ if (!isEditableImage(file)) {
22847
+ edited.push(file);
22848
+ continue;
22849
+ }
22850
+ const result = await this.openEditor(file, size);
22851
+ if (result?.file)
22852
+ edited.push(result.file);
22853
+ else if (result?.unreadable) {
22854
+ rejected.push({ name: file.name, reason: 'unreadable' });
22855
+ }
22856
+ }
22857
+ const sized = screenFiles(edited, [], this.maxSize());
22858
+ return {
22859
+ accepted: sized.accepted,
22860
+ rejected: [...rejected, ...sized.rejected],
22861
+ };
22862
+ };
22863
+ openEditor = async (file, size) => {
22864
+ const modalStore = this.modalStore;
22865
+ if (!modalStore)
22866
+ return undefined;
22867
+ const { ImageEditorComponent } = await import('./magmonium-one-image-editor-aBl2dVEc.mjs');
22868
+ const ratio = String(this.config()?.ratio ?? '');
22869
+ return new Promise((resolve) => {
22870
+ const modalRef = new ModalRef();
22871
+ const modalId = modalStore.open({
22872
+ component: ImageEditorComponent,
22873
+ providers: [{ provide: MODAL_REF, useValue: modalRef }],
22874
+ bindings: [
22875
+ inputBinding('file', () => file),
22876
+ inputBinding('ratio', () => ratio),
22877
+ inputBinding('width', () => size.width),
22878
+ ],
22879
+ // Wider than a confirm's default 440px, so the stage is big enough to
22880
+ // frame in; the editor fills whatever width the modal gives it.
22881
+ config: { maxWidth: '560px' },
22882
+ });
22883
+ modalRef.onClose((result) => {
22884
+ resolve(result);
22885
+ modalStore.close(modalId);
22886
+ });
22887
+ });
22212
22888
  };
22213
22889
  pickFolder = async () => {
22214
22890
  const picked = await this.files.pickFolder();
22215
22891
  if (!picked)
22216
22892
  return;
22217
- this.pickedLabel.set(picked.name);
22893
+ this.pickedNames.set([picked.name]);
22218
22894
  this.setValue(picked.name);
22219
22895
  this.folderPickListener?.(picked.handle, picked.name);
22220
22896
  };
22897
+ previewFor = (source, blob) => {
22898
+ if (typeof URL.createObjectURL !== 'function')
22899
+ return undefined;
22900
+ let url = this.previews.get(source);
22901
+ if (!url) {
22902
+ url = URL.createObjectURL(blob());
22903
+ this.previews.set(source, url);
22904
+ }
22905
+ return url;
22906
+ };
22907
+ toHeld = (name, source, preview) => ({
22908
+ name,
22909
+ source,
22910
+ kind: fileExtension(name).toUpperCase() || 'FILE',
22911
+ icon: fileIcon(name),
22912
+ preview,
22913
+ });
22914
+ setValue = (value) => {
22915
+ this.value.set(value);
22916
+ this.touched.set(true);
22917
+ };
22918
+ isEmpty = (value) => value === undefined ||
22919
+ value === null ||
22920
+ value === '' ||
22921
+ (Array.isArray(value) && value.length === 0);
22221
22922
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FileUploadInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
22222
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: FileUploadInputComponent, isStandalone: true, selector: "m-file-upload-input", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
22923
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: FileUploadInputComponent, isStandalone: true, selector: "m-file-upload-input", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, usesInheritance: true, ngImport: i0, template: `
22924
+ <ng-template #fileList>
22925
+ <ul class="file-tiles" [class.file-tiles--below]="!hasDropZone()">
22926
+ @for (held of heldFiles(); track $index) {
22927
+ <li class="file-tile" [attr.title]="held.name">
22928
+ <div class="file-tile__box">
22929
+ @if (held.preview) {
22930
+ <img
22931
+ class="file-tile__preview"
22932
+ [src]="held.preview"
22933
+ [alt]="held.name"
22934
+ />
22935
+ } @else {
22936
+ <div class="file-tile__type">
22937
+ <m-icon [name]="held.icon" color="mm" [one]="true" />
22938
+ <span class="file-tile__kind">{{ held.kind }}</span>
22939
+ </div>
22940
+ }
22941
+ <span class="file-tile__remove">
22942
+ <m-button
22943
+ [config]="removeButton()"
22944
+ (click)="removeAt($index, $event)"
22945
+ />
22946
+ </span>
22947
+ </div>
22948
+ <span class="file-tile__name">{{ held.name }}</span>
22949
+ </li>
22950
+ }
22951
+ </ul>
22952
+ </ng-template>
22223
22953
  @if (config(); as fieldConfig) {
22224
22954
  @if (fieldConfig.label) {
22225
22955
  <m-label
@@ -22229,7 +22959,49 @@ class FileUploadInputComponent extends BaseTextInputComponent {
22229
22959
  [disabled]="disabled()"
22230
22960
  />
22231
22961
  }
22232
- <m-button (click)="openPicker()" [config]="buttonConfig()" />
22962
+ @if (hasDropZone()) {
22963
+ <div
22964
+ class="drop-zone"
22965
+ role="button"
22966
+ [attr.tabindex]="isLocked() ? -1 : 0"
22967
+ [attr.aria-disabled]="isLocked()"
22968
+ [class.drop-zone--dragging]="isDragging()"
22969
+ [class.drop-zone--locked]="isLocked()"
22970
+ [class.error]="showErrors() || rejections().length > 0"
22971
+ (click)="openPicker()"
22972
+ (keydown.enter)="openPicker()"
22973
+ (keydown.space)="onSpace($event)"
22974
+ (dragover)="onDragOver($event)"
22975
+ (dragleave)="isDragging.set(false)"
22976
+ (drop)="onDrop($event)"
22977
+ >
22978
+ @if (heldFiles().length) {
22979
+ <ng-container *ngTemplateOutlet="fileList" />
22980
+ } @else {
22981
+ <div class="drop-zone__empty">
22982
+ <m-icon
22983
+ [name]="fieldConfig.icon ?? 'upload'"
22984
+ color="mm"
22985
+ [one]="true"
22986
+ />
22987
+ <span>{{ dropPlaceholder() }}</span>
22988
+ </div>
22989
+ }
22990
+ </div>
22991
+ } @else {
22992
+ <m-button (click)="openPicker()" [config]="buttonConfig()" />
22993
+ @if (heldFiles().length) {
22994
+ <ng-container *ngTemplateOutlet="fileList" />
22995
+ }
22996
+ }
22997
+ @for (rejection of rejectionMessages(); track $index) {
22998
+ <m-text-output
22999
+ variant="footer"
23000
+ color="error"
23001
+ [label]="rejection.key"
23002
+ [params]="rejection.params"
23003
+ />
23004
+ }
22233
23005
  @if (showErrors()) {
22234
23006
  @for (error of errors(); track $index) {
22235
23007
  <m-text-output
@@ -22240,11 +23012,40 @@ class FileUploadInputComponent extends BaseTextInputComponent {
22240
23012
  }
22241
23013
  }
22242
23014
  }
22243
- `, isInline: true, styles: [":host{display:block}\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: LabelComponent, selector: "m-label", inputs: ["for", "placeholder", "params", "required", "disabled", "color"] }, { kind: "component", type: TextOutputComponent, selector: "m-text-output", inputs: ["config", "align", "variant", "color", "fontWeight", "label", "noTranslate", "params"], outputs: ["configChange", "clicked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
23015
+ `, 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:block}.drop-zone{display:flex;align-items:center;background:var(--m-background);height:calc(var(--input-size, 1em) * 2);min-height:calc(var(--input-size, 1em) * 2);border-width:max(1px,var(--input-size, 1em) * .0625);border-radius:calc(var(--input-size, 1em) * .4);padding:calc(var(--input-size, 1em) * .5) calc(var(--input-size, 1em) * .5);gap:calc(var(--input-size, 1em) * .375);font-size:var(--input-size, 1em);border-width:var(--m-input-border-width, 2px);border-radius:var(--m-input-radius, 4px);height:calc(var(--input-size, 1em) * 2.25);min-height:calc(var(--input-size, 1em) * 2.25);padding-top:0;padding-bottom:0;border-color:var(--m-input-color, var(--m-mm));transition:border-color .2s ease,box-shadow .2s ease,background-color .2s ease,opacity .2s ease}.drop-zone:hover:not(:disabled){background-color:color-mix(in srgb,var(--m-input-color, var(--m-mm)) 6%,transparent)}.drop-zone:disabled{opacity:.6;cursor:not-allowed}.drop-zone{border-style:solid;backdrop-filter:var(--m-text-input-backdrop-filter, none);-webkit-backdrop-filter:var(--m-text-input-backdrop-filter, none);box-shadow:var(--m-text-input-shadow, none)}.drop-zone:has(>m-one-button,>m-button,>.input-indicator,>.input-suffix,>m-icon:last-child){padding-right:0}.drop-zone:focus-visible:not(:disabled),.drop-zone:focus-within:not(:disabled){border-color:var(--m-text-input-focus-border, color-mix(in srgb, var(--m-focus) 45%, transparent));box-shadow:var(--m-text-input-shadow, none)}.drop-zone:has(.error){border-color:var(--m-error);box-shadow:none}.drop-zone:has(.error):focus-within{border-color:var(--m-error);box-shadow:none}.drop-zone input,.drop-zone textarea{flex:1;border:none;outline:none;background:transparent;color:var(--m-text);font-family:inherit;font-size:inherit;padding:0}.drop-zone input:focus,.drop-zone textarea:focus{border-color:transparent;box-shadow:none}.drop-zone{flex-direction:column;align-items:stretch;justify-content:center;width:100%;height:auto;min-height:calc(var(--m-textarea-input-height, 4.5em) + 1.5em);padding:.75em;border-style:dashed;cursor:pointer}.drop-zone--dragging{border-color:var(--m-focus);background:var(--m-focus-bg)}.drop-zone--locked{cursor:not-allowed;opacity:.6}.drop-zone.error{border-color:var(--m-error)}.drop-zone__empty{display:flex;flex-direction:column;align-items:center;gap:.5em;color:var(--m-mm);text-align:center}.file-tiles{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;justify-content:center;gap:.75em}.file-tiles--below{margin-top:.75em}.file-tile{--m-file-tile-size: 150px;display:flex;flex-direction:column;gap:.25em;width:var(--m-file-tile-size);max-width:100%}.file-tile__box{position:relative;width:100%;aspect-ratio:1;border:1px solid var(--m-border);border-radius:var(--m-input-radius, 4px);background:var(--m-background-lite);overflow:hidden}.file-tile__preview{display:block;width:100%;height:100%;object-fit:cover}.file-tile__type{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5em;height:100%;color:var(--m-mm);--m-icon-size: 2.5em}.file-tile__kind{font-weight:600;letter-spacing:.05em}.file-tile__remove{position:absolute;top:.25em;right:.25em;display:flex;border-radius:50%;background:var(--m-background)}.file-tile__name{text-align:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.7em;color:var(--m-text)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { 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: LabelComponent, selector: "m-label", inputs: ["for", "placeholder", "params", "required", "disabled", "color"] }, { kind: "component", type: TextOutputComponent, selector: "m-text-output", inputs: ["config", "align", "variant", "color", "fontWeight", "label", "noTranslate", "params"], outputs: ["configChange", "clicked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
22244
23016
  }
22245
23017
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FileUploadInputComponent, decorators: [{
22246
23018
  type: Component,
22247
23019
  args: [{ selector: 'm-file-upload-input', template: `
23020
+ <ng-template #fileList>
23021
+ <ul class="file-tiles" [class.file-tiles--below]="!hasDropZone()">
23022
+ @for (held of heldFiles(); track $index) {
23023
+ <li class="file-tile" [attr.title]="held.name">
23024
+ <div class="file-tile__box">
23025
+ @if (held.preview) {
23026
+ <img
23027
+ class="file-tile__preview"
23028
+ [src]="held.preview"
23029
+ [alt]="held.name"
23030
+ />
23031
+ } @else {
23032
+ <div class="file-tile__type">
23033
+ <m-icon [name]="held.icon" color="mm" [one]="true" />
23034
+ <span class="file-tile__kind">{{ held.kind }}</span>
23035
+ </div>
23036
+ }
23037
+ <span class="file-tile__remove">
23038
+ <m-button
23039
+ [config]="removeButton()"
23040
+ (click)="removeAt($index, $event)"
23041
+ />
23042
+ </span>
23043
+ </div>
23044
+ <span class="file-tile__name">{{ held.name }}</span>
23045
+ </li>
23046
+ }
23047
+ </ul>
23048
+ </ng-template>
22248
23049
  @if (config(); as fieldConfig) {
22249
23050
  @if (fieldConfig.label) {
22250
23051
  <m-label
@@ -22254,7 +23055,49 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
22254
23055
  [disabled]="disabled()"
22255
23056
  />
22256
23057
  }
22257
- <m-button (click)="openPicker()" [config]="buttonConfig()" />
23058
+ @if (hasDropZone()) {
23059
+ <div
23060
+ class="drop-zone"
23061
+ role="button"
23062
+ [attr.tabindex]="isLocked() ? -1 : 0"
23063
+ [attr.aria-disabled]="isLocked()"
23064
+ [class.drop-zone--dragging]="isDragging()"
23065
+ [class.drop-zone--locked]="isLocked()"
23066
+ [class.error]="showErrors() || rejections().length > 0"
23067
+ (click)="openPicker()"
23068
+ (keydown.enter)="openPicker()"
23069
+ (keydown.space)="onSpace($event)"
23070
+ (dragover)="onDragOver($event)"
23071
+ (dragleave)="isDragging.set(false)"
23072
+ (drop)="onDrop($event)"
23073
+ >
23074
+ @if (heldFiles().length) {
23075
+ <ng-container *ngTemplateOutlet="fileList" />
23076
+ } @else {
23077
+ <div class="drop-zone__empty">
23078
+ <m-icon
23079
+ [name]="fieldConfig.icon ?? 'upload'"
23080
+ color="mm"
23081
+ [one]="true"
23082
+ />
23083
+ <span>{{ dropPlaceholder() }}</span>
23084
+ </div>
23085
+ }
23086
+ </div>
23087
+ } @else {
23088
+ <m-button (click)="openPicker()" [config]="buttonConfig()" />
23089
+ @if (heldFiles().length) {
23090
+ <ng-container *ngTemplateOutlet="fileList" />
23091
+ }
23092
+ }
23093
+ @for (rejection of rejectionMessages(); track $index) {
23094
+ <m-text-output
23095
+ variant="footer"
23096
+ color="error"
23097
+ [label]="rejection.key"
23098
+ [params]="rejection.params"
23099
+ />
23100
+ }
22258
23101
  @if (showErrors()) {
22259
23102
  @for (error of errors(); track $index) {
22260
23103
  <m-text-output
@@ -22265,8 +23108,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
22265
23108
  }
22266
23109
  }
22267
23110
  }
22268
- `, imports: [ButtonComponent, LabelComponent, TextOutputComponent], changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}\n"] }]
22269
- }], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }] } });
23111
+ `, imports: [
23112
+ NgTemplateOutlet,
23113
+ ButtonComponent,
23114
+ IconComponent,
23115
+ LabelComponent,
23116
+ TextOutputComponent,
23117
+ ], 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)}}:host{display:block}.drop-zone{display:flex;align-items:center;background:var(--m-background);height:calc(var(--input-size, 1em) * 2);min-height:calc(var(--input-size, 1em) * 2);border-width:max(1px,var(--input-size, 1em) * .0625);border-radius:calc(var(--input-size, 1em) * .4);padding:calc(var(--input-size, 1em) * .5) calc(var(--input-size, 1em) * .5);gap:calc(var(--input-size, 1em) * .375);font-size:var(--input-size, 1em);border-width:var(--m-input-border-width, 2px);border-radius:var(--m-input-radius, 4px);height:calc(var(--input-size, 1em) * 2.25);min-height:calc(var(--input-size, 1em) * 2.25);padding-top:0;padding-bottom:0;border-color:var(--m-input-color, var(--m-mm));transition:border-color .2s ease,box-shadow .2s ease,background-color .2s ease,opacity .2s ease}.drop-zone:hover:not(:disabled){background-color:color-mix(in srgb,var(--m-input-color, var(--m-mm)) 6%,transparent)}.drop-zone:disabled{opacity:.6;cursor:not-allowed}.drop-zone{border-style:solid;backdrop-filter:var(--m-text-input-backdrop-filter, none);-webkit-backdrop-filter:var(--m-text-input-backdrop-filter, none);box-shadow:var(--m-text-input-shadow, none)}.drop-zone:has(>m-one-button,>m-button,>.input-indicator,>.input-suffix,>m-icon:last-child){padding-right:0}.drop-zone:focus-visible:not(:disabled),.drop-zone:focus-within:not(:disabled){border-color:var(--m-text-input-focus-border, color-mix(in srgb, var(--m-focus) 45%, transparent));box-shadow:var(--m-text-input-shadow, none)}.drop-zone:has(.error){border-color:var(--m-error);box-shadow:none}.drop-zone:has(.error):focus-within{border-color:var(--m-error);box-shadow:none}.drop-zone input,.drop-zone textarea{flex:1;border:none;outline:none;background:transparent;color:var(--m-text);font-family:inherit;font-size:inherit;padding:0}.drop-zone input:focus,.drop-zone textarea:focus{border-color:transparent;box-shadow:none}.drop-zone{flex-direction:column;align-items:stretch;justify-content:center;width:100%;height:auto;min-height:calc(var(--m-textarea-input-height, 4.5em) + 1.5em);padding:.75em;border-style:dashed;cursor:pointer}.drop-zone--dragging{border-color:var(--m-focus);background:var(--m-focus-bg)}.drop-zone--locked{cursor:not-allowed;opacity:.6}.drop-zone.error{border-color:var(--m-error)}.drop-zone__empty{display:flex;flex-direction:column;align-items:center;gap:.5em;color:var(--m-mm);text-align:center}.file-tiles{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;justify-content:center;gap:.75em}.file-tiles--below{margin-top:.75em}.file-tile{--m-file-tile-size: 150px;display:flex;flex-direction:column;gap:.25em;width:var(--m-file-tile-size);max-width:100%}.file-tile__box{position:relative;width:100%;aspect-ratio:1;border:1px solid var(--m-border);border-radius:var(--m-input-radius, 4px);background:var(--m-background-lite);overflow:hidden}.file-tile__preview{display:block;width:100%;height:100%;object-fit:cover}.file-tile__type{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5em;height:100%;color:var(--m-mm);--m-icon-size: 2.5em}.file-tile__kind{font-weight:600;letter-spacing:.05em}.file-tile__remove{position:absolute;top:.25em;right:.25em;display:flex;border-radius:50%;background:var(--m-background)}.file-tile__name{text-align:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.7em;color:var(--m-text)}\n"] }]
23118
+ }], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
22270
23119
 
22271
23120
  var fileUploadInput = /*#__PURE__*/Object.freeze({
22272
23121
  __proto__: null,
@@ -29646,6 +30495,172 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
29646
30495
  args: ['click', ['$event']]
29647
30496
  }] } });
29648
30497
 
30498
+ /**
30499
+ * The route half of a [NavVisibilityRule] (m-one-ui CONTEXT.md). One guard for
30500
+ * the whole tree rather than one per rule: every emitted route already carries
30501
+ * `data: { navId }` (libs/one ADR 0014), and a NavId *is* its ancestry, so the
30502
+ * guard walks up from the route it was stamped on and asks every ancestor's
30503
+ * registration in turn.
30504
+ *
30505
+ * That ancestry walk is why the cascade works at all. Routes are emitted flat
30506
+ * until a Screen draws a RouterOutletControl, so a child Nav is routinely a
30507
+ * *sibling* route rather than a nested one — a `canActivate` on the parent
30508
+ * entry would guard nothing below it. Walking the id covers both shapes with
30509
+ * one stamp and no knowledge of which one the emitter chose.
30510
+ *
30511
+ * It **waits** where the menu hides. `navVisible` answering `undefined` means
30512
+ * the state the gate reads has not arrived, and a Router can hold a navigation
30513
+ * where a panel cannot hold a render: refusing on `undefined` would bounce
30514
+ * every cold deep link into a guarded page, which is the whole case the gate's
30515
+ * arguments are resolved before it is called for.
30516
+ *
30517
+ * It also **fires the loads itself, and waits for them** before it asks any
30518
+ * gate. The nav store fires them too, but a deep link is precisely the
30519
+ * navigation that happens before any panel has drawn — the store's own effect
30520
+ * has not run for this address yet, and waiting for it would be waiting for the
30521
+ * thing the wait is supposed to end. A load answers a promise that settles when
30522
+ * its request is done, and a gate is only asked after every one has: a gate
30523
+ * reading a map that already holds *other* keys answers `false`, not
30524
+ * `undefined`, and believing it before the load landed would bounce a
30525
+ * reachable page. A CacheMethod shares one in-flight request per argument set,
30526
+ * so the two firings cost one request between them.
30527
+ *
30528
+ * And it **awaits** where the menu remembers. A gate may be `async` — an
30529
+ * entitlement is routinely a call the client has to make — and awaiting it is
30530
+ * the plainest thing a `canActivate` does. The panel cannot: it has already
30531
+ * rendered, so the nav store settles the same promise once and keeps the
30532
+ * answer.
30533
+ */
30534
+ /**
30535
+ * Every path parameter on the chain being activated, deepest last — the same
30536
+ * merge `NavStore` does on a finished navigation, redone here because the
30537
+ * guard runs *before* that. Two dynamic Navs on one path each contribute their
30538
+ * own (`:id/:issueId`), and only the chain holds both.
30539
+ */
30540
+ const paramsOf = (root) => {
30541
+ const params = {};
30542
+ for (let r = root; r; r = r.firstChild) {
30543
+ for (const [key, value] of Object.entries(r.params ?? {})) {
30544
+ if (typeof value === 'string')
30545
+ params[key] = value;
30546
+ }
30547
+ }
30548
+ return params;
30549
+ };
30550
+ /**
30551
+ * The NavId this route was stamped with, read off the deepest entry that
30552
+ * carries one. `data` inherits down the chain, so a child route in a Screen's
30553
+ * own router file reads its own stamp and not its host's.
30554
+ */
30555
+ const navIdOf = (route) => {
30556
+ const stamped = route.data?.['navId'];
30557
+ return typeof stamped === 'string' && stamped ? stamped : undefined;
30558
+ };
30559
+ /**
30560
+ * Last-wins across the multi-provided maps, matching how `NavStore` resolves a
30561
+ * registration: the library provides its Platform panels first so an app
30562
+ * registering at the same NavId replaces them (ADR 0016).
30563
+ */
30564
+ const entryAt = (maps, navId) => {
30565
+ for (let i = maps.length - 1; i >= 0; i--) {
30566
+ const entry = maps[i]()[navId];
30567
+ if (entry !== undefined)
30568
+ return entry;
30569
+ }
30570
+ return undefined;
30571
+ };
30572
+ const navVisibilityGuard = (route, state) => {
30573
+ const router = inject(Router);
30574
+ // Multi-provided, so the injected value is the array of maps and not one —
30575
+ // the same cast `NavStore` makes, and last-wins for the same reason: the
30576
+ // library provides its Platform panels first (ADR 0016).
30577
+ const maps = inject(NAV_WIDGET_MAP, {
30578
+ optional: true,
30579
+ }) ?? [];
30580
+ const navId = navIdOf(route);
30581
+ if (!navId)
30582
+ return of(true);
30583
+ const params = paramsOf(state.root);
30584
+ /**
30585
+ * Every gate at or above, and its load. Read once and untracked: firing a
30586
+ * store method inside the `computed` below would write state during a read,
30587
+ * and the loads are about *starting* the fetch rather than about what the
30588
+ * gates then say.
30589
+ */
30590
+ const gates = navIdChain(navId).flatMap((id) => {
30591
+ const entry = entryAt(maps, id);
30592
+ return entry && isNavVisibilityConfig(entry) ? [entry] : [];
30593
+ });
30594
+ // Fired together, awaited together: the loads are independent. A load that
30595
+ // throws or rejects ends its wait rather than the navigation — the gate is
30596
+ // still asked, and decides on whatever state there is.
30597
+ const loads = gates.flatMap((gate) => {
30598
+ try {
30599
+ const started = gate.navVisibleLoad?.(params);
30600
+ return isThenable(started)
30601
+ ? [Promise.resolve(started).catch(() => undefined)]
30602
+ : [];
30603
+ }
30604
+ catch {
30605
+ return [];
30606
+ }
30607
+ });
30608
+ /**
30609
+ * Every rule at or above this route, as one answer. `false` the moment any
30610
+ * ancestor refuses — a subtree is unreachable when its root is — and
30611
+ * `undefined` while any of them is still unresolved, so the wait below is a
30612
+ * wait for *all* of them rather than for the first one that happened to
30613
+ * answer.
30614
+ */
30615
+ const verdict = computed(() => {
30616
+ let unresolved = false;
30617
+ const asked = [];
30618
+ for (const gate of gates) {
30619
+ const answer = gate.navVisible(params);
30620
+ // A synchronous `false` settles it whatever the rest say, and without
30621
+ // firing the requests the asynchronous ones would have made.
30622
+ if (answer === false)
30623
+ return false;
30624
+ if (answer === undefined)
30625
+ unresolved = true;
30626
+ else if (isPromise(answer))
30627
+ asked.push(answer);
30628
+ }
30629
+ // Still missing an argument: say nothing yet, so the wait below holds
30630
+ // rather than the gate reading an absent value as a refusal.
30631
+ if (unresolved)
30632
+ return undefined;
30633
+ if (!asked.length)
30634
+ return true;
30635
+ // Every gate at or above has to say yes, so the whole chain is one promise
30636
+ // — and `all` rather than a loop of awaits, the requests being independent.
30637
+ return Promise.all(asked).then((answers) => answers.every((answer) => answer === true));
30638
+ }, ...(ngDevMode ? [{ debugName: "verdict" }] : /* istanbul ignore next */ []));
30639
+ // Created here, in the guard's injection context — `toObservable` cannot be
30640
+ // called from inside the pipe below.
30641
+ const verdict$ = toObservable(verdict);
30642
+ // No load to wait on asks the gate at once, as before any load could answer.
30643
+ const loaded$ = loads.length
30644
+ ? from(Promise.all(loads))
30645
+ : of(undefined);
30646
+ return loaded$.pipe(
30647
+ // Asked fresh once the loads are done, not replayed: the observable's last
30648
+ // value may predate the landing it was waiting for. Still `undefined` means
30649
+ // an argument has not arrived yet, so hold for the next change.
30650
+ switchMap$1(() => verdict$.pipe(startWith(undefined))), map(() => verdict()), filter((answer) => answer !== undefined), take(1), switchMap$1((answer) => (isPromise(answer) ? from(answer) : of(answer))),
30651
+ // A gate that threw is a gate that did not say yes — closed rather than
30652
+ // open, the direction the nav store's own resolution takes and for the same
30653
+ // reason.
30654
+ catchError(() => of(false)),
30655
+ // The landing is the one address always guaranteed to exist: the nearest
30656
+ // visible ancestor is routinely a grouping Nav that emits no route at all,
30657
+ // and staying put strands a cold deep link on nothing (CONTEXT.md
30658
+ // NavVisibilitySource).
30659
+ map((allowed) => allowed || router.createUrlTree(['/'])));
30660
+ };
30661
+ const isThenable = (value) => typeof value?.then === 'function';
30662
+ const isPromise = (value) => typeof value?.then === 'function';
30663
+
29649
30664
  class NavTrailComponent {
29650
30665
  config = input.required(...(ngDevMode ? [{ debugName: "config" }] : /* istanbul ignore next */ []));
29651
30666
  Size = Size;
@@ -35546,5 +36561,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
35546
36561
  * Generated bundle index. Do not edit.
35547
36562
  */
35548
36563
 
35549
- export { DEFAULT_FILTER_RANGE_MODE as $, ACCESS_DOMAINS as A, BaseInputComponent as B, COMPONENT_INPUT_REGISTRY as C, CardComponent as D, CardWrapperComponent as E, CarouselComponent as F, ChartComponent as G, ChatBubbleComponent as H, IS_DESIGN_MODE as I, CheckboxInputComponent as J, ClearableInputComponent as K, LabelComponent as L, ColComponent as M, ColorPickerInputComponent as N, CommentItemComponent as O, CommentsApiService as P, CommentsComponent as Q, CommentsStore as R, CompactNumberPipe as S, TranslatePipe as T, ComponentInputComponent as U, ComponentStepperComponent as V, ConfigComponent as W, ConfirmComponent as X, ContextMenuComponent as Y, CustomIconClass as Z, CustomIconEditComponent as _, BaseTextInputComponent as a, MoneyPipe as a$, DEFAULT_FILTER_VARIANT as a0, DEFAULT_NAV_PARAM as a1, DEFAULT_NAV_SEGMENT as a2, DEFAULT_SIZE as a3, DashboardCardComponent as a4, DateInputComponent as a5, DatePickerComponent as a6, DeviceService as a7, DomService as a8, Domain as a9, IconComponent as aA, ImgComponent as aB, InputType as aC, InstrumentScoreComponent as aD, InterceptorObservables as aE, JumbotronComponent as aF, KeyValueComponent as aG, LAYOUT_ASSET_FOLDER as aH, LOGIN_COMPONENT as aI, LOGIN_STORE as aJ, LanguageComponent as aK, ListComponent as aL, LogoComponent as aM, MAG_SOCKET_EVENT as aN, MHeroColorDirective as aO, MHeroComponent as aP, MODAL_REF as aQ, MODAL_STORE_REF as aR, MRefDirective as aS, MStepComponent as aT, MURL_PARAM as aU, MURL_SEP as aV, ManifestEnrichmentService as aW, MenuComponent as aX, ModalDirective as aY, ModalRef as aZ, ModalStore as a_, DotGridComponent as aa, DragListDirective as ab, DragListItemDirective as ac, DraggableDirective as ad, DropdownInputComponent as ae, FILTER_GROUP_CONTEXT as af, FILTER_RANGE_MODES as ag, FILTER_VARIANTS as ah, FLEX_VARIANTS as ai, FOLDER_PICK_LISTENER as aj, FORM_ASSET_FOLDER as ak, FileService as al, FileUploadDirective as am, FileUploadInputComponent as an, FlexComponent as ao, FlexItemComponent as ap, FormGroupComponent as aq, FrameComponent as ar, FreezeService as as, GRID_BREAKPOINTS as at, GetNavService as au, HeaderComponent$1 as av, HighlightDirective as aw, HttpService as ax, ICON_SOURCE as ay, IS_SIDE_PANEL as az, TextOutputComponent as b, SearchUserPanelComponent as b$, MultiRangeInputComponent as b0, MurlUrlSerializer as b1, NAV_DEFAULT_MURL as b2, NAV_ID_SEP as b3, NAV_MAIN_BUTTONS as b4, NAV_SEGMENT_RE as b5, NAV_STORE_REF as b6, NAV_WC_COMPONENTS as b7, NAV_WIDGET_MAP as b8, NavComponent as b9, PanelComponent as bA, PercentagePipe as bB, PlaygroundComponent as bC, PositionDirective as bD, PwaInstallComponent as bE, ROOT_NAV$1 as bF, RadioGroupComponent as bG, RadioInputComponent as bH, RangeInputComponent as bI, RatingInputComponent as bJ, ReactiveElementComponent as bK, RemoteComponent as bL, RemoteLoaderService as bM, ResizeElementComponent as bN, RouteContainer as bO, RowComponent as bP, SEARCH_QUERY as bQ, SEARCH_RESULTS_EVENT as bR, SECTION_ACCORDION_GROUP as bS, SECTION_FORM_CONTEXT as bT, SHARED_ICONS as bU, SIZE_CONTEXT as bV, ScoreComponent as bW, ScrollComponent as bX, ScrollService as bY, SearchPanelComponent as bZ, SearchStore as b_, 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, ButtonComponent as c, TreeGridComponent as c$, SectionAccordionDirective as c0, SectionAccordionGroupDirective as c1, SectionBackComponent as c2, SectionBadgesComponent as c3, SectionButtonGroupComponent as c4, SectionCardComponent as c5, SectionCarouselComponent as c6, SectionComponent as c7, SectionFilterComponent as c8, SectionFilterGroupComponent as c9, StepperComponent as cA, StepsComponent as cB, StorageService as cC, StrokeLinecap as cD, StrokeLinejoin as cE, SummaryComponent as cF, SvgGeneratorComponent as cG, SvgGeneratorService as cH, SvgService as cI, TOTAL_COLUMNS as cJ, TRANSLATION_SOURCE as cK, TableComponent as cL, TechnicalMeterComponent as cM, TextInputComponent as cN, TextareaInputComponent as cO, ThemeComponent as cP, ThemeDataService as cQ, ThemeService as cR, ThemeStore as cS, TimeAgoPipe as cT, TimelineComponent as cU, ToggleButtonComponent as cV, ToggleInputComponent as cW, ToggleRadioInputComponent as cX, ToolTipDirective as cY, TooltipComponent as cZ, TranslateService as c_, SectionFilterMenuComponent as ca, SectionFilterPanelComponent as cb, SectionFilterRangePanelComponent as cc, SectionFooterComponent as cd, SectionFormComponent as ce, SectionFormItemComponent as cf, SectionHeaderComponent as cg, SectionHeroComponent as ch, SectionPaginationComponent as ci, SectionSearchComponent as cj, SectionStepperComponent as ck, SectionTabsComponent as cl, SectionToggleComponent as cm, SectionToggleItemDirective as cn, SelectableCardInputComponent as co, SelectorDirective as cp, SettingsSearchBarComponent as cq, SettingsSearchService as cr, ShapeComponent as cs, SharedStoreRegistry as ct, SidePanelDirective as cu, Size as cv, SocketStore as cw, SortComponent as cx, StatComponent as cy, StepComponent as cz, APP_CONTEXT_REF as d, getScrollParent as d$, URL_SEP as d0, USER_STORE_REF as d1, USER_TAB_MAP as d2, UniverseComponent as d3, UserApiService as d4, UserAvatarComponent as d5, UserComponent as d6, UserNavComponent as d7, UserSettingsComponent as d8, UserStore as d9, deriveContrastColor as dA, deriveOppositeColor as dB, derivePropertyName as dC, emailValidation as dD, evaluate as dE, evaluateBool as dF, filterHoldsList as dG, filterHoldsOneBound as dH, filterHoldsOptions as dI, filterHoldsRange as dJ, filterList as dK, filterNumber as dL, filterNumberList as dM, filterOne as dN, filterPanelOf as dO, filterPanelWidth as dP, filterRange as dQ, filterTreeGridRows as dR, filterValueList as dS, filterValues as dT, flattenTreeGridRows as dU, formatBadgeCount as dV, fullName as dW, generateClipPath as dX, generateTransform as dY, getClassList as dZ, getProperty as d_, WC_ROUTE_CHANGED_EVENT as da, WC_SEARCH_GROUPS as db, WIN_USER_TAB_HOOK as dc, WIN_USER_TAB_KEY as dd, WatermarkComponent as de, WcRouterStore as df, WrapperInputComponent as dg, anchorNavId as dh, applyColorsToElement as di, assetOptions as dj, bootstrapMagApp as dk, bootstrapPwaInstall as dl, buildWcBaseUrl as dm, calculateLuminance as dn, calculateRanks as dp, cellText as dq, checkFilterCondition as dr, childNavId as ds, classListSignal as dt, coerceSize as du, cornerEdge as dv, cornerSide as dw, createMap as dx, createPlatformNavMap as dy, deriveAvatarGradient as dz, ASSET_BASE_URL as e, processImageToSvg as e$, getTierFromPreviewPath as e0, getTreeGridRow as e1, getUniqueId as e2, getValue as e3, hasErrorComputed as e4, hexToRgb as e5, hslToRgb$1 as e6, initMagmoniumApp as e7, initialNotificationState as e8, initialState$2 as e9, matchFieldValidation as eA, maxLengthValidation as eB, maxValidation as eC, mergePlatformNav as eD, mergeUnique as eE, mergeUniqueBy as eF, mergeUniqueWith as eG, minAgeValidation as eH, minLengthValidation as eI, minValidation as eJ, miniMarkToHtml as eK, navIdChain as eL, navIdFor as eM, navIdSegment as eN, navIdToRoutePath as eO, navIdToSegments as eP, navParamOf as eQ, navToId as eR, normalizeAssetOptions as eS, parentNavId as eT, parseAddress as eU, parseColor as eV, parsePatternNames as eW, patternValidation as eX, patternsValidation as eY, platformNavWidgets as eZ, privateGuard as e_, initials as ea, injectAuthenticate as eb, injectInstallApp as ec, injectParentSize as ed, injectScrollSticky as ee, isButtonName as ef, isCancelledComputed as eg, isExtensiblePlatformNavId as eh, isJson as ei, isLoadingComputed as ej, isLocalhost as ek, isNavInstanceConfig as el, isNavMenuConfig as em, isNavRowsConfig as en, isPlatformNavId as eo, isSize as ep, isTierPreview as eq, isUrlLocalhost as er, isValidNavId as es, isValidNavSegment as et, isWebComponent as eu, linkToId as ev, linkToNav as ew, loadingActions as ex, mInterceptor as ey, manualValidation as ez, AccordionBodyDirective as f, provideAppContext as f0, provideMagAppConfig as f1, provideMagWcConfig as f2, provideMagWcRoutes as f3, provideModalComponents as f4, provideMurlUrlSerializer as f5, provideNavWidgets as f6, provideOverlayWidgets as f7, providePlatformNavWidgets as f8, provideSearch as f9, toHostNavId as fA, toLength$1 as fB, toLocalNavId as fC, toggleTreeGridRow as fD, unfetchedPlatformNav as fE, urlValidation as fF, provideSizeContext as fa, provideUserTabs as fb, publicGuard as fc, readFieldPatterns as fd, renderAddress as fe, requiredValidation as ff, resolveConfigAsset as fg, resolveIconSize as fh, resolvePallet as fi, resolvePatternRules as fj, resolveSize as fk, rgbToHex as fl, rgbToHsl as fm, rowHasChildren as fn, samePatterns as fo, segmentsToNavId as fp, setProperty as fq, setTreeGridChildren as fr, settingsWidgets as fs, shouldShowBadge as ft, splitNavId as fu, splitOnMatch as fv, stringToColor as fw, toAttrBool as fx, toAttrNumber as fy, toCssLength as fz, AccordionComponent as g, AccordionGroupComponent as h, ActionComponent as i, AnimatedGraphsComponent as j, AppCardComponent as k, AppRelationType as l, AppTileComponent as m, AssetStore as n, AssetUrlPipe as o, Assets as p, AuthActivityPageComponent as q, AuthApiService as r, AuthStore as s, AutosizeDirective as t, BadgeComponent as u, BandingComponent as v, BaseArrayInputComponent as w, BaseRootWebComponent as x, BaseWebComponent as y, ButtonGroupComponent as z };
35550
- //# sourceMappingURL=magmonium-one-magmonium-one-CVuP1oHe.mjs.map
36564
+ export { ColComponent 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, MHeroComponent as a$, ColorPickerInputComponent as a0, CommentItemComponent as a1, CommentsApiService as a2, CommentsComponent as a3, CommentsStore as a4, CompactNumberPipe as a5, ComponentInputComponent as a6, ComponentStepperComponent as a7, ConfigComponent as a8, ConfirmComponent as a9, FileUploadDirective as aA, FileUploadInputComponent as aB, FlexComponent as aC, FlexItemComponent as aD, FormGroupComponent as aE, FrameComponent as aF, FreezeService as aG, GRID_BREAKPOINTS as aH, GetNavService as aI, HighlightDirective as aJ, HttpService as aK, ICON_SOURCE as aL, IS_SIDE_PANEL as aM, IconComponent as aN, ImgComponent as aO, InstrumentScoreComponent as aP, InterceptorObservables as aQ, JumbotronComponent as aR, KeyValueComponent as aS, LAYOUT_ASSET_FOLDER as aT, LOGIN_COMPONENT as aU, LOGIN_STORE as aV, LanguageComponent as aW, ListComponent as aX, LogoComponent as aY, MAG_SOCKET_EVENT as aZ, MHeroColorDirective as a_, ContextMenuComponent as aa, CustomIconClass as ab, CustomIconEditComponent as ac, DEFAULT_FILTER_RANGE_MODE as ad, DEFAULT_FILTER_VARIANT as ae, DEFAULT_NAV_PARAM as af, DEFAULT_NAV_SEGMENT as ag, DEFAULT_SIZE as ah, DashboardCardComponent as ai, DateInputComponent as aj, DatePickerComponent as ak, DeviceService as al, DomService as am, Domain as an, DotGridComponent as ao, DragListDirective as ap, DragListItemDirective as aq, DraggableDirective as ar, DropdownInputComponent as as, FILTER_GROUP_CONTEXT as at, FILTER_RANGE_MODES as au, FILTER_VARIANTS as av, FLEX_VARIANTS as aw, FOLDER_PICK_LISTENER as ax, FORM_ASSET_FOLDER as ay, FileService as az, MAX_ZOOM as b, SEARCH_RESULTS_EVENT as b$, MODAL_STORE_REF as b0, MRefDirective as b1, MStepComponent as b2, MURL_PARAM as b3, MURL_SEP as b4, ManifestEnrichmentService as b5, MenuComponent as b6, ModalDirective as b7, ModalRef as b8, ModalStore as b9, OVERLAY_WIDGETS as bA, OneApp as bB, OptionsSourceDirective as bC, OverlayBodyComponent as bD, OverlayRef as bE, OverlayService as bF, PLATFORM_BUTTON_NAV_IDS as bG, PLATFORM_EXTENSIBLE_NAV_IDS as bH, PLATFORM_NAV_MAP as bI, PLATFORM_ROOT_CHILDREN as bJ, PaginationComponent as bK, PanelComponent as bL, PercentagePipe as bM, PlaygroundComponent as bN, PositionDirective as bO, PwaInstallComponent as bP, ROOT_NAV$1 as bQ, RadioGroupComponent as bR, RadioInputComponent as bS, RatingInputComponent as bT, ReactiveElementComponent as bU, RemoteComponent as bV, RemoteLoaderService as bW, ResizeElementComponent as bX, RouteContainer as bY, RowComponent as bZ, SEARCH_QUERY as b_, MoneyPipe as ba, MultiRangeInputComponent as bb, MurlUrlSerializer as bc, NAV_DEFAULT_MURL as bd, NAV_ID_SEP as be, NAV_MAIN_BUTTONS as bf, NAV_SEGMENT_RE as bg, NAV_STORE_REF as bh, NAV_WC_COMPONENTS as bi, NAV_WIDGET_MAP as bj, NavComponent as bk, NavDetailsComponent as bl, NavHeaderComponent as bm, NavMenuComponent as bn, NavStore as bo, NavTrailComponent as bp, NothingComponent as bq, NotificationElementComponent as br, NotificationGroupComponent as bs, NotificationPopupComponent as bt, NotificationService as bu, NotificationStore as bv, NotificationType as bw, NotificationWidgetComponent as bx, ONE_ASSET_BASE_URL as by, OPTIONS_SOURCE as bz, cropRect as c, ThemeService as c$, SECTION_ACCORDION_GROUP as c0, SECTION_FORM_CONTEXT as c1, SHARED_ICONS as c2, SIZE_CONTEXT as c3, ScoreComponent as c4, ScrollComponent as c5, ScrollService as c6, SearchPanelComponent as c7, SearchStore as c8, SearchUserPanelComponent as c9, SettingsSearchBarComponent as cA, SettingsSearchService as cB, ShapeComponent as cC, SharedStoreRegistry as cD, SidePanelDirective as cE, Size as cF, SocketStore as cG, SortComponent as cH, StatComponent as cI, StepComponent as cJ, StepperComponent as cK, StepsComponent as cL, StorageService as cM, StrokeLinecap as cN, StrokeLinejoin as cO, SummaryComponent as cP, SvgGeneratorComponent as cQ, SvgGeneratorService as cR, SvgService as cS, TOTAL_COLUMNS as cT, TRANSLATION_SOURCE as cU, TableComponent as cV, TechnicalMeterComponent as cW, TextInputComponent as cX, TextareaInputComponent as cY, ThemeComponent as cZ, ThemeDataService as c_, SectionAccordionDirective as ca, SectionAccordionGroupDirective as cb, SectionBackComponent as cc, SectionBadgesComponent as cd, SectionButtonGroupComponent as ce, SectionCardComponent as cf, SectionCarouselComponent as cg, SectionComponent as ch, SectionFilterComponent as ci, SectionFilterGroupComponent as cj, SectionFilterMenuComponent as ck, SectionFilterPanelComponent as cl, SectionFilterRangePanelComponent as cm, SectionFooterComponent as cn, SectionFormComponent as co, SectionFormItemComponent as cp, SectionHeaderComponent as cq, SectionHeroComponent as cr, SectionPaginationComponent as cs, SectionSearchComponent as ct, SectionStepperComponent as cu, SectionTabsComponent as cv, SectionToggleComponent as cw, SectionToggleItemDirective as cx, SelectableCardInputComponent as cy, SelectorDirective as cz, drawFramed as d, filterTreeGridRows as d$, ThemeStore as d0, TimeAgoPipe as d1, TimelineComponent as d2, ToggleButtonComponent as d3, ToggleInputComponent as d4, ToggleRadioInputComponent as d5, ToolTipDirective as d6, TooltipComponent as d7, TranslateService as d8, TreeGridComponent as d9, cellText as dA, checkFilterCondition as dB, childNavId as dC, classListSignal as dD, coerceSize as dE, cornerEdge as dF, cornerSide as dG, createMap as dH, createPlatformNavMap as dI, deriveAvatarGradient as dJ, deriveContrastColor as dK, deriveOppositeColor as dL, derivePropertyName as dM, emailValidation as dN, evaluate as dO, evaluateBool as dP, filterHoldsList as dQ, filterHoldsOneBound as dR, filterHoldsOptions as dS, filterHoldsRange as dT, filterList as dU, filterNumber as dV, filterNumberList as dW, filterOne as dX, filterPanelOf as dY, filterPanelWidth as dZ, filterRange as d_, URL_SEP as da, USER_STORE_REF as db, USER_TAB_MAP as dc, UniverseComponent as dd, UserApiService as de, UserAvatarComponent as df, UserComponent as dg, UserNavComponent as dh, UserSettingsComponent as di, UserStore as dj, WC_ROUTE_CHANGED_EVENT as dk, WC_SEARCH_GROUPS as dl, WIN_USER_TAB_HOOK as dm, WIN_USER_TAB_KEY as dn, WatermarkComponent as dp, WcRouterStore as dq, WrapperInputComponent as dr, anchorNavId as ds, applyColorsToElement as dt, assetOptions as du, bootstrapMagApp as dv, bootstrapPwaInstall as dw, buildWcBaseUrl as dx, calculateLuminance as dy, calculateRanks as dz, encodeFramed as e, navParamOf as e$, filterValueList as e0, filterValues as e1, flattenTreeGridRows as e2, formatBadgeCount as e3, fullName as e4, generateClipPath as e5, generateTransform as e6, getClassList as e7, getProperty as e8, getScrollParent as e9, isSize as eA, isTierPreview as eB, isUrlLocalhost as eC, isValidNavId as eD, isValidNavSegment as eE, isWebComponent as eF, linkToId as eG, linkToNav as eH, loadingActions as eI, mInterceptor as eJ, manualValidation as eK, matchFieldValidation as eL, maxLengthValidation as eM, maxValidation as eN, mergePlatformNav as eO, mergeUnique as eP, mergeUniqueBy as eQ, mergeUniqueWith as eR, minAgeValidation as eS, minLengthValidation as eT, minValidation as eU, miniMarkToHtml as eV, navIdChain as eW, navIdFor as eX, navIdSegment as eY, navIdToRoutePath as eZ, navIdToSegments as e_, getTierFromPreviewPath as ea, getTreeGridRow as eb, getUniqueId as ec, getValue as ed, hasErrorComputed as ee, hexToRgb as ef, hslToRgb$1 as eg, initMagmoniumApp as eh, initialNotificationState as ei, initialState$2 as ej, initials as ek, injectAuthenticate as el, injectInstallApp as em, injectParentSize as en, injectScrollSticky as eo, isButtonName as ep, isCancelledComputed as eq, isExtensiblePlatformNavId as er, isJson as es, isLoadingComputed as et, isLocalhost as eu, isNavInstanceConfig as ev, isNavMenuConfig as ew, isNavRowsConfig as ex, isNavVisibilityConfig as ey, isPlatformNavId as ez, clampFraming as f, navToId as f0, navVisibilityGuard as f1, normalizeAssetOptions as f2, parentNavId as f3, parseAddress as f4, parseColor as f5, parsePatternNames as f6, patternValidation as f7, patternsValidation as f8, platformNavWidgets as f9, samePatterns as fA, segmentsToNavId as fB, setProperty as fC, setTreeGridChildren as fD, settingsWidgets as fE, shouldShowBadge as fF, splitNavId as fG, splitOnMatch as fH, stringToColor as fI, toAttrBool as fJ, toAttrNumber as fK, toCssLength as fL, toHostNavId as fM, toLength$1 as fN, toLocalNavId as fO, toggleTreeGridRow as fP, unfetchedPlatformNav as fQ, urlValidation as fR, privateGuard as fa, processImageToSvg as fb, provideAppContext as fc, provideMagAppConfig as fd, provideMagWcConfig as fe, provideMagWcRoutes as ff, provideModalComponents as fg, provideMurlUrlSerializer as fh, provideNavWidgets as fi, provideOverlayWidgets as fj, providePlatformNavWidgets as fk, provideSearch as fl, provideSizeContext as fm, provideUserTabs as fn, publicGuard as fo, readFieldPatterns as fp, renderAddress as fq, requiredValidation as fr, resolveConfigAsset as fs, resolveIconSize as ft, resolvePallet as fu, resolvePatternRules as fv, resolveSize as fw, rgbToHex as fx, rgbToHsl as fy, rowHasChildren as fz, BaseInputComponent as g, 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 };
36565
+ //# sourceMappingURL=magmonium-one-magmonium-one-CWtMvVOS.mjs.map