mn-angular-lib 1.0.78 → 1.0.80
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.
- package/fesm2022/mn-angular-lib.mjs +74 -25
- package/fesm2022/mn-angular-lib.mjs.map +1 -1
- package/package.json +1 -1
- package/src/lib/features/mn-checkbox/mn-checkbox.css +8 -121
- package/src/lib/features/mn-modal/components/mn-modal-shell/mn-modal-shell.component.css +25 -5
- package/types/mn-angular-lib.d.ts +15 -1
|
@@ -2013,28 +2013,28 @@ const mnCheckboxVariants = tv({
|
|
|
2013
2013
|
base: 'mn-checkbox',
|
|
2014
2014
|
variants: {
|
|
2015
2015
|
size: {
|
|
2016
|
-
xs: '
|
|
2017
|
-
sm: '
|
|
2018
|
-
md: '
|
|
2019
|
-
lg: '
|
|
2020
|
-
xl: '
|
|
2016
|
+
xs: 'size-4 p-0.5',
|
|
2017
|
+
sm: 'size-5 p-[0.1875rem]',
|
|
2018
|
+
md: 'size-6 p-1',
|
|
2019
|
+
lg: 'size-7 p-[0.3125rem]',
|
|
2020
|
+
xl: 'size-8 p-1.5',
|
|
2021
2021
|
},
|
|
2022
2022
|
color: {
|
|
2023
|
-
primary: '
|
|
2024
|
-
secondary: '
|
|
2025
|
-
accent: '
|
|
2026
|
-
neutral: '
|
|
2027
|
-
info: '
|
|
2028
|
-
success: '
|
|
2029
|
-
warning: '
|
|
2030
|
-
error: '
|
|
2023
|
+
primary: 'border-primary checked:bg-primary indeterminate:bg-primary focus-visible:outline-primary text-primary-content',
|
|
2024
|
+
secondary: 'border-secondary checked:bg-secondary indeterminate:bg-secondary focus-visible:outline-secondary text-secondary-content',
|
|
2025
|
+
accent: 'border-accent checked:bg-accent indeterminate:bg-accent focus-visible:outline-accent text-accent-content',
|
|
2026
|
+
neutral: 'border-neutral checked:bg-neutral indeterminate:bg-neutral focus-visible:outline-neutral text-neutral-content',
|
|
2027
|
+
info: 'border-info checked:bg-info indeterminate:bg-info focus-visible:outline-info text-info-content',
|
|
2028
|
+
success: 'border-success checked:bg-success indeterminate:bg-success focus-visible:outline-success text-success-content',
|
|
2029
|
+
warning: 'border-warning checked:bg-warning indeterminate:bg-warning focus-visible:outline-warning text-warning-content',
|
|
2030
|
+
error: 'border-error checked:bg-error indeterminate:bg-error focus-visible:outline-error text-error-content',
|
|
2031
2031
|
},
|
|
2032
2032
|
borderRadius: {
|
|
2033
|
-
none: '
|
|
2034
|
-
xs: '
|
|
2035
|
-
sm: '
|
|
2036
|
-
md: '
|
|
2037
|
-
lg: '
|
|
2033
|
+
none: 'rounded-none',
|
|
2034
|
+
xs: 'rounded-xs',
|
|
2035
|
+
sm: 'rounded-sm',
|
|
2036
|
+
md: 'rounded-md',
|
|
2037
|
+
lg: 'rounded-lg',
|
|
2038
2038
|
},
|
|
2039
2039
|
},
|
|
2040
2040
|
defaultVariants: {
|
|
@@ -2205,11 +2205,11 @@ class MnCheckbox {
|
|
|
2205
2205
|
});
|
|
2206
2206
|
}
|
|
2207
2207
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: MnCheckbox, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2208
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: MnCheckbox, isStandalone: true, selector: "mn-lib-checkbox", inputs: { props: "props", checked: "checked" }, outputs: { checkedChange: "checkedChange" }, usesOnChanges: true, ngImport: i0, template: "<div [class.is-fullwidth]=\"props.fullWidth\" class=\"flex flex-col items-start\">\n <label [attr.for]=\"resolvedId\" [ngClass]=\"wrapperClasses\"\n class=\"flex flex-row items-center gap-x-2 select-none cursor-pointer\">\n <input\n type=\"checkbox\"\n [id]=\"resolvedId\"\n [attr.name]=\"resolvedName\"\n [attr.aria-label]=\"uiConfig.ariaLabel || uiConfig.label || props.label || null\"\n [attr.aria-invalid]=\"showError || null\"\n [attr.aria-describedby]=\"showError ? resolvedId + '-error' : null\"\n [disabled]=\"isDisabled\"\n [checked]=\"value\"\n [ngClass]=\"checkboxClasses\"\n (change)=\"handleChange($any($event.target).checked)\"\n (blur)=\"handleBlur()\"\n />\n @if (uiConfig.label || props.label) {\n <span class=\"flex flex-row items-center gap-x-0.5\">\n <span>{{ uiConfig.label || props.label }}</span>\n @if (isRequired()) {\n <span class=\"text-red-500\">*</span>\n }\n </span>\n }\n </label>\n\n @if (showError) {\n @if (props.showAllErrors) {\n <div class=\"flex flex-col gap-y-1 mt-1\">\n @for (error of errorMessages; track $index) {\n <mn-error-message [errorMessage]=\"error\" [id]=\"resolvedId + '-' + $index\"></mn-error-message>\n }\n </div>\n } @else {\n @if (errorMessage !== null) {\n <mn-error-message [errorMessage]=\"errorMessage\" [id]=\"resolvedId\"></mn-error-message>\n }\n }\n }\n</div>\n", styles: [".mn-checkbox{
|
|
2208
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: MnCheckbox, isStandalone: true, selector: "mn-lib-checkbox", inputs: { props: "props", checked: "checked" }, outputs: { checkedChange: "checkedChange" }, usesOnChanges: true, ngImport: i0, template: "<div [class.is-fullwidth]=\"props.fullWidth\" class=\"flex flex-col items-start\">\n <label [attr.for]=\"resolvedId\" [ngClass]=\"wrapperClasses\"\n class=\"flex flex-row items-center gap-x-2 select-none cursor-pointer\">\n <input\n type=\"checkbox\"\n [id]=\"resolvedId\"\n [attr.name]=\"resolvedName\"\n [attr.aria-label]=\"uiConfig.ariaLabel || uiConfig.label || props.label || null\"\n [attr.aria-invalid]=\"showError || null\"\n [attr.aria-describedby]=\"showError ? resolvedId + '-error' : null\"\n [disabled]=\"isDisabled\"\n [checked]=\"value\"\n [ngClass]=\"checkboxClasses\"\n (change)=\"handleChange($any($event.target).checked)\"\n (blur)=\"handleBlur()\"\n />\n @if (uiConfig.label || props.label) {\n <span class=\"flex flex-row items-center gap-x-0.5\">\n <span>{{ uiConfig.label || props.label }}</span>\n @if (isRequired()) {\n <span class=\"text-red-500\">*</span>\n }\n </span>\n }\n </label>\n\n @if (showError) {\n @if (props.showAllErrors) {\n <div class=\"flex flex-col gap-y-1 mt-1\">\n @for (error of errorMessages; track $index) {\n <mn-error-message [errorMessage]=\"error\" [id]=\"resolvedId + '-' + $index\"></mn-error-message>\n }\n </div>\n } @else {\n @if (errorMessage !== null) {\n <mn-error-message [errorMessage]=\"errorMessage\" [id]=\"resolvedId\"></mn-error-message>\n }\n }\n }\n</div>\n", styles: [".mn-checkbox{position:relative;display:inline-block;flex-shrink:0;box-sizing:border-box;vertical-align:middle;cursor:pointer;appearance:none;-webkit-appearance:none;border-width:1px;border-style:solid;box-shadow:0 1px #0000001a inset,0 0 #0000 inset,0 0 #0000;transition:background-color .2s,box-shadow .2s}.mn-checkbox:before{content:\"\";display:block;width:100%;height:100%;rotate:45deg;background-color:currentColor;opacity:0;box-shadow:0 3px #ffffff1a inset;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 80%,70% 80%,70% 100%);transition:clip-path .3s,opacity .1s,rotate .3s,translate .3s;transition-delay:.1s}.mn-checkbox:focus-visible{outline-width:2px;outline-style:solid;outline-offset:2px}.mn-checkbox:checked,.mn-checkbox[aria-checked=true]{box-shadow:0 0 #0000 inset,0 8px 0 -4px #ffffff1a inset,0 1px #0000001a}.mn-checkbox:checked:before,.mn-checkbox[aria-checked=true]:before{opacity:1;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 0%,70% 0%,70% 100%)}.mn-checkbox:indeterminate:before{opacity:1;rotate:0deg;translate:0 -35%;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 80%,80% 80%,80% 100%)}.mn-checkbox:disabled{cursor:not-allowed;opacity:.2}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MnErrorMessage, selector: "mn-error-message", inputs: ["errorMessage", "id"] }] });
|
|
2209
2209
|
}
|
|
2210
2210
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: MnCheckbox, decorators: [{
|
|
2211
2211
|
type: Component,
|
|
2212
|
-
args: [{ selector: 'mn-lib-checkbox', standalone: true, imports: [NgClass, MnErrorMessage], template: "<div [class.is-fullwidth]=\"props.fullWidth\" class=\"flex flex-col items-start\">\n <label [attr.for]=\"resolvedId\" [ngClass]=\"wrapperClasses\"\n class=\"flex flex-row items-center gap-x-2 select-none cursor-pointer\">\n <input\n type=\"checkbox\"\n [id]=\"resolvedId\"\n [attr.name]=\"resolvedName\"\n [attr.aria-label]=\"uiConfig.ariaLabel || uiConfig.label || props.label || null\"\n [attr.aria-invalid]=\"showError || null\"\n [attr.aria-describedby]=\"showError ? resolvedId + '-error' : null\"\n [disabled]=\"isDisabled\"\n [checked]=\"value\"\n [ngClass]=\"checkboxClasses\"\n (change)=\"handleChange($any($event.target).checked)\"\n (blur)=\"handleBlur()\"\n />\n @if (uiConfig.label || props.label) {\n <span class=\"flex flex-row items-center gap-x-0.5\">\n <span>{{ uiConfig.label || props.label }}</span>\n @if (isRequired()) {\n <span class=\"text-red-500\">*</span>\n }\n </span>\n }\n </label>\n\n @if (showError) {\n @if (props.showAllErrors) {\n <div class=\"flex flex-col gap-y-1 mt-1\">\n @for (error of errorMessages; track $index) {\n <mn-error-message [errorMessage]=\"error\" [id]=\"resolvedId + '-' + $index\"></mn-error-message>\n }\n </div>\n } @else {\n @if (errorMessage !== null) {\n <mn-error-message [errorMessage]=\"errorMessage\" [id]=\"resolvedId\"></mn-error-message>\n }\n }\n }\n</div>\n", styles: [".mn-checkbox{
|
|
2212
|
+
args: [{ selector: 'mn-lib-checkbox', standalone: true, imports: [NgClass, MnErrorMessage], template: "<div [class.is-fullwidth]=\"props.fullWidth\" class=\"flex flex-col items-start\">\n <label [attr.for]=\"resolvedId\" [ngClass]=\"wrapperClasses\"\n class=\"flex flex-row items-center gap-x-2 select-none cursor-pointer\">\n <input\n type=\"checkbox\"\n [id]=\"resolvedId\"\n [attr.name]=\"resolvedName\"\n [attr.aria-label]=\"uiConfig.ariaLabel || uiConfig.label || props.label || null\"\n [attr.aria-invalid]=\"showError || null\"\n [attr.aria-describedby]=\"showError ? resolvedId + '-error' : null\"\n [disabled]=\"isDisabled\"\n [checked]=\"value\"\n [ngClass]=\"checkboxClasses\"\n (change)=\"handleChange($any($event.target).checked)\"\n (blur)=\"handleBlur()\"\n />\n @if (uiConfig.label || props.label) {\n <span class=\"flex flex-row items-center gap-x-0.5\">\n <span>{{ uiConfig.label || props.label }}</span>\n @if (isRequired()) {\n <span class=\"text-red-500\">*</span>\n }\n </span>\n }\n </label>\n\n @if (showError) {\n @if (props.showAllErrors) {\n <div class=\"flex flex-col gap-y-1 mt-1\">\n @for (error of errorMessages; track $index) {\n <mn-error-message [errorMessage]=\"error\" [id]=\"resolvedId + '-' + $index\"></mn-error-message>\n }\n </div>\n } @else {\n @if (errorMessage !== null) {\n <mn-error-message [errorMessage]=\"errorMessage\" [id]=\"resolvedId\"></mn-error-message>\n }\n }\n }\n</div>\n", styles: [".mn-checkbox{position:relative;display:inline-block;flex-shrink:0;box-sizing:border-box;vertical-align:middle;cursor:pointer;appearance:none;-webkit-appearance:none;border-width:1px;border-style:solid;box-shadow:0 1px #0000001a inset,0 0 #0000 inset,0 0 #0000;transition:background-color .2s,box-shadow .2s}.mn-checkbox:before{content:\"\";display:block;width:100%;height:100%;rotate:45deg;background-color:currentColor;opacity:0;box-shadow:0 3px #ffffff1a inset;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 80%,70% 80%,70% 100%);transition:clip-path .3s,opacity .1s,rotate .3s,translate .3s;transition-delay:.1s}.mn-checkbox:focus-visible{outline-width:2px;outline-style:solid;outline-offset:2px}.mn-checkbox:checked,.mn-checkbox[aria-checked=true]{box-shadow:0 0 #0000 inset,0 8px 0 -4px #ffffff1a inset,0 1px #0000001a}.mn-checkbox:checked:before,.mn-checkbox[aria-checked=true]:before{opacity:1;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 0%,70% 0%,70% 100%)}.mn-checkbox:indeterminate:before{opacity:1;rotate:0deg;translate:0 -35%;clip-path:polygon(20% 100%,20% 80%,50% 80%,50% 80%,80% 80%,80% 100%)}.mn-checkbox:disabled{cursor:not-allowed;opacity:.2}\n"] }]
|
|
2213
2213
|
}], ctorParameters: () => [], propDecorators: { props: [{
|
|
2214
2214
|
type: Input,
|
|
2215
2215
|
args: [{ required: true }]
|
|
@@ -6020,20 +6020,65 @@ class MnModalShellComponent {
|
|
|
6020
6020
|
return config;
|
|
6021
6021
|
}
|
|
6022
6022
|
static SWIPE_DISMISS_THRESHOLD = 150;
|
|
6023
|
+
/** Upper bound for the close wait if no animation/transition end event fires
|
|
6024
|
+
* (e.g. an animation was suppressed). Longer than the slowest close path
|
|
6025
|
+
* (mobile slide-down 0.25s, swipe glide 0.3s) so it never preempts. */
|
|
6026
|
+
static CLOSE_FALLBACK_MS = 450;
|
|
6023
6027
|
/** Whether this modal renders as a bottom sheet on small screens (default: true). */
|
|
6024
6028
|
get isMobileSheet() {
|
|
6025
6029
|
return this.config.mobileBottomSheet !== false;
|
|
6026
6030
|
}
|
|
6027
|
-
/**
|
|
6031
|
+
/**
|
|
6032
|
+
* Triggers the closing animation and resolves once it has actually finished.
|
|
6033
|
+
*
|
|
6034
|
+
* Deferred via setTimeout to avoid NG0100 when called during a CD cycle.
|
|
6035
|
+
* Rather than guess a fixed duration (the old hardcoded 150ms truncated the
|
|
6036
|
+
* mobile slide-down, which runs 250ms — and the swipe glide, 300ms), we wait
|
|
6037
|
+
* for the container's `animationend`/`transitionend` and tear down then. A
|
|
6038
|
+
* fallback timeout guarantees resolution if no such event fires, and we
|
|
6039
|
+
* short-circuit entirely under reduced motion (the CSS collapses to instant).
|
|
6040
|
+
*/
|
|
6028
6041
|
startClosing() {
|
|
6029
6042
|
return new Promise(resolve => {
|
|
6030
6043
|
setTimeout(() => {
|
|
6031
6044
|
this.isClosing = true;
|
|
6032
6045
|
this.cdr.detectChanges();
|
|
6033
|
-
|
|
6046
|
+
if (this.prefersReducedMotion()) {
|
|
6047
|
+
resolve();
|
|
6048
|
+
return;
|
|
6049
|
+
}
|
|
6050
|
+
const container = this.el.nativeElement.querySelector('.modal-container');
|
|
6051
|
+
if (!container) {
|
|
6052
|
+
resolve();
|
|
6053
|
+
return;
|
|
6054
|
+
}
|
|
6055
|
+
let settled = false;
|
|
6056
|
+
const done = (event) => {
|
|
6057
|
+
// Ignore end events bubbling up from descendant animations/transitions.
|
|
6058
|
+
if (event && event.target !== container)
|
|
6059
|
+
return;
|
|
6060
|
+
if (settled)
|
|
6061
|
+
return;
|
|
6062
|
+
settled = true;
|
|
6063
|
+
container.removeEventListener('animationend', done);
|
|
6064
|
+
container.removeEventListener('transitionend', done);
|
|
6065
|
+
clearTimeout(fallback);
|
|
6066
|
+
resolve();
|
|
6067
|
+
};
|
|
6068
|
+
// Normal close ends via a keyframe (animationend); the swipe-dismiss
|
|
6069
|
+
// glide ends via the transform transition (transitionend).
|
|
6070
|
+
container.addEventListener('animationend', done);
|
|
6071
|
+
container.addEventListener('transitionend', done);
|
|
6072
|
+
// `done` only runs asynchronously, after this assignment completes.
|
|
6073
|
+
const fallback = setTimeout(done, MnModalShellComponent.CLOSE_FALLBACK_MS);
|
|
6034
6074
|
});
|
|
6035
6075
|
});
|
|
6036
6076
|
}
|
|
6077
|
+
prefersReducedMotion() {
|
|
6078
|
+
return typeof window !== 'undefined'
|
|
6079
|
+
&& typeof window.matchMedia === 'function'
|
|
6080
|
+
&& window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
6081
|
+
}
|
|
6037
6082
|
onEscapeKey(event) {
|
|
6038
6083
|
if (this.config.keyboard === KeyboardMode.ENABLED) {
|
|
6039
6084
|
this.handleClose(ModalCloseReason.ESCAPE);
|
|
@@ -6043,7 +6088,9 @@ class MnModalShellComponent {
|
|
|
6043
6088
|
}
|
|
6044
6089
|
}
|
|
6045
6090
|
onBackdropClick() {
|
|
6046
|
-
|
|
6091
|
+
const shouldClose = this.config.backdrop === BackdropMode.CLOSABLE
|
|
6092
|
+
|| (this.isMobileSheet && this.config.backdrop !== BackdropMode.STATIC);
|
|
6093
|
+
if (shouldClose) {
|
|
6047
6094
|
this.handleClose(ModalCloseReason.BACKDROP);
|
|
6048
6095
|
}
|
|
6049
6096
|
}
|
|
@@ -6247,7 +6294,7 @@ class MnModalShellComponent {
|
|
|
6247
6294
|
}
|
|
6248
6295
|
}
|
|
6249
6296
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: MnModalShellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6250
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: MnModalShellComponent, isStandalone: true, selector: "mn-modal-shell", inputs: { config: "config", modalRef: "modalRef" }, host: { listeners: { "document:keydown.escape": "onEscapeKey($event)" }, properties: { "class": "this.hostClasses" } }, ngImport: i0, template: "@if (showBackdrop) {\n <!-- The backdrop is a visual overlay \u2014 keyboard dismiss is handled at component level via Escape key -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <div class=\"modal-backdrop absolute inset-0 bg-black/50 animate-[fadeIn_0.2s_ease-in-out]\" (click)=\"onBackdropClick()\"></div>\n}\n\n<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\n<div\n class=\"modal-container relative bg-base-100 rounded-lg shadow-xl max-h-[90vh] overflow-hidden flex flex-col\"\n [class.sheet-dragging]=\"isDraggingSheet\"\n [ngClass]=\"containerSizeClass\"\n [style.height]=\"containerHeightStyle\"\n [style.transform]=\"sheetDragY ? 'translateY(' + sheetDragY + 'px)' : null\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"config.title ? 'mn-modal-title' : null\"\n [attr.aria-describedby]=\"config.description ? 'mn-modal-description' : null\"\n tabindex=\"-1\"\n (click)=\"$event.stopPropagation()\"\n>\n @if (isMobileSheet) {\n <!-- Drag handle for swipe-to-dismiss, visible only on mobile bottom sheets -->\n <div\n (pointercancel)=\"onSheetPointerUp()\"\n (pointerdown)=\"onSheetPointerDown($event)\"\n (pointermove)=\"onSheetPointerMove($event)\"\n (pointerup)=\"onSheetPointerUp()\"\n class=\"sm:hidden flex justify-center pt-2 pb-1 touch-none cursor-grab\"\n >\n <div class=\"h-1.5 w-10 rounded-full bg-base-300\"></div>\n </div>\n }\n\n <!-- On mobile the whole header doubles as a swipe-to-dismiss surface (drags that\n start on the close button are ignored). The grabber above is the visual cue. -->\n <div [class.border-b]=\"config.kind !== ModalKind.WIZARD\"\n [class.border-base-300]=\"config.kind !== ModalKind.WIZARD\"\n (pointercancel)=\"onSheetPointerUp()\"\n (pointerdown)=\"onSheetPointerDown($event)\"\n (pointermove)=\"onSheetPointerMove($event)\"\n (pointerup)=\"onSheetPointerUp()\"\n [class.cursor-grab]=\"isMobileSheet\"\n [class.sm:cursor-auto]=\"isMobileSheet\"\n [class.sm:touch-auto]=\"isMobileSheet\"\n [class.touch-none]=\"isMobileSheet\"\n class=\"flex items-center justify-between p-6\">\n <div class=\"flex flex-col gap-0.5\">\n @if (config.title) {\n <h2 class=\"m-0 text-xl font-semibold text-base-content\" id=\"mn-modal-title\">{{ config.title }}</h2>\n }\n @if (config.subtitle) {\n <p class=\"m-0 text-sm text-base-content/60 font-normal\">{{ config.subtitle }}</p>\n }\n </div>\n @if (showCloseButton) {\n <
|
|
6297
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: MnModalShellComponent, isStandalone: true, selector: "mn-modal-shell", inputs: { config: "config", modalRef: "modalRef" }, host: { listeners: { "document:keydown.escape": "onEscapeKey($event)" }, properties: { "class": "this.hostClasses" } }, ngImport: i0, template: "@if (showBackdrop) {\n <!-- The backdrop is a visual overlay \u2014 keyboard dismiss is handled at component level via Escape key -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <div class=\"modal-backdrop absolute inset-0 bg-black/50 animate-[fadeIn_0.2s_ease-in-out]\" (click)=\"onBackdropClick()\"></div>\n}\n\n<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\n<div\n class=\"modal-container relative bg-base-100 rounded-lg shadow-xl max-h-[90vh] overflow-hidden flex flex-col\"\n [class.sheet-dragging]=\"isDraggingSheet\"\n [ngClass]=\"containerSizeClass\"\n [style.height]=\"containerHeightStyle\"\n [style.transform]=\"sheetDragY ? 'translateY(' + sheetDragY + 'px)' : null\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"config.title ? 'mn-modal-title' : null\"\n [attr.aria-describedby]=\"config.description ? 'mn-modal-description' : null\"\n tabindex=\"-1\"\n (click)=\"$event.stopPropagation()\"\n>\n @if (isMobileSheet) {\n <!-- Drag handle for swipe-to-dismiss, visible only on mobile bottom sheets -->\n <div\n (pointercancel)=\"onSheetPointerUp()\"\n (pointerdown)=\"onSheetPointerDown($event)\"\n (pointermove)=\"onSheetPointerMove($event)\"\n (pointerup)=\"onSheetPointerUp()\"\n class=\"sm:hidden flex justify-center pt-2 pb-1 touch-none cursor-grab\"\n >\n <div class=\"h-1.5 w-10 rounded-full bg-base-300\"></div>\n </div>\n }\n\n <!-- On mobile the whole header doubles as a swipe-to-dismiss surface (drags that\n start on the close button are ignored). The grabber above is the visual cue. -->\n <div [class.border-b]=\"config.kind !== ModalKind.WIZARD\"\n [class.border-base-300]=\"config.kind !== ModalKind.WIZARD\"\n (pointercancel)=\"onSheetPointerUp()\"\n (pointerdown)=\"onSheetPointerDown($event)\"\n (pointermove)=\"onSheetPointerMove($event)\"\n (pointerup)=\"onSheetPointerUp()\"\n [class.cursor-grab]=\"isMobileSheet\"\n [class.sm:cursor-auto]=\"isMobileSheet\"\n [class.sm:touch-auto]=\"isMobileSheet\"\n [class.touch-none]=\"isMobileSheet\"\n class=\"flex items-center justify-between p-6\">\n <div class=\"flex flex-col gap-0.5\">\n @if (config.title) {\n <h2 class=\"m-0 text-xl font-semibold text-base-content\" id=\"mn-modal-title\">{{ config.title }}</h2>\n }\n @if (config.subtitle) {\n <p class=\"m-0 text-sm text-base-content/60 font-normal\">{{ config.subtitle }}</p>\n }\n </div>\n @if (showCloseButton) {\n <div [class]=\"isMobileSheet ? 'hidden sm:flex' : ''\">\n <button\n mnButton\n [data]=\"{ size: 'sm', variant: 'text', color: 'gray', hover: true, borderRadius: 'md' }\"\n type=\"button\"\n class=\"w-8 h-8\"\n (click)=\"onCloseButtonClick()\"\n aria-label=\"Close modal\"\n >\n <svg lucideX [size]=\"18\"></svg>\n </button>\n </div>\n }\n </div>\n @if (config.description) {\n <p class=\"m-0 px-6 text-sm text-base-content/60 leading-relaxed\" id=\"mn-modal-description\">{{ config.description }}</p>\n }\n\n @if (config.kind === ModalKind.WIZARD) {\n <!-- Wizard manages its own internal scrolling so the steps header and footer\n stay fixed while only the step body scrolls. No padding/scroll here. -->\n <div class=\"flex-auto min-h-0 overflow-hidden flex flex-col\">\n <mn-wizard-body\n [config]=\"asWizard(config)\"\n [modalRef]=\"$any(modalRef)\"\n class=\"flex-auto min-h-0 flex flex-col\"\n ></mn-wizard-body>\n </div>\n } @else {\n <div class=\"flex-1 overflow-y-auto px-6 pt-6\">\n @if (config.kind === ModalKind.FORM) {\n <mn-form-body\n [config]=\"asForm(config)\"\n [modalRef]=\"$any(modalRef)\"\n class=\"block h-full\"\n ></mn-form-body>\n }\n\n @if (config.kind === ModalKind.CONFIRMATION) {\n <mn-confirmation-body\n [config]=\"asConfirmation(config)\"\n [modalRef]=\"$any(modalRef)\"\n ></mn-confirmation-body>\n }\n\n @if (config.kind === ModalKind.CUSTOM) {\n <mn-custom-body-host\n [config]=\"asCustom(config)\"\n [modalRef]=\"$any(modalRef)\"\n class=\"block pb-6\"\n ></mn-custom-body-host>\n }\n </div>\n }\n\n <!-- Custom Footer Actions (not for wizard modals, they render their own) -->\n @if (hasCustomFooterActions && config.kind !== ModalKind.WIZARD) {\n <div class=\"flex gap-3 p-6 border-t border-base-300\">\n <mn-footer-actions\n [actions]=\"config.footerActions || []\"\n (actionClick)=\"onFooterAction($event)\"\n ></mn-footer-actions>\n </div>\n }\n</div>\n", styles: [":host{--mn-sheet-ease: cubic-bezier(.32, .72, 0, 1);position:fixed;inset:0;z-index:1000;display:flex;align-items:center;justify-content:center;transition:transform .3s ease-in-out,filter .3s ease-in-out,opacity .3s ease-in-out}:host(.is-stacked){transform:scale(.96) translateY(-1rem);filter:brightness(.9) blur(1px);pointer-events:none;opacity:.8}.modal-container{transition:transform .35s var(--mn-sheet-ease)}.modal-container.sheet-dragging{transition:none}:host(.swipe-dismissing) .modal-container,:host(.swipe-dismissing).closing .modal-container{animation:none!important;transition:transform .3s var(--mn-sheet-ease)}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideIn{0%{opacity:0;transform:translateY(-1rem)}to{opacity:1;transform:translateY(0)}}@keyframes zoomIn{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}@keyframes fadeOut{0%{opacity:1}to{opacity:0}}@keyframes slideOut{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(1rem)}}@keyframes zoomOut{0%{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.95)}}@keyframes slideUpIn{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}@keyframes slideUpOut{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(100%)}}:host(.anim-slide) .modal-container{animation:slideIn .2s ease-in-out}:host(.anim-fade) .modal-container{animation:fadeIn .2s ease-in-out}:host(.anim-zoom) .modal-container{animation:zoomIn .2s ease-in-out}:host(.closing) .modal-backdrop{animation:fadeOut .15s ease-in-out forwards}:host(.closing).anim-slide .modal-container{animation:slideOut .15s ease-in-out forwards}:host(.closing).anim-fade .modal-container{animation:fadeOut .15s ease-in-out forwards}:host(.closing).anim-zoom .modal-container{animation:zoomOut .15s ease-in-out forwards}@media(max-width:639.98px){:host(.mobile-sheet){align-items:flex-end}:host(.mobile-sheet) .modal-container{width:100%;max-width:100%;max-height:92vh;border-radius:1rem 1rem 0 0;animation:slideUpIn .35s var(--mn-sheet-ease)}:host(.mobile-sheet).anim-slide .modal-container,:host(.mobile-sheet).anim-fade .modal-container,:host(.mobile-sheet).anim-zoom .modal-container{animation:slideUpIn .35s var(--mn-sheet-ease)}:host(.mobile-sheet).closing .modal-container,:host(.mobile-sheet).closing.anim-slide .modal-container,:host(.mobile-sheet).closing.anim-fade .modal-container,:host(.mobile-sheet).closing.anim-zoom .modal-container{animation:slideUpOut .25s var(--mn-sheet-ease) forwards}}@media(prefers-reduced-motion:reduce){:host .modal-backdrop,:host .modal-container{animation-duration:.01ms!important;animation-delay:0ms!important;transition-duration:.01ms!important}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MnWizardBodyComponent, selector: "mn-wizard-body", inputs: ["config", "modalRef"] }, { kind: "component", type: MnFormBodyComponent, selector: "mn-form-body", inputs: ["config", "modalRef", "hideFooter", "hideCustomBody"], outputs: ["formStatusChange"] }, { kind: "component", type: MnConfirmationBodyComponent, selector: "mn-confirmation-body", inputs: ["config", "modalRef"] }, { kind: "component", type: MnCustomBodyHostComponent, selector: "mn-custom-body-host", inputs: ["config", "modalRef"] }, { kind: "component", type: MnFooterActionsComponent, selector: "mn-footer-actions", inputs: ["actions"], outputs: ["actionClick"] }, { kind: "component", type: MnButton, selector: "button[mnButton], a[mnButton]", inputs: ["data"] }, { kind: "component", type: LucideX, selector: "svg[lucideX]" }] });
|
|
6251
6298
|
}
|
|
6252
6299
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: MnModalShellComponent, decorators: [{
|
|
6253
6300
|
type: Component,
|
|
@@ -6258,7 +6305,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
6258
6305
|
MnConfirmationBodyComponent,
|
|
6259
6306
|
MnCustomBodyHostComponent,
|
|
6260
6307
|
MnFooterActionsComponent,
|
|
6261
|
-
|
|
6308
|
+
MnButton,
|
|
6309
|
+
LucideX,
|
|
6310
|
+
], template: "@if (showBackdrop) {\n <!-- The backdrop is a visual overlay \u2014 keyboard dismiss is handled at component level via Escape key -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events,@angular-eslint/template/interactive-supports-focus -->\n <div class=\"modal-backdrop absolute inset-0 bg-black/50 animate-[fadeIn_0.2s_ease-in-out]\" (click)=\"onBackdropClick()\"></div>\n}\n\n<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\n<div\n class=\"modal-container relative bg-base-100 rounded-lg shadow-xl max-h-[90vh] overflow-hidden flex flex-col\"\n [class.sheet-dragging]=\"isDraggingSheet\"\n [ngClass]=\"containerSizeClass\"\n [style.height]=\"containerHeightStyle\"\n [style.transform]=\"sheetDragY ? 'translateY(' + sheetDragY + 'px)' : null\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"config.title ? 'mn-modal-title' : null\"\n [attr.aria-describedby]=\"config.description ? 'mn-modal-description' : null\"\n tabindex=\"-1\"\n (click)=\"$event.stopPropagation()\"\n>\n @if (isMobileSheet) {\n <!-- Drag handle for swipe-to-dismiss, visible only on mobile bottom sheets -->\n <div\n (pointercancel)=\"onSheetPointerUp()\"\n (pointerdown)=\"onSheetPointerDown($event)\"\n (pointermove)=\"onSheetPointerMove($event)\"\n (pointerup)=\"onSheetPointerUp()\"\n class=\"sm:hidden flex justify-center pt-2 pb-1 touch-none cursor-grab\"\n >\n <div class=\"h-1.5 w-10 rounded-full bg-base-300\"></div>\n </div>\n }\n\n <!-- On mobile the whole header doubles as a swipe-to-dismiss surface (drags that\n start on the close button are ignored). The grabber above is the visual cue. -->\n <div [class.border-b]=\"config.kind !== ModalKind.WIZARD\"\n [class.border-base-300]=\"config.kind !== ModalKind.WIZARD\"\n (pointercancel)=\"onSheetPointerUp()\"\n (pointerdown)=\"onSheetPointerDown($event)\"\n (pointermove)=\"onSheetPointerMove($event)\"\n (pointerup)=\"onSheetPointerUp()\"\n [class.cursor-grab]=\"isMobileSheet\"\n [class.sm:cursor-auto]=\"isMobileSheet\"\n [class.sm:touch-auto]=\"isMobileSheet\"\n [class.touch-none]=\"isMobileSheet\"\n class=\"flex items-center justify-between p-6\">\n <div class=\"flex flex-col gap-0.5\">\n @if (config.title) {\n <h2 class=\"m-0 text-xl font-semibold text-base-content\" id=\"mn-modal-title\">{{ config.title }}</h2>\n }\n @if (config.subtitle) {\n <p class=\"m-0 text-sm text-base-content/60 font-normal\">{{ config.subtitle }}</p>\n }\n </div>\n @if (showCloseButton) {\n <div [class]=\"isMobileSheet ? 'hidden sm:flex' : ''\">\n <button\n mnButton\n [data]=\"{ size: 'sm', variant: 'text', color: 'gray', hover: true, borderRadius: 'md' }\"\n type=\"button\"\n class=\"w-8 h-8\"\n (click)=\"onCloseButtonClick()\"\n aria-label=\"Close modal\"\n >\n <svg lucideX [size]=\"18\"></svg>\n </button>\n </div>\n }\n </div>\n @if (config.description) {\n <p class=\"m-0 px-6 text-sm text-base-content/60 leading-relaxed\" id=\"mn-modal-description\">{{ config.description }}</p>\n }\n\n @if (config.kind === ModalKind.WIZARD) {\n <!-- Wizard manages its own internal scrolling so the steps header and footer\n stay fixed while only the step body scrolls. No padding/scroll here. -->\n <div class=\"flex-auto min-h-0 overflow-hidden flex flex-col\">\n <mn-wizard-body\n [config]=\"asWizard(config)\"\n [modalRef]=\"$any(modalRef)\"\n class=\"flex-auto min-h-0 flex flex-col\"\n ></mn-wizard-body>\n </div>\n } @else {\n <div class=\"flex-1 overflow-y-auto px-6 pt-6\">\n @if (config.kind === ModalKind.FORM) {\n <mn-form-body\n [config]=\"asForm(config)\"\n [modalRef]=\"$any(modalRef)\"\n class=\"block h-full\"\n ></mn-form-body>\n }\n\n @if (config.kind === ModalKind.CONFIRMATION) {\n <mn-confirmation-body\n [config]=\"asConfirmation(config)\"\n [modalRef]=\"$any(modalRef)\"\n ></mn-confirmation-body>\n }\n\n @if (config.kind === ModalKind.CUSTOM) {\n <mn-custom-body-host\n [config]=\"asCustom(config)\"\n [modalRef]=\"$any(modalRef)\"\n class=\"block pb-6\"\n ></mn-custom-body-host>\n }\n </div>\n }\n\n <!-- Custom Footer Actions (not for wizard modals, they render their own) -->\n @if (hasCustomFooterActions && config.kind !== ModalKind.WIZARD) {\n <div class=\"flex gap-3 p-6 border-t border-base-300\">\n <mn-footer-actions\n [actions]=\"config.footerActions || []\"\n (actionClick)=\"onFooterAction($event)\"\n ></mn-footer-actions>\n </div>\n }\n</div>\n", styles: [":host{--mn-sheet-ease: cubic-bezier(.32, .72, 0, 1);position:fixed;inset:0;z-index:1000;display:flex;align-items:center;justify-content:center;transition:transform .3s ease-in-out,filter .3s ease-in-out,opacity .3s ease-in-out}:host(.is-stacked){transform:scale(.96) translateY(-1rem);filter:brightness(.9) blur(1px);pointer-events:none;opacity:.8}.modal-container{transition:transform .35s var(--mn-sheet-ease)}.modal-container.sheet-dragging{transition:none}:host(.swipe-dismissing) .modal-container,:host(.swipe-dismissing).closing .modal-container{animation:none!important;transition:transform .3s var(--mn-sheet-ease)}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideIn{0%{opacity:0;transform:translateY(-1rem)}to{opacity:1;transform:translateY(0)}}@keyframes zoomIn{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}@keyframes fadeOut{0%{opacity:1}to{opacity:0}}@keyframes slideOut{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(1rem)}}@keyframes zoomOut{0%{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.95)}}@keyframes slideUpIn{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}@keyframes slideUpOut{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(100%)}}:host(.anim-slide) .modal-container{animation:slideIn .2s ease-in-out}:host(.anim-fade) .modal-container{animation:fadeIn .2s ease-in-out}:host(.anim-zoom) .modal-container{animation:zoomIn .2s ease-in-out}:host(.closing) .modal-backdrop{animation:fadeOut .15s ease-in-out forwards}:host(.closing).anim-slide .modal-container{animation:slideOut .15s ease-in-out forwards}:host(.closing).anim-fade .modal-container{animation:fadeOut .15s ease-in-out forwards}:host(.closing).anim-zoom .modal-container{animation:zoomOut .15s ease-in-out forwards}@media(max-width:639.98px){:host(.mobile-sheet){align-items:flex-end}:host(.mobile-sheet) .modal-container{width:100%;max-width:100%;max-height:92vh;border-radius:1rem 1rem 0 0;animation:slideUpIn .35s var(--mn-sheet-ease)}:host(.mobile-sheet).anim-slide .modal-container,:host(.mobile-sheet).anim-fade .modal-container,:host(.mobile-sheet).anim-zoom .modal-container{animation:slideUpIn .35s var(--mn-sheet-ease)}:host(.mobile-sheet).closing .modal-container,:host(.mobile-sheet).closing.anim-slide .modal-container,:host(.mobile-sheet).closing.anim-fade .modal-container,:host(.mobile-sheet).closing.anim-zoom .modal-container{animation:slideUpOut .25s var(--mn-sheet-ease) forwards}}@media(prefers-reduced-motion:reduce){:host .modal-backdrop,:host .modal-container{animation-duration:.01ms!important;animation-delay:0ms!important;transition-duration:.01ms!important}}\n"] }]
|
|
6262
6311
|
}], propDecorators: { config: [{
|
|
6263
6312
|
type: Input
|
|
6264
6313
|
}], modalRef: [{
|