@magmonium/one 0.0.17 → 0.0.18

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.
@@ -10,7 +10,7 @@ import { io } from 'socket.io-client';
10
10
  import { DefaultUrlSerializer, UrlSerializer, Router, NavigationEnd, RouterModule, RouterLink, provideRouter, withComponentInputBinding, 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, form, email, required, minLength, maxLength, min, max, validate } from '@angular/forms/signals';
13
+ import { FormField, form, email, required, minLength, maxLength, min, max, validate, apply } from '@angular/forms/signals';
14
14
  import { bootstrapApplication, DomSanitizer } from '@angular/platform-browser';
15
15
  import { createCustomElement } from '@angular/elements';
16
16
  import { provideAnimations } from '@angular/platform-browser/animations';
@@ -14935,7 +14935,7 @@ class WrapperInputComponent extends ConfigComponent {
14935
14935
  break;
14936
14936
  }
14937
14937
  case InputType.TOGGLE: {
14938
- const { ToggleInputComponent } = await import('./magmonium-one-toggle-CqQCBYIw.mjs');
14938
+ const { ToggleInputComponent } = await import('./magmonium-one-toggle-Ds299_0s.mjs');
14939
14939
  this.createDynamicComponent(seq, ToggleInputComponent, [], true);
14940
14940
  break;
14941
14941
  }
@@ -14947,12 +14947,12 @@ class WrapperInputComponent extends ConfigComponent {
14947
14947
  break;
14948
14948
  }
14949
14949
  case InputType.PASSWORD: {
14950
- const { PasswordInputComponent } = await import('./magmonium-one-password-3SqPjCcD.mjs');
14950
+ const { PasswordInputComponent } = await import('./magmonium-one-password-BsaeoGHN.mjs');
14951
14951
  this.createDynamicComponent(seq, PasswordInputComponent);
14952
14952
  break;
14953
14953
  }
14954
14954
  case InputType.OTP: {
14955
- const { OtpInputComponent } = await import('./magmonium-one-otp-BDj-zpyL.mjs');
14955
+ const { OtpInputComponent } = await import('./magmonium-one-otp-DjC2iX42.mjs');
14956
14956
  this.createDynamicComponent(seq, OtpInputComponent);
14957
14957
  break;
14958
14958
  }
@@ -16920,6 +16920,72 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
16920
16920
  `, 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;width:100%}.form-group{display:flex;flex-direction:column;gap:var(--m-form-group-gap, 1.5rem)}.form-group__header{display:flex;flex-direction:column;gap:4px;margin-bottom:.5rem}.form-group__subtitle{font-size:.7rem;font-weight:600;text-transform:uppercase;letter-spacing:.1em;opacity:.5;color:var(--mm-color, #ffd700)}.form-group__title{font-size:1.25rem;font-weight:700;letter-spacing:-.01em;opacity:.9}.form-group__content{display:flex;flex-wrap:wrap;gap:var(--m-form-group-content-gap, 1rem 1.25rem)}.form-group__content>*{flex:1 1 100%;min-width:0}.form-group__content>.col-1{flex:1 1 calc(1 * (100% + 1.25rem) / 12 - 1.25rem)}.form-group__content>.col-2{flex:2 1 calc(2 * (100% + 1.25rem) / 12 - 1.25rem)}.form-group__content>.col-3{flex:3 1 calc(.25*(100% + 1.25rem) - 1.25rem)}.form-group__content>.col-4{flex:4 1 calc(4 * (100% + 1.25rem) / 12 - 1.25rem)}.form-group__content>.col-5{flex:5 1 calc(5 * (100% + 1.25rem) / 12 - 1.25rem)}.form-group__content>.col-6{flex:6 1 calc(.5*(100% + 1.25rem) - 1.25rem)}.form-group__content>.col-7{flex:7 1 calc(7 * (100% + 1.25rem) / 12 - 1.25rem)}.form-group__content>.col-8{flex:8 1 calc(8 * (100% + 1.25rem) / 12 - 1.25rem)}.form-group__content>.col-9{flex:9 1 calc(.75*(100% + 1.25rem) - 1.25rem)}.form-group__content>.col-10{flex:10 1 calc(10 * (100% + 1.25rem) / 12 - 1.25rem)}.form-group__content>.col-11{flex:11 1 calc(11 * (100% + 1.25rem) / 12 - 1.25rem)}.form-group__content>.col-12{flex:12 1 calc(1*(100% + 1.25rem) - 1.25rem)}@media(max-width:480px){.form-group__content>*{flex-basis:100%}}:host(.m-form--compact) .form-group{gap:.5rem}:host(.m-form--compact) .form-group__content{display:block;gap:0}\n"] }]
16921
16921
  }], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], dataChange: [{ type: i0.Output, args: ["dataChange"] }], act: [{ type: i0.Output, args: ["act"] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }, { type: i0.Output, args: ["stateChange"] }], validation: [{ type: i0.Input, args: [{ isSignal: true, alias: "validation", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], fieldConfigs: [{ type: i0.Input, args: [{ isSignal: true, alias: "fieldConfigs", required: false }] }], aclResolver: [{ type: i0.Input, args: [{ isSignal: true, alias: "aclResolver", required: false }] }], autofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocus", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], fieldRenderIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "fieldRenderIds", required: false }] }], elements: [{ type: i0.Input, args: [{ isSignal: true, alias: "elements", required: false }] }], datas: [{ type: i0.Input, args: [{ isSignal: true, alias: "datas", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }] } });
16922
16922
 
16923
+ const emailValidation = (schemaPath) => email(schemaPath, {
16924
+ message: 'not-a-valid-email',
16925
+ });
16926
+ const requiredValidation = (s, paths) => paths.forEach((path) => required(s[path], {
16927
+ message: 'this-field-is-required',
16928
+ }));
16929
+ const minLengthValidation = (s, paths, len) => paths.forEach((path) => minLength(s[path], len, {
16930
+ message: `min-length?len=${len}`,
16931
+ }));
16932
+ const maxLengthValidation = (s, paths, len) => paths.forEach((path) => maxLength(s[path], len, {
16933
+ message: `max-length?len=${len}`,
16934
+ }));
16935
+ const minValidation = (s, paths, limit) => paths.forEach((path) => min(s[path], limit, {
16936
+ message: `min-length?len=${limit}`,
16937
+ }));
16938
+ const maxValidation = (s, paths, limit) => paths.forEach((path) => max(s[path], limit, {
16939
+ message: `max-length?len=${limit}`,
16940
+ }));
16941
+ const manualValidation = (errorMap) => errorMap.forEach(({ error, path }) => validate(path, () => {
16942
+ const message = error();
16943
+ return message ? { kind: 'manual', message } : null;
16944
+ }));
16945
+ const minAgeValidation = (schemaPath, minAge, dateFormat = 'YYYY-MM-DD') => validate(schemaPath, (ctx) => {
16946
+ const value = ctx.value();
16947
+ if (!value)
16948
+ return null;
16949
+ const birthDate = parseDate(value, dateFormat);
16950
+ if (!birthDate)
16951
+ return null;
16952
+ const today = new Date();
16953
+ const age = today.getFullYear() - birthDate.getFullYear();
16954
+ const monthDiff = today.getMonth() - birthDate.getMonth();
16955
+ const dayDiff = today.getDate() - birthDate.getDate();
16956
+ const actualAge = monthDiff < 0 || (monthDiff === 0 && dayDiff < 0) ? age - 1 : age;
16957
+ return actualAge < minAge
16958
+ ? { kind: 'minAge', message: `min-age?age=${minAge}` }
16959
+ : null;
16960
+ });
16961
+ const matchFieldValidation = (schemaPath, matchSchemaPath, fieldLabel) => validate(schemaPath, (ctx) => {
16962
+ const value = ctx.value();
16963
+ if (!value)
16964
+ return null;
16965
+ const matchValue = ctx.valueOf(matchSchemaPath);
16966
+ return value !== matchValue
16967
+ ? { kind: 'matchField', message: `field-mismatch?field=${fieldLabel}` }
16968
+ : null;
16969
+ });
16970
+ const urlValidation = (schemaPath) => validate(schemaPath, (ctx) => {
16971
+ const value = ctx.value();
16972
+ if (!value)
16973
+ return null;
16974
+ try {
16975
+ new URL(value);
16976
+ return null;
16977
+ }
16978
+ catch {
16979
+ return { kind: 'url', message: 'not-a-valid-url' };
16980
+ }
16981
+ });
16982
+ const patternValidation = (schemaPath, regex, message = 'not-a-valid-pattern') => validate(schemaPath, (ctx) => {
16983
+ const value = ctx.value();
16984
+ if (!value)
16985
+ return null;
16986
+ return regex.test(value) ? null : { kind: 'pattern', message };
16987
+ });
16988
+
16923
16989
  class SectionFormComponent extends ConfigComponent {
16924
16990
  // Same folder FormGroup resolves from: a form's asset is a form's asset
16925
16991
  // whichever component renders it, so `name="contact"` finds
@@ -16957,11 +17023,48 @@ class SectionFormComponent extends ConfigComponent {
16957
17023
  // `(fieldKey)` hook). Merged with `config.inputs` so the FieldTree always
16958
17024
  // has a slot for every rendered field.
16959
17025
  registeredFields = signal([], ...(ngDevMode ? [{ debugName: "registeredFields" }] : /* istanbul ignore next */ []));
16960
- registerField = (name) => {
16961
- if (!name || this.registeredFields().includes(name))
17026
+ // Keys whose item carries `required` — the tag's word, which has to become
17027
+ // the FieldTree's word too. Kept apart from `registeredFields` because a key
17028
+ // is announced once and its required flag can flip whenever the Field's
17029
+ // config or asset changes.
17030
+ requiredFields = signal([], ...(ngDevMode ? [{ debugName: "requiredFields" }] : /* istanbul ignore next */ []));
17031
+ // Untracked: items call this from their own effect, so reading these signals
17032
+ // plainly would make every item re-run whenever any sibling registers.
17033
+ registerField = (name, required = false) => {
17034
+ if (!name)
16962
17035
  return;
16963
- this.registeredFields.update((fields) => [...fields, name]);
17036
+ untracked(() => {
17037
+ if (!this.registeredFields().includes(name)) {
17038
+ this.registeredFields.update((fields) => [...fields, name]);
17039
+ }
17040
+ this.setRequired(name, required);
17041
+ });
17042
+ };
17043
+ releaseField = (name) => {
17044
+ if (!name)
17045
+ return;
17046
+ untracked(() => this.setRequired(name, false));
16964
17047
  };
17048
+ setRequired = (name, required) => {
17049
+ const has = this.requiredFields().includes(name);
17050
+ if (has === required)
17051
+ return;
17052
+ this.requiredFields.update((fields) => required ? [...fields, name] : fields.filter((field) => field !== name));
17053
+ };
17054
+ // The caller's own schema plus a `required` rule per Field that declares one.
17055
+ // Both, not either: a form given a `validation` schema still has to honour the
17056
+ // attribute its markup was written with.
17057
+ resolvedValidation = computed(() => {
17058
+ const own = this.validation();
17059
+ const requiredPaths = this.requiredFields();
17060
+ if (!requiredPaths.length)
17061
+ return own;
17062
+ return (path) => {
17063
+ requiredValidation(path, requiredPaths);
17064
+ if (own)
17065
+ apply(path, own);
17066
+ };
17067
+ }, ...(ngDevMode ? [{ debugName: "resolvedValidation" }] : /* istanbul ignore next */ []));
16965
17068
  modelKeys = computed(() => {
16966
17069
  const fromConfig = this.config()?.inputs?.flat() ?? [];
16967
17070
  return Array.from(new Set([...fromConfig, ...this.registeredFields()]));
@@ -17088,7 +17191,9 @@ class SectionFormComponent extends ConfigComponent {
17088
17191
  // create (item register / config.inputs change) has no field until reset.
17089
17192
  effect(() => {
17090
17193
  void this.modelKeys();
17091
- void this.validation();
17194
+ // The merged schema, so a Field reporting `required` rebuilds the tree
17195
+ // with its validator on it — a rule added after create binds to nothing.
17196
+ void this.resolvedValidation();
17092
17197
  untracked(() => this.reset());
17093
17198
  });
17094
17199
  effect(() => {
@@ -17105,7 +17210,7 @@ class SectionFormComponent extends ConfigComponent {
17105
17210
  }
17106
17211
  reset = () => {
17107
17212
  untracked(() => {
17108
- const validation = this.validation();
17213
+ const validation = this.resolvedValidation();
17109
17214
  try {
17110
17215
  const newForm = runInInjectionContext(this.injector, () => validation ? form(this.model, validation) : form(this.model));
17111
17216
  this.formGroup.set(newForm);
@@ -17125,6 +17230,7 @@ class SectionFormComponent extends ConfigComponent {
17125
17230
  return {
17126
17231
  form: self.formGroup,
17127
17232
  registerField: self.registerField,
17233
+ releaseField: self.releaseField,
17128
17234
  blocked: self.blocked,
17129
17235
  submit: self.submitNow,
17130
17236
  };
@@ -17171,6 +17277,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
17171
17277
  return {
17172
17278
  form: self.formGroup,
17173
17279
  registerField: self.registerField,
17280
+ releaseField: self.releaseField,
17174
17281
  blocked: self.blocked,
17175
17282
  submit: self.submitNow,
17176
17283
  };
@@ -17310,6 +17417,13 @@ class SectionFormItemComponent extends ConfigComponent {
17310
17417
  }
17311
17418
  return formTree[name];
17312
17419
  }, ...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
17420
+ // Read off `config()`, not off the `required` input: the asset under a Field
17421
+ // may set it too, and either source spells it `true` or 'true' depending on
17422
+ // whether it arrived as a binding or as a plain attribute.
17423
+ isRequired = computed(() => {
17424
+ const required = this.config()?.required;
17425
+ return required === true || `${required}` === 'true';
17426
+ }, ...(ngDevMode ? [{ debugName: "isRequired" }] : /* istanbul ignore next */ []));
17313
17427
  isVisible = computed(() => {
17314
17428
  const acl = this.config()?.acl;
17315
17429
  if (!acl)
@@ -17352,8 +17466,10 @@ class SectionFormItemComponent extends ConfigComponent {
17352
17466
  const name = this.modelKey();
17353
17467
  if (name) {
17354
17468
  // Slot the key on the parent FieldTree before we read `field()` —
17355
- // content-projected items cannot wire `(fieldKey)` like FormGroup.
17356
- this.sectionForm?.registerField(name);
17469
+ // content-projected items cannot wire `(fieldKey)` like FormGroup. The
17470
+ // required flag rides along: `required` on the tag has to reach the
17471
+ // FieldTree, or the form is valid empty and every submit control unlocks.
17472
+ this.sectionForm?.registerField(name, this.isRequired());
17357
17473
  this.fieldKey.emit(name);
17358
17474
  }
17359
17475
  void this.field();
@@ -17374,6 +17490,11 @@ class SectionFormItemComponent extends ConfigComponent {
17374
17490
  ngOnDestroy() {
17375
17491
  this.isDestroyed = true;
17376
17492
  this.dynamicSeq++;
17493
+ // A Field removed from a Screen (or hidden behind an @if) must stop being
17494
+ // required, otherwise the form stays invalid over a key nothing renders.
17495
+ const name = this.modelKey();
17496
+ if (name)
17497
+ this.sectionForm?.releaseField(name);
17377
17498
  }
17378
17499
  onButtonClick() {
17379
17500
  const config = this.config();
@@ -17435,7 +17556,7 @@ class SectionFormItemComponent extends ConfigComponent {
17435
17556
  break;
17436
17557
  }
17437
17558
  case InputType.TOGGLE: {
17438
- const { ToggleInputComponent } = await import('./magmonium-one-toggle-CqQCBYIw.mjs');
17559
+ const { ToggleInputComponent } = await import('./magmonium-one-toggle-Ds299_0s.mjs');
17439
17560
  this.createDynamicComponent(seq, ToggleInputComponent, [], true);
17440
17561
  break;
17441
17562
  }
@@ -17447,12 +17568,12 @@ class SectionFormItemComponent extends ConfigComponent {
17447
17568
  break;
17448
17569
  }
17449
17570
  case InputType.PASSWORD: {
17450
- const { PasswordInputComponent } = await import('./magmonium-one-password-3SqPjCcD.mjs');
17571
+ const { PasswordInputComponent } = await import('./magmonium-one-password-BsaeoGHN.mjs');
17451
17572
  this.createDynamicComponent(seq, PasswordInputComponent);
17452
17573
  break;
17453
17574
  }
17454
17575
  case InputType.OTP: {
17455
- const { OtpInputComponent } = await import('./magmonium-one-otp-BDj-zpyL.mjs');
17576
+ const { OtpInputComponent } = await import('./magmonium-one-otp-DjC2iX42.mjs');
17456
17577
  this.createDynamicComponent(seq, OtpInputComponent);
17457
17578
  break;
17458
17579
  }
@@ -17566,72 +17687,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
17566
17687
  }, 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(--m-form-group-gap, 1.5rem);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"] }]
17567
17688
  }], 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 }] }], 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 }] }], 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 }] }], optionsAsset: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionsAsset", 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 }] }] } });
17568
17689
 
17569
- const emailValidation = (schemaPath) => email(schemaPath, {
17570
- message: 'not-a-valid-email',
17571
- });
17572
- const requiredValidation = (s, paths) => paths.forEach((path) => required(s[path], {
17573
- message: 'this-field-is-required',
17574
- }));
17575
- const minLengthValidation = (s, paths, len) => paths.forEach((path) => minLength(s[path], len, {
17576
- message: `min-length?len=${len}`,
17577
- }));
17578
- const maxLengthValidation = (s, paths, len) => paths.forEach((path) => maxLength(s[path], len, {
17579
- message: `max-length?len=${len}`,
17580
- }));
17581
- const minValidation = (s, paths, limit) => paths.forEach((path) => min(s[path], limit, {
17582
- message: `min-length?len=${limit}`,
17583
- }));
17584
- const maxValidation = (s, paths, limit) => paths.forEach((path) => max(s[path], limit, {
17585
- message: `max-length?len=${limit}`,
17586
- }));
17587
- const manualValidation = (errorMap) => errorMap.forEach(({ error, path }) => validate(path, () => {
17588
- const message = error();
17589
- return message ? { kind: 'manual', message } : null;
17590
- }));
17591
- const minAgeValidation = (schemaPath, minAge, dateFormat = 'YYYY-MM-DD') => validate(schemaPath, (ctx) => {
17592
- const value = ctx.value();
17593
- if (!value)
17594
- return null;
17595
- const birthDate = parseDate(value, dateFormat);
17596
- if (!birthDate)
17597
- return null;
17598
- const today = new Date();
17599
- const age = today.getFullYear() - birthDate.getFullYear();
17600
- const monthDiff = today.getMonth() - birthDate.getMonth();
17601
- const dayDiff = today.getDate() - birthDate.getDate();
17602
- const actualAge = monthDiff < 0 || (monthDiff === 0 && dayDiff < 0) ? age - 1 : age;
17603
- return actualAge < minAge
17604
- ? { kind: 'minAge', message: `min-age?age=${minAge}` }
17605
- : null;
17606
- });
17607
- const matchFieldValidation = (schemaPath, matchSchemaPath, fieldLabel) => validate(schemaPath, (ctx) => {
17608
- const value = ctx.value();
17609
- if (!value)
17610
- return null;
17611
- const matchValue = ctx.valueOf(matchSchemaPath);
17612
- return value !== matchValue
17613
- ? { kind: 'matchField', message: `field-mismatch?field=${fieldLabel}` }
17614
- : null;
17615
- });
17616
- const urlValidation = (schemaPath) => validate(schemaPath, (ctx) => {
17617
- const value = ctx.value();
17618
- if (!value)
17619
- return null;
17620
- try {
17621
- new URL(value);
17622
- return null;
17623
- }
17624
- catch {
17625
- return { kind: 'url', message: 'not-a-valid-url' };
17626
- }
17627
- });
17628
- const patternValidation = (schemaPath, regex, message = 'not-a-valid-pattern') => validate(schemaPath, (ctx) => {
17629
- const value = ctx.value();
17630
- if (!value)
17631
- return null;
17632
- return regex.test(value) ? null : { kind: 'pattern', message };
17633
- });
17634
-
17635
17690
  class StepComponent {
17636
17691
  index = input.required(...(ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []));
17637
17692
  step = input.required(...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
@@ -25732,6 +25787,17 @@ class NotificationElementComponent {
25732
25787
  }
25733
25788
  }, ...(ngDevMode ? [{ debugName: "severityChar" }] : /* istanbul ignore next */ []));
25734
25789
  // --- Handlers ---
25790
+ /** The whole row is the affordance: reading it marks it read, and one
25791
+ * carrying an `onClick` runs it — which is how a notification becomes the
25792
+ * way to what it is about (`Notification.onClick`). */
25793
+ onActivate() {
25794
+ const notification = this.notification();
25795
+ if (!notification)
25796
+ return;
25797
+ if (!notification.read)
25798
+ this.markAsRead();
25799
+ notification.onClick?.();
25800
+ }
25735
25801
  markAsRead() {
25736
25802
  const id = this.notification()?.id;
25737
25803
  if (id) {
@@ -25778,11 +25844,9 @@ class NotificationElementComponent {
25778
25844
  [class.notification-item--popup]="autoClose()"
25779
25845
  role="button"
25780
25846
  tabindex="0"
25781
- (click)="!notification()?.read && markAsRead()"
25782
- (keydown.enter)="!notification()?.read && markAsRead()"
25783
- (keydown.space)="
25784
- !notification()?.read && markAsRead(); $event.preventDefault()
25785
- "
25847
+ (click)="onActivate()"
25848
+ (keydown.enter)="onActivate()"
25849
+ (keydown.space)="onActivate(); $event.preventDefault()"
25786
25850
  >
25787
25851
  <div class="notification-item__avatar-container">
25788
25852
  <div class="notification-item__avatar">
@@ -25823,7 +25887,15 @@ class NotificationElementComponent {
25823
25887
  <div class="notification-item__dot"></div>
25824
25888
  }
25825
25889
  @if (autoClose()) {
25826
- <m-one-button [name]="'close-icon-only'" (clicked)="onDismiss()" />
25890
+ <!-- Dismiss sits inside the row, and the row is itself a button.
25891
+ The clicked output carries the Button and not the DOM event,
25892
+ so the stop rides on the host click — without it, closing a
25893
+ navigable notification would also follow it. -->
25894
+ <m-one-button
25895
+ [name]="'close-icon-only'"
25896
+ (click)="$event.stopPropagation()"
25897
+ (clicked)="onDismiss()"
25898
+ />
25827
25899
  }
25828
25900
  </div>
25829
25901
  </div>
@@ -25873,11 +25945,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
25873
25945
  [class.notification-item--popup]="autoClose()"
25874
25946
  role="button"
25875
25947
  tabindex="0"
25876
- (click)="!notification()?.read && markAsRead()"
25877
- (keydown.enter)="!notification()?.read && markAsRead()"
25878
- (keydown.space)="
25879
- !notification()?.read && markAsRead(); $event.preventDefault()
25880
- "
25948
+ (click)="onActivate()"
25949
+ (keydown.enter)="onActivate()"
25950
+ (keydown.space)="onActivate(); $event.preventDefault()"
25881
25951
  >
25882
25952
  <div class="notification-item__avatar-container">
25883
25953
  <div class="notification-item__avatar">
@@ -25918,7 +25988,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
25918
25988
  <div class="notification-item__dot"></div>
25919
25989
  }
25920
25990
  @if (autoClose()) {
25921
- <m-one-button [name]="'close-icon-only'" (clicked)="onDismiss()" />
25991
+ <!-- Dismiss sits inside the row, and the row is itself a button.
25992
+ The clicked output carries the Button and not the DOM event,
25993
+ so the stop rides on the host click — without it, closing a
25994
+ navigable notification would also follow it. -->
25995
+ <m-one-button
25996
+ [name]="'close-icon-only'"
25997
+ (click)="$event.stopPropagation()"
25998
+ (clicked)="onDismiss()"
25999
+ />
25922
26000
  }
25923
26001
  </div>
25924
26002
  </div>
@@ -30606,4 +30684,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
30606
30684
  */
30607
30685
 
30608
30686
  export { DomService as $, ACCESS_DOMAINS as A, BaseInputComponent as B, COLOR_SCHEMES$1 as C, ChartComponent as D, ErrorsComponent as E, CheckboxInputComponent as F, ClearableInputComponent as G, ColComponent as H, ColorPickerInputComponent as I, CommentItemComponent as J, CommentsApiService as K, LabelComponent as L, CommentsComponent as M, CommentsStore as N, ComponentInputComponent as O, ComponentStepperComponent as P, ConfigComponent as Q, ConfirmComponent as R, ContextMenuComponent as S, TranslatePipe as T, CustomIconClass as U, CustomIconEditComponent as V, DEFAULT_SIZE as W, DashboardCardComponent as X, DateInputComponent as Y, DatePickerComponent as Z, DeviceService as _, BaseTextInputComponent as a, NAV_MAIN_BUTTONS as a$, Domain as a0, DotGridComponent as a1, DragListDirective as a2, DragListItemDirective as a3, DraggableDirective as a4, DropdownInputComponent as a5, FLEX_VARIANTS as a6, FOLDER_PICK_LISTENER as a7, FORM_ASSET_FOLDER as a8, FileService as a9, LOGIN_PROCESS as aA, LOGIN_STORE as aB, LanguageComponent as aC, LoginDataService as aD, LoginOneComponent as aE, LoginStore as aF, LogoComponent as aG, MAG_SOCKET_EVENT as aH, MHeroColorDirective as aI, MHeroComponent as aJ, MODAL_REF as aK, MODAL_STORE_REF as aL, MRefDirective as aM, MStepComponent as aN, MURL_PARAM as aO, MURL_SEP as aP, ManifestEnrichmentService as aQ, MenuComponent as aR, ModalDirective as aS, ModalRef as aT, ModalStore as aU, MoneyPipe as aV, MultiRangeInputComponent as aW, MurlUrlSerializer as aX, NAV_DEFAULT_MURL as aY, NAV_DISPLAY_ORDER as aZ, NAV_ID_SEP as a_, FileUploadDirective as aa, FileUploadInputComponent as ab, FlexComponent as ac, FlexItemComponent as ad, FormGroupComponent as ae, FrameComponent as af, FreezeService as ag, GEN_NAV_DISPLAY_ORDER as ah, GRID_BREAKPOINTS as ai, GetNavService as aj, HeaderComponent$1 as ak, HighlightDirective as al, HttpService as am, ICON_SOURCE as an, IS_DESIGN_MODE as ao, IS_SIDE_PANEL as ap, IconComponent as aq, ImgComponent as ar, InputType as as, InstrumentScoreComponent as at, InterceptorObservables as au, JumbotronComponent as av, KeyValueComponent as aw, LAYOUT_ASSET_FOLDER as ax, LOGIN_COMPONENT as ay, LOGIN_FORM_GROUP as az, ButtonComponent as b, SectionFilterComponent as b$, NAV_SEGMENT_RE as b0, NAV_STORE_REF as b1, NAV_WC_COMPONENTS as b2, NAV_WIDGET_MAP as b3, NavComponent as b4, NavDetailsComponent as b5, NavMenuComponent as b6, NavStore as b7, NavTrailComponent as b8, NothingComponent as b9, RangeInputComponent as bA, RatingInputComponent as bB, ReactiveElementComponent as bC, RemoteComponent as bD, RemoteLoaderService as bE, ResizeElementComponent as bF, RouteContainer as bG, RowComponent as bH, SEARCH_QUERY as bI, SEARCH_RESULTS_EVENT as bJ, SECTION_ACCORDION_GROUP as bK, SECTION_FORM_CONTEXT as bL, SHARED_ICONS as bM, SIZE_CONTEXT as bN, ScoreComponent as bO, ScrollComponent as bP, ScrollService as bQ, SearchPanelComponent as bR, SearchStore as bS, SearchUserPanelComponent as bT, SectionAccordionDirective as bU, SectionAccordionGroupDirective as bV, SectionBackComponent as bW, SectionBadgesComponent as bX, SectionButtonGroupComponent as bY, SectionCardComponent as bZ, SectionComponent as b_, NotificationElementComponent as ba, NotificationGroupComponent as bb, NotificationPopupComponent as bc, NotificationService as bd, NotificationStore as be, NotificationType as bf, NotificationWidgetComponent as bg, ONE_ASSET_BASE_URL as bh, OPTIONS_SOURCE as bi, OneApp as bj, OptionsSourceDirective as bk, OverlayBodyComponent as bl, OverlayRef as bm, OverlayService as bn, PLATFORM_BUTTON_NAV_IDS as bo, PLATFORM_EXTENSIBLE_NAV_IDS as bp, PLATFORM_NAV_MAP as bq, PLATFORM_ROOT_CHILDREN as br, PaginationComponent as bs, PanelComponent as bt, PlaygroundComponent as bu, PositionDirective as bv, PwaInstallComponent as bw, ROOT_NAV$1 as bx, RadioGroupComponent as by, RadioInputComponent as bz, APP_CONTEXT_REF as c, WIN_USER_TAB_KEY as c$, SectionFooterComponent as c0, SectionFormComponent as c1, SectionFormItemComponent as c2, SectionHeaderComponent as c3, SectionSearchComponent as c4, SectionStepperComponent as c5, SectionTabsComponent as c6, SectionToggleComponent as c7, SectionToggleItemDirective as c8, SelectableCardInputComponent as c9, TextareaInputComponent as cA, ThemeComponent as cB, ThemeService as cC, ThemeStore as cD, TimeAgoPipe as cE, TimelineComponent as cF, ToggleButtonComponent as cG, ToggleInputComponent as cH, ToggleRadioInputComponent as cI, ToolTipDirective as cJ, TooltipComponent as cK, TranslateService as cL, TreeGridComponent as cM, URL_SEP as cN, USER_STORE_REF as cO, USER_TAB_MAP as cP, UlComponent as cQ, UniverseComponent as cR, UserApiService as cS, UserAvatarComponent as cT, UserComponent as cU, UserNavComponent as cV, UserSettingsComponent as cW, UserStore as cX, WC_ROUTE_CHANGED_EVENT as cY, WC_SEARCH_GROUPS as cZ, WIN_USER_TAB_HOOK as c_, SelectorDirective as ca, SettingsSearchBarComponent as cb, SettingsSearchService as cc, Sex as cd, ShapeComponent as ce, SharedStoreRegistry as cf, SidePanelDirective as cg, Size as ch, SocketStore as ci, SortComponent as cj, StepComponent as ck, StepperComponent as cl, StepsComponent as cm, StorageService as cn, StrokeLinecap as co, StrokeLinejoin as cp, SummaryComponent as cq, SvgGeneratorComponent as cr, SvgGeneratorService as cs, SvgService as ct, TOTAL_COLUMNS as cu, TRANSLATION_SOURCE as cv, TableComponent as cw, TechnicalMeterComponent as cx, TextInputComponent as cy, TextOutputComponent as cz, ASSET_BASE_URL as d, loginState as d$, WatermarkComponent as d0, WcRouterStore as d1, WrapperInputComponent as d2, anchorNavId as d3, applyColorsToElement as d4, authGuard as d5, bootstrapMagApp as d6, bootstrapPwaInstall as d7, buildWcBaseUrl as d8, calculateLuminance as d9, getValue as dA, hasErrorComputed as dB, hexToRgb as dC, hslToRgb$1 as dD, initMagmoniumApp as dE, initialNotificationState as dF, initials as dG, injectAuthenticate as dH, injectInstallApp as dI, injectParentSize as dJ, injectScrollSticky as dK, isButtonName as dL, isCancelledComputed as dM, isExtensiblePlatformNavId as dN, isJson as dO, isLoadingComputed as dP, isLocalhost as dQ, isPlatformNavId as dR, isSize as dS, isTierPreview as dT, isUrlLocalhost as dU, isValidNavId as dV, isValidNavSegment as dW, isWebComponent as dX, linkToId as dY, linkToNav as dZ, loadingActions as d_, calculateRanks as da, cellText as db, checkFilterCondition as dc, childNavId as dd, classListSignal as de, createMap as df, createPlatformNavMap as dg, deriveAvatarGradient as dh, deriveContrastColor as di, deriveOppositeColor as dj, derivePropertyName as dk, emailValidation as dl, evaluate as dm, evaluateBool as dn, flattenTreeGridRows as dp, formatBadgeCount as dq, fullName as dr, generateClipPath as ds, generateTransform as dt, getClassList as du, getProperty as dv, getScrollParent as dw, getTierFromPreviewPath as dx, getTreeGridRow as dy, getUniqueId as dz, AccordionBodyDirective as e, mInterceptor as e0, manualValidation as e1, matchFieldValidation as e2, maxLengthValidation as e3, maxValidation as e4, mergePlatformNav as e5, mergeUnique as e6, mergeUniqueBy as e7, mergeUniqueWith as e8, minAgeValidation as e9, provideUserTabs as eA, publicGuard as eB, renderAddress as eC, requiredValidation as eD, resolveConfigAsset as eE, resolvePallet as eF, resolveSize as eG, rgbToHex as eH, rgbToHsl as eI, rowHasChildren as eJ, segmentsToNavId as eK, setProperty as eL, setTreeGridChildren as eM, settingsWidgets as eN, shouldShowBadge as eO, splitNavId as eP, stringToColor as eQ, toAttrBool as eR, toAttrNumber as eS, toCssLength as eT, toHostNavId as eU, toLength$1 as eV, toLocalNavId as eW, toggleTreeGridRow as eX, unfetchedPlatformNav as eY, urlValidation as eZ, minLengthValidation as ea, minValidation as eb, miniMarkToHtml as ec, navIdChain as ed, navIdFor as ee, navIdSegment as ef, navIdToRoutePath as eg, navIdToSegments as eh, navToId as ei, parentNavId as ej, parseAddress as ek, parseColor as el, patternValidation as em, platformNavWidgets as en, privateGuard as eo, processImageToSvg as ep, provideAppContext as eq, provideMagAppConfig as er, provideMagWcConfig as es, provideMagWcRoutes as et, provideModalComponents as eu, provideMurlUrlSerializer as ev, provideNavWidgets as ew, providePlatformNavWidgets as ex, provideSearch as ey, provideSizeContext as ez, AccordionComponent as f, AccordionGroupComponent as g, ActionComponent as h, AnimatedGraphsComponent as i, AppCardComponent as j, AppRelationType as k, AppTileComponent as l, AssetStore as m, AssetUrlPipe as n, Assets as o, AutosizeDirective as p, BadgeComponent as q, BandingComponent as r, BaseArrayInputComponent as s, BaseRootWebComponent as t, BaseWebComponent as u, ButtonGroupComponent as v, COMPONENT_INPUT_REGISTRY as w, CardComponent as x, CardWrapperComponent as y, CarouselComponent as z };
30609
- //# sourceMappingURL=magmonium-one-magmonium-one-C_V7zLMa.mjs.map
30687
+ //# sourceMappingURL=magmonium-one-magmonium-one-CgJtuPEF.mjs.map