ps-helix 3.0.4 → 3.0.5
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/README.md +3 -3
- package/fesm2022/ps-helix.mjs +13 -3
- package/fesm2022/ps-helix.mjs.map +1 -1
- package/index.d.ts +11 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A comprehensive Angular component library built with Angular 21+ featuring modern design patterns, accessibility-first development, and optimal developer experience.
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/ps-helix)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
[](https://angular.dev/)
|
|
8
8
|
[](https://www.typescriptlang.org/)
|
|
@@ -118,7 +118,7 @@ After installation, verify that ps-helix is in your `package.json`:
|
|
|
118
118
|
```json
|
|
119
119
|
{
|
|
120
120
|
"dependencies": {
|
|
121
|
-
"ps-helix": "^3.0.
|
|
121
|
+
"ps-helix": "^3.0.5"
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
```
|
|
@@ -1173,7 +1173,7 @@ Copyright (c) 2025 PACK Solutions
|
|
|
1173
1173
|
|
|
1174
1174
|
---
|
|
1175
1175
|
|
|
1176
|
-
**Version**: 3.0.
|
|
1176
|
+
**Version**: 3.0.5
|
|
1177
1177
|
**Built with**: Angular 21.0.3, TypeScript 5.9.0, Phosphor Icons 2.0.3
|
|
1178
1178
|
**Author**: Fabrice PEREZ | Product Designer at PACK Solutions
|
|
1179
1179
|
**Last Updated**: January 2026
|
package/fesm2022/ps-helix.mjs
CHANGED
|
@@ -2136,6 +2136,16 @@ class PshModalComponent {
|
|
|
2136
2136
|
* ```
|
|
2137
2137
|
*/
|
|
2138
2138
|
this.styleClass = input('', ...(ngDevMode ? [{ debugName: "styleClass" }] : []));
|
|
2139
|
+
/**
|
|
2140
|
+
* Custom CSS class(es) to apply to the modal backdrop
|
|
2141
|
+
* Useful for stacked modals with different z-index or opacity
|
|
2142
|
+
*
|
|
2143
|
+
* @example
|
|
2144
|
+
* ```html
|
|
2145
|
+
* <psh-modal backdropClass="higher-z-index" />
|
|
2146
|
+
* ```
|
|
2147
|
+
*/
|
|
2148
|
+
this.backdropClass = input('', ...(ngDevMode ? [{ debugName: "backdropClass" }] : []));
|
|
2139
2149
|
/**
|
|
2140
2150
|
* Emitted when the modal is closed
|
|
2141
2151
|
*/
|
|
@@ -2405,12 +2415,12 @@ class PshModalComponent {
|
|
|
2405
2415
|
this.detachModalFromBody();
|
|
2406
2416
|
}
|
|
2407
2417
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: PshModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2408
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: PshModalComponent, isStandalone: true, selector: "psh-modal", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, showClose: { classPropertyName: "showClose", publicName: "showClose", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdrop: { classPropertyName: "closeOnBackdrop", publicName: "closeOnBackdrop", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "closeOnEscape", isSignal: true, isRequired: false, transformFunction: null }, preventScroll: { classPropertyName: "preventScroll", publicName: "preventScroll", isSignal: true, isRequired: false, transformFunction: null }, showFooter: { classPropertyName: "showFooter", publicName: "showFooter", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, dismissLabel: { classPropertyName: "dismissLabel", publicName: "dismissLabel", isSignal: true, isRequired: false, transformFunction: null }, confirmLabel: { classPropertyName: "confirmLabel", publicName: "confirmLabel", isSignal: true, isRequired: false, transformFunction: null }, cancelLabel: { classPropertyName: "cancelLabel", publicName: "cancelLabel", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", closed: "closed", confirmed: "confirmed" }, queries: [{ propertyName: "customFooter", first: true, predicate: ["modalFooter"], descendants: true, isSignal: true }], viewQueries: [{ propertyName: "modalBackdrop", first: true, predicate: ["modalBackdrop"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n #modalBackdrop\n class=\"modal-backdrop\"\n [class.open]=\"open()\"\n (click)=\"handleBackdropClick($event)\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-hidden]=\"!open()\"\n [attr.aria-labelledby]=\"modalDialogId() + '-title'\"\n [attr.aria-describedby]=\"modalDescriptionId()\"\n [attr.data-state]=\"state()\"\n>\n <div\n [class]=\"'modal-container ' + styleClass()\"\n [class.small]=\"size() === 'small'\"\n [class.medium]=\"size() === 'medium'\"\n [class.large]=\"size() === 'large'\"\n [attr.id]=\"modalDialogId()\"\n role=\"document\"\n >\n <div class=\"modal-content-wrapper\">\n <div class=\"modal-header\">\n <h2 class=\"modal-title\" [attr.id]=\"modalDialogId() + '-title'\">\n <ng-content select=\"[modal-title]\">{{ title() }}</ng-content>\n </h2>\n @if (showClose()) {\n <button\n type=\"button\"\n class=\"modal-close\"\n (click)=\"handleClose()\"\n [attr.aria-label]=\"dismissLabel()\"\n >\n <i class=\"ph ph-x\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n\n <div class=\"modal-content\" [attr.id]=\"modalDescriptionId()\">\n <ng-content>\n <p>\n Modal content goes here. You can replace this with your own content.\n </p>\n </ng-content>\n </div>\n\n @if (showFooter() && !hasCustomFooter()) {\n <div class=\"modal-footer\">\n <psh-button\n appearance=\"outline\"\n variant=\"primary\"\n size=\"medium\"\n [fullWidth]=\"isMobileScreen()\"\n (clicked)=\"handleClose()\">\n {{ cancelLabel() }}\n </psh-button>\n <psh-button\n appearance=\"filled\"\n variant=\"primary\"\n size=\"medium\"\n [fullWidth]=\"isMobileScreen()\"\n (clicked)=\"handleConfirm()\">\n {{ confirmLabel() }}\n </psh-button>\n </div>\n } @if (showFooter() && hasCustomFooter()) {\n <div class=\"modal-footer\">\n <!--\n Note: When using a custom footer, buttons should also use [fullWidth]=\"isMobileScreen()\"\n to ensure proper responsive behavior on mobile devices.\n Example:\n <psh-button [fullWidth]=\"isMobileScreen()\" (clicked)=\"action()\">Custom Button</psh-button>\n -->\n <ng-content select=\"[modal-footer]\" #modalFooter></ng-content>\n </div>\n }\n </div>\n </div>\n</div>\n", styles: [":root{--modal-max-width-sm: 25rem;--modal-max-width-md: 37.5rem;--modal-max-width-lg: 50rem;--modal-backdrop-opacity: .6;--modal-backdrop-blur: 4px;--modal-animation-distance: 20px;--modal-animation-scale: .95}.modal-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(var(--surface-900-rgb),var(--modal-backdrop-opacity));-webkit-backdrop-filter:blur(var(--modal-backdrop-blur));backdrop-filter:blur(var(--modal-backdrop-blur));align-items:center;justify-content:center;z-index:var(--z-index-modal-backdrop);pointer-events:none;opacity:0;display:none;transition:opacity var(--animation-duration-default) var(--animation-easing-smooth)}.modal-backdrop.open{opacity:1;pointer-events:all;display:flex}.modal-content-wrapper{display:flex;flex-direction:column;max-height:90vh;min-height:0}.modal-container{background:var(--surface-card);border-radius:var(--border-radius-lg);box-shadow:var(--shadow-lg),0 0 0 1px rgba(var(--primary-color-rgb),.05);max-width:var(--modal-max-width-md);transform:translateY(var(--modal-animation-distance)) scale(var(--modal-animation-scale));transition:transform var(--animation-duration-default) var(--animation-easing-smooth),opacity var(--animation-duration-default) var(--animation-easing-smooth);border:1px solid var(--surface-border)}.modal-backdrop.open .modal-container{transform:translateY(0) scale(1)}.modal-container.small{width:50%;max-width:var(--modal-max-width-sm)}.modal-container.medium{width:70%;max-width:var(--modal-max-width-md)}.modal-container.large{width:90%;max-width:var(--modal-max-width-lg)}.modal-header{display:flex;align-items:center;justify-content:space-between;padding:var(--spacing-lg) var(--spacing-xl);border-bottom:1px solid var(--surface-border);background:var(--surface-ground);border-top-left-radius:var(--border-radius-lg);border-top-right-radius:var(--border-radius-lg)}.modal-title{font-size:var(--font-size-xl);font-weight:var(--font-weight-semibold);color:var(--text-color);margin:0;display:flex;align-items:center;gap:var(--spacing-sm)}.modal-close{background:transparent;border:none;color:var(--text-color-secondary);padding:var(--spacing-sm);cursor:pointer;border-radius:var(--border-radius);display:flex;align-items:center;justify-content:center;transition:all var(--animation-duration-fast) var(--animation-easing-smooth);margin:var(--negative-spacing-sm)}.modal-close:hover{background:var(--surface-hover);color:var(--text-color);transform:scale(1.1)}.modal-close:focus-visible{outline:var(--focus-outline-width) var(--focus-outline-style) var(--focus-outline-color);outline-offset:var(--focus-outline-offset)}.modal-close i{font-size:var(--font-size-xl)}.modal-content{padding:var(--spacing-xl);overflow-y:auto;flex-grow:1;min-height:0;color:var(--text-color-secondary);line-height:var(--line-height-relaxed)}.modal-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--spacing-md);padding:var(--spacing-lg) var(--spacing-xl);border-top:1px solid var(--surface-border);background:var(--surface-ground);border-bottom-left-radius:var(--border-radius-lg);border-bottom-right-radius:var(--border-radius-lg)}@media (max-width: 768px){.modal-container{width:95%;margin:var(--spacing-md)}.modal-header{padding:var(--spacing-md) var(--spacing-lg)}.modal-title{font-size:var(--font-size-lg)}.modal-content{padding:var(--spacing-lg)}.modal-footer{padding:var(--spacing-md) var(--spacing-lg);flex-direction:column-reverse;gap:var(--spacing-sm)}}@media (max-width: 480px){.modal-container{width:100%;max-height:100vh;margin:0;border-radius:0}.modal-header{padding:var(--spacing-sm) var(--spacing-md);border-top-left-radius:0;border-top-right-radius:0}.modal-title{font-size:var(--font-size-base)}.modal-content{padding:var(--spacing-md);flex:0 1 auto}.modal-footer{padding:var(--spacing-sm) var(--spacing-md);border-bottom-left-radius:0;border-bottom-right-radius:0}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: PshButtonComponent, selector: "psh-button", inputs: ["appearance", "variant", "size", "disabled", "loading", "fullWidth", "iconPosition", "icon", "ariaLabel", "loadingText", "disabledText", "iconOnlyText", "type"], outputs: ["fullWidthChange", "clicked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2418
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: PshModalComponent, isStandalone: true, selector: "psh-modal", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, showClose: { classPropertyName: "showClose", publicName: "showClose", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdrop: { classPropertyName: "closeOnBackdrop", publicName: "closeOnBackdrop", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "closeOnEscape", isSignal: true, isRequired: false, transformFunction: null }, preventScroll: { classPropertyName: "preventScroll", publicName: "preventScroll", isSignal: true, isRequired: false, transformFunction: null }, showFooter: { classPropertyName: "showFooter", publicName: "showFooter", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, dismissLabel: { classPropertyName: "dismissLabel", publicName: "dismissLabel", isSignal: true, isRequired: false, transformFunction: null }, confirmLabel: { classPropertyName: "confirmLabel", publicName: "confirmLabel", isSignal: true, isRequired: false, transformFunction: null }, cancelLabel: { classPropertyName: "cancelLabel", publicName: "cancelLabel", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null }, backdropClass: { classPropertyName: "backdropClass", publicName: "backdropClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", closed: "closed", confirmed: "confirmed" }, queries: [{ propertyName: "customFooter", first: true, predicate: ["modalFooter"], descendants: true, isSignal: true }], viewQueries: [{ propertyName: "modalBackdrop", first: true, predicate: ["modalBackdrop"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n #modalBackdrop\n [class]=\"'modal-backdrop ' + backdropClass()\"\n [class.open]=\"open()\"\n (click)=\"handleBackdropClick($event)\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-hidden]=\"!open()\"\n [attr.aria-labelledby]=\"modalDialogId() + '-title'\"\n [attr.aria-describedby]=\"modalDescriptionId()\"\n [attr.data-state]=\"state()\"\n>\n <div\n [class]=\"'modal-container ' + styleClass()\"\n [class.small]=\"size() === 'small'\"\n [class.medium]=\"size() === 'medium'\"\n [class.large]=\"size() === 'large'\"\n [attr.id]=\"modalDialogId()\"\n role=\"document\"\n >\n <div class=\"modal-content-wrapper\">\n <div class=\"modal-header\">\n <h2 class=\"modal-title\" [attr.id]=\"modalDialogId() + '-title'\">\n <ng-content select=\"[modal-title]\">{{ title() }}</ng-content>\n </h2>\n @if (showClose()) {\n <button\n type=\"button\"\n class=\"modal-close\"\n (click)=\"handleClose()\"\n [attr.aria-label]=\"dismissLabel()\"\n >\n <i class=\"ph ph-x\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n\n <div class=\"modal-content\" [attr.id]=\"modalDescriptionId()\">\n <ng-content>\n <p>\n Modal content goes here. You can replace this with your own content.\n </p>\n </ng-content>\n </div>\n\n @if (showFooter() && !hasCustomFooter()) {\n <div class=\"modal-footer\">\n <psh-button\n appearance=\"outline\"\n variant=\"primary\"\n size=\"medium\"\n [fullWidth]=\"isMobileScreen()\"\n (clicked)=\"handleClose()\">\n {{ cancelLabel() }}\n </psh-button>\n <psh-button\n appearance=\"filled\"\n variant=\"primary\"\n size=\"medium\"\n [fullWidth]=\"isMobileScreen()\"\n (clicked)=\"handleConfirm()\">\n {{ confirmLabel() }}\n </psh-button>\n </div>\n } @if (showFooter() && hasCustomFooter()) {\n <div class=\"modal-footer\">\n <!--\n Note: When using a custom footer, buttons should also use [fullWidth]=\"isMobileScreen()\"\n to ensure proper responsive behavior on mobile devices.\n Example:\n <psh-button [fullWidth]=\"isMobileScreen()\" (clicked)=\"action()\">Custom Button</psh-button>\n -->\n <ng-content select=\"[modal-footer]\" #modalFooter></ng-content>\n </div>\n }\n </div>\n </div>\n</div>\n", styles: [":root{--modal-max-width-sm: 25rem;--modal-max-width-md: 37.5rem;--modal-max-width-lg: 50rem;--modal-backdrop-opacity: .6;--modal-backdrop-blur: 4px;--modal-animation-distance: 20px;--modal-animation-scale: .95}.modal-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(var(--surface-900-rgb),var(--modal-backdrop-opacity));-webkit-backdrop-filter:blur(var(--modal-backdrop-blur));backdrop-filter:blur(var(--modal-backdrop-blur));align-items:center;justify-content:center;z-index:var(--z-index-modal-backdrop);pointer-events:none;opacity:0;display:none;transition:opacity var(--animation-duration-default) var(--animation-easing-smooth)}.modal-backdrop.open{opacity:1;pointer-events:all;display:flex}.modal-content-wrapper{display:flex;flex-direction:column;max-height:90vh;min-height:0}.modal-container{background:var(--surface-card);border-radius:var(--border-radius-lg);box-shadow:var(--shadow-lg),0 0 0 1px rgba(var(--primary-color-rgb),.05);max-width:var(--modal-max-width-md);transform:translateY(var(--modal-animation-distance)) scale(var(--modal-animation-scale));transition:transform var(--animation-duration-default) var(--animation-easing-smooth),opacity var(--animation-duration-default) var(--animation-easing-smooth);border:1px solid var(--surface-border)}.modal-backdrop.open .modal-container{transform:translateY(0) scale(1)}.modal-container.small{width:50%;max-width:var(--modal-max-width-sm)}.modal-container.medium{width:70%;max-width:var(--modal-max-width-md)}.modal-container.large{width:90%;max-width:var(--modal-max-width-lg)}.modal-header{display:flex;align-items:center;justify-content:space-between;padding:var(--spacing-lg) var(--spacing-xl);border-bottom:1px solid var(--surface-border);background:var(--surface-ground);border-top-left-radius:var(--border-radius-lg);border-top-right-radius:var(--border-radius-lg)}.modal-title{font-size:var(--font-size-xl);font-weight:var(--font-weight-semibold);color:var(--text-color);margin:0;display:flex;align-items:center;gap:var(--spacing-sm)}.modal-close{background:transparent;border:none;color:var(--text-color-secondary);padding:var(--spacing-sm);cursor:pointer;border-radius:var(--border-radius);display:flex;align-items:center;justify-content:center;transition:all var(--animation-duration-fast) var(--animation-easing-smooth);margin:var(--negative-spacing-sm)}.modal-close:hover{background:var(--surface-hover);color:var(--text-color);transform:scale(1.1)}.modal-close:focus-visible{outline:var(--focus-outline-width) var(--focus-outline-style) var(--focus-outline-color);outline-offset:var(--focus-outline-offset)}.modal-close i{font-size:var(--font-size-xl)}.modal-content{padding:var(--spacing-xl);overflow-y:auto;flex-grow:1;min-height:0;color:var(--text-color-secondary);line-height:var(--line-height-relaxed)}.modal-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--spacing-md);padding:var(--spacing-lg) var(--spacing-xl);border-top:1px solid var(--surface-border);background:var(--surface-ground);border-bottom-left-radius:var(--border-radius-lg);border-bottom-right-radius:var(--border-radius-lg)}@media (max-width: 768px){.modal-container{width:95%;margin:var(--spacing-md)}.modal-header{padding:var(--spacing-md) var(--spacing-lg)}.modal-title{font-size:var(--font-size-lg)}.modal-content{padding:var(--spacing-lg)}.modal-footer{padding:var(--spacing-md) var(--spacing-lg);flex-direction:column-reverse;gap:var(--spacing-sm)}}@media (max-width: 480px){.modal-container{width:100%;max-height:100vh;margin:0;border-radius:0}.modal-header{padding:var(--spacing-sm) var(--spacing-md);border-top-left-radius:0;border-top-right-radius:0}.modal-title{font-size:var(--font-size-base)}.modal-content{padding:var(--spacing-md);flex:0 1 auto}.modal-footer{padding:var(--spacing-sm) var(--spacing-md);border-bottom-left-radius:0;border-bottom-right-radius:0}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: PshButtonComponent, selector: "psh-button", inputs: ["appearance", "variant", "size", "disabled", "loading", "fullWidth", "iconPosition", "icon", "ariaLabel", "loadingText", "disabledText", "iconOnlyText", "type"], outputs: ["fullWidthChange", "clicked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2409
2419
|
}
|
|
2410
2420
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: PshModalComponent, decorators: [{
|
|
2411
2421
|
type: Component,
|
|
2412
|
-
args: [{ selector: 'psh-modal', imports: [CommonModule, PshButtonComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n #modalBackdrop\n class=\"modal-backdrop\"\n [class.open]=\"open()\"\n (click)=\"handleBackdropClick($event)\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-hidden]=\"!open()\"\n [attr.aria-labelledby]=\"modalDialogId() + '-title'\"\n [attr.aria-describedby]=\"modalDescriptionId()\"\n [attr.data-state]=\"state()\"\n>\n <div\n [class]=\"'modal-container ' + styleClass()\"\n [class.small]=\"size() === 'small'\"\n [class.medium]=\"size() === 'medium'\"\n [class.large]=\"size() === 'large'\"\n [attr.id]=\"modalDialogId()\"\n role=\"document\"\n >\n <div class=\"modal-content-wrapper\">\n <div class=\"modal-header\">\n <h2 class=\"modal-title\" [attr.id]=\"modalDialogId() + '-title'\">\n <ng-content select=\"[modal-title]\">{{ title() }}</ng-content>\n </h2>\n @if (showClose()) {\n <button\n type=\"button\"\n class=\"modal-close\"\n (click)=\"handleClose()\"\n [attr.aria-label]=\"dismissLabel()\"\n >\n <i class=\"ph ph-x\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n\n <div class=\"modal-content\" [attr.id]=\"modalDescriptionId()\">\n <ng-content>\n <p>\n Modal content goes here. You can replace this with your own content.\n </p>\n </ng-content>\n </div>\n\n @if (showFooter() && !hasCustomFooter()) {\n <div class=\"modal-footer\">\n <psh-button\n appearance=\"outline\"\n variant=\"primary\"\n size=\"medium\"\n [fullWidth]=\"isMobileScreen()\"\n (clicked)=\"handleClose()\">\n {{ cancelLabel() }}\n </psh-button>\n <psh-button\n appearance=\"filled\"\n variant=\"primary\"\n size=\"medium\"\n [fullWidth]=\"isMobileScreen()\"\n (clicked)=\"handleConfirm()\">\n {{ confirmLabel() }}\n </psh-button>\n </div>\n } @if (showFooter() && hasCustomFooter()) {\n <div class=\"modal-footer\">\n <!--\n Note: When using a custom footer, buttons should also use [fullWidth]=\"isMobileScreen()\"\n to ensure proper responsive behavior on mobile devices.\n Example:\n <psh-button [fullWidth]=\"isMobileScreen()\" (clicked)=\"action()\">Custom Button</psh-button>\n -->\n <ng-content select=\"[modal-footer]\" #modalFooter></ng-content>\n </div>\n }\n </div>\n </div>\n</div>\n", styles: [":root{--modal-max-width-sm: 25rem;--modal-max-width-md: 37.5rem;--modal-max-width-lg: 50rem;--modal-backdrop-opacity: .6;--modal-backdrop-blur: 4px;--modal-animation-distance: 20px;--modal-animation-scale: .95}.modal-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(var(--surface-900-rgb),var(--modal-backdrop-opacity));-webkit-backdrop-filter:blur(var(--modal-backdrop-blur));backdrop-filter:blur(var(--modal-backdrop-blur));align-items:center;justify-content:center;z-index:var(--z-index-modal-backdrop);pointer-events:none;opacity:0;display:none;transition:opacity var(--animation-duration-default) var(--animation-easing-smooth)}.modal-backdrop.open{opacity:1;pointer-events:all;display:flex}.modal-content-wrapper{display:flex;flex-direction:column;max-height:90vh;min-height:0}.modal-container{background:var(--surface-card);border-radius:var(--border-radius-lg);box-shadow:var(--shadow-lg),0 0 0 1px rgba(var(--primary-color-rgb),.05);max-width:var(--modal-max-width-md);transform:translateY(var(--modal-animation-distance)) scale(var(--modal-animation-scale));transition:transform var(--animation-duration-default) var(--animation-easing-smooth),opacity var(--animation-duration-default) var(--animation-easing-smooth);border:1px solid var(--surface-border)}.modal-backdrop.open .modal-container{transform:translateY(0) scale(1)}.modal-container.small{width:50%;max-width:var(--modal-max-width-sm)}.modal-container.medium{width:70%;max-width:var(--modal-max-width-md)}.modal-container.large{width:90%;max-width:var(--modal-max-width-lg)}.modal-header{display:flex;align-items:center;justify-content:space-between;padding:var(--spacing-lg) var(--spacing-xl);border-bottom:1px solid var(--surface-border);background:var(--surface-ground);border-top-left-radius:var(--border-radius-lg);border-top-right-radius:var(--border-radius-lg)}.modal-title{font-size:var(--font-size-xl);font-weight:var(--font-weight-semibold);color:var(--text-color);margin:0;display:flex;align-items:center;gap:var(--spacing-sm)}.modal-close{background:transparent;border:none;color:var(--text-color-secondary);padding:var(--spacing-sm);cursor:pointer;border-radius:var(--border-radius);display:flex;align-items:center;justify-content:center;transition:all var(--animation-duration-fast) var(--animation-easing-smooth);margin:var(--negative-spacing-sm)}.modal-close:hover{background:var(--surface-hover);color:var(--text-color);transform:scale(1.1)}.modal-close:focus-visible{outline:var(--focus-outline-width) var(--focus-outline-style) var(--focus-outline-color);outline-offset:var(--focus-outline-offset)}.modal-close i{font-size:var(--font-size-xl)}.modal-content{padding:var(--spacing-xl);overflow-y:auto;flex-grow:1;min-height:0;color:var(--text-color-secondary);line-height:var(--line-height-relaxed)}.modal-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--spacing-md);padding:var(--spacing-lg) var(--spacing-xl);border-top:1px solid var(--surface-border);background:var(--surface-ground);border-bottom-left-radius:var(--border-radius-lg);border-bottom-right-radius:var(--border-radius-lg)}@media (max-width: 768px){.modal-container{width:95%;margin:var(--spacing-md)}.modal-header{padding:var(--spacing-md) var(--spacing-lg)}.modal-title{font-size:var(--font-size-lg)}.modal-content{padding:var(--spacing-lg)}.modal-footer{padding:var(--spacing-md) var(--spacing-lg);flex-direction:column-reverse;gap:var(--spacing-sm)}}@media (max-width: 480px){.modal-container{width:100%;max-height:100vh;margin:0;border-radius:0}.modal-header{padding:var(--spacing-sm) var(--spacing-md);border-top-left-radius:0;border-top-right-radius:0}.modal-title{font-size:var(--font-size-base)}.modal-content{padding:var(--spacing-md);flex:0 1 auto}.modal-footer{padding:var(--spacing-sm) var(--spacing-md);border-bottom-left-radius:0;border-bottom-right-radius:0}}\n"] }]
|
|
2413
|
-
}], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], showClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClose", required: false }] }], closeOnBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdrop", required: false }] }], closeOnEscape: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnEscape", required: false }] }], preventScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "preventScroll", required: false }] }], showFooter: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFooter", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], dismissLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissLabel", required: false }] }], confirmLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmLabel", required: false }] }], cancelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelLabel", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], confirmed: [{ type: i0.Output, args: ["confirmed"] }], customFooter: [{ type: i0.ContentChild, args: ['modalFooter', { isSignal: true }] }], modalBackdrop: [{ type: i0.ViewChild, args: ['modalBackdrop', { isSignal: true }] }] } });
|
|
2422
|
+
args: [{ selector: 'psh-modal', imports: [CommonModule, PshButtonComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n #modalBackdrop\n [class]=\"'modal-backdrop ' + backdropClass()\"\n [class.open]=\"open()\"\n (click)=\"handleBackdropClick($event)\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-hidden]=\"!open()\"\n [attr.aria-labelledby]=\"modalDialogId() + '-title'\"\n [attr.aria-describedby]=\"modalDescriptionId()\"\n [attr.data-state]=\"state()\"\n>\n <div\n [class]=\"'modal-container ' + styleClass()\"\n [class.small]=\"size() === 'small'\"\n [class.medium]=\"size() === 'medium'\"\n [class.large]=\"size() === 'large'\"\n [attr.id]=\"modalDialogId()\"\n role=\"document\"\n >\n <div class=\"modal-content-wrapper\">\n <div class=\"modal-header\">\n <h2 class=\"modal-title\" [attr.id]=\"modalDialogId() + '-title'\">\n <ng-content select=\"[modal-title]\">{{ title() }}</ng-content>\n </h2>\n @if (showClose()) {\n <button\n type=\"button\"\n class=\"modal-close\"\n (click)=\"handleClose()\"\n [attr.aria-label]=\"dismissLabel()\"\n >\n <i class=\"ph ph-x\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n\n <div class=\"modal-content\" [attr.id]=\"modalDescriptionId()\">\n <ng-content>\n <p>\n Modal content goes here. You can replace this with your own content.\n </p>\n </ng-content>\n </div>\n\n @if (showFooter() && !hasCustomFooter()) {\n <div class=\"modal-footer\">\n <psh-button\n appearance=\"outline\"\n variant=\"primary\"\n size=\"medium\"\n [fullWidth]=\"isMobileScreen()\"\n (clicked)=\"handleClose()\">\n {{ cancelLabel() }}\n </psh-button>\n <psh-button\n appearance=\"filled\"\n variant=\"primary\"\n size=\"medium\"\n [fullWidth]=\"isMobileScreen()\"\n (clicked)=\"handleConfirm()\">\n {{ confirmLabel() }}\n </psh-button>\n </div>\n } @if (showFooter() && hasCustomFooter()) {\n <div class=\"modal-footer\">\n <!--\n Note: When using a custom footer, buttons should also use [fullWidth]=\"isMobileScreen()\"\n to ensure proper responsive behavior on mobile devices.\n Example:\n <psh-button [fullWidth]=\"isMobileScreen()\" (clicked)=\"action()\">Custom Button</psh-button>\n -->\n <ng-content select=\"[modal-footer]\" #modalFooter></ng-content>\n </div>\n }\n </div>\n </div>\n</div>\n", styles: [":root{--modal-max-width-sm: 25rem;--modal-max-width-md: 37.5rem;--modal-max-width-lg: 50rem;--modal-backdrop-opacity: .6;--modal-backdrop-blur: 4px;--modal-animation-distance: 20px;--modal-animation-scale: .95}.modal-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(var(--surface-900-rgb),var(--modal-backdrop-opacity));-webkit-backdrop-filter:blur(var(--modal-backdrop-blur));backdrop-filter:blur(var(--modal-backdrop-blur));align-items:center;justify-content:center;z-index:var(--z-index-modal-backdrop);pointer-events:none;opacity:0;display:none;transition:opacity var(--animation-duration-default) var(--animation-easing-smooth)}.modal-backdrop.open{opacity:1;pointer-events:all;display:flex}.modal-content-wrapper{display:flex;flex-direction:column;max-height:90vh;min-height:0}.modal-container{background:var(--surface-card);border-radius:var(--border-radius-lg);box-shadow:var(--shadow-lg),0 0 0 1px rgba(var(--primary-color-rgb),.05);max-width:var(--modal-max-width-md);transform:translateY(var(--modal-animation-distance)) scale(var(--modal-animation-scale));transition:transform var(--animation-duration-default) var(--animation-easing-smooth),opacity var(--animation-duration-default) var(--animation-easing-smooth);border:1px solid var(--surface-border)}.modal-backdrop.open .modal-container{transform:translateY(0) scale(1)}.modal-container.small{width:50%;max-width:var(--modal-max-width-sm)}.modal-container.medium{width:70%;max-width:var(--modal-max-width-md)}.modal-container.large{width:90%;max-width:var(--modal-max-width-lg)}.modal-header{display:flex;align-items:center;justify-content:space-between;padding:var(--spacing-lg) var(--spacing-xl);border-bottom:1px solid var(--surface-border);background:var(--surface-ground);border-top-left-radius:var(--border-radius-lg);border-top-right-radius:var(--border-radius-lg)}.modal-title{font-size:var(--font-size-xl);font-weight:var(--font-weight-semibold);color:var(--text-color);margin:0;display:flex;align-items:center;gap:var(--spacing-sm)}.modal-close{background:transparent;border:none;color:var(--text-color-secondary);padding:var(--spacing-sm);cursor:pointer;border-radius:var(--border-radius);display:flex;align-items:center;justify-content:center;transition:all var(--animation-duration-fast) var(--animation-easing-smooth);margin:var(--negative-spacing-sm)}.modal-close:hover{background:var(--surface-hover);color:var(--text-color);transform:scale(1.1)}.modal-close:focus-visible{outline:var(--focus-outline-width) var(--focus-outline-style) var(--focus-outline-color);outline-offset:var(--focus-outline-offset)}.modal-close i{font-size:var(--font-size-xl)}.modal-content{padding:var(--spacing-xl);overflow-y:auto;flex-grow:1;min-height:0;color:var(--text-color-secondary);line-height:var(--line-height-relaxed)}.modal-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--spacing-md);padding:var(--spacing-lg) var(--spacing-xl);border-top:1px solid var(--surface-border);background:var(--surface-ground);border-bottom-left-radius:var(--border-radius-lg);border-bottom-right-radius:var(--border-radius-lg)}@media (max-width: 768px){.modal-container{width:95%;margin:var(--spacing-md)}.modal-header{padding:var(--spacing-md) var(--spacing-lg)}.modal-title{font-size:var(--font-size-lg)}.modal-content{padding:var(--spacing-lg)}.modal-footer{padding:var(--spacing-md) var(--spacing-lg);flex-direction:column-reverse;gap:var(--spacing-sm)}}@media (max-width: 480px){.modal-container{width:100%;max-height:100vh;margin:0;border-radius:0}.modal-header{padding:var(--spacing-sm) var(--spacing-md);border-top-left-radius:0;border-top-right-radius:0}.modal-title{font-size:var(--font-size-base)}.modal-content{padding:var(--spacing-md);flex:0 1 auto}.modal-footer{padding:var(--spacing-sm) var(--spacing-md);border-bottom-left-radius:0;border-bottom-right-radius:0}}\n"] }]
|
|
2423
|
+
}], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], showClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClose", required: false }] }], closeOnBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdrop", required: false }] }], closeOnEscape: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnEscape", required: false }] }], preventScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "preventScroll", required: false }] }], showFooter: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFooter", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], dismissLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissLabel", required: false }] }], confirmLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmLabel", required: false }] }], cancelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelLabel", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], backdropClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "backdropClass", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], confirmed: [{ type: i0.Output, args: ["confirmed"] }], customFooter: [{ type: i0.ContentChild, args: ['modalFooter', { isSignal: true }] }], modalBackdrop: [{ type: i0.ViewChild, args: ['modalBackdrop', { isSignal: true }] }] } });
|
|
2414
2424
|
|
|
2415
2425
|
const PAGINATION_CONFIG = new InjectionToken('PAGINATION_CONFIG', {
|
|
2416
2426
|
factory: () => ({
|