@alyle/ui
Version:
Minimal Design, a set of components for Angular
456 lines (444 loc) • 25.7 kB
JavaScript
import * as i0 from '@angular/core';
import { Input, Directive, EventEmitter, Output, ContentChild, Inject, ChangeDetectionStrategy, Component, NgModule } from '@angular/core';
import * as i1 from '@alyle/ui';
import { getLyThemeVariableUndefinedError, StyleRenderer, mixinStyleUpdater, mixinBg, mixinColor, mixinElevation, mixinShadowColor, LyExpansionIconModule, NgTranscludeModule } from '@alyle/ui';
import { Subject, Subscription } from 'rxjs';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import * as i1$1 from '@angular/common';
import { CommonModule } from '@angular/common';
import { trigger, state, transition, style, animate } from '@angular/animations';
import { distinctUntilChanged, startWith, filter, first } from 'rxjs/operators';
const STYLE_PRIORITY = -0.9;
const STYLES = (theme, ref) => {
const classes = ref.selectorsOf(STYLES);
const { after } = theme;
return {
$priority: STYLE_PRIORITY,
$name: LyAccordion.и,
$global: () => (_className) => `${_className} ${classes.panelTitle},${_className} ${classes.panelDescription}{display:flex;margin-${after}:16px;}${_className} ${classes.panel}:not(${classes.disabled}) ${classes.panelTitle}{color:${theme.text.default};}${_className} ${classes.panel}:not(${classes.disabled}) ${classes.panelDescription}{color:${theme.text.secondary};}`,
root: (theme.expansion?.root) ? () => theme.expansion.root(classes) : null,
panel: () => (_className) => `${_className}{display:block;overflow:hidden;position:relative;}${_className}:not(${classes.disabled}) ${classes.panelHeader}{cursor:pointer;}`,
panelHeader: () => (_className) => `${_className}{display:flex;position:relative;flex-direction:row;align-items:center;padding:0 24px;transition:height ${theme.animations.durations.entering}ms ${theme.animations.curves.standard};font-family:${theme.typography.fontFamily};font-size:${theme.pxToRem(15)};font-weight:400;}${classes.panel}:not(${classes.expanded}):not(${classes.disabled}) ${_className}:hover{background:${theme.hover};} (hover: none){${classes.panel}:not(${classes.expanded}):not(${classes.disabled}) ${_className}:hover{background:none;}}`,
panelHeaderContent: (_className) => `${_className}{display:flex;flex:1;flex-direction:row;align-items:center;overflow:hidden;}`,
panelContent: (_className) => `${_className}{display:flex;flex-direction:column;overflow:visible;}`,
panelBody: (_className) => `${_className}{visibility:hidden;padding:0 24px 16px;transition:visibility ${theme.animations.durations.entering}ms ${theme.animations.curves.standard};font-family:${theme.typography.fontFamily};font-size:${theme.pxToRem(14)};font-weight:400;line-height:${theme.pxToRem(20)};}`,
panelTitle: (_className) => `${_className}{flex-grow:1;}`,
panelDescription: (_className) => `${_className}{flex-grow:2;}`,
panelActionRow: (_className) => `${_className}{border-top:1px solid ${theme.divider};display:flex;flex-direction:row;justify-content:flex-end;padding:16px 8px 16px 24px;}`,
expanded: () => (_className) => `${_className} ${classes.panelBody}{visibility:visible;}`,
disabled: (_className) => `${_className}{color:${theme.disabled.contrast};}`
};
};
class LyAccordion {
/** @docs-private */
static { this.и = 'LyAccordion'; }
set appearance(val) {
this._appearance = val;
const newClass = this._theme.renderStyle(`${LyAccordion.и}--${val}-appearance`, (theme, ref) => {
if (!(theme.expansion.appearance && theme.expansion.appearance[val])) {
throw new Error(`Value expansion.appearance['${val}'] not found in ThemeVariables`);
}
const classes = ref.selectorsOf(STYLES);
return theme.expansion.appearance[val](classes);
}, STYLE_PRIORITY);
this._appearanceClass = this.sRenderer.updateClass(newClass, this._appearanceClass);
}
get appearance() {
return this._appearance;
}
set multiple(val) {
this._multiple = coerceBooleanProperty(val);
}
get multiple() {
return this._multiple;
}
set hasToggle(val) {
this._hasToggle = coerceBooleanProperty(val);
}
get hasToggle() {
return this._hasToggle;
}
constructor(sRenderer, _theme, _renderer, _el) {
this.sRenderer = sRenderer;
this._theme = _theme;
this._renderer = _renderer;
this._el = _el;
/** @docs-private */
this.classes = this._theme.addStyleSheet(STYLES);
this._hasToggle = true;
/** Stream that emits true/false when openAll/closeAll is triggered. */
this._openCloseAllActions = new Subject();
}
ngOnInit() {
const { expansion } = this._theme.variables;
if (expansion) {
this._renderer.addClass(this._el.nativeElement, this.classes.root);
// Apply default config
if (expansion.defaultConfig && expansion.defaultConfig.appearance) {
if (this.appearance == null) {
this.appearance = expansion.defaultConfig.appearance;
}
}
}
else {
throw getLyThemeVariableUndefinedError('expansion');
}
}
closeAll() {
this._openCloseAll(true);
}
openAll() {
this._openCloseAll(false);
}
_openCloseAll(expanded) {
if (this.multiple) {
this._openCloseAllActions.next(expanded);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyAccordion, deps: [{ token: i1.StyleRenderer }, { token: i1.LyTheme2 }, { token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.10", type: LyAccordion, isStandalone: false, selector: "ly-accordion", inputs: { appearance: "appearance", multiple: "multiple", hasToggle: "hasToggle" }, providers: [
StyleRenderer,
], exportAs: ["lyAccordion"], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyAccordion, decorators: [{
type: Directive,
args: [{
selector: 'ly-accordion',
exportAs: 'lyAccordion',
providers: [
StyleRenderer,
],
standalone: false
}]
}], ctorParameters: () => [{ type: i1.StyleRenderer }, { type: i1.LyTheme2 }, { type: i0.Renderer2 }, { type: i0.ElementRef }], propDecorators: { appearance: [{
type: Input
}], multiple: [{
type: Input
}], hasToggle: [{
type: Input
}] } });
const lyExpansionAnimations = {
contentExpansion: trigger('contentExpansion', [
state('collapsed, void', style({ height: '0px', visibility: 'hidden' })),
state('expanded', style({ height: '*', visibility: 'visible' })),
transition('expanded <=> collapsed, void => collapsed', animate('{{panelAnimationTiming}}')),
])
};
class LyExpansionPanelContent {
constructor(_template) {
this._template = _template;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyExpansionPanelContent, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.10", type: LyExpansionPanelContent, isStandalone: false, selector: "ng-template[lyExpansionPanelContent]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyExpansionPanelContent, decorators: [{
type: Directive,
args: [{
selector: 'ng-template[lyExpansionPanelContent]',
standalone: false
}]
}], ctorParameters: () => [{ type: i0.TemplateRef }] });
/** @docs-private */
class LyExpansionPanelBase {
constructor(_theme) {
this._theme = _theme;
}
}
/** @docs-private */
const LyButtonMixinBase = mixinStyleUpdater(mixinBg(mixinColor(mixinElevation(mixinShadowColor(LyExpansionPanelBase)))));
class LyExpansionPanel extends LyButtonMixinBase {
set disabled(val) {
const newVal = coerceBooleanProperty(val);
if (newVal !== this.disabled) {
this._disabled = newVal;
if (newVal) {
this._renderer.addClass(this._el.nativeElement, this._accordion.classes.disabled);
}
else {
this._renderer.removeClass(this._el.nativeElement, this._accordion.classes.disabled);
}
}
}
get disabled() {
return this._disabled;
}
set expanded(val) {
const newVal = coerceBooleanProperty(val);
if (newVal !== this.expanded && !this.disabled) {
// unselect other panels
if (newVal && !this._accordion.multiple) {
this._accordion._openCloseAllActions.next(false);
}
this._expanded = newVal;
if (newVal) {
this._renderer.addClass(this._el.nativeElement, this._accordion.classes.expanded);
this.opened.emit();
}
else {
this._renderer.removeClass(this._el.nativeElement, this._accordion.classes.expanded);
this.closed.emit();
}
this._cd.markForCheck();
}
}
get expanded() {
return this._expanded;
}
set hasToggle(val) {
this._hasToggle = coerceBooleanProperty(val);
}
get hasToggle() {
return this._hasToggle == null ? this._accordion.hasToggle : this._hasToggle;
}
constructor(_el, _renderer, _cd, _theme, _accordion) {
super(_theme);
this._el = _el;
this._renderer = _renderer;
this._cd = _cd;
this._accordion = _accordion;
/** @docs-private */
this.classes = this._accordion.classes;
this._panelAnimationTiming = `${this._theme.variables.animations.durations.entering}ms ${this._theme.variables.animations.curves.standard}`;
/** Subscription to openAll/closeAll events. */
this._openCloseAllSubscription = Subscription.EMPTY;
this._hasToggle = !!this._accordion.hasToggle;
/** Event emitted every time the LyExpansionPanel is closed. */
this.closed = new EventEmitter();
/** Event emitted every time the LyExpansionPanel is opened. */
this.opened = new EventEmitter();
/** An event emitted after the body's collapse animation happens. */
this.afterCollapse = new EventEmitter();
/** An event emitted after the body's expansion animation happens. */
this.afterExpand = new EventEmitter();
/** Event emitted when the LyExpansionPanel is destroyed. */
this.destroyed = new EventEmitter();
/** Stream of body animation done events. */
this._bodyAnimationDone = new Subject();
_renderer.addClass(_el.nativeElement, this._accordion.classes.panel);
this._openCloseAllSubscription = this._subscribeToOpenCloseAllActions();
this._bodyAnimationDone.pipe(distinctUntilChanged((x, y) => {
return x.fromState === y.fromState && x.toState === y.toState;
})).subscribe(event => {
if (event.fromState !== 'void') {
if (event.toState === 'expanded') {
this.afterExpand.emit();
}
else if (event.toState === 'collapsed') {
this.afterCollapse.emit();
}
}
});
}
ngOnChanges() {
this.updateStyle(this._el);
}
ngOnInit() {
let requireUpdate = false;
if (this.bg == null) {
this.bg = 'paper';
requireUpdate = true;
}
if (this.color == null) {
this.color = 'text';
requireUpdate = true;
}
if (this.elevation == null) {
this.elevation = 2;
requireUpdate = true;
}
if (requireUpdate) {
this.ngOnChanges();
}
}
ngAfterContentInit() {
if (this._lazyContent) {
this.opened.pipe(startWith(null), filter(() => !!this.expanded && !this._lazyContentRef), first()).subscribe(() => this._lazyContentRef = this._lazyContent._template);
}
}
ngOnDestroy() {
this._openCloseAllSubscription.unsubscribe();
}
close() {
this.expanded = false;
}
open() {
this.expanded = true;
}
toggle() {
this.expanded = !this.expanded;
}
/** Gets the expanded state string. */
_getExpandedState() {
return this.expanded ? 'expanded' : 'collapsed';
}
_subscribeToOpenCloseAllActions() {
return this._accordion._openCloseAllActions.subscribe(expanded => {
this.expanded = expanded;
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyExpansionPanel, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: i1.LyTheme2 }, { token: LyAccordion }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.10", type: LyExpansionPanel, isStandalone: false, selector: "ly-expansion-panel", inputs: { bg: "bg", color: "color", elevation: "elevation", shadowColor: "shadowColor", disabled: "disabled", expanded: "expanded", hasToggle: "hasToggle" }, outputs: { closed: "closed", opened: "opened", afterCollapse: "afterCollapse", afterExpand: "afterExpand", destroyed: "destroyed" }, queries: [{ propertyName: "_lazyContent", first: true, predicate: LyExpansionPanelContent, descendants: true }], exportAs: ["lyExpansionPanel"], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<ng-content select=\"ly-expansion-panel-header\"></ng-content>\n<div [className]=\"classes.panelContent\"\n [@contentExpansion]=\"{\n value: _getExpandedState(),\n params: {\n panelAnimationTiming: _panelAnimationTiming\n }\n }\"\n (@contentExpansion.done)=\"_bodyAnimationDone.next($event)\"\n>\n <div [className]=\"classes.panelBody\">\n <ng-content></ng-content>\n <ng-template [ngTransclude]=\"_lazyContentRef\"></ng-template>\n </div>\n <ng-content select=\"ly-action-row\"></ng-content>\n</div>", dependencies: [{ kind: "directive", type: i1.NgTranscludeDirective, selector: "[ngTransclude]", inputs: ["timeout", "ngTransclude"], exportAs: ["ngTransclude"] }], animations: [
lyExpansionAnimations.contentExpansion
], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyExpansionPanel, decorators: [{
type: Component,
args: [{ selector: 'ly-expansion-panel', changeDetection: ChangeDetectionStrategy.OnPush, exportAs: 'lyExpansionPanel', animations: [
lyExpansionAnimations.contentExpansion
], inputs: [
'bg',
'color',
'elevation',
'shadowColor'
], standalone: false, template: "<ng-content select=\"ly-expansion-panel-header\"></ng-content>\n<div [className]=\"classes.panelContent\"\n [@contentExpansion]=\"{\n value: _getExpandedState(),\n params: {\n panelAnimationTiming: _panelAnimationTiming\n }\n }\"\n (@contentExpansion.done)=\"_bodyAnimationDone.next($event)\"\n>\n <div [className]=\"classes.panelBody\">\n <ng-content></ng-content>\n <ng-template [ngTransclude]=\"_lazyContentRef\"></ng-template>\n </div>\n <ng-content select=\"ly-action-row\"></ng-content>\n</div>" }]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: i1.LyTheme2 }, { type: LyAccordion, decorators: [{
type: Inject,
args: [LyAccordion]
}] }], propDecorators: { _lazyContent: [{
type: ContentChild,
args: [LyExpansionPanelContent]
}], closed: [{
type: Output
}], opened: [{
type: Output
}], afterCollapse: [{
type: Output
}], afterExpand: [{
type: Output
}], destroyed: [{
type: Output
}], disabled: [{
type: Input
}], expanded: [{
type: Input
}], hasToggle: [{
type: Input
}] } });
class LyExpansionPanelHeader {
constructor(el, renderer, _accordion, _expansionPanel) {
this._accordion = _accordion;
this._expansionPanel = _expansionPanel;
/** @docs-private */
this.classes = this._accordion.classes;
renderer.addClass(el.nativeElement, this._accordion.classes.panelHeader);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyExpansionPanelHeader, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: LyAccordion }, { token: LyExpansionPanel }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.10", type: LyExpansionPanelHeader, isStandalone: false, selector: "ly-expansion-panel-header", host: { listeners: { "click": "_expansionPanel.toggle()" } }, ngImport: i0, template: "<span [className]=\"classes.panelHeaderContent\">\n <ng-content select=\"ly-panel-title\"></ng-content>\n <ng-content select=\"ly-panel-description\"></ng-content>\n <ng-content></ng-content>\n</span>\n<ly-expansion-icon\n *ngIf=\"!_expansionPanel.disabled && _expansionPanel.hasToggle\"\n [up]=\"_expansionPanel.expanded\"\n></ly-expansion-icon>", dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i1.LyExpansionIcon, selector: "ly-expansion-icon", inputs: ["color", "up"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyExpansionPanelHeader, decorators: [{
type: Component,
args: [{ selector: 'ly-expansion-panel-header', host: {
'(click)': '_expansionPanel.toggle()'
}, standalone: false, template: "<span [className]=\"classes.panelHeaderContent\">\n <ng-content select=\"ly-panel-title\"></ng-content>\n <ng-content select=\"ly-panel-description\"></ng-content>\n <ng-content></ng-content>\n</span>\n<ly-expansion-icon\n *ngIf=\"!_expansionPanel.disabled && _expansionPanel.hasToggle\"\n [up]=\"_expansionPanel.expanded\"\n></ly-expansion-icon>" }]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: LyAccordion, decorators: [{
type: Inject,
args: [LyAccordion]
}] }, { type: LyExpansionPanel, decorators: [{
type: Inject,
args: [LyExpansionPanel]
}] }] });
class LyExpansionPanelTitle {
constructor(el, renderer, accordion) {
renderer.addClass(el.nativeElement, accordion.classes.panelTitle);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyExpansionPanelTitle, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: LyAccordion }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.10", type: LyExpansionPanelTitle, isStandalone: false, selector: "ly-panel-title", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyExpansionPanelTitle, decorators: [{
type: Directive,
args: [{
selector: 'ly-panel-title',
standalone: false
}]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: LyAccordion, decorators: [{
type: Inject,
args: [LyAccordion]
}] }] });
class LyExpansionPanelDescription {
constructor(el, renderer, accordion) {
renderer.addClass(el.nativeElement, accordion.classes.panelDescription);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyExpansionPanelDescription, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: LyAccordion }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.10", type: LyExpansionPanelDescription, isStandalone: false, selector: "ly-panel-description", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyExpansionPanelDescription, decorators: [{
type: Directive,
args: [{
selector: 'ly-panel-description',
standalone: false
}]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: LyAccordion, decorators: [{
type: Inject,
args: [LyAccordion]
}] }] });
class LyExpansionPanelAction {
constructor(el, renderer, accordion) {
renderer.addClass(el.nativeElement, accordion.classes.panelActionRow);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyExpansionPanelAction, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: LyAccordion }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.10", type: LyExpansionPanelAction, isStandalone: false, selector: "ly-action-row", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyExpansionPanelAction, decorators: [{
type: Directive,
args: [{
selector: 'ly-action-row',
standalone: false
}]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: LyAccordion, decorators: [{
type: Inject,
args: [LyAccordion]
}] }] });
class LyExpansionModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyExpansionModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.10", ngImport: i0, type: LyExpansionModule, declarations: [LyAccordion,
LyExpansionPanel,
LyExpansionPanelHeader,
LyExpansionPanelContent,
LyExpansionPanelTitle,
LyExpansionPanelDescription,
LyExpansionPanelAction], imports: [CommonModule,
LyExpansionIconModule,
NgTranscludeModule], exports: [LyAccordion,
LyExpansionPanel,
LyExpansionPanelHeader,
LyExpansionPanelContent,
LyExpansionPanelTitle,
LyExpansionPanelDescription,
LyExpansionPanelAction] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyExpansionModule, imports: [CommonModule,
LyExpansionIconModule,
NgTranscludeModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyExpansionModule, decorators: [{
type: NgModule,
args: [{
declarations: [
LyAccordion,
LyExpansionPanel,
LyExpansionPanelHeader,
LyExpansionPanelContent,
LyExpansionPanelTitle,
LyExpansionPanelDescription,
LyExpansionPanelAction
],
imports: [
CommonModule,
LyExpansionIconModule,
NgTranscludeModule
],
exports: [
LyAccordion,
LyExpansionPanel,
LyExpansionPanelHeader,
LyExpansionPanelContent,
LyExpansionPanelTitle,
LyExpansionPanelDescription,
LyExpansionPanelAction
]
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { LyAccordion, LyButtonMixinBase, LyExpansionModule, LyExpansionPanel, LyExpansionPanelAction, LyExpansionPanelBase, LyExpansionPanelContent, LyExpansionPanelDescription, LyExpansionPanelHeader, LyExpansionPanelTitle, STYLES };
//# sourceMappingURL=alyle-ui-expansion.mjs.map