@ionic/angular 7.3.1-nightly.20230818 → 7.3.1-nightly.20230822

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,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Directive, HostListener, Component, ChangeDetectionStrategy, Injectable, InjectionToken, Inject, Optional, inject, NgZone, ApplicationRef, Injector, createComponent, EventEmitter, ViewContainerRef, EnvironmentInjector, Attribute, SkipSelf, Input, Output, reflectComponentType, ElementRef, ViewChild, ContentChild, ContentChildren, TemplateRef, APP_INITIALIZER, NgModule } from '@angular/core';
3
- import { NgControl, NG_VALUE_ACCESSOR } from '@angular/forms';
2
+ import { Directive, HostListener, Component, ChangeDetectionStrategy, Injectable, InjectionToken, Inject, Optional, inject, NgZone, ApplicationRef, Injector, createComponent, EventEmitter, ViewContainerRef, EnvironmentInjector, Attribute, SkipSelf, Input, Output, reflectComponentType, ElementRef, ViewChild, ContentChild, ContentChildren, TemplateRef, forwardRef, APP_INITIALIZER, NgModule } from '@angular/core';
3
+ import { NgControl, NG_VALUE_ACCESSOR, NG_VALIDATORS, MaxValidator, MinValidator } from '@angular/forms';
4
4
  import { __decorate, __awaiter } from 'tslib';
5
5
  import { fromEvent, Subject, BehaviorSubject, combineLatest, of } from 'rxjs';
6
6
  import * as i3 from '@angular/router';
@@ -3267,6 +3267,12 @@ class StackController {
3267
3267
  getActiveStackId() {
3268
3268
  return this.activeView ? this.activeView.stackId : undefined;
3269
3269
  }
3270
+ /**
3271
+ * @internal
3272
+ */
3273
+ getActiveView() {
3274
+ return this.activeView;
3275
+ }
3270
3276
  hasRunningTask() {
3271
3277
  return this.runningTask !== undefined;
3272
3278
  }
@@ -3380,7 +3386,10 @@ class IonRouterOutlet {
3380
3386
  * The name of the outlet
3381
3387
  */
3382
3388
  this.name = PRIMARY_OUTLET;
3383
- this.stackEvents = new EventEmitter();
3389
+ /** @internal */
3390
+ this.stackWillChange = new EventEmitter();
3391
+ /** @internal */
3392
+ this.stackDidChange = new EventEmitter();
3384
3393
  // eslint-disable-next-line @angular-eslint/no-output-rename
3385
3394
  this.activateEvents = new EventEmitter();
3386
3395
  // eslint-disable-next-line @angular-eslint/no-output-rename
@@ -3579,9 +3588,14 @@ class IonRouterOutlet {
3579
3588
  * To avoid a race condition, we assign the top outlet synchronously.
3580
3589
  */
3581
3590
  this.navCtrl.setTopOutlet(this);
3591
+ const leavingView = this.stackCtrl.getActiveView();
3592
+ this.stackWillChange.emit({
3593
+ enteringView,
3594
+ tabSwitch: isTabSwitch(enteringView, leavingView),
3595
+ });
3582
3596
  this.stackCtrl.setActive(enteringView).then((data) => {
3583
3597
  this.activateEvents.emit(cmpRef.instance);
3584
- this.stackEvents.emit(data);
3598
+ this.stackDidChange.emit(data);
3585
3599
  });
3586
3600
  }
3587
3601
  /**
@@ -3669,7 +3683,7 @@ class IonRouterOutlet {
3669
3683
  }
3670
3684
  }
3671
3685
  /** @nocollapse */ IonRouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: IonRouterOutlet, deps: [{ token: 'name', attribute: true }, { token: 'tabs', attribute: true, optional: true }, { token: i1.Location }, { token: i0.ElementRef }, { token: i3.Router }, { token: i0.NgZone }, { token: i3.ActivatedRoute }, { token: IonRouterOutlet, optional: true, skipSelf: true }], target: i0.ɵɵFactoryTarget.Directive });
3672
- /** @nocollapse */ IonRouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.12", type: IonRouterOutlet, selector: "ion-router-outlet", inputs: { animated: "animated", animation: "animation", mode: "mode", swipeGesture: "swipeGesture", name: "name" }, outputs: { stackEvents: "stackEvents", activateEvents: "activate", deactivateEvents: "deactivate" }, exportAs: ["outlet"], ngImport: i0 });
3686
+ /** @nocollapse */ IonRouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.12", type: IonRouterOutlet, selector: "ion-router-outlet", inputs: { animated: "animated", animation: "animation", mode: "mode", swipeGesture: "swipeGesture", name: "name" }, outputs: { stackWillChange: "stackWillChange", stackDidChange: "stackDidChange", activateEvents: "activate", deactivateEvents: "deactivate" }, exportAs: ["outlet"], ngImport: i0 });
3673
3687
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: IonRouterOutlet, decorators: [{
3674
3688
  type: Directive,
3675
3689
  args: [{
@@ -3694,7 +3708,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
3694
3708
  }] }];
3695
3709
  }, propDecorators: { name: [{
3696
3710
  type: Input
3697
- }], stackEvents: [{
3711
+ }], stackWillChange: [{
3712
+ type: Output
3713
+ }], stackDidChange: [{
3698
3714
  type: Output
3699
3715
  }], activateEvents: [{
3700
3716
  type: Output,
@@ -3795,7 +3811,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
3795
3811
  class IonTabs {
3796
3812
  constructor(navCtrl) {
3797
3813
  this.navCtrl = navCtrl;
3814
+ /**
3815
+ * Emitted before the tab view is changed.
3816
+ */
3798
3817
  this.ionTabsWillChange = new EventEmitter();
3818
+ /**
3819
+ * Emitted after the tab view is changed.
3820
+ */
3799
3821
  this.ionTabsDidChange = new EventEmitter();
3800
3822
  this.tabBarSlot = 'bottom';
3801
3823
  }
@@ -3808,10 +3830,18 @@ class IonTabs {
3808
3830
  /**
3809
3831
  * @internal
3810
3832
  */
3811
- onPageSelected(detail) {
3812
- const stackId = detail.enteringView.stackId;
3813
- if (detail.tabSwitch && stackId !== undefined) {
3833
+ onStackWillChange({ enteringView, tabSwitch }) {
3834
+ const stackId = enteringView.stackId;
3835
+ if (tabSwitch && stackId !== undefined) {
3814
3836
  this.ionTabsWillChange.emit({ tab: stackId });
3837
+ }
3838
+ }
3839
+ /**
3840
+ * @internal
3841
+ */
3842
+ onStackDidChange({ enteringView, tabSwitch }) {
3843
+ const stackId = enteringView.stackId;
3844
+ if (tabSwitch && stackId !== undefined) {
3815
3845
  if (this.tabBar) {
3816
3846
  this.tabBar.selectedTab = stackId;
3817
3847
  }
@@ -3923,16 +3953,26 @@ class IonTabs {
3923
3953
  /** @nocollapse */ IonTabs.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: IonTabs, selector: "ion-tabs", outputs: { ionTabsWillChange: "ionTabsWillChange", ionTabsDidChange: "ionTabsDidChange" }, host: { listeners: { "ionTabButtonClick": "select($event)" } }, queries: [{ propertyName: "tabBar", first: true, predicate: IonTabBar, descendants: true }, { propertyName: "tabBars", predicate: IonTabBar }], viewQueries: [{ propertyName: "outlet", first: true, predicate: ["outlet"], descendants: true, read: IonRouterOutlet }, { propertyName: "tabsInner", first: true, predicate: ["tabsInner"], descendants: true, read: ElementRef, static: true }], ngImport: i0, template: `
3924
3954
  <ng-content select="[slot=top]"></ng-content>
3925
3955
  <div class="tabs-inner" #tabsInner>
3926
- <ion-router-outlet #outlet tabs="true" (stackEvents)="onPageSelected($event)"></ion-router-outlet>
3956
+ <ion-router-outlet
3957
+ #outlet
3958
+ tabs="true"
3959
+ (stackWillChange)="onStackWillChange($event)"
3960
+ (stackDidChange)="onStackDidChange($event)"
3961
+ ></ion-router-outlet>
3927
3962
  </div>
3928
3963
  <ng-content></ng-content>
3929
- `, isInline: true, styles: [":host{display:flex;position:absolute;inset:0;flex-direction:column;width:100%;height:100%;contain:layout size style}.tabs-inner{position:relative;flex:1;contain:layout size style}\n"], dependencies: [{ kind: "directive", type: IonRouterOutlet, selector: "ion-router-outlet", inputs: ["animated", "animation", "mode", "swipeGesture", "name"], outputs: ["stackEvents", "activate", "deactivate"], exportAs: ["outlet"] }] });
3964
+ `, isInline: true, styles: [":host{display:flex;position:absolute;inset:0;flex-direction:column;width:100%;height:100%;contain:layout size style}.tabs-inner{position:relative;flex:1;contain:layout size style}\n"], dependencies: [{ kind: "directive", type: IonRouterOutlet, selector: "ion-router-outlet", inputs: ["animated", "animation", "mode", "swipeGesture", "name"], outputs: ["stackWillChange", "stackDidChange", "activate", "deactivate"], exportAs: ["outlet"] }] });
3930
3965
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: IonTabs, decorators: [{
3931
3966
  type: Component,
3932
3967
  args: [{ selector: 'ion-tabs', template: `
3933
3968
  <ng-content select="[slot=top]"></ng-content>
3934
3969
  <div class="tabs-inner" #tabsInner>
3935
- <ion-router-outlet #outlet tabs="true" (stackEvents)="onPageSelected($event)"></ion-router-outlet>
3970
+ <ion-router-outlet
3971
+ #outlet
3972
+ tabs="true"
3973
+ (stackWillChange)="onStackWillChange($event)"
3974
+ (stackDidChange)="onStackDidChange($event)"
3975
+ ></ion-router-outlet>
3936
3976
  </div>
3937
3977
  <ng-content></ng-content>
3938
3978
  `, styles: [":host{display:flex;position:absolute;inset:0;flex-direction:column;width:100%;height:100%;contain:layout size style}.tabs-inner{position:relative;flex:1;contain:layout size style}\n"] }]
@@ -4329,6 +4369,54 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
4329
4369
  args: [TemplateRef, { static: false }]
4330
4370
  }] } });
4331
4371
 
4372
+ /**
4373
+ * @description
4374
+ * Provider which adds `MaxValidator` to the `NG_VALIDATORS` multi-provider list.
4375
+ */
4376
+ const ION_MAX_VALIDATOR = {
4377
+ provide: NG_VALIDATORS,
4378
+ useExisting: forwardRef(() => IonMaxValidator),
4379
+ multi: true,
4380
+ };
4381
+ // eslint-disable-next-line @angular-eslint/directive-class-suffix
4382
+ class IonMaxValidator extends MaxValidator {
4383
+ }
4384
+ /** @nocollapse */ IonMaxValidator.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: IonMaxValidator, deps: null, target: i0.ɵɵFactoryTarget.Directive });
4385
+ /** @nocollapse */ IonMaxValidator.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.12", type: IonMaxValidator, selector: "ion-input[type=number][max][formControlName],ion-input[type=number][max][formControl],ion-input[type=number][max][ngModel]", host: { properties: { "attr.max": "_enabled ? max : null" } }, providers: [ION_MAX_VALIDATOR], usesInheritance: true, ngImport: i0 });
4386
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: IonMaxValidator, decorators: [{
4387
+ type: Directive,
4388
+ args: [{
4389
+ selector: 'ion-input[type=number][max][formControlName],ion-input[type=number][max][formControl],ion-input[type=number][max][ngModel]',
4390
+ providers: [ION_MAX_VALIDATOR],
4391
+ // eslint-disable-next-line @angular-eslint/no-host-metadata-property
4392
+ host: { '[attr.max]': '_enabled ? max : null' },
4393
+ }]
4394
+ }] });
4395
+
4396
+ /**
4397
+ * @description
4398
+ * Provider which adds `MinValidator` to the `NG_VALIDATORS` multi-provider list.
4399
+ */
4400
+ const ION_MIN_VALIDATOR = {
4401
+ provide: NG_VALIDATORS,
4402
+ useExisting: forwardRef(() => IonMinValidator),
4403
+ multi: true,
4404
+ };
4405
+ // eslint-disable-next-line @angular-eslint/directive-class-suffix
4406
+ class IonMinValidator extends MinValidator {
4407
+ }
4408
+ /** @nocollapse */ IonMinValidator.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: IonMinValidator, deps: null, target: i0.ɵɵFactoryTarget.Directive });
4409
+ /** @nocollapse */ IonMinValidator.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.12", type: IonMinValidator, selector: "ion-input[type=number][min][formControlName],ion-input[type=number][min][formControl],ion-input[type=number][min][ngModel]", host: { properties: { "attr.min": "_enabled ? min : null" } }, providers: [ION_MIN_VALIDATOR], usesInheritance: true, ngImport: i0 });
4410
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: IonMinValidator, decorators: [{
4411
+ type: Directive,
4412
+ args: [{
4413
+ selector: 'ion-input[type=number][min][formControlName],ion-input[type=number][min][formControl],ion-input[type=number][min][ngModel]',
4414
+ providers: [ION_MIN_VALIDATOR],
4415
+ // eslint-disable-next-line @angular-eslint/no-host-metadata-property
4416
+ host: { '[attr.min]': '_enabled ? min : null' },
4417
+ }]
4418
+ }] });
4419
+
4332
4420
  // TODO(FW-2827): types
4333
4421
  class OverlayBaseController {
4334
4422
  constructor(ctrl) {
@@ -4840,6 +4928,9 @@ const DECLARATIONS = [
4840
4928
  NavDelegate,
4841
4929
  RouterLinkDelegateDirective,
4842
4930
  RouterLinkWithHrefDelegateDirective,
4931
+ // validators
4932
+ IonMinValidator,
4933
+ IonMaxValidator,
4843
4934
  ];
4844
4935
  class IonicModule {
4845
4936
  static forRoot(config) {
@@ -4882,7 +4973,10 @@ class IonicModule {
4882
4973
  IonBackButtonDelegateDirective,
4883
4974
  NavDelegate,
4884
4975
  RouterLinkDelegateDirective,
4885
- RouterLinkWithHrefDelegateDirective], imports: [CommonModule], exports: [IonAccordion, IonAccordionGroup, IonActionSheet, IonAlert, IonApp, IonAvatar, IonBackButton, IonBackdrop, IonBadge, IonBreadcrumb, IonBreadcrumbs, IonButton, IonButtons, IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonCheckbox, IonChip, IonCol, IonContent, IonDatetime, IonDatetimeButton, IonFab, IonFabButton, IonFabList, IonFooter, IonGrid, IonHeader, IonIcon, IonImg, IonInfiniteScroll, IonInfiniteScrollContent, IonInput, IonItem, IonItemDivider, IonItemGroup, IonItemOption, IonItemOptions, IonItemSliding, IonLabel, IonList, IonListHeader, IonLoading, IonMenu, IonMenuButton, IonMenuToggle, IonNav, IonNavLink, IonNote, IonPicker, IonProgressBar, IonRadio, IonRadioGroup, IonRange, IonRefresher, IonRefresherContent, IonReorder, IonReorderGroup, IonRippleEffect, IonRow, IonSearchbar, IonSegment, IonSegmentButton, IonSelect, IonSelectOption, IonSkeletonText, IonSpinner, IonSplitPane, IonTabBar, IonTabButton, IonText, IonTextarea, IonThumbnail, IonTitle, IonToast, IonToggle, IonToolbar,
4976
+ RouterLinkWithHrefDelegateDirective,
4977
+ // validators
4978
+ IonMinValidator,
4979
+ IonMaxValidator], imports: [CommonModule], exports: [IonAccordion, IonAccordionGroup, IonActionSheet, IonAlert, IonApp, IonAvatar, IonBackButton, IonBackdrop, IonBadge, IonBreadcrumb, IonBreadcrumbs, IonButton, IonButtons, IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonCheckbox, IonChip, IonCol, IonContent, IonDatetime, IonDatetimeButton, IonFab, IonFabButton, IonFabList, IonFooter, IonGrid, IonHeader, IonIcon, IonImg, IonInfiniteScroll, IonInfiniteScrollContent, IonInput, IonItem, IonItemDivider, IonItemGroup, IonItemOption, IonItemOptions, IonItemSliding, IonLabel, IonList, IonListHeader, IonLoading, IonMenu, IonMenuButton, IonMenuToggle, IonNav, IonNavLink, IonNote, IonPicker, IonProgressBar, IonRadio, IonRadioGroup, IonRange, IonRefresher, IonRefresherContent, IonReorder, IonReorderGroup, IonRippleEffect, IonRow, IonSearchbar, IonSegment, IonSegmentButton, IonSelect, IonSelectOption, IonSkeletonText, IonSpinner, IonSplitPane, IonTabBar, IonTabButton, IonText, IonTextarea, IonThumbnail, IonTitle, IonToast, IonToggle, IonToolbar,
4886
4980
  // manual proxies
4887
4981
  IonModal,
4888
4982
  IonPopover,
@@ -4898,7 +4992,10 @@ class IonicModule {
4898
4992
  IonBackButtonDelegateDirective,
4899
4993
  NavDelegate,
4900
4994
  RouterLinkDelegateDirective,
4901
- RouterLinkWithHrefDelegateDirective] });
4995
+ RouterLinkWithHrefDelegateDirective,
4996
+ // validators
4997
+ IonMinValidator,
4998
+ IonMaxValidator] });
4902
4999
  /** @nocollapse */ IonicModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: IonicModule, providers: [AngularDelegate, ModalController, PopoverController], imports: [CommonModule] });
4903
5000
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: IonicModule, decorators: [{
4904
5001
  type: NgModule,
@@ -4926,5 +5023,5 @@ function componentInputBindingFactory(router) {
4926
5023
  * Generated bundle index. Do not edit.
4927
5024
  */
4928
5025
 
4929
- export { ActionSheetController, AlertController, AngularDelegate, AnimationController, BooleanValueAccessorDirective as BooleanValueAccessor, Config, DomController, GestureController, IonAccordion, IonAccordionGroup, IonActionSheet, IonAlert, IonApp, IonAvatar, IonBackButton, IonBackButtonDelegateDirective as IonBackButtonDelegate, IonBackdrop, IonBadge, IonBreadcrumb, IonBreadcrumbs, IonButton, IonButtons, IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonCheckbox, IonChip, IonCol, IonContent, IonDatetime, IonDatetimeButton, IonFab, IonFabButton, IonFabList, IonFooter, IonGrid, IonHeader, IonIcon, IonImg, IonInfiniteScroll, IonInfiniteScrollContent, IonInput, IonItem, IonItemDivider, IonItemGroup, IonItemOption, IonItemOptions, IonItemSliding, IonLabel, IonList, IonListHeader, IonLoading, IonMenu, IonMenuButton, IonMenuToggle, IonModal, IonNav, IonNavLink, IonNote, IonPicker, IonPopover, IonProgressBar, IonRadio, IonRadioGroup, IonRange, IonRefresher, IonRefresherContent, IonReorder, IonReorderGroup, IonRippleEffect, IonRouterOutlet, IonRow, IonSearchbar, IonSegment, IonSegmentButton, IonSelect, IonSelectOption, IonSkeletonText, IonSpinner, IonSplitPane, IonTabBar, IonTabButton, IonTabs, IonText, IonTextarea, IonThumbnail, IonTitle, IonToast, IonToggle, IonToolbar, IonicModule, IonicRouteStrategy, LoadingController, MenuController, ModalController, NavController, NavDelegate, NavParams, NumericValueAccessorDirective as NumericValueAccessor, PickerController, Platform, PopoverController, RadioValueAccessorDirective as RadioValueAccessor, RouterLinkDelegateDirective as RouterLinkDelegate, RouterLinkWithHrefDelegateDirective as RouterLinkWithHrefDelegate, SelectValueAccessorDirective as SelectValueAccessor, TextValueAccessorDirective as TextValueAccessor, ToastController };
5026
+ export { ActionSheetController, AlertController, AngularDelegate, AnimationController, BooleanValueAccessorDirective as BooleanValueAccessor, Config, DomController, GestureController, ION_MAX_VALIDATOR, ION_MIN_VALIDATOR, IonAccordion, IonAccordionGroup, IonActionSheet, IonAlert, IonApp, IonAvatar, IonBackButton, IonBackButtonDelegateDirective as IonBackButtonDelegate, IonBackdrop, IonBadge, IonBreadcrumb, IonBreadcrumbs, IonButton, IonButtons, IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonCheckbox, IonChip, IonCol, IonContent, IonDatetime, IonDatetimeButton, IonFab, IonFabButton, IonFabList, IonFooter, IonGrid, IonHeader, IonIcon, IonImg, IonInfiniteScroll, IonInfiniteScrollContent, IonInput, IonItem, IonItemDivider, IonItemGroup, IonItemOption, IonItemOptions, IonItemSliding, IonLabel, IonList, IonListHeader, IonLoading, IonMaxValidator, IonMenu, IonMenuButton, IonMenuToggle, IonMinValidator, IonModal, IonNav, IonNavLink, IonNote, IonPicker, IonPopover, IonProgressBar, IonRadio, IonRadioGroup, IonRange, IonRefresher, IonRefresherContent, IonReorder, IonReorderGroup, IonRippleEffect, IonRouterOutlet, IonRow, IonSearchbar, IonSegment, IonSegmentButton, IonSelect, IonSelectOption, IonSkeletonText, IonSpinner, IonSplitPane, IonTabBar, IonTabButton, IonTabs, IonText, IonTextarea, IonThumbnail, IonTitle, IonToast, IonToggle, IonToolbar, IonicModule, IonicRouteStrategy, LoadingController, MenuController, ModalController, NavController, NavDelegate, NavParams, NumericValueAccessorDirective as NumericValueAccessor, PickerController, Platform, PopoverController, RadioValueAccessorDirective as RadioValueAccessor, RouterLinkDelegateDirective as RouterLinkDelegate, RouterLinkWithHrefDelegateDirective as RouterLinkWithHrefDelegate, SelectValueAccessorDirective as SelectValueAccessor, TextValueAccessorDirective as TextValueAccessor, ToastController };
4930
5027
  //# sourceMappingURL=ionic-angular.mjs.map