@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 } from 'tslib';
5
5
  import { fromEvent, Subject, BehaviorSubject, combineLatest, of } from 'rxjs';
6
6
  import * as i3 from '@angular/router';
@@ -3258,6 +3258,12 @@ class StackController {
3258
3258
  getActiveStackId() {
3259
3259
  return this.activeView ? this.activeView.stackId : undefined;
3260
3260
  }
3261
+ /**
3262
+ * @internal
3263
+ */
3264
+ getActiveView() {
3265
+ return this.activeView;
3266
+ }
3261
3267
  hasRunningTask() {
3262
3268
  return this.runningTask !== undefined;
3263
3269
  }
@@ -3369,7 +3375,10 @@ class IonRouterOutlet {
3369
3375
  * The name of the outlet
3370
3376
  */
3371
3377
  this.name = PRIMARY_OUTLET;
3372
- this.stackEvents = new EventEmitter();
3378
+ /** @internal */
3379
+ this.stackWillChange = new EventEmitter();
3380
+ /** @internal */
3381
+ this.stackDidChange = new EventEmitter();
3373
3382
  // eslint-disable-next-line @angular-eslint/no-output-rename
3374
3383
  this.activateEvents = new EventEmitter();
3375
3384
  // eslint-disable-next-line @angular-eslint/no-output-rename
@@ -3566,9 +3575,14 @@ class IonRouterOutlet {
3566
3575
  * To avoid a race condition, we assign the top outlet synchronously.
3567
3576
  */
3568
3577
  this.navCtrl.setTopOutlet(this);
3578
+ const leavingView = this.stackCtrl.getActiveView();
3579
+ this.stackWillChange.emit({
3580
+ enteringView,
3581
+ tabSwitch: isTabSwitch(enteringView, leavingView),
3582
+ });
3569
3583
  this.stackCtrl.setActive(enteringView).then((data) => {
3570
3584
  this.activateEvents.emit(cmpRef.instance);
3571
- this.stackEvents.emit(data);
3585
+ this.stackDidChange.emit(data);
3572
3586
  });
3573
3587
  }
3574
3588
  /**
@@ -3656,7 +3670,7 @@ class IonRouterOutlet {
3656
3670
  }
3657
3671
  }
3658
3672
  /** @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 });
3659
- /** @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 });
3673
+ /** @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 });
3660
3674
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: IonRouterOutlet, decorators: [{
3661
3675
  type: Directive,
3662
3676
  args: [{
@@ -3679,7 +3693,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
3679
3693
  type: Optional
3680
3694
  }] }]; }, propDecorators: { name: [{
3681
3695
  type: Input
3682
- }], stackEvents: [{
3696
+ }], stackWillChange: [{
3697
+ type: Output
3698
+ }], stackDidChange: [{
3683
3699
  type: Output
3684
3700
  }], activateEvents: [{
3685
3701
  type: Output,
@@ -3779,7 +3795,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
3779
3795
  class IonTabs {
3780
3796
  constructor(navCtrl) {
3781
3797
  this.navCtrl = navCtrl;
3798
+ /**
3799
+ * Emitted before the tab view is changed.
3800
+ */
3782
3801
  this.ionTabsWillChange = new EventEmitter();
3802
+ /**
3803
+ * Emitted after the tab view is changed.
3804
+ */
3783
3805
  this.ionTabsDidChange = new EventEmitter();
3784
3806
  this.tabBarSlot = 'bottom';
3785
3807
  }
@@ -3792,10 +3814,18 @@ class IonTabs {
3792
3814
  /**
3793
3815
  * @internal
3794
3816
  */
3795
- onPageSelected(detail) {
3796
- const stackId = detail.enteringView.stackId;
3797
- if (detail.tabSwitch && stackId !== undefined) {
3817
+ onStackWillChange({ enteringView, tabSwitch }) {
3818
+ const stackId = enteringView.stackId;
3819
+ if (tabSwitch && stackId !== undefined) {
3798
3820
  this.ionTabsWillChange.emit({ tab: stackId });
3821
+ }
3822
+ }
3823
+ /**
3824
+ * @internal
3825
+ */
3826
+ onStackDidChange({ enteringView, tabSwitch }) {
3827
+ const stackId = enteringView.stackId;
3828
+ if (tabSwitch && stackId !== undefined) {
3799
3829
  if (this.tabBar) {
3800
3830
  this.tabBar.selectedTab = stackId;
3801
3831
  }
@@ -3915,16 +3945,26 @@ class IonTabs {
3915
3945
  /** @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: `
3916
3946
  <ng-content select="[slot=top]"></ng-content>
3917
3947
  <div class="tabs-inner" #tabsInner>
3918
- <ion-router-outlet #outlet tabs="true" (stackEvents)="onPageSelected($event)"></ion-router-outlet>
3948
+ <ion-router-outlet
3949
+ #outlet
3950
+ tabs="true"
3951
+ (stackWillChange)="onStackWillChange($event)"
3952
+ (stackDidChange)="onStackDidChange($event)"
3953
+ ></ion-router-outlet>
3919
3954
  </div>
3920
3955
  <ng-content></ng-content>
3921
- `, 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"] }] });
3956
+ `, 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"] }] });
3922
3957
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: IonTabs, decorators: [{
3923
3958
  type: Component,
3924
3959
  args: [{ selector: 'ion-tabs', template: `
3925
3960
  <ng-content select="[slot=top]"></ng-content>
3926
3961
  <div class="tabs-inner" #tabsInner>
3927
- <ion-router-outlet #outlet tabs="true" (stackEvents)="onPageSelected($event)"></ion-router-outlet>
3962
+ <ion-router-outlet
3963
+ #outlet
3964
+ tabs="true"
3965
+ (stackWillChange)="onStackWillChange($event)"
3966
+ (stackDidChange)="onStackDidChange($event)"
3967
+ ></ion-router-outlet>
3928
3968
  </div>
3929
3969
  <ng-content></ng-content>
3930
3970
  `, 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"] }]
@@ -4312,6 +4352,54 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
4312
4352
  args: [TemplateRef, { static: false }]
4313
4353
  }] } });
4314
4354
 
4355
+ /**
4356
+ * @description
4357
+ * Provider which adds `MaxValidator` to the `NG_VALIDATORS` multi-provider list.
4358
+ */
4359
+ const ION_MAX_VALIDATOR = {
4360
+ provide: NG_VALIDATORS,
4361
+ useExisting: forwardRef(() => IonMaxValidator),
4362
+ multi: true,
4363
+ };
4364
+ // eslint-disable-next-line @angular-eslint/directive-class-suffix
4365
+ class IonMaxValidator extends MaxValidator {
4366
+ }
4367
+ /** @nocollapse */ IonMaxValidator.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: IonMaxValidator, deps: null, target: i0.ɵɵFactoryTarget.Directive });
4368
+ /** @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 });
4369
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: IonMaxValidator, decorators: [{
4370
+ type: Directive,
4371
+ args: [{
4372
+ selector: 'ion-input[type=number][max][formControlName],ion-input[type=number][max][formControl],ion-input[type=number][max][ngModel]',
4373
+ providers: [ION_MAX_VALIDATOR],
4374
+ // eslint-disable-next-line @angular-eslint/no-host-metadata-property
4375
+ host: { '[attr.max]': '_enabled ? max : null' },
4376
+ }]
4377
+ }] });
4378
+
4379
+ /**
4380
+ * @description
4381
+ * Provider which adds `MinValidator` to the `NG_VALIDATORS` multi-provider list.
4382
+ */
4383
+ const ION_MIN_VALIDATOR = {
4384
+ provide: NG_VALIDATORS,
4385
+ useExisting: forwardRef(() => IonMinValidator),
4386
+ multi: true,
4387
+ };
4388
+ // eslint-disable-next-line @angular-eslint/directive-class-suffix
4389
+ class IonMinValidator extends MinValidator {
4390
+ }
4391
+ /** @nocollapse */ IonMinValidator.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: IonMinValidator, deps: null, target: i0.ɵɵFactoryTarget.Directive });
4392
+ /** @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 });
4393
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: IonMinValidator, decorators: [{
4394
+ type: Directive,
4395
+ args: [{
4396
+ selector: 'ion-input[type=number][min][formControlName],ion-input[type=number][min][formControl],ion-input[type=number][min][ngModel]',
4397
+ providers: [ION_MIN_VALIDATOR],
4398
+ // eslint-disable-next-line @angular-eslint/no-host-metadata-property
4399
+ host: { '[attr.min]': '_enabled ? min : null' },
4400
+ }]
4401
+ }] });
4402
+
4315
4403
  // TODO(FW-2827): types
4316
4404
  class OverlayBaseController {
4317
4405
  constructor(ctrl) {
@@ -4836,6 +4924,9 @@ const DECLARATIONS = [
4836
4924
  NavDelegate,
4837
4925
  RouterLinkDelegateDirective,
4838
4926
  RouterLinkWithHrefDelegateDirective,
4927
+ // validators
4928
+ IonMinValidator,
4929
+ IonMaxValidator,
4839
4930
  ];
4840
4931
  class IonicModule {
4841
4932
  static forRoot(config) {
@@ -4878,7 +4969,10 @@ class IonicModule {
4878
4969
  IonBackButtonDelegateDirective,
4879
4970
  NavDelegate,
4880
4971
  RouterLinkDelegateDirective,
4881
- 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,
4972
+ RouterLinkWithHrefDelegateDirective,
4973
+ // validators
4974
+ IonMinValidator,
4975
+ 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,
4882
4976
  // manual proxies
4883
4977
  IonModal,
4884
4978
  IonPopover,
@@ -4894,7 +4988,10 @@ class IonicModule {
4894
4988
  IonBackButtonDelegateDirective,
4895
4989
  NavDelegate,
4896
4990
  RouterLinkDelegateDirective,
4897
- RouterLinkWithHrefDelegateDirective] });
4991
+ RouterLinkWithHrefDelegateDirective,
4992
+ // validators
4993
+ IonMinValidator,
4994
+ IonMaxValidator] });
4898
4995
  /** @nocollapse */ IonicModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: IonicModule, providers: [AngularDelegate, ModalController, PopoverController], imports: [CommonModule] });
4899
4996
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: IonicModule, decorators: [{
4900
4997
  type: NgModule,
@@ -4922,5 +5019,5 @@ function componentInputBindingFactory(router) {
4922
5019
  * Generated bundle index. Do not edit.
4923
5020
  */
4924
5021
 
4925
- 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 };
5022
+ 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 };
4926
5023
  //# sourceMappingURL=ionic-angular.mjs.map